diff --git a/TODO.md b/TODO.md index 96c3a46..b933293 100644 --- a/TODO.md +++ b/TODO.md @@ -1,7 +1,4 @@ - [ ] OpenUI and shadcn/ui - -- [ ] Upload and Serve endpoints for files in the workspace -- [ ] Make the user able to manage their files in the workspace via endpoints related to workspace management /worksapce - [ ] Github OAuth - [ ] Implement an user management system so the user can customize its name, change password, profile picture and settings diff --git a/graphify-out/.graphify_labels.json b/graphify-out/.graphify_labels.json index 30986d4..f2f53dd 100644 --- a/graphify-out/.graphify_labels.json +++ b/graphify-out/.graphify_labels.json @@ -207,14 +207,9 @@ "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", @@ -262,7 +257,6 @@ "260": "Community 260", "261": "Community 261", "262": "Community 262", - "263": "Community 263", "264": "Community 264", "265": "Community 265", "266": "Community 266", @@ -473,7 +467,6 @@ "471": "Community 471", "472": "Community 472", "473": "Community 473", - "474": "Community 474", "475": "Community 475", "476": "Community 476", "477": "Community 477", @@ -485,16 +478,13 @@ "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", @@ -502,17 +492,19 @@ "500": "Community 500", "501": "Community 501", "502": "Community 502", + "503": "Community 503", "504": "Community 504", + "505": "Community 505", + "506": "Community 506", "507": "Community 507", "509": "Community 509", "510": "Community 510", - "512": "Community 512", + "511": "Community 511", "513": "Community 513", "514": "Community 514", "515": "Community 515", "516": "Community 516", "518": "Community 518", - "519": "Community 519", "520": "Community 520", "522": "Community 522", "527": "Community 527" diff --git a/graphify-out/GRAPH_REPORT.md b/graphify-out/GRAPH_REPORT.md index b606064..dd75a55 100644 --- a/graphify-out/GRAPH_REPORT.md +++ b/graphify-out/GRAPH_REPORT.md @@ -1,16 +1,16 @@ -# Graph Report - server (2026-08-15) +# Graph Report - server (2026-08-16) ## Corpus Check -- 100 files · ~41,695 words +- 102 files · ~46,927 words - Verdict: corpus is large enough that graph structure adds value. ## Summary -- 5404 nodes · 7272 edges · 517 communities (292 shown, 225 thin omitted) -- Extraction: 83% EXTRACTED · 17% INFERRED · 0% AMBIGUOUS · INFERRED: 1215 edges (avg confidence: 0.69) +- 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) - Token cost: 0 input · 0 output ## Graph Freshness -- Built from commit: `733e8a8d` +- Built from commit: `5f72f66a` - Run `git rev-parse HEAD` and compare to check if the graph is stale. - Run `graphify update .` after code changes (no API cost). @@ -223,14 +223,9 @@ - [[_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]] @@ -278,7 +273,6 @@ - [[_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]] @@ -480,7 +474,6 @@ - [[_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]] @@ -492,29 +485,27 @@ - [[_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]] - [[_COMMUNITY_Community 504|Community 504]] +- [[_COMMUNITY_Community 505|Community 505]] +- [[_COMMUNITY_Community 506|Community 506]] - [[_COMMUNITY_Community 507|Community 507]] - [[_COMMUNITY_Community 509|Community 509]] - [[_COMMUNITY_Community 510|Community 510]] -- [[_COMMUNITY_Community 512|Community 512]] - [[_COMMUNITY_Community 518|Community 518]] -- [[_COMMUNITY_Community 519|Community 519]] - [[_COMMUNITY_Community 520|Community 520]] - [[_COMMUNITY_Community 522|Community 522]] - [[_COMMUNITY_Community 527|Community 527]] @@ -526,7 +517,7 @@ 4. `UserManager` - 55 edges 5. `Permission` - 50 edges 6. `Pytest Testing` - 50 edges -7. `StocksQueryManager` - 47 edges +7. `StocksQueryManager` - 48 edges 8. `Roles` - 45 edges 9. `Prometheus` - 41 edges 10. `TestQueryFundamental` - 38 edges @@ -540,8 +531,8 @@ main/app/prometheus/state.py → tests/test_sandbox_tools.py - `HarnessState` --uses--> `TestDispatchToolCallSandbox` [INFERRED] main/app/prometheus/state.py → tests/test_sandbox_tools.py -- `Config` --uses--> `Prometheus` [INFERRED] - config.py → main/app/prometheus/agent.py +- `get_state()` --calls--> `test_get_state_no_state_returns_error()` [INFERRED] + main/app/prometheus/tools.py → tests/test_prometheus_tools.py ## Hyperedges (group relationships) - **Authentication Module** — AuthenticationManager, SessionManager, auth_util, auth_constants, getGoogleSSO [INFERRED] @@ -551,7 +542,7 @@ - **Configuration & Database Infrastructure** — config_Config, config_engine, config_stocksEngine [INFERRED] - **User Authentication & Authorization** — user_service, authentication, user_roles, permission_system [INFERRED] -## Communities (517 total, 225 thin omitted) +## Communities (509 total, 225 thin omitted) ### Community 0 - "Stocks API Endpoints" Cohesion: 0.0 @@ -566,16 +557,16 @@ Cohesion: 0.13 Nodes (21): Thin async wrapper around the CubeSandbox/E2B HTTP API. All methods are sta, SandboxManager, _mock_forgevm(), Unit tests for SandboxManager — HTTP calls mocked via a fake client class., Wire up mock forgevm AsyncClient that returns sandbox with all methods., Wire up mock forgevm AsyncClient that returns sandbox with all methods., test_create_sandbox(), test_destroy_sandbox() (+13 more) ### Community 3 - "Prometheus Agent" -Cohesion: 0.07 -Nodes (23): 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., Tests covering cache.py lines 28-76., Regression: is_string_dtype fails when column has strings + None (pandas 2.x). (+15 more) +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) ### Community 4 - "Data Models & Types" -Cohesion: 0.16 -Nodes (11): PrometheusSandbox, cleanup_expired_sandboxes(), Remove DB mappings for sandboxes that no longer exist in ForgeVM., 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., Enforce one active sandbox per user via application logic., test_cleanup_keeps_alive_sandboxes() (+3 more) +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.05 -Nodes (44): AuthForm(), registry, SUGGESTIONS, apiFetch(), authHeaders(), createSession(), deleteSession(), deleteWorkspaceFile() (+36 more) +Cohesion: 0.22 +Nodes (13): AuthForm(), apiFetch(), authHeaders(), createSession(), deleteSession(), deleteWorkspaceFile(), googleAuthUrl(), listWorkspaceFiles() (+5 more) ### Community 6 - "Database Schema" Cohesion: 0.04 @@ -587,7 +578,7 @@ Nodes (29): Algorithmic Compression (`compact.py`) Implementation Plan, code:pyt ### Community 8 - "Device Detection" Cohesion: 0.06 -Nodes (28): 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 (+20 more) +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) ### Community 9 - "Server Configuration" Cohesion: 0.11 @@ -622,8 +613,8 @@ 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) ### Community 17 - "Community 17" -Cohesion: 0.05 -Nodes (40): 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. (+32 more) +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) ### Community 18 - "Community 18" Cohesion: 0.07 @@ -639,7 +630,7 @@ Nodes (35): 1. Memory System (B+), 2. Summarizer/Episodes (B), 3. Loop Events (A ### Community 21 - "Community 21" Cohesion: 0.05 -Nodes (41): 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. (+33 more) +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) ### Community 22 - "Community 22" Cohesion: 0.07 @@ -667,7 +658,7 @@ Nodes (14): getRelevanceScore(), _FakeMemory, A memory with no lastAccessedAt sh ### Community 28 - "Community 28" Cohesion: 0.07 -Nodes (27): No historical data columns -> inner 400 caught by outer except -> 500., 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., No historical data columns -> inner 400 caught by outer except -> 500., If an unexpected exception occurs (line 132)., If an unexpected exception occurs (line 132)., Historical query with a year range. (+19 more) +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) ### Community 29 - "Community 29" Cohesion: 0.09 @@ -686,8 +677,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.12 -Nodes (14): BaseHTTPMiddleware, BaseModel, Tests for standardized error responses (errors.py)., SampleBody, TestErrorResponseModel, TestGenericExceptionHandler, TestHTTPExceptionHandler, TestRequestContextFilter (+6 more) +Cohesion: 0.06 +Nodes (23): BaseHTTPMiddleware, BaseModel, Tests for standardized error responses (errors.py)., SampleBody, TestErrorResponseModel, TestGenericExceptionHandler, TestHTTPExceptionHandler, TestRequestContextFilter (+15 more) ### Community 34 - "Community 34" Cohesion: 0.11 @@ -710,8 +701,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.11 -Nodes (17): search.strip() == '' should still dedup (line 181)., Multiple search terms with tickerIndex., Multiple search terms with tickerIndex., Search with no index match falls back to string startswith., Search with no index match falls back to string startswith., Search with no index match falls back to string startswith., Multiple search terms with tickerIndex., Multiple search terms with tickerIndex. (+9 more) +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) ### Community 40 - "Community 40" Cohesion: 0.12 @@ -726,8 +717,8 @@ Cohesion: 0.09 Nodes (16): StocksCacheManager, Tests for dynamic ticker index feature, Ticker index should be built when cache is loaded, Ticker index should contain all tickers from cache, Ticker index should be case-insensitive, Looking up ticker should return valid row index, Ticker index should be rebuilt when cache refreshes, TestTickerIndex (+8 more) ### Community 43 - "Community 43" -Cohesion: 0.13 -Nodes (9): Authentication System, authenticateUser(), createUserAccount(), hashPassword(), verifyPassword(), Google OAuth, JWT Authentication, TestAuthUtil (+1 more) +Cohesion: 0.14 +Nodes (6): authenticateUser(), createUserAccount(), hashPassword(), verifyPassword(), TestAuthUtil, TestAuthUtilEdgeCases ### Community 44 - "Community 44" Cohesion: 0.14 @@ -750,8 +741,8 @@ 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 ### Community 49 - "Community 49" -Cohesion: 0.13 -Nodes (18): dispatchToolCall(), TDD tests: verify memory tools are wired into the Prometheus agent. RED: Thes, 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(), test_search_memory_routed_to_executeMemoryTool() (+10 more) +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) ### Community 50 - "Community 50" Cohesion: 0.07 @@ -766,12 +757,12 @@ Cohesion: 0.08 Nodes (7): Cover all methods in chat.py (lines 11-120)., Cover all methods in chat.py (lines 11-120)., Cover all methods in chat.py (lines 11-120)., Cover all methods in chat.py (lines 11-120)., Cover all methods in chat.py (lines 11-120)., Cover all methods in chat.py (lines 11-120)., TestPrometheusChatManager ### Community 53 - "Community 53" -Cohesion: 0.13 -Nodes (20): applyUpdate(), archiveDead(), count_memories(), countMemories(), decayScores(), deleteMemory(), extract(), findSimilarKey() (+12 more) +Cohesion: 0.12 +Nodes (19): archiveDead(), count_memories(), countMemories(), decayScores(), deleteMemory(), extract(), findSimilarKey(), _fulltext_search() (+11 more) ### Community 54 - "Community 54" Cohesion: 0.06 -Nodes (31): initialize(), 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. (+23 more) +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) ### Community 55 - "Community 55" Cohesion: 0.11 @@ -786,12 +777,12 @@ Cohesion: 0.09 Nodes (15): Performance benchmark tests for stocks API, Performance benchmark tests for stocks API, Ticker index lookup should be O(1) - very fast, Ticker index lookup should be O(1) - very fast, Prefix scan should be much slower than index lookup, Prefix scan should be much slower than index lookup, Index lookup should be significantly faster than scan, Index lookup should be significantly faster than scan (+7 more) ### Community 58 - "Community 58" -Cohesion: 0.15 +Cohesion: 0.17 Nodes (14): getGoogleSSO(), createAccessToken(), googleCallback(), googleLogin(), isSecureScheme(), issueSessionCookie(), login(), logout() (+6 more) ### Community 59 - "Community 59" Cohesion: 0.05 -Nodes (43): lifespan(), status(), Tests for main/utils/connectivity.py — covers all branches., checkServiceConnection — success, not found, errors., checkServiceConnection — success, not found, errors., checkMySqlConnection — success, errors, engine=None paths., checkMySqlConnection — success, errors, engine=None paths., test_both_engines_ok() (+35 more) +Nodes (44): lifespan(), status(), Tests for main/utils/connectivity.py — covers all branches., checkServiceConnection — success, not found, errors., checkServiceConnection — success, not found, errors., checkMySqlConnection — success, errors, engine=None paths., checkMySqlConnection — success, errors, engine=None paths., test_both_engines_ok() (+36 more) ### Community 60 - "Community 60" Cohesion: 0.09 @@ -802,8 +793,8 @@ Cohesion: 0.1 Nodes (20): architectures, attention_probs_dropout_prob, gradient_checkpointing, hidden_act, hidden_dropout_prob, hidden_size, initializer_range, intermediate_size (+12 more) ### Community 63 - "Community 63" -Cohesion: 0.13 -Nodes (9): _filterCotationByDate(), filterCotationData(), _parseCotationDate(), Fetch live prices for B3 tickers via yfinance. B3 tickers must match, Parse DD-MM-YYYY from COTACAO 10Y JSON DATA field. ponytail: stdlib datetime onl, Filter COTACAO 10Y JSON entries by their inner DATA field (DD-MM-YYYY)., sanitizeNanValues(), StocksQueryManager (+1 more) +Cohesion: 0.15 +Nodes (11): normalizeKey(), Store a value in state. Marks state as changed for context injection., _filterCotationByDate(), filterCotationData(), _parseCotationDate(), Shared query pipeline for historical and fundamental endpoints., Fetch live prices for B3 tickers via yfinance. B3 tickers must match, Parse DD-MM-YYYY from COTACAO 10Y JSON DATA field. ponytail: stdlib datetime onl (+3 more) ### Community 64 - "Community 64" Cohesion: 0.06 @@ -822,8 +813,8 @@ Cohesion: 0.13 Nodes (18): SessionManager, PrometheusChatManager, Cover getGoogleSSO (lines 6-14)., Cover getGoogleSSO (lines 6-14)., Cover __init__ and updateDates., Cover __init__ and updateDates (lines 22-37)., Cover streamMessage in agent.py., Cover sendMessage and streamMessage in agent.py. (+10 more) ### Community 69 - "Community 69" -Cohesion: 0.2 -Nodes (26): downloadWorkspaceFile(), _base_url(), baseUrl(), checkpoint(), create(), delete_file(), destroy(), execute() (+18 more) +Cohesion: 0.22 +Nodes (25): _base_url(), baseUrl(), checkpoint(), create(), delete_file(), destroy(), execute(), executeWithWorkspace() (+17 more) ### Community 70 - "Community 70" Cohesion: 0.11 @@ -834,8 +825,8 @@ Cohesion: 0.11 Nodes (19): API Key System, B3 Scraper, Fundamental Data, Gemini Model, Historical Data, Ma'at Stock Algorithm, Mansa Server, MySQL Database (+11 more) ### Community 72 - "Community 72" -Cohesion: 0.1 -Nodes (6): B3Scraper, getCurrentSelic(), getInitialData(), calculateInvestingScore(), runScraper(), ScraperService +Cohesion: 0.2 +Nodes (4): B3Scraper, calculateInvestingScore(), runScraper(), ScraperService ### Community 73 - "Community 73" Cohesion: 0.16 @@ -858,20 +849,20 @@ Cohesion: 0.11 Nodes (16): Architecture, Architecture, Architecture, code:block1 (Agent calls tools (StocksAPI, etc.) → gets data → agent deci), code:python (import sys, io, base64, json, matplotlib), code:json ({"type": "sandbox_start", "stream": "system"}), code:json ({), code:python (class MemoryManager:) (+8 more) ### Community 78 - "Community 78" -Cohesion: 0.11 -Nodes (8): verifyAccessToken(), getSessions(), Covers lines 50-51: jwt.InvalidTokenError., Covers lines 50-51: jwt.InvalidTokenError., Covers lines 50-51: jwt.InvalidTokenError., Covers lines 50-51: jwt.InvalidTokenError., Covers lines 50-51: jwt.InvalidTokenError., Covers lines 50-51: jwt.InvalidTokenError. +Cohesion: 0.12 +Nodes (16): Covers line 16: empty password raises ValueError., Covers line 16: empty password raises ValueError., Covers line 16: empty password raises ValueError., Covers lines 45-51: verifyAccessToken with expired and invalid tokens., Covers line 16: empty password raises ValueError., Covers lines 48-49: jwt.ExpiredSignatureError., Covers lines 45-51: verifyAccessToken with expired and invalid tokens., Covers lines 45-51: verifyAccessToken with expired and invalid tokens. (+8 more) ### Community 79 - "Community 79" Cohesion: 0.05 Nodes (38): cn(), AlertDialogAction(), AlertDialogCancel(), AlertDialogContent(), AlertDialogDescription(), AlertDialogFooter(), AlertDialogHeader(), AlertDialogMedia() (+30 more) ### Community 80 - "Community 80" -Cohesion: 0.12 -Nodes (16): countTokens(), getTokenizer(), PrometheusSummarizer, Summarize conversation history into episode summaries., Check if accumulated tokens exceed episode threshold., Get messages since the last episode for summarization., Check if accumulated tokens exceed episode threshold., Check if accumulated tokens exceed episode threshold. (+8 more) +Cohesion: 0.1 +Nodes (19): countTokens(), getTokenizer(), PrometheusSummarizer, Summarize conversation history into episode summaries., Check if accumulated tokens exceed episode threshold., Get messages since the last episode for summarization., Check if accumulated tokens exceed episode threshold., Check if accumulated tokens exceed episode threshold. (+11 more) ### Community 81 - "Community 81" -Cohesion: 0.12 -Nodes (11): getHistorical(), JSONBytesResponse, Get year-based historical financial data for Brazilian B3 stocks. Returns, Get year-based historical financial data for Brazilian B3 stocks. Returns, Sends pre-serialized JSON bytes without re-encoding (cache-friendly)., Get year-based historical financial data for Brazilian B3 stocks. Returns, Get year-based historical financial data for Brazilian B3 stocks. Returns, Get year-based historical financial data for Brazilian B3 stocks. Returns (+3 more) +Cohesion: 0.11 +Nodes (13): getLiveCotation(), JSONBytesResponse, Get real-time price quotation for a single Brazilian B3 stock. Returns th, Get real-time price quotation for a single Brazilian B3 stock. Returns th, Sends pre-serialized JSON bytes without re-encoding (cache-friendly)., Get real-time price quotation for a single Brazilian B3 stock. Returns th, Get real-time price quotation for a single Brazilian B3 stock. Returns th, Get real-time price quotation for a single Brazilian B3 stock. Returns th (+5 more) ### Community 82 - "Community 82" Cohesion: 0.18 @@ -882,20 +873,20 @@ Cohesion: 0.12 Nodes (16): Brazilian Stocks Market Scraper, code:env (#), code:json ({), Configuration Parameters, Constraint Engine ($\Lambda$), Engines, Fundamental Engine ($\Phi$), Global Score Function (+8 more) ### Community 84 - "Community 84" -Cohesion: 0.15 -Nodes (11): chat(), chat_stream(), createSession(), _forward(), getHistory(), Verify the user owns the session, raise 403 otherwise., Verify the user owns the session, raise 403 otherwise., resumeChatStream() (+3 more) +Cohesion: 0.06 +Nodes (27): chat(), chat_stream(), create_memory(), createMemory(), createSession(), downloadWorkspaceFile(), _forward(), getHistory() (+19 more) ### Community 85 - "Community 85" Cohesion: 0.1 Nodes (17): Covers lines 126-136: DELETE /user/sessions/{sessionId}., Covers lines 126-136: DELETE /user/sessions/{sessionId}., Covers lines 126, 131, 135-136., Covers lines 126, 131, 135-136., Covers lines 126-136: DELETE /user/sessions/{sessionId}., Covers lines 126, 131, 135-136., Covers lines 127-129: session not found., Covers lines 127-129: session not found. (+9 more) ### Community 86 - "Community 86" -Cohesion: 0.22 -Nodes (13): _mock_forgevm(), Wire up mock forgevm AsyncClient that returns sandbox with all methods., Wire up mock forgevm AsyncClient that returns sandbox with all methods., Wire up mock forgevm AsyncClient that returns sandbox with all methods., test_get_or_create_creates_new_when_no_existing(), test_get_or_create_reuses_existing(), test_restore_workspace(), test_sync_from_sandbox() (+5 more) +Cohesion: 0.08 +Nodes (30): check_cache(), _getDb(), Search user's saved memories, preferences, and past analysis context. Use t, Search user's saved memories, preferences, and past analysis context. Use t, Read a file from the sandbox filesystem. Args: path: Absolute pa, Read a file from the sandbox filesystem. Args: path: Absolute pa, Get a download link for a workspace file to share with the user. Use this, Search user's saved memories, preferences, and past analysis context. Use (+22 more) ### Community 87 - "Community 87" -Cohesion: 0.21 -Nodes (10): buildSummary(), charCount(), countTokens(), extractDecisions(), extractMetrics(), extractSnapshots(), extractTickers(), extractToolCalls() (+2 more) +Cohesion: 0.17 +Nodes (14): buildSummary(), charCount(), countTokens(), extractDecisions(), extractMetrics(), extractSnapshots(), extractTickers(), extractToolCalls() (+6 more) ### Community 88 - "Community 88" Cohesion: 0.12 @@ -922,12 +913,8 @@ Cohesion: 0.12 Nodes (10): System prompt should instruct LLM about harness state usage., System prompt should instruct LLM about harness state usage., System prompt should instruct LLM about harness state usage., System prompt should instruct LLM about memory vs state., System prompt should instruct LLM about memory vs state., System prompt should instruct LLM about memory vs state., System prompt should instruct LLM about memory vs state., TestSendMessageStateIntegration (+2 more) ### Community 94 - "Community 94" -Cohesion: 0.15 -Nodes (11): test_setup_discord_handler_disabled(), test_setup_discord_handler_enabled(), TestSetupLogging, Many concurrent emit() calls must not create more threads than max_workers., Verify that DiscordHandler submits to a bounded executor, not raw threads., The module-level discordExecutor must exist with max_workers <= 5., DiscordHandler.emit() must use discordExecutor.submit, not Thread.start., TestDiscordHandlerThreadPool (+3 more) - -### Community 95 - "Community 95" -Cohesion: 0.12 -Nodes (6): Config, AuthenticationService, MCPDetectMiddleware, StocksAPIService, UserService, ServiceManager +Cohesion: 0.25 +Nodes (5): Many concurrent emit() calls must not create more threads than max_workers., Verify that DiscordHandler submits to a bounded executor, not raw threads., The module-level discordExecutor must exist with max_workers <= 5., DiscordHandler.emit() must use discordExecutor.submit, not Thread.start., TestDiscordHandlerThreadPool ### Community 96 - "Community 96" Cohesion: 0.2 @@ -943,11 +930,11 @@ Nodes (6): extractTokenPayload(), Tests for extractTokenPayload — the standalo ### Community 99 - "Community 99" Cohesion: 0.18 -Nodes (11): client(), TestClient with all routers mounted — no lifespan (no DB/service init). O, TestClient with all routers mounted — no lifespan (no DB/service init). O, TestClient with all routers mounted — no lifespan (no DB/service init). O, TestClient with all routers mounted — no lifespan (no DB/service init). O, TestClient with all routers mounted — no lifespan (no DB/service init). O, TestClient with stocks router + verifyAPIKey + getCurrentUser overrides., TestClient with all routers mounted — no lifespan (no DB/service init). O (+3 more) +Nodes (6): System prompt should include state context when provided., System prompt should not include state section when empty., State section should appear after memories section., All state entries should appear in the prompt., System prompt should work without state parameter., TestBuildSystemPromptState ### Community 100 - "Community 100" -Cohesion: 0.09 -Nodes (15): Store a value in the harness state for this session. Use this to save inter, Store a value in the harness state for this session. Use this to save interm, Store a value in the harness state for this session. Use this to save inter, Store a value in the harness state for this session. Use this to save inter, Store a value in the harness state for this session. Use this to save inter, Store a value in the harness state for this session. Use this to save inter, set_state(), _assert_gemini_safe() (+7 more) +Cohesion: 0.06 +Nodes (14): _assert_gemini_safe(), Every function in TOOL_REGISTRY must have Gemini-safe signatures. Custom cl, Every function in TOOL_REGISTRY must have Gemini-safe signatures. Custom cl, Regression: HarnessState must never leak into tool signatures., Regression: HarnessState must never leak into tool signatures., Assert a tool function has only Gemini-compatible parameter types., Assert a tool function has only Gemini-compatible parameter types., test_get_state_no_state_returns_error() (+6 more) ### Community 101 - "Community 101" Cohesion: 0.13 @@ -955,7 +942,7 @@ Nodes (13): Covers lines 83-84: session not found., Covers lines 77, 83-84, 86: ### Community 102 - "Community 102" Cohesion: 0.12 -Nodes (10): BaseSettings, BaseMansaSettings, DiscordSettings, MysqlSettings, PrometheusSettings, ScraperSettings, StocksApiSettings, UserSettings (+2 more) +Nodes (11): BaseSettings, BaseMansaSettings, Config, DiscordSettings, MysqlSettings, PrometheusSettings, ScraperSettings, StocksApiSettings (+3 more) ### Community 103 - "Community 103" Cohesion: 0.13 @@ -966,8 +953,8 @@ Cohesion: 0.13 Nodes (13): Covers lines 100-104, 106: GET /user/sessions/current., Covers lines 100-104, 106: GET /user/sessions/current., Covers lines 100-104, 106: session found., Covers lines 100-104, 106: session found., Covers lines 100-104, 106: GET /user/sessions/current., Covers lines 100-104, 106: session found., Covers line 104: session not found., Covers line 104: session not found. (+5 more) ### Community 105 - "Community 105" -Cohesion: 0.36 -Nodes (7): create_memory(), createMemory(), _downloadModel(), embed(), getEmbeddingModel(), executeMemoryTool(), embed() +Cohesion: 0.17 +Nodes (5): Tests for StocksCacheManager queryCache LRU eviction., Create a StocksCacheManager with a mock DB engine., When columns is None, cache key should be None., TestCacheLRUEviction, TestCacheTTLLogic ### Community 106 - "Community 106" Cohesion: 0.22 @@ -1002,11 +989,11 @@ Cohesion: 0.17 Nodes (12): Covers line 67: extractTokenPayload re-raises HTTPException from verifyAccessTok, Covers line 67: extractTokenPayload re-raises HTTPException from verifyAccessTok, Covers line 67: HTTPException raised by verifyAccessToken is re-raised., Covers line 67: extractTokenPayload re-raises HTTPException from verifyAccessTok, Covers line 67: extractTokenPayload re-raises HTTPException from verifyAccessTok, Covers line 67: HTTPException raised by verifyAccessToken is re-raised., Covers line 67: HTTPException raised by verifyAccessToken is re-raised., Covers line 67: extractTokenPayload re-raises HTTPException from verifyAccessTok (+4 more) ### Community 115 - "Community 115" -Cohesion: 0.21 -Nodes (9): Same input → same hash., Different inputs → different hashes., Returns 32-char hex string., TestContentHash, ALL(), content_hash(), contentHash(), MD5 hash for change detection. (+1 more) +Cohesion: 0.15 +Nodes (12): applyUpdate(), upsertMemory(), contentHash(), Same input → same hash., Different inputs → different hashes., Returns 32-char hex string., TestContentHash, ALL() (+4 more) ### Community 116 - "Community 116" -Cohesion: 0.15 +Cohesion: 0.14 Nodes (15): _build_system_prompt(), buildSystemPrompt(), chatSession(), _execute_memory_tool(), executeMemoryTool(), _get_client(), _get_memory_tools(), getClient() (+7 more) ### Community 117 - "Community 117" @@ -1022,24 +1009,24 @@ Cohesion: 0.07 Nodes (26): code:python ("""Tests for SandboxManager file mutation helpers (delete_fi), code:python (from main.app.prometheus.sandbox import SandboxManager, host), code:python (@router.post("/workspace/upload")), code:bash (git add main/controller/prometheus_controller.py tests/test_), code:python (from unittest.mock import patch, MagicMock), code:python (from main.app.prometheus.sandbox import SandboxManager, host), code:python (async def serve_file(path: str, **_) -> dict:), code:python ("serve_file": serve_file,) (+18 more) ### Community 120 - "Community 120" -Cohesion: 0.08 -Nodes (40): _make_auth_client(), Tests to cover uncovered lines across controllers, UserManager, and auth util., Covers lines 87-93, 102: login success and failure paths., Covers lines 87-93, 102: login success and failure paths., Return (client, app) with auth + user routers and mocked getSession., Covers lines 107, 109-130, 133: logout token extraction and revocation., Covers lines 111-113: token extracted from Authorization Bearer header., Covers lines 155-156, 158, 160-168, 170-177, 179-184, 186, 190-204: googleCallba (+32 more) +Cohesion: 0.1 +Nodes (33): _make_auth_client(), Tests to cover uncovered lines across controllers, UserManager, and auth util., Covers lines 87-93, 102: login success and failure paths., Covers lines 87-93, 102: login success and failure paths., Return (client, app) with auth + user routers and mocked getSession., Covers lines 155-156, 158, 160-168, 170-177, 179-184, 186, 190-204: googleCallba, Covers lines 155-156, 158, 160-168, 170-177, 179-184, 186, 190-204: googleCallba, test_callback_existing_user() (+25 more) ### Community 121 - "Community 121" Cohesion: 0.21 Nodes (12): code:python (import inspect), code:python (from main.app.prometheus.sandbox import SandboxManager), code:python (TOOL_REGISTRY: dict[str, Any] = {), code:python (## Code Sandbox (On-Demand)), code:bash (git add main/app/prometheus/agent.py), code:dockerfile (FROM python:3.11-slim), code:bash (git add Dockerfile.sandbox), Phase 6: Agent Integration (All Layers) (+4 more) ### Community 122 - "Community 122" -Cohesion: 0.38 -Nodes (9): Tests for main/utils/logging_config.py — covers DiscordHandler branches., test_discord_disabled(), test_discord_no_webhook(), test_exception_in_submit(), test_level_below_error(), test_message_truncation(), test_submit_called_on_error(), test_with_exception_info() (+1 more) +Cohesion: 0.2 +Nodes (15): Tests for main/utils/logging_config.py — covers DiscordHandler branches., test_discord_disabled(), test_discord_no_webhook(), test_exception_in_submit(), test_level_below_error(), test_message_truncation(), test_setup_discord_handler_disabled(), test_setup_discord_handler_enabled() (+7 more) ### Community 123 - "Community 123" Cohesion: 0.17 Nodes (12): Appendix A: Codebase Findings, code:block6 (D:\Repositories\server\), code:python (engine = create_engine(...) # user_db (mansa_db)), Critical path correction, Existing dependencies (from `requirements.txt`), Key config patterns, Port collision in current setup, Project structure (key files only) (+4 more) ### Community 124 - "Community 124" -Cohesion: 0.25 -Nodes (8): getLiveCotation(), Get real-time price quotation for a single Brazilian B3 stock. Returns th, Get real-time price quotation for a single Brazilian B3 stock. Returns th, Get real-time price quotation for a single Brazilian B3 stock. Returns th, Get real-time price quotation for a single Brazilian B3 stock. Returns th, Get real-time price quotation for a single Brazilian B3 stock. Returns th, Get real-time price quotation for a single Brazilian B3 stock. Returns th, Get real-time price quotation for a single Brazilian B3 stock. Returns th +Cohesion: 0.07 +Nodes (27): code:python (# tests/test_stocks_payload_cache.py), code:python (pc = self.cacheManager.tickerPayloads), code:python (# tests/test_stocks_sync_handlers.py), code:bash (git add main/controller/stocksapi_controller.py main/app/sto), code:python (def test_payload_cache_cotation_index():), code:python (self._cotations: dict[str, bytes] = {}), code:python (cotationCols = ["TICKER", "NOME", "TIME", "COTACAO 10Y PADRA), code:python (self._cotations = cot) (+19 more) ### Community 125 - "Community 125" Cohesion: 0.14 @@ -1062,12 +1049,12 @@ Cohesion: 0.2 Nodes (10): Tests for stocks API field validation — verifies the fields parameter accepts a, Integration: /stocks/fundamental must accept slash and dot fields., Minimal TestClient with just the stocks router for validation tests., GET /fundamental?fields=P/L must not return 422 (validation error)., GET /fundamental?fields=P/L must not return 422 (validation error)., Integration: /stocks/fundamental must accept slash and dot fields., GET /fundamental?fields=P/L must not return 422 (validation error)., GET /historical?fields=P/L must not return 422. (+2 more) ### Community 130 - "Community 130" -Cohesion: 0.38 -Nodes (9): compactCotations(), compactRow(), compactValue(), compressResponse(), fixHeaders(), getAbbr(), getNest(), toColumnar() (+1 more) +Cohesion: 0.25 +Nodes (13): compactCotations(), compactRow(), compactValue(), compressResponse(), fixHeaders(), getAbbr(), getNest(), toColumnar() (+5 more) ### Community 131 - "Community 131" -Cohesion: 0.05 -Nodes (50): Base, PrometheusMemory, PrometheusMemory, MemoryManager, PrometheusMemory, All memory operations. Stateless class methods., PrometheusService, _count_memories() (+42 more) +Cohesion: 0.22 +Nodes (7): verifyAccessToken(), Covers lines 50-51: jwt.InvalidTokenError., Covers lines 50-51: jwt.InvalidTokenError., Covers lines 50-51: jwt.InvalidTokenError., Covers lines 50-51: jwt.InvalidTokenError., Covers lines 50-51: jwt.InvalidTokenError., Covers lines 50-51: jwt.InvalidTokenError. ### Community 132 - "Community 132" Cohesion: 0.11 @@ -1090,8 +1077,8 @@ Cohesion: 0.2 Nodes (9): Invalid date format raises exception (line 132)., Invalid date format raises exception (line 132)., Invalid date format raises exception (line 132)., Invalid date format raises exception (line 132)., Invalid date format raises exception (line 132)., Invalid date format raises exception (line 132)., Invalid date format raises exception (line 132)., Invalid date format raises exception (line 132). (+1 more) ### Community 137 - "Community 137" -Cohesion: 0.29 -Nodes (6): Covers lines 19-20: user not found raises 404., Covers lines 19-20: user not found raises 404., Covers lines 19-20: user not found raises 404., Covers lines 19-20: user not found raises 404., Covers lines 19-20: user not found raises 404., Covers lines 19-20: user not found raises 404. +Cohesion: 0.11 +Nodes (16): Covers lines 13, 17, 19-20, 22-27: UserManager.addRoleToUser., Covers lines 13, 17, 19-20, 22-27: UserManager.addRoleToUser., Covers lines 17, 22-27: user found, role not present, role added., Covers lines 17, 22-27: user found, role not present, role added., Covers lines 13, 17, 19-20, 22-27: UserManager.addRoleToUser., Covers lines 17, 22-27: user found, role not present, role added., Covers lines 13, 17, 19-20, 22-27: UserManager.addRoleToUser., Covers lines 17, 22-27: user found, role not present, role added. (+8 more) ### Community 138 - "Community 138" Cohesion: 0.18 @@ -1102,8 +1089,8 @@ Cohesion: 0.24 Nodes (6): Dataset, produce_data(), Train script for a single file Need to set the TPU address first: export XRT_TP, A class that handles the reddit data files, A class that handles one dataset, RedditDataset ### Community 140 - "Community 140" -Cohesion: 0.29 -Nodes (7): listFields(), Discover available field names before querying /historical or /fundamental., Discover available field names before querying /historical or /fundamental., Discover available field names before querying /historical or /fundamental., Discover available field names before querying /historical or /fundamental., Discover available field names before querying /historical or /fundamental., Discover available field names before querying /historical or /fundamental. +Cohesion: 0.25 +Nodes (8): listFields(), Discover available field names before querying /historical or /fundamental., Discover available field names before querying /historical or /fundamental., Discover available field names before querying /historical or /fundamental., Discover available field names before querying /historical or /fundamental., Discover available field names before querying /historical or /fundamental., Discover available field names before querying /historical or /fundamental., Discover available field names before querying /historical or /fundamental. ### Community 141 - "Community 141" Cohesion: 0.24 @@ -1126,8 +1113,8 @@ Cohesion: 0.2 Nodes (10): code:python (import logging), code:bash (git add main/app/prometheus/sandbox.py tests/test_sandbox.py), code:python (class PrometheusSettings(BaseMansaSettings):), code:yaml (environment:), code:yaml (sandbox:), code:bash (git add config.py docker-compose.yml), code:python (import pytest), Phase 2: Sandbox Execution (+2 more) ### Community 146 - "Community 146" -Cohesion: 0.29 -Nodes (6): Covers lines 48-49: user not in DB., Covers lines 48-49: user not in DB., Covers lines 48-49: user not in DB., Covers lines 48-49: user not in DB., Covers lines 48-49: user not in DB., Covers line 16: empty password raises ValueError. +Cohesion: 0.05 +Nodes (51): Base, PrometheusMemory, PrometheusMemory, MemoryManager, PrometheusMemory, All memory operations. Stateless class methods., PrometheusService, _count_memories() (+43 more) ### Community 147 - "Community 147" Cohesion: 0.23 @@ -1137,13 +1124,17 @@ Nodes (3): categorizeColumns(), TestCategorizeColumns, TestCategorizeColumns Cohesion: 0.2 Nodes (4): createSession(), getSessionById(), revokeSession(), validateSession() +### Community 150 - "Community 150" +Cohesion: 0.12 +Nodes (7): extractHashToken(), fetchHistory(), fetchMe(), fetchSessions(), getCookie(), sendBtn, textarea + ### Community 151 - "Community 151" Cohesion: 0.2 Nodes (3): MEMORY_TOOLS must be defined as a Tool wrapping FunctionDeclarations., MEMORY_TOOLS must be a list of callables with proper signatures., TestMemoryToolsDefinition ### Community 152 - "Community 152" -Cohesion: 0.11 -Nodes (19): list_files(), Read a file from the workspace. Args: path: Path to the file (e., Write a file to the workspace. Use this to save data files (CSV, JSON, scri, Write a file to the workspace. Use this to save data files (CSV, JSON, scri, Read a file from the sandbox filesystem. Args: path: Absolute pa, Read a file from the sandbox filesystem. Args: path: Absolute pa, List files in the workspace directory. Args: path: Directory pat, List files in the workspace directory. Args: path: Directory pat (+11 more) +Cohesion: 0.1 +Nodes (21): list_files(), Read a file from the workspace. Args: path: Path to the file (e., Read a file from the workspace. Args: path: Path to the file (e., Write a file to the workspace. Use this to save data files (CSV, JSON, scri, Write a file to the workspace. Use this to save data files (CSV, JSON, scri, Write a file to the workspace. Use this to save data files (CSV, JSON, scri, Read a file from the sandbox filesystem. Args: path: Absolute pa, Read a file from the sandbox filesystem. Args: path: Absolute pa (+13 more) ### Community 153 - "Community 153" Cohesion: 0.12 @@ -1161,6 +1152,10 @@ Nodes (9): id, ids, tokens, special_tokens, id, ids, tokens, [CLS] (+1 more) Cohesion: 0.22 Nodes (8): API Endpoints, code:env (#), code:bash (python __init__.py), code:mermaid (graph TD), License, Prometheus, Usage, Workflow +### Community 157 - "Community 157" +Cohesion: 0.22 +Nodes (9): getFundamental(), Get point-in-time fundamental/valuation data for Brazilian B3 stocks. Ret, Get point-in-time fundamental/valuation data for Brazilian B3 stocks. Ret, Get point-in-time fundamental/valuation data for Brazilian B3 stocks. Ret, Get point-in-time fundamental/valuation data for Brazilian B3 stocks. Ret, Get point-in-time fundamental/valuation data for Brazilian B3 stocks. Ret, Get point-in-time fundamental/valuation data for Brazilian B3 stocks. Ret, Get point-in-time fundamental/valuation data for Brazilian B3 stocks. Ret (+1 more) + ### Community 158 - "Community 158" Cohesion: 0.22 Nodes (8): code:python (SYSTEM_PROMPT = """), code:bash (git add main/app/prometheus/agent.py), File Map, Global Constraints, How This Compares to ComputerUse, Prometheus Harness Architecture — Observable Loops, Sandbox Execution, Persistent States, Summary, Task 8: System Prompt — Teach LLM About Sandbox @@ -1202,8 +1197,8 @@ Cohesion: 0.4 Nodes (4): compilerOptions, baseUrl, paths, @/* ### Community 169 - "Community 169" -Cohesion: 0.25 -Nodes (8): getCotations(), Get 10-year daily price history (cotation) for Brazilian B3 stocks. Retur, Get 10-year daily price history (cotation) for Brazilian B3 stocks. Retur, Get 10-year daily price history (cotation) for Brazilian B3 stocks. Retur, Get 10-year daily price history (cotation) for Brazilian B3 stocks. Retur, Get 10-year daily price history (cotation) for Brazilian B3 stocks. Retur, Get 10-year daily price history (cotation) for Brazilian B3 stocks. Retur, Get 10-year daily price history (cotation) for Brazilian B3 stocks. Retur +Cohesion: 0.2 +Nodes (10): getCotations(), Get 10-year daily price history (cotation) for Brazilian B3 stocks. Retur, Get 10-year daily price history (cotation) for Brazilian B3 stocks. Retur, Get 10-year daily price history (cotation) for Brazilian B3 stocks. Retur, Get 10-year daily price history (cotation) for Brazilian B3 stocks. Retur, Get 10-year daily price history (cotation) for Brazilian B3 stocks. Retur, Get 10-year daily price history (cotation) for Brazilian B3 stocks. Retur, Get 10-year daily price history (cotation) for Brazilian B3 stocks. Retur (+2 more) ### Community 170 - "Community 170" Cohesion: 0.25 @@ -1258,16 +1253,16 @@ Cohesion: 0.38 Nodes (7): code:python (import pytest), code:python (from __future__ import annotations), code:bash (git add main/app/prometheus/context.py tests/test_context.py), Phase 4: ToolContext (Bundled Dispatch Dependencies), Phase 4: ToolContext (Replace God Function), Task 5: ToolContext — Dataclass for Agent Use, Task 5: ToolContext — Single Dispatch Object ### Community 186 - "Community 186" -Cohesion: 0.18 -Nodes (6): System prompt should include state context when provided., System prompt should not include state section when empty., State section should appear after memories section., All state entries should appear in the prompt., System prompt should work without state parameter., TestBuildSystemPromptState +Cohesion: 0.21 +Nodes (7): ResultCache — SHA256-keyed file-based cache for computed results., File-based cache keyed by SHA256 of code. Stores results as JSON under:, Return cached result dict or None if miss., Store result with timestamp., Delete all cached results for a session., Check if a result exists for the given code., ResultCache ### Community 187 - "Community 187" Cohesion: 0.29 Nodes (6): DEVELOPER:, PREMIUM:, Prometheus, STOCKS_API, USER:, User structure defined by string roles: ### Community 188 - "Community 188" -Cohesion: 0.22 -Nodes (10): check_cache(), Read a file from the sandbox filesystem. Args: path: Absolute pa, Read a file from the sandbox filesystem. Args: path: Absolute pa, Get a download link for a workspace file to share with the user. Use this, Upload a file to the sandbox filesystem. Use this to push data files (CSV,, Get a download link for a workspace file to share with the user. Use this, Check if a computed result exists in the cache. Use before executing expens, read_sandbox_file() (+2 more) +Cohesion: 0.14 +Nodes (14): execute_code(), Store a value in the harness state for this session. Use this to save inter, Execute Python code in an isolated sandbox. Use for quantitative analysis,, Execute Python code in an isolated sandbox. Use for quantitative analysis,, Execute Python code in an isolated sandbox. Use for quantitative analysis,, Execute Python code in an isolated sandbox. Use for quantitative analysis,, Execute Python code in an isolated sandbox. Use for quantitative analysis,, Store a value in the harness state for this session. Use this to save interm (+6 more) ### Community 189 - "Community 189" Cohesion: 0.36 @@ -1302,8 +1297,8 @@ Cohesion: 0.33 Nodes (5): cls_token, mask_token, pad_token, sep_token, unk_token ### Community 197 - "Community 197" -Cohesion: 0.29 -Nodes (6): Covers lines 65-67: unexpected exception., Covers lines 65-67: unexpected exception., Covers lines 65-67: unexpected exception., Covers lines 65-67: unexpected exception., Covers lines 65-67: unexpected exception., Covers lines 48-49: jwt.ExpiredSignatureError. +Cohesion: 0.4 +Nodes (4): COTACAO 10Y PADRAO and COTACAO 10Y AJUSTADA belong to /cotations, not /fundament, COTACAO 10Y PADRAO and COTACAO 10Y AJUSTADA belong to /cotations, not /fundament, COTACAO 10Y PADRAO and COTACAO 10Y AJUSTADA belong to /cotations, not /fundament, COTACAO 10Y PADRAO and COTACAO 10Y AJUSTADA belong to /cotations, not /fundament ### Community 198 - "Community 198" Cohesion: 0.33 @@ -1345,33 +1340,17 @@ Nodes (6): API Design (3), Architecture (7), Frontend (4), P0 — Must Fix (Crit Cohesion: 0.33 Nodes (6): API Design (6), Architecture (8), Frontend (7), P1 — Should Fix, Security (6), Testing (4) -### Community 208 - "Community 208" -Cohesion: 0.29 -Nodes (6): Covers lines 37-38, 46, 51, 58 (sessionId is None): skips session validation., Covers lines 37-38, 46, 51, 58 (sessionId is None): skips session validation., Covers lines 37-38, 46, 51, 58 (sessionId is None): skips session validation., Covers lines 37-38, 46, 51, 58 (sessionId is None): skips session validation., Covers lines 37-38, 46, 51, 58 (sessionId is None): skips session validation., Covers lines 37-38, 46, 51, 58 (sessionId is None): skips session validation. - ### Community 209 - "Community 209" Cohesion: 0.33 Nodes (6): 4.1 Sandbox Technology Landscape, 4.2 Instant Startup Patterns, 4.3 Cost & Scaling Math, 4.4 Anthropic Containment Patterns, 4.5 Hybrid Library Policy, 4. Background Research -### Community 212 - "Community 212" -Cohesion: 0.33 -Nodes (5): Non-JSON-dict/list string is left as-is., Non-JSON-dict/list string is left as-is., Non-JSON-dict/list string is left as-is., Non-JSON-dict/list string is left as-is., Non-JSON-dict/list string is left as-is. - -### Community 213 - "Community 213" -Cohesion: 0.33 -Nodes (6): Covers lines 13, 17, 19-20, 22-27: UserManager.addRoleToUser., Covers lines 13, 17, 19-20, 22-27: UserManager.addRoleToUser., Covers lines 13, 17, 19-20, 22-27: UserManager.addRoleToUser., Covers lines 13, 17, 19-20, 22-27: UserManager.addRoleToUser., Covers lines 36-38, 40-44, 46, 48-49, 51, 58-59, 61: successful user retrieval., TestAddRoleToUser - -### Community 214 - "Community 214" -Cohesion: 0.33 -Nodes (5): Covers lines 17, 22-27: user found, role not present, role added., Covers lines 17, 22-27: user found, role not present, role added., Covers lines 17, 22-27: user found, role not present, role added., Covers lines 17, 22-27: user found, role not present, role added., Covers lines 17, 22-27: user found, role not present, role added. - -### Community 215 - "Community 215" -Cohesion: 0.33 -Nodes (5): Covers line 27: user already has the role., Covers line 27: user already has the role., Covers line 27: user already has the role., Covers line 27: user already has the role., Covers lines 42-44: session validation fails. +### Community 211 - "Community 211" +Cohesion: 0.12 +Nodes (5): registry, SUGGESTIONS, { container }, nodes, { rerender } ### Community 216 - "Community 216" -Cohesion: 0.33 -Nodes (5): Covers lines 42-44: session validation fails., Covers lines 42-44: session validation fails., Covers lines 42-44: session validation fails., Covers lines 42-44: session validation fails., Covers lines 42-44: session validation fails. +Cohesion: 0.29 +Nodes (8): readEventStream(), resumeChat(), fetchMock, file, onChunk, onCursor, onDone, onSession ### Community 217 - "Community 217" Cohesion: 0.33 @@ -1390,8 +1369,8 @@ Cohesion: 0.4 Nodes (5): model, continuing_subword_prefix, max_input_chars_per_word, type, unk_token ### Community 221 - "Community 221" -Cohesion: 0.39 -Nodes (8): _build_error_response(), buildErrorResponse(), generic_exception_handler(), genericExceptionHandler(), http_exception_handler(), httpExceptionHandler(), validation_exception_handler(), validationExceptionHandler() +Cohesion: 0.2 +Nodes (9): Covers lines 143, 145, 147-148: POST /user/sessions/revoke-all., Covers lines 143, 145, 147-148: POST /user/sessions/revoke-all., Covers lines 143, 145, 147-148., Covers lines 143, 145, 147-148., Covers lines 143, 145, 147-148: POST /user/sessions/revoke-all., Covers lines 143, 145, 147-148., Covers lines 143, 145, 147-148: POST /user/sessions/revoke-all., Covers lines 143, 145, 147-148. (+1 more) ### Community 222 - "Community 222" Cohesion: 0.33 @@ -1442,8 +1421,8 @@ Cohesion: 0.4 Nodes (5): 8. Build Sequence (4 phases, each independently shippable), Phase 0 — Sandbox foundation (1-2 days, no user-facing change), Phase 1 — MCP exposure of STOCKS_API (1 day), Phase 2 — Refactor PROMETHEUS to agentic (3-5 days, the big one), Phase 3 — Hardening (1-2 days, can ship incrementally) ### Community 234 - "Community 234" -Cohesion: 0.05 -Nodes (16): ResultCache — SHA256-keyed file-based cache for computed results., File-based cache keyed by SHA256 of code. Stores results as JSON under:, Return cached result dict or None if miss., Store result with timestamp., Delete all cached results for a session., Check if a result exists for the given code., ResultCache, cache() (+8 more) +Cohesion: 0.11 +Nodes (4): cache(), Tests for ResultCache., TestColumnValidator, TestResultCache ### Community 236 - "Community 236" Cohesion: 0.5 @@ -1510,16 +1489,16 @@ Cohesion: 0.5 Nodes (3): Basic fields like ROE must still pass., Basic fields like ROE must still pass., Basic fields like ROE must still pass. ### Community 256 - "Community 256" -Cohesion: 0.25 -Nodes (13): compactCotations(), compactRow(), compactValue(), compressResponse(), fixHeaders(), getAbbr(), getNest(), toColumnar() (+5 more) +Cohesion: 0.38 +Nodes (9): compactCotations(), compactRow(), compactValue(), compressResponse(), fixHeaders(), getAbbr(), getNest(), toColumnar() (+1 more) ### Community 258 - "Community 258" Cohesion: 0.67 Nodes (3): checkMySqlConnection, MySQL Engine (user_db), MySQL Engine (stocks_db) ### Community 259 - "Community 259" -Cohesion: 0.1 -Nodes (15): Tests for connection pool configuration, Stocks engine should have optimized pool settings, Tests for lazy JSON deserialization, Query manager should have deserialize method, Integration tests for all query optimizations, All optimizations should be implemented, Query filter should use ticker index, Performance tests for query operations (+7 more) +Cohesion: 0.33 +Nodes (4): Integration tests for all query optimizations, All optimizations should be implemented, Query filter should use ticker index, TestQueryOptimization ### Community 261 - "Community 261" Cohesion: 0.67 @@ -1529,17 +1508,9 @@ Nodes (3): 3. Goals & Non-Goals, Goals, Non-Goals (YAGNI) Cohesion: 0.5 Nodes (4): code:python (def test_link_memory_to_entities(db_session, sample_user):), code:python (# Add to main/app/prometheus/memory.py), code:bash (git add main/app/prometheus/memory.py tests/test_memory_grap), Task 5: Graph Memory Operations -### Community 263 - "Community 263" -Cohesion: 0.12 -Nodes (16): Covers line 16: empty password raises ValueError., Covers line 16: empty password raises ValueError., Covers line 16: empty password raises ValueError., Covers lines 45-51: verifyAccessToken with expired and invalid tokens., Covers line 16: empty password raises ValueError., Covers lines 48-49: jwt.ExpiredSignatureError., Covers lines 45-51: verifyAccessToken with expired and invalid tokens., Covers lines 45-51: verifyAccessToken with expired and invalid tokens. (+8 more) - -### Community 474 - "Community 474" -Cohesion: 0.33 -Nodes (6): 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., makeChat must include MEMORY_TOOLS alongside MCP sessions., TestMakeChatIncludesMemoryTools - ### Community 475 - "Community 475" -Cohesion: 0.33 -Nodes (5): Performance tests for query operations, Performance tests for query operations, Query should respond within 1 second, Query should respond within 1 second, TestQueryPerformance +Cohesion: 0.2 +Nodes (10): getHistorical(), Get year-based historical financial data for Brazilian B3 stocks. Returns, Get year-based historical financial data for Brazilian B3 stocks. Returns, Get year-based historical financial data for Brazilian B3 stocks. Returns, Get year-based historical financial data for Brazilian B3 stocks. Returns, Get year-based historical financial data for Brazilian B3 stocks. Returns, Get year-based historical financial data for Brazilian B3 stocks. Returns, Get year-based historical financial data for Brazilian B3 stocks. Returns (+2 more) ### Community 476 - "Community 476" Cohesion: 0.22 @@ -1581,104 +1552,88 @@ Nodes (4): code:python (def test_count_tokens_portuguese():), code:python (# mai Cohesion: 0.5 Nodes (4): Priority 1: Fix Critical Gaps, Priority 2: Improve Retrieval, Priority 3: Lifecycle Improvements, What We Should Adopt from Mem0 -### Community 486 - "Community 486" -Cohesion: 0.25 -Nodes (8): Search user's saved memories, preferences, and past analysis context. Use t, Search user's saved memories, preferences, and past analysis context. Use t, Search user's saved memories, preferences, and past analysis context. Use, Search user's saved memories, preferences, and past analysis context. Use, Search user's saved memories, preferences, and past analysis context. Use, Search user's saved memories, preferences, and past analysis context. Use, Search user's saved memories, preferences, and past analysis context. Use, search_memory() - ### Community 487 - "Community 487" Cohesion: 0.16 Nodes (16): verifyAPIKey(), Tests to increase coverage for query.py, key.py, and cache.py in stocks_api., Tests covering key.py lines 15-40. Uses asyncio.run() since pytest-asyncio, Tests covering key.py lines 15-40. Uses asyncio.run() since pytest-asyncio, Tests covering key.py lines 15-40. Uses asyncio.run() since pytest-asyncio, Tests covering key.py lines 15-40. Uses asyncio.run() since pytest-asyncio, test_cache_scheduler_starts_apscheduler(), test_cache_scheduler_starts_daemon_thread() (+8 more) ### Community 488 - "Community 488" -Cohesion: 0.33 -Nodes (5): Tests for optimized search filtering, Filter should use ticker index for O(1) lookup, Tests for optimized search filtering, Filter should use ticker index for O(1) lookup, TestFilterBySearchTerms +Cohesion: 0.1 +Nodes (16): Tests for connection pool configuration, Stocks engine should have optimized pool settings, Tests for lazy JSON deserialization, Query manager should have deserialize method, Tests for optimized search filtering, Filter should use ticker index for O(1) lookup, Performance tests for query operations, Query should respond within 1 second (+8 more) ### Community 489 - "Community 489" Cohesion: 0.6 Nodes (4): hammer_measured(), main(), Fire n requests with c concurrent workers, measuring ttfb + total per request., stats() -### Community 490 - "Community 490" -Cohesion: 0.33 -Nodes (6): execute_code(), Execute Python code in an isolated sandbox. Use for quantitative analysis,, Execute Python code in an isolated sandbox. Use for quantitative analysis,, Execute Python code in an isolated sandbox. Use for quantitative analysis,, Execute Python code in an isolated sandbox. Use for quantitative analysis,, Execute Python code in an isolated sandbox. Use for quantitative analysis, - -### Community 491 - "Community 491" -Cohesion: 0.25 -Nodes (8): Store a memory about the user's preferences, analysis results, or feedback., Store a memory about the user's preferences, analysis results, or feedback., Store a memory about the user's preferences, analysis results, or feedback., Store a memory about the user's preferences, analysis results, or feedback., Store a memory about the user's preferences, analysis results, or feedback., Store a memory about the user's preferences, analysis results, or feedback., Store a memory about the user's preferences, analysis results, or feedback., save_memory() - ### Community 492 - "Community 492" Cohesion: 0.2 Nodes (9): Covers lines 66, 68-72, 74: GET /user/sessions., Covers lines 66, 68-72, 74: GET /user/sessions., Covers lines 66, 68-72, 74: full sessions listing., Covers lines 66, 68-72, 74: full sessions listing., Covers lines 66, 68-72, 74: GET /user/sessions., Covers lines 66, 68-72, 74: full sessions listing., Covers lines 66, 68-72, 74: GET /user/sessions., Covers lines 66, 68-72, 74: full sessions listing. (+1 more) ### Community 493 - "Community 493" -Cohesion: 0.2 -Nodes (9): Covers lines 34, 36-38, 40-44, 46, 48-49, 51, 58-59, 61, 63-67: UserManager.getC, Covers lines 34, 36-38, 40-44, 46, 48-49, 51, 58-59, 61, 63-67: UserManager.getC, Covers lines 34, 36-38, 40-44, 46, 48-49, 51, 58-59, 61, 63-67: UserManager.getC, Covers lines 34, 36-38, 40-44, 46, 48-49, 51, 58-59, 61, 63-67: UserManager.getC, Covers lines 36-38, 40-44, 46, 48-49, 51, 58-59, 61: successful user retrieval., Covers lines 36-38, 40-44, 46, 48-49, 51, 58-59, 61: successful user retrieval., Covers lines 34, 36-38, 40-44, 46, 48-49, 51, 58-59, 61, 63-67: UserManager.getC, Covers lines 36-38, 40-44, 46, 48-49, 51, 58-59, 61: successful user retrieval. (+1 more) - -### Community 495 - "Community 495" -Cohesion: 0.67 -Nodes (3): countTokens(), _get_tokenizer(), Count tokens using Gemini's local tokenizer. Accurate for Portuguese. +Cohesion: 0.05 +Nodes (38): Covers line 27: user already has the role., Covers line 27: user already has the role., Covers line 27: user already has the role., Covers line 27: user already has the role., Covers lines 34, 36-38, 40-44, 46, 48-49, 51, 58-59, 61, 63-67: UserManager.getC, Covers lines 34, 36-38, 40-44, 46, 48-49, 51, 58-59, 61, 63-67: UserManager.getC, Covers lines 34, 36-38, 40-44, 46, 48-49, 51, 58-59, 61, 63-67: UserManager.getC, Covers lines 34, 36-38, 40-44, 46, 48-49, 51, 58-59, 61, 63-67: UserManager.getC (+30 more) -### Community 497 - "Community 497" -Cohesion: 0.11 -Nodes (6): normalizeKey(), Store a value in state. Marks state as changed for context injection., Verify the actual async tool functions have correct signatures., TOOL_REGISTRY pattern must work correctly., TestMemoryToolFunctions, TestToolRegistry +### Community 498 - "Community 498" +Cohesion: 0.25 +Nodes (4): Authentication System, Google OAuth, JWT Authentication, TestSessionExpiryConfig ### Community 500 - "Community 500" -Cohesion: 0.25 +Cohesion: 0.2 Nodes (3): Pytest Testing, Tests for main/utils/http_session.py — covers all branches., TestGetSession ### Community 501 - "Community 501" Cohesion: 0.22 -Nodes (8): Hit the actual /stocks/cotations HTTP endpoint with adjusted=false., Hit the actual /stocks/cotations HTTP endpoint with adjusted=false., Hit the actual /stocks/cotations HTTP endpoint with adjusted=false., Hit the actual /stocks/cotations HTTP endpoint with adjusted=false., Hit the actual /stocks/cotations HTTP endpoint with adjusted=false., Hit the actual /stocks/cotations HTTP endpoint with adjusted=false., Hit the actual /stocks/cotations HTTP endpoint with adjusted=false., Hit the actual /stocks/cotations HTTP endpoint with adjusted=false. +Nodes (3): getCurrentSession(), getSessions(), sessionToDict() ### Community 502 - "Community 502" Cohesion: 0.11 Nodes (15): Tests for connection pool configuration, Tests for connection pool configuration, Stocks engine should have optimized pool settings, Stocks engine should have optimized pool settings, Tests for lazy JSON deserialization, Tests for lazy JSON deserialization, Query manager should have deserialize method, Query manager should have deserialize method (+7 more) +### Community 503 - "Community 503" +Cohesion: 0.22 +Nodes (8): Hit the actual /stocks/cotations HTTP endpoint with adjusted=false., Hit the actual /stocks/cotations HTTP endpoint with adjusted=false., Hit the actual /stocks/cotations HTTP endpoint with adjusted=false., Hit the actual /stocks/cotations HTTP endpoint with adjusted=false., Hit the actual /stocks/cotations HTTP endpoint with adjusted=false., Hit the actual /stocks/cotations HTTP endpoint with adjusted=false., Hit the actual /stocks/cotations HTTP endpoint with adjusted=false., Hit the actual /stocks/cotations HTTP endpoint with adjusted=false. + ### Community 504 - "Community 504" -Cohesion: 0.25 -Nodes (8): getFundamental(), Get point-in-time fundamental/valuation data for Brazilian B3 stocks. Ret, Get point-in-time fundamental/valuation data for Brazilian B3 stocks. Ret, Get point-in-time fundamental/valuation data for Brazilian B3 stocks. Ret, Get point-in-time fundamental/valuation data for Brazilian B3 stocks. Ret, Get point-in-time fundamental/valuation data for Brazilian B3 stocks. Ret, Get point-in-time fundamental/valuation data for Brazilian B3 stocks. Ret, Get point-in-time fundamental/valuation data for Brazilian B3 stocks. Ret +Cohesion: 0.22 +Nodes (8): Historical query with a year range., Historical query with a year range., Historical query with a year range., Historical query with a year range., Historical query with a year range., Historical query with a year range., Historical query with a year range., Historical query with a year range. + +### Community 505 - "Community 505" +Cohesion: 0.33 +Nodes (5): streamChat(), events, onChunk, onDone, onError + +### Community 506 - "Community 506" +Cohesion: 0.29 +Nodes (6): chunks, events, fullText, onChunk, onDone, receivedChunks ### Community 509 - "Community 509" -Cohesion: 0.25 -Nodes (7): 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)., 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). +Cohesion: 0.33 +Nodes (5): Tests for optimized search filtering, Tests for optimized search filtering, Filter should use ticker index for O(1) lookup, Filter should use ticker index for O(1) lookup, TestFilterBySearchTerms ### Community 510 - "Community 510" Cohesion: 0.6 Nodes (3): bench(), main(), stats() -### Community 512 - "Community 512" -Cohesion: 0.33 -Nodes (6): dispatchToolCall must route memory tool names via TOOL_REGISTRY., dispatchToolCall must route memory tool names to executeMemoryTool., dispatchToolCall must route memory tool names to executeMemoryTool., dispatchToolCall must route memory tool names to executeMemoryTool., dispatchToolCall must route memory tool names to executeMemoryTool., TestDispatchRoutesMemoryTools - -### Community 518 - "Community 518" -Cohesion: 0.33 -Nodes (5): Every function in TOOL_REGISTRY must have Gemini-safe signatures. Custom cl, Every function in TOOL_REGISTRY must have Gemini-safe signatures. Custom cl, Regression: HarnessState must never leak into tool signatures., Regression: HarnessState must never leak into tool signatures., TestGeminiCompatibility - -### Community 519 - "Community 519" -Cohesion: 0.4 -Nodes (4): COTACAO 10Y PADRAO and COTACAO 10Y AJUSTADA belong to /cotations, not /fundament, COTACAO 10Y PADRAO and COTACAO 10Y AJUSTADA belong to /cotations, not /fundament, COTACAO 10Y PADRAO and COTACAO 10Y AJUSTADA belong to /cotations, not /fundament, COTACAO 10Y PADRAO and COTACAO 10Y AJUSTADA belong to /cotations, not /fundament - ### Community 520 - "Community 520" Cohesion: 0.33 Nodes (6): Tests covering key.py lines 48-66., Tests covering key.py lines 48-66., Tests covering key.py lines 48-66., Tests covering key.py lines 48-66., Tests covering key.py lines 48-66., TestCreateKey ### Community 527 - "Community 527" -Cohesion: 0.17 -Nodes (6): pytest_configure(), Set required env vars before test collection. config.py eagerly instantia, Reset slowapi in-memory rate limiter between every test., Set required env vars before test collection. config.py eagerly instantia, Set required env vars before test collection. config.py eagerly instantia, _reset_rate_limiter() +Cohesion: 0.09 +Nodes (17): client(), pytest_configure(), TestClient with all routers mounted — no lifespan (no DB/service init). O, Set required env vars before test collection. config.py eagerly instantia, Reset slowapi in-memory rate limiter between every test., Set required env vars before test collection. config.py eagerly instantia, TestClient with all routers mounted — no lifespan (no DB/service init). O, TestClient with all routers mounted — no lifespan (no DB/service init). O (+9 more) ## Knowledge Gaps -- **2708 isolated node(s):** `$schema`, `style`, `rsc`, `tsx`, `config` (+2703 more) +- **2740 isolated node(s):** `$schema`, `style`, `rsc`, `tsx`, `config` (+2735 more) These have ≤1 connection - possible missing edges or undocumented components. - **225 thin communities (<3 nodes) omitted from report** — run `graphify query` to explore isolated nodes. ## Suggested Questions _Questions this graph is uniquely positioned to answer:_ -- **Why does `Pytest Testing` connect `Community 500` to `Authentication Core`, `Frontend Components`, `Community 131`, `Community 132`, `Community 129`, `Community 259`, `Device Detection`, `Community 138`, `Community 527`, `Community 18`, `Community 147`, `Community 150`, `Community 24`, `Community 25`, `Community 27`, `Community 29`, `Community 32`, `Community 33`, `Community 40`, `Community 43`, `Community 44`, `Community 45`, `Community 48`, `Community 49`, `Community 51`, `Community 54`, `Community 184`, `Community 59`, `Community 67`, `Community 86`, `Community 93`, `Community 477`, `Community 482`, `Community 100`, `Community 102`, `Community 487`, `Community 234`, `Community 115`, `Community 502`, `Community 120`, `Community 122`, `Community 125`, `Community 126`?** - _High betweenness centrality (0.144) - this node is a cross-community bridge._ -- **Why does `FastAPI` connect `Community 132` to `Community 129`, `Community 18`, `Community 147`, `Community 21`, `Community 150`, `Community 33`, `Community 34`, `Community 37`, `Community 40`, `Community 43`, `Community 45`, `Community 181`, `Community 58`, `Community 59`, `Community 63`, `Community 71`, `Community 73`, `Community 78`, `Community 81`, `Community 84`, `Community 221`, `Community 477`, `Community 95`, `Community 482`, `Community 487`, `Community 120`?** - _High betweenness centrality (0.071) - this node is a cross-community bridge._ -- **Why does `Prometheus` connect `Community 116` to `Community 512`, `Frontend Components`, `Community 131`, `Device Detection`, `Community 138`, `Frontend App Shell`, `Community 151`, `Community 24`, `Community 178`, `Community 52`, `Community 186`, `Community 60`, `Community 194`, `Community 68`, `Community 80`, `Community 87`, `Community 88`, `Community 474`, `Community 93`, `Community 95`, `Community 234`, `Community 107`, `Community 497`, `Community 125`?** - _High betweenness centrality (0.048) - this node is a cross-community bridge._ +- **Why does `Pytest Testing` connect `Community 500` to `Authentication Core`, `Frontend Components`, `Community 129`, `Community 132`, `Data Models & Types`, `Device Detection`, `Community 138`, `Community 527`, `Community 146`, `Community 18`, `Community 147`, `Community 24`, `Community 25`, `Community 27`, `Community 29`, `Community 32`, `Community 33`, `Community 40`, `Community 44`, `Community 45`, `Community 48`, `Community 49`, `Community 51`, `Community 54`, `Community 184`, `Community 59`, `Community 67`, `Community 93`, `Community 477`, `Community 482`, `Community 100`, `Community 487`, `Community 488`, `Community 234`, `Community 498`, `Community 115`, `Community 502`, `Community 120`, `Community 122`, `Community 125`, `Community 126`?** + _High betweenness centrality (0.165) - this node is a cross-community bridge._ +- **Why does `FastAPI` connect `Community 132` to `Community 129`, `Community 131`, `Community 18`, `Community 147`, `Community 33`, `Community 34`, `Community 37`, `Community 40`, `Community 43`, `Community 45`, `Community 181`, `Community 58`, `Community 59`, `Community 63`, `Community 71`, `Community 73`, `Community 81`, `Community 84`, `Community 477`, `Community 482`, `Community 487`, `Community 115`, `Community 501`, `Community 120`?** + _High betweenness centrality (0.055) - this node is a cross-community bridge._ +- **Why does `UserManager` connect `Community 21` to `Prometheus Agent`, `Community 520`, `Community 137`, `Prometheus Memory`, `Community 141`, `User Roles & Permissions`, `Community 16`, `Community 146`, `Community 22`, `Community 37`, `Community 47`, `Community 181`, `Community 56`, `Community 58`, `Community 61`, `Community 68`, `Community 78`, `Community 85`, `Community 221`, `Community 101`, `Community 487`, `Community 104`, `Community 492`, `Community 493`, `Community 110`, `Community 114`, `Community 120`, `Community 125`, `Community 126`?** + _High betweenness centrality (0.041) - this node is a cross-community bridge._ - **Are the 72 inferred relationships involving `StocksCacheManager` (e.g. with `TestStocksCacheManager` and `TestVerifyAPIKey`) actually correct?** _`StocksCacheManager` has 72 INFERRED edges - model-reasoned connections that need verification._ - **Are the 52 inferred relationships involving `HarnessState` (e.g. with `Prometheus` and `.streamMessage()`) actually correct?** diff --git a/graphify-out/graph.json b/graphify-out/graph.json index 5c4d472..78e1a47 100644 --- a/graphify-out/graph.json +++ b/graphify-out/graph.json @@ -246,7 +246,7 @@ "source_file": "config.py", "source_location": "L92", "id": "server_config_config", - "community": 95, + "community": 102, "norm_label": "config" }, { @@ -633,7 +633,7 @@ "source_file": "frontend/src/api.js", "source_location": "L49", "id": "src_api_fetchme", - "community": 5, + "community": 150, "norm_label": "fetchme()" }, { @@ -642,7 +642,7 @@ "source_file": "frontend/src/api.js", "source_location": "L71", "id": "src_api_extracthashtoken", - "community": 5, + "community": 150, "norm_label": "extracthashtoken()" }, { @@ -660,7 +660,7 @@ "source_file": "frontend/src/api.js", "source_location": "L85", "id": "src_api_fetchsessions", - "community": 5, + "community": 150, "norm_label": "fetchsessions()" }, { @@ -705,7 +705,7 @@ "source_file": "frontend/src/api.js", "source_location": "L126", "id": "src_api_fetchhistory", - "community": 5, + "community": 150, "norm_label": "fetchhistory()" }, { @@ -714,7 +714,7 @@ "source_file": "frontend/src/api.js", "source_location": "L133", "id": "src_api_readeventstream", - "community": 5, + "community": 216, "norm_label": "readeventstream()" }, { @@ -723,7 +723,7 @@ "source_file": "frontend/src/api.js", "source_location": "L185", "id": "src_api_streamchat", - "community": 5, + "community": 505, "norm_label": "streamchat()" }, { @@ -732,7 +732,7 @@ "source_file": "frontend/src/api.js", "source_location": "L198", "id": "src_api_resumechat", - "community": 5, + "community": 216, "norm_label": "resumechat()" }, { @@ -741,7 +741,7 @@ "source_file": "frontend/src/App.jsx", "source_location": "L1", "id": "frontend_src_app_jsx", - "community": 5, + "community": 150, "norm_label": "app.jsx" }, { @@ -750,43 +750,70 @@ "source_file": "frontend/src/App.jsx", "source_location": "L16", "id": "src_app_settleloopevents", - "community": 5, + "community": 150, "norm_label": "settleloopevents()" }, { "label": "readResume()", "file_type": "code", "source_file": "frontend/src/App.jsx", - "source_location": "L42", + "source_location": "L43", "id": "src_app_readresume", - "community": 5, + "community": 150, "norm_label": "readresume()" }, { "label": "saveResume()", "file_type": "code", "source_file": "frontend/src/App.jsx", - "source_location": "L50", + "source_location": "L51", "id": "src_app_saveresume", - "community": 5, + "community": 150, "norm_label": "saveresume()" }, { "label": "clearResume()", "file_type": "code", "source_file": "frontend/src/App.jsx", - "source_location": "L54", + "source_location": "L55", "id": "src_app_clearresume", - "community": 5, + "community": 150, "norm_label": "clearresume()" }, + { + "label": "clearLastSession()", + "file_type": "code", + "source_file": "frontend/src/App.jsx", + "source_location": "L59", + "id": "src_app_clearlastsession", + "community": 150, + "norm_label": "clearlastsession()" + }, + { + "label": "readLastSession()", + "file_type": "code", + "source_file": "frontend/src/App.jsx", + "source_location": "L63", + "id": "src_app_readlastsession", + "community": 150, + "norm_label": "readlastsession()" + }, + { + "label": "saveLastSession()", + "file_type": "code", + "source_file": "frontend/src/App.jsx", + "source_location": "L71", + "id": "src_app_savelastsession", + "community": 150, + "norm_label": "savelastsession()" + }, { "label": "App()", "file_type": "code", "source_file": "frontend/src/App.jsx", - "source_location": "L58", + "source_location": "L80", "id": "src_app_app", - "community": 5, + "community": 150, "norm_label": "app()" }, { @@ -795,7 +822,7 @@ "source_file": "frontend/src/App.resume.test.jsx", "source_location": "L1", "id": "frontend_src_app_resume_test_jsx", - "community": 5, + "community": 150, "norm_label": "app.resume.test.jsx" }, { @@ -804,7 +831,7 @@ "source_file": "frontend/src/App.resume.test.jsx", "source_location": "L72", "id": "src_app_resume_test_sendbtn", - "community": 5, + "community": 150, "norm_label": "sendbtn" }, { @@ -813,7 +840,7 @@ "source_file": "frontend/src/App.resume.test.jsx", "source_location": "L82", "id": "src_app_resume_test_textarea", - "community": 5, + "community": 150, "norm_label": "textarea" }, { @@ -822,7 +849,7 @@ "source_file": "frontend/src/main.jsx", "source_location": "L1", "id": "frontend_src_main_jsx", - "community": 5, + "community": 150, "norm_label": "main.jsx" }, { @@ -831,7 +858,7 @@ "source_file": "frontend/src/components/AgentLoop.jsx", "source_location": "L1", "id": "frontend_src_components_agentloop_jsx", - "community": 5, + "community": 211, "norm_label": "agentloop.jsx" }, { @@ -840,7 +867,7 @@ "source_file": "frontend/src/components/AgentLoop.jsx", "source_location": "L4", "id": "components_agentloop_agentloop", - "community": 5, + "community": 211, "norm_label": "agentloop()" }, { @@ -867,7 +894,7 @@ "source_file": "frontend/src/components/InputBar.jsx", "source_location": "L1", "id": "frontend_src_components_inputbar_jsx", - "community": 5, + "community": 150, "norm_label": "inputbar.jsx" }, { @@ -876,7 +903,7 @@ "source_file": "frontend/src/components/InputBar.jsx", "source_location": "L5", "id": "components_inputbar_inputbar", - "community": 5, + "community": 150, "norm_label": "inputbar()" }, { @@ -885,7 +912,7 @@ "source_file": "frontend/src/components/MdocMessage.jsx", "source_location": "L1", "id": "frontend_src_components_mdocmessage_jsx", - "community": 5, + "community": 211, "norm_label": "mdocmessage.jsx" }, { @@ -894,7 +921,7 @@ "source_file": "frontend/src/components/MdocMessage.jsx", "source_location": "L4", "id": "components_mdocmessage_registry", - "community": 5, + "community": 211, "norm_label": "registry" }, { @@ -903,7 +930,7 @@ "source_file": "frontend/src/components/MdocMessage.jsx", "source_location": "L14", "id": "components_mdocmessage_preprocessgeminitags", - "community": 5, + "community": 211, "norm_label": "preprocessgeminitags()" }, { @@ -912,7 +939,7 @@ "source_file": "frontend/src/components/MdocMessage.jsx", "source_location": "L61", "id": "components_mdocmessage_workspacelink", - "community": 5, + "community": 211, "norm_label": "workspacelink()" }, { @@ -921,7 +948,7 @@ "source_file": "frontend/src/components/MdocMessage.jsx", "source_location": "L91", "id": "components_mdocmessage_mdocmessage", - "community": 5, + "community": 211, "norm_label": "mdocmessage()" }, { @@ -930,25 +957,25 @@ "source_file": "frontend/src/components/MessageList.jsx", "source_location": "L1", "id": "frontend_src_components_messagelist_jsx", - "community": 5, + "community": 211, "norm_label": "messagelist.jsx" }, { "label": "SUGGESTIONS", "file_type": "code", "source_file": "frontend/src/components/MessageList.jsx", - "source_location": "L7", + "source_location": "L8", "id": "components_messagelist_suggestions", - "community": 5, + "community": 211, "norm_label": "suggestions" }, { "label": "MessageList()", "file_type": "code", "source_file": "frontend/src/components/MessageList.jsx", - "source_location": "L13", + "source_location": "L14", "id": "components_messagelist_messagelist", - "community": 5, + "community": 211, "norm_label": "messagelist()" }, { @@ -982,7 +1009,7 @@ "label": "SettingsDialog()", "file_type": "code", "source_file": "frontend/src/components/SettingsDialog.jsx", - "source_location": "L14", + "source_location": "L15", "id": "components_settingsdialog_settingsdialog", "community": 5, "norm_label": "settingsdialog()" @@ -1695,7 +1722,7 @@ "source_file": "main/app/authentication/util.py", "source_location": "L1", "id": "main_app_authentication_util_py", - "community": 43, + "community": 131, "norm_label": "util.py" }, { @@ -1731,7 +1758,7 @@ "source_file": "main/app/authentication/util.py", "source_location": "L43", "id": "authentication_util_verifyaccesstoken", - "community": 78, + "community": 131, "norm_label": "verifyaccesstoken()" }, { @@ -1753,37 +1780,19 @@ "norm_label": "agent.py" }, { - "label": "onExtractionDone()", + "label": "safeFilter()", "file_type": "code", "source_file": "main/app/prometheus/agent.py", "source_location": "L26", - "id": "prometheus_agent_onextractiondone", - "community": 116, - "norm_label": "onextractiondone()" - }, - { - "label": "spawnExtraction()", - "file_type": "code", - "source_file": "main/app/prometheus/agent.py", - "source_location": "L34", - "id": "prometheus_agent_spawnextraction", - "community": 116, - "norm_label": "spawnextraction()" - }, - { - "label": "_safe_filter()", - "file_type": "code", - "source_file": "main/app/prometheus/agent.py", - "source_location": "L45", - "id": "prometheus_agent_safe_filter", + "id": "prometheus_agent_safefilter", "community": 116, - "norm_label": "_safe_filter()" + "norm_label": "safefilter()" }, { "label": "getClient()", "file_type": "code", "source_file": "main/app/prometheus/agent.py", - "source_location": "L58", + "source_location": "L39", "id": "prometheus_agent_getclient", "community": 116, "norm_label": "getclient()" @@ -1792,7 +1801,7 @@ "label": "Prometheus", "file_type": "code", "source_file": "main/app/prometheus/agent.py", - "source_location": "L221", + "source_location": "L202", "id": "prometheus_agent_prometheus", "community": 116, "norm_label": "prometheus" @@ -1801,7 +1810,7 @@ "label": ".__init__()", "file_type": "code", "source_file": "main/app/prometheus/agent.py", - "source_location": "L222", + "source_location": "L203", "id": "prometheus_agent_prometheus_init", "community": 116, "norm_label": ".__init__()" @@ -1810,7 +1819,7 @@ "label": "buildSystemPrompt()", "file_type": "code", "source_file": "main/app/prometheus/agent.py", - "source_location": "L226", + "source_location": "L207", "id": "prometheus_agent_buildsystemprompt", "community": 116, "norm_label": "buildsystemprompt()" @@ -1819,7 +1828,7 @@ "label": ".makeChat()", "file_type": "code", "source_file": "main/app/prometheus/agent.py", - "source_location": "L259", + "source_location": "L236", "id": "prometheus_agent_prometheus_makechat", "community": 116, "norm_label": ".makechat()" @@ -1828,7 +1837,7 @@ "label": ".streamMessage()", "file_type": "code", "source_file": "main/app/prometheus/agent.py", - "source_location": "L270", + "source_location": "L247", "id": "prometheus_agent_prometheus_streammessage", "community": 116, "norm_label": ".streammessage()" @@ -1951,64 +1960,55 @@ "norm_label": "counttokens()" }, { - "label": "FieldRegistry", - "file_type": "code", - "source_file": "main/app/prometheus/compact.py", - "source_location": "L89", - "id": "prometheus_compact_fieldregistry", - "community": 178, - "norm_label": "fieldregistry" - }, - { - "label": ".buildUrl()", + "label": "loadFieldData()", "file_type": "code", "source_file": "main/app/prometheus/compact.py", - "source_location": "L94", - "id": "prometheus_compact_fieldregistry_buildurl", - "community": 178, - "norm_label": ".buildurl()" + "source_location": "L93", + "id": "prometheus_compact_loadfielddata", + "community": 87, + "norm_label": "loadfielddata()" }, { - "label": ".fetchFields()", + "label": "getHistoricalFields()", "file_type": "code", "source_file": "main/app/prometheus/compact.py", - "source_location": "L99", - "id": "prometheus_compact_fieldregistry_fetchfields", - "community": 178, - "norm_label": ".fetchfields()" + "source_location": "L119", + "id": "prometheus_compact_gethistoricalfields", + "community": 87, + "norm_label": "gethistoricalfields()" }, { - "label": ".getFields()", + "label": "getFundamentalColumns()", "file_type": "code", "source_file": "main/app/prometheus/compact.py", - "source_location": "L120", - "id": "prometheus_compact_fieldregistry_getfields", - "community": 178, - "norm_label": ".getfields()" + "source_location": "L123", + "id": "prometheus_compact_getfundamentalcolumns", + "community": 87, + "norm_label": "getfundamentalcolumns()" }, { - "label": ".buildMetricRegex()", + "label": "invalidateFieldData()", "file_type": "code", "source_file": "main/app/prometheus/compact.py", "source_location": "L127", - "id": "prometheus_compact_fieldregistry_buildmetricregex", - "community": 178, - "norm_label": ".buildmetricregex()" + "id": "prometheus_compact_invalidatefielddata", + "community": 87, + "norm_label": "invalidatefielddata()" }, { - "label": ".getMetricRegex()", + "label": "getMetricRegex()", "file_type": "code", "source_file": "main/app/prometheus/compact.py", - "source_location": "L134", - "id": "prometheus_compact_fieldregistry_getmetricregex", - "community": 178, - "norm_label": ".getmetricregex()" + "source_location": "L133", + "id": "prometheus_compact_getmetricregex", + "community": 87, + "norm_label": "getmetricregex()" }, { "label": "extractTickers()", "file_type": "code", "source_file": "main/app/prometheus/compact.py", - "source_location": "L143", + "source_location": "L145", "id": "prometheus_compact_extracttickers", "community": 87, "norm_label": "extracttickers()" @@ -2017,7 +2017,7 @@ "label": "extractMetrics()", "file_type": "code", "source_file": "main/app/prometheus/compact.py", - "source_location": "L147", + "source_location": "L149", "id": "prometheus_compact_extractmetrics", "community": 87, "norm_label": "extractmetrics()" @@ -2026,7 +2026,7 @@ "label": "extractDecisions()", "file_type": "code", "source_file": "main/app/prometheus/compact.py", - "source_location": "L157", + "source_location": "L159", "id": "prometheus_compact_extractdecisions", "community": 87, "norm_label": "extractdecisions()" @@ -2035,7 +2035,7 @@ "label": "extractSnapshots()", "file_type": "code", "source_file": "main/app/prometheus/compact.py", - "source_location": "L171", + "source_location": "L173", "id": "prometheus_compact_extractsnapshots", "community": 87, "norm_label": "extractsnapshots()" @@ -2044,7 +2044,7 @@ "label": "extractToolCalls()", "file_type": "code", "source_file": "main/app/prometheus/compact.py", - "source_location": "L184", + "source_location": "L186", "id": "prometheus_compact_extracttoolcalls", "community": 87, "norm_label": "extracttoolcalls()" @@ -2053,7 +2053,7 @@ "label": "buildSummary()", "file_type": "code", "source_file": "main/app/prometheus/compact.py", - "source_location": "L200", + "source_location": "L202", "id": "prometheus_compact_buildsummary", "community": 87, "norm_label": "buildsummary()" @@ -2062,25 +2062,16 @@ "label": "PrometheusCompactor", "file_type": "code", "source_file": "main/app/prometheus/compact.py", - "source_location": "L221", + "source_location": "L223", "id": "prometheus_compact_prometheuscompactor", "community": 87, "norm_label": "prometheuscompactor" }, - { - "label": ".__init__()", - "file_type": "code", - "source_file": "main/app/prometheus/compact.py", - "source_location": "L222", - "id": "prometheus_compact_prometheuscompactor_init", - "community": 87, - "norm_label": ".__init__()" - }, { "label": ".shouldCompact()", "file_type": "code", "source_file": "main/app/prometheus/compact.py", - "source_location": "L225", + "source_location": "L224", "id": "prometheus_compact_prometheuscompactor_shouldcompact", "community": 87, "norm_label": ".shouldcompact()" @@ -2089,7 +2080,7 @@ "label": ".getCompactableChunk()", "file_type": "code", "source_file": "main/app/prometheus/compact.py", - "source_location": "L231", + "source_location": "L230", "id": "prometheus_compact_prometheuscompactor_getcompactablechunk", "community": 87, "norm_label": ".getcompactablechunk()" @@ -2098,7 +2089,7 @@ "label": ".extractEpisode()", "file_type": "code", "source_file": "main/app/prometheus/compact.py", - "source_location": "L240", + "source_location": "L239", "id": "prometheus_compact_prometheuscompactor_extractepisode", "community": 87, "norm_label": ".extractepisode()" @@ -2107,7 +2098,7 @@ "label": ".consolidate()", "file_type": "code", "source_file": "main/app/prometheus/compact.py", - "source_location": "L262", + "source_location": "L261", "id": "prometheus_compact_prometheuscompactor_consolidate", "community": 87, "norm_label": ".consolidate()" @@ -2116,7 +2107,7 @@ "label": ".compact()", "file_type": "code", "source_file": "main/app/prometheus/compact.py", - "source_location": "L289", + "source_location": "L288", "id": "prometheus_compact_prometheuscompactor_compact", "community": 87, "norm_label": ".compact()" @@ -2125,7 +2116,7 @@ "label": ".getEpisodes()", "file_type": "code", "source_file": "main/app/prometheus/compact.py", - "source_location": "L328", + "source_location": "L327", "id": "prometheus_compact_prometheuscompactor_getepisodes", "community": 87, "norm_label": ".getepisodes()" @@ -2224,7 +2215,7 @@ "label": "getClient()", "file_type": "code", "source_file": "main/app/prometheus/memory.py", - "source_location": "L40", + "source_location": "L39", "id": "prometheus_memory_getclient", "community": 53, "norm_label": "getclient()" @@ -2233,16 +2224,16 @@ "label": "normalizeKey()", "file_type": "code", "source_file": "main/app/prometheus/memory.py", - "source_location": "L47", + "source_location": "L46", "id": "prometheus_memory_normalizekey", - "community": 497, + "community": 63, "norm_label": "normalizekey()" }, { "label": "findSimilarKey()", "file_type": "code", "source_file": "main/app/prometheus/memory.py", - "source_location": "L54", + "source_location": "L53", "id": "prometheus_memory_findsimilarkey", "community": 53, "norm_label": "findsimilarkey()" @@ -2251,16 +2242,16 @@ "label": "PrometheusMemory", "file_type": "code", "source_file": "main/app/prometheus/memory.py", - "source_location": "L77", + "source_location": "L76", "id": "prometheus_memory_prometheusmemory", - "community": 131, + "community": 146, "norm_label": "prometheusmemory" }, { "label": "getMemoryLimit()", "file_type": "code", "source_file": "main/app/prometheus/memory.py", - "source_location": "L79", + "source_location": "L78", "id": "prometheus_memory_getmemorylimit", "community": 53, "norm_label": "getmemorylimit()" @@ -2269,7 +2260,7 @@ "label": "countMemories()", "file_type": "code", "source_file": "main/app/prometheus/memory.py", - "source_location": "L85", + "source_location": "L84", "id": "prometheus_memory_countmemories", "community": 53, "norm_label": "countmemories()" @@ -2278,16 +2269,16 @@ "label": "upsertMemory()", "file_type": "code", "source_file": "main/app/prometheus/memory.py", - "source_location": "L94", + "source_location": "L93", "id": "prometheus_memory_upsertmemory", - "community": 53, + "community": 115, "norm_label": "upsertmemory()" }, { "label": "search()", "file_type": "code", "source_file": "main/app/prometheus/memory.py", - "source_location": "L169", + "source_location": "L168", "id": "prometheus_memory_search", "community": 53, "norm_label": "search()" @@ -2296,7 +2287,7 @@ "label": "fullTextSearch()", "file_type": "code", "source_file": "main/app/prometheus/memory.py", - "source_location": "L235", + "source_location": "L234", "id": "prometheus_memory_fulltextsearch", "community": 53, "norm_label": "fulltextsearch()" @@ -2305,7 +2296,7 @@ "label": "getUserMemories()", "file_type": "code", "source_file": "main/app/prometheus/memory.py", - "source_location": "L293", + "source_location": "L292", "id": "prometheus_memory_getusermemories", "community": 53, "norm_label": "getusermemories()" @@ -2314,7 +2305,7 @@ "label": "deleteMemory()", "file_type": "code", "source_file": "main/app/prometheus/memory.py", - "source_location": "L318", + "source_location": "L317", "id": "prometheus_memory_deletememory", "community": 53, "norm_label": "deletememory()" @@ -2323,7 +2314,7 @@ "label": "extract()", "file_type": "code", "source_file": "main/app/prometheus/memory.py", - "source_location": "L335", + "source_location": "L334", "id": "prometheus_memory_extract", "community": 53, "norm_label": "extract()" @@ -2494,7 +2485,7 @@ "label": "StreamChannel", "file_type": "code", "source_file": "main/app/prometheus/stream_bus.py", - "source_location": "L10", + "source_location": "L11", "id": "prometheus_stream_bus_streamchannel", "community": 210, "norm_label": "streamchannel" @@ -2503,7 +2494,7 @@ "label": ".__init__()", "file_type": "code", "source_file": "main/app/prometheus/stream_bus.py", - "source_location": "L11", + "source_location": "L12", "id": "prometheus_stream_bus_streamchannel_init", "community": 210, "norm_label": ".__init__()" @@ -2512,7 +2503,7 @@ "label": ".publish()", "file_type": "code", "source_file": "main/app/prometheus/stream_bus.py", - "source_location": "L17", + "source_location": "L18", "id": "prometheus_stream_bus_streamchannel_publish", "community": 210, "norm_label": ".publish()" @@ -2521,7 +2512,7 @@ "label": "StreamBus", "file_type": "code", "source_file": "main/app/prometheus/stream_bus.py", - "source_location": "L28", + "source_location": "L29", "id": "prometheus_stream_bus_streambus", "community": 210, "norm_label": "streambus" @@ -2530,7 +2521,7 @@ "label": ".__init__()", "file_type": "code", "source_file": "main/app/prometheus/stream_bus.py", - "source_location": "L29", + "source_location": "L30", "id": "prometheus_stream_bus_streambus_init", "community": 210, "norm_label": ".__init__()" @@ -2539,7 +2530,7 @@ "label": ".getOrCreate()", "file_type": "code", "source_file": "main/app/prometheus/stream_bus.py", - "source_location": "L32", + "source_location": "L33", "id": "prometheus_stream_bus_streambus_getorcreate", "community": 210, "norm_label": ".getorcreate()" @@ -2548,7 +2539,7 @@ "label": ".publish()", "file_type": "code", "source_file": "main/app/prometheus/stream_bus.py", - "source_location": "L39", + "source_location": "L40", "id": "prometheus_stream_bus_streambus_publish", "community": 210, "norm_label": ".publish()" @@ -2557,7 +2548,7 @@ "label": ".subscribe()", "file_type": "code", "source_file": "main/app/prometheus/stream_bus.py", - "source_location": "L42", + "source_location": "L43", "id": "prometheus_stream_bus_streambus_subscribe", "community": 210, "norm_label": ".subscribe()" @@ -2566,7 +2557,7 @@ "label": ".unsubscribe()", "file_type": "code", "source_file": "main/app/prometheus/stream_bus.py", - "source_location": "L55", + "source_location": "L56", "id": "prometheus_stream_bus_streambus_unsubscribe", "community": 210, "norm_label": ".unsubscribe()" @@ -2575,18 +2566,27 @@ "label": ".startRun()", "file_type": "code", "source_file": "main/app/prometheus/stream_bus.py", - "source_location": "L60", + "source_location": "L61", "id": "prometheus_stream_bus_streambus_startrun", "community": 210, "norm_label": ".startrun()" }, + { + "label": ".forward()", + "file_type": "code", + "source_file": "main/app/prometheus/stream_bus.py", + "source_location": "L83", + "id": "prometheus_stream_bus_streambus_forward", + "community": 210, + "norm_label": ".forward()" + }, { "label": "tools.py", "file_type": "code", "source_file": "main/app/prometheus/tools.py", "source_location": "L1", "id": "main_app_prometheus_tools_py", - "community": 188, + "community": 86, "norm_label": "tools.py" }, { @@ -2595,7 +2595,7 @@ "source_file": "main/app/prometheus/tools.py", "source_location": "L18", "id": "prometheus_tools_search_memory", - "community": 486, + "community": 86, "norm_label": "search_memory()" }, { @@ -2604,7 +2604,7 @@ "source_file": "main/app/prometheus/tools.py", "source_location": "L48", "id": "prometheus_tools_save_memory", - "community": 491, + "community": 86, "norm_label": "save_memory()" }, { @@ -2613,7 +2613,7 @@ "source_file": "main/app/prometheus/tools.py", "source_location": "L89", "id": "prometheus_tools_execute_code", - "community": 490, + "community": 188, "norm_label": "execute_code()" }, { @@ -2649,7 +2649,7 @@ "source_file": "main/app/prometheus/tools.py", "source_location": "L153", "id": "prometheus_tools_serve_file", - "community": 188, + "community": 86, "norm_label": "serve_file()" }, { @@ -2667,7 +2667,7 @@ "source_file": "main/app/prometheus/tools.py", "source_location": "L19", "id": "prometheus_tools_rationale_19", - "community": 486, + "community": 86, "norm_label": "search user's saved memories, preferences, and past analysis context. use" }, { @@ -2676,7 +2676,7 @@ "source_file": "main/app/prometheus/tools.py", "source_location": "L49", "id": "prometheus_tools_rationale_49", - "community": 491, + "community": 86, "norm_label": "store a memory about the user's preferences, analysis results, or feedback." }, { @@ -2685,7 +2685,7 @@ "source_file": "main/app/prometheus/tools.py", "source_location": "L90", "id": "prometheus_tools_rationale_90", - "community": 490, + "community": 188, "norm_label": "execute python code in an isolated sandbox. use for quantitative analysis," }, { @@ -2721,7 +2721,7 @@ "source_file": "main/app/prometheus/tools.py", "source_location": "L154", "id": "prometheus_tools_rationale_154", - "community": 188, + "community": 86, "norm_label": "get a download link for a workspace file to share with the user. use this" }, { @@ -2739,7 +2739,7 @@ "source_file": "main/app/prometheus/vector.py", "source_location": "L10", "id": "prometheus_vector_embed", - "community": 105, + "community": 53, "norm_label": "embed()" }, { @@ -2766,7 +2766,7 @@ "source_file": "main/app/prometheus/vector.py", "source_location": "L35", "id": "prometheus_vector_contenthash", - "community": 53, + "community": 115, "norm_label": "contenthash()" }, { @@ -2784,23 +2784,23 @@ "source_file": "main/app/scraper_b3/scraper.py", "source_location": "L1", "id": "main_app_scraper_b3_scraper_py", - "community": 72, + "community": 95, "norm_label": "scraper.py" }, { "label": "getCurrentSelic()", "file_type": "code", "source_file": "main/app/scraper_b3/scraper.py", - "source_location": "L29", + "source_location": "L34", "id": "scraper_b3_scraper_getcurrentselic", - "community": 72, + "community": 95, "norm_label": "getcurrentselic()" }, { "label": "B3Scraper", "file_type": "code", "source_file": "main/app/scraper_b3/scraper.py", - "source_location": "L39", + "source_location": "L44", "id": "scraper_b3_scraper_b3scraper", "community": 72, "norm_label": "b3scraper" @@ -2809,70 +2809,70 @@ "label": ".__init__()", "file_type": "code", "source_file": "main/app/scraper_b3/scraper.py", - "source_location": "L40", + "source_location": "L45", "id": "scraper_b3_scraper_b3scraper_init", - "community": 72, + "community": 95, "norm_label": ".__init__()" }, { "label": "getInitialData()", "file_type": "code", "source_file": "main/app/scraper_b3/scraper.py", - "source_location": "L54", + "source_location": "L59", "id": "scraper_b3_scraper_getinitialdata", - "community": 72, + "community": 95, "norm_label": "getinitialdata()" }, { "label": "historicalRentability()", "file_type": "code", "source_file": "main/app/scraper_b3/scraper.py", - "source_location": "L109", + "source_location": "L114", "id": "scraper_b3_scraper_historicalrentability", - "community": 72, + "community": 95, "norm_label": "historicalrentability()" }, { "label": "historicalDividends()", "file_type": "code", "source_file": "main/app/scraper_b3/scraper.py", - "source_location": "L132", + "source_location": "L137", "id": "scraper_b3_scraper_historicaldividends", - "community": 72, + "community": 95, "norm_label": "historicaldividends()" }, { "label": "historicalDividendYields()", "file_type": "code", "source_file": "main/app/scraper_b3/scraper.py", - "source_location": "L163", + "source_location": "L168", "id": "scraper_b3_scraper_historicaldividendyields", - "community": 72, + "community": 95, "norm_label": "historicaldividendyields()" }, { "label": "historicalRevenue()", "file_type": "code", "source_file": "main/app/scraper_b3/scraper.py", - "source_location": "L191", + "source_location": "L196", "id": "scraper_b3_scraper_historicalrevenue", - "community": 72, + "community": 95, "norm_label": "historicalrevenue()" }, { "label": "historicalCotationProfits()", "file_type": "code", "source_file": "main/app/scraper_b3/scraper.py", - "source_location": "L212", + "source_location": "L217", "id": "scraper_b3_scraper_historicalcotationprofits", - "community": 72, + "community": 95, "norm_label": "historicalcotationprofits()" }, { "label": ".historicalCotationProfits_Oceans14()", "file_type": "code", "source_file": "main/app/scraper_b3/scraper.py", - "source_location": "L225", + "source_location": "L230", "id": "scraper_b3_scraper_b3scraper_historicalcotationprofits_oceans14", "community": 72, "norm_label": ".historicalcotationprofits_oceans14()" @@ -2881,34 +2881,34 @@ "label": "historicalCotations()", "file_type": "code", "source_file": "main/app/scraper_b3/scraper.py", - "source_location": "L238", + "source_location": "L243", "id": "scraper_b3_scraper_historicalcotations", - "community": 72, + "community": 95, "norm_label": "historicalcotations()" }, { "label": "tagAlong()", "file_type": "code", "source_file": "main/app/scraper_b3/scraper.py", - "source_location": "L255", + "source_location": "L260", "id": "scraper_b3_scraper_tagalong", - "community": 72, + "community": 95, "norm_label": "tagalong()" }, { "label": "stockNews()", "file_type": "code", "source_file": "main/app/scraper_b3/scraper.py", - "source_location": "L280", + "source_location": "L285", "id": "scraper_b3_scraper_stocknews", - "community": 72, + "community": 95, "norm_label": "stocknews()" }, { "label": ".fundamentalIndicators()", "file_type": "code", "source_file": "main/app/scraper_b3/scraper.py", - "source_location": "L293", + "source_location": "L298", "id": "scraper_b3_scraper_b3scraper_fundamentalindicators", "community": 72, "norm_label": ".fundamentalindicators()" @@ -2917,7 +2917,7 @@ "label": ".processTicker()", "file_type": "code", "source_file": "main/app/scraper_b3/scraper.py", - "source_location": "L416", + "source_location": "L421", "id": "scraper_b3_scraper_b3scraper_processticker", "community": 72, "norm_label": ".processticker()" @@ -2926,7 +2926,7 @@ "label": ".scrapeStocks()", "file_type": "code", "source_file": "main/app/scraper_b3/scraper.py", - "source_location": "L447", + "source_location": "L452", "id": "scraper_b3_scraper_b3scraper_scrapestocks", "community": 72, "norm_label": ".scrapestocks()" @@ -2935,7 +2935,7 @@ "label": ".reorderColumns()", "file_type": "code", "source_file": "main/app/scraper_b3/scraper.py", - "source_location": "L494", + "source_location": "L499", "id": "scraper_b3_scraper_b3scraper_reordercolumns", "community": 72, "norm_label": ".reordercolumns()" @@ -2944,7 +2944,7 @@ "label": ".serializeComplexTypes()", "file_type": "code", "source_file": "main/app/scraper_b3/scraper.py", - "source_location": "L503", + "source_location": "L508", "id": "scraper_b3_scraper_b3scraper_serializecomplextypes", "community": 72, "norm_label": ".serializecomplextypes()" @@ -2953,7 +2953,7 @@ "label": ".exportJson()", "file_type": "code", "source_file": "main/app/scraper_b3/scraper.py", - "source_location": "L522", + "source_location": "L527", "id": "scraper_b3_scraper_b3scraper_exportjson", "community": 72, "norm_label": ".exportjson()" @@ -2962,7 +2962,7 @@ "label": ".exportMysql()", "file_type": "code", "source_file": "main/app/scraper_b3/scraper.py", - "source_location": "L530", + "source_location": "L535", "id": "scraper_b3_scraper_b3scraper_exportmysql", "community": 72, "norm_label": ".exportmysql()" @@ -2998,7 +2998,7 @@ "label": "optimizeDtypes()", "file_type": "code", "source_file": "main/app/stocks_api/cache.py", - "source_location": "L38", + "source_location": "L37", "id": "stocks_api_cache_optimizedtypes", "community": 82, "norm_label": "optimizedtypes()" @@ -3007,7 +3007,7 @@ "label": "arrowTypeFor()", "file_type": "code", "source_file": "main/app/stocks_api/cache.py", - "source_location": "L58", + "source_location": "L57", "id": "stocks_api_cache_arrowtypefor", "community": 82, "norm_label": "arrowtypefor()" @@ -3016,7 +3016,7 @@ "label": "buildFeatherCache()", "file_type": "code", "source_file": "main/app/stocks_api/cache.py", - "source_location": "L69", + "source_location": "L68", "id": "stocks_api_cache_buildfeathercache", "community": 82, "norm_label": "buildfeathercache()" @@ -3025,7 +3025,7 @@ "label": "tryBuildLock()", "file_type": "code", "source_file": "main/app/stocks_api/cache.py", - "source_location": "L151", + "source_location": "L150", "id": "stocks_api_cache_trybuildlock", "community": 82, "norm_label": "trybuildlock()" @@ -3034,7 +3034,7 @@ "label": "StocksCacheManager", "file_type": "code", "source_file": "main/app/stocks_api/cache.py", - "source_location": "L169", + "source_location": "L167", "id": "stocks_api_cache_stockscachemanager", "community": 42, "norm_label": "stockscachemanager" @@ -3043,7 +3043,7 @@ "label": ".__init__()", "file_type": "code", "source_file": "main/app/stocks_api/cache.py", - "source_location": "L170", + "source_location": "L168", "id": "stocks_api_cache_stockscachemanager_init", "community": 42, "norm_label": ".__init__()" @@ -3052,7 +3052,7 @@ "label": ".cacheScheduler()", "file_type": "code", "source_file": "main/app/stocks_api/cache.py", - "source_location": "L178", + "source_location": "L176", "id": "stocks_api_cache_stockscachemanager_cachescheduler", "community": 82, "norm_label": ".cachescheduler()" @@ -3061,7 +3061,7 @@ "label": ".loadFromFeather()", "file_type": "code", "source_file": "main/app/stocks_api/cache.py", - "source_location": "L185", + "source_location": "L183", "id": "stocks_api_cache_stockscachemanager_loadfromfeather", "community": 82, "norm_label": ".loadfromfeather()" @@ -3070,7 +3070,7 @@ "label": ".getCachedStocks()", "file_type": "code", "source_file": "main/app/stocks_api/cache.py", - "source_location": "L203", + "source_location": "L201", "id": "stocks_api_cache_stockscachemanager_getcachedstocks", "community": 82, "norm_label": ".getcachedstocks()" @@ -3277,7 +3277,7 @@ "label": ".queryFundamental()", "file_type": "code", "source_file": "main/app/stocks_api/query.py", - "source_location": "L190", + "source_location": "L192", "id": "stocks_api_query_stocksquerymanager_queryfundamental", "community": 63, "norm_label": ".queryfundamental()" @@ -3286,7 +3286,7 @@ "label": ".queryCotations()", "file_type": "code", "source_file": "main/app/stocks_api/query.py", - "source_location": "L279", + "source_location": "L281", "id": "stocks_api_query_stocksquerymanager_querycotations", "community": 63, "norm_label": ".querycotations()" @@ -3295,11 +3295,29 @@ "label": ".queryLiveCotation()", "file_type": "code", "source_file": "main/app/stocks_api/query.py", - "source_location": "L332", + "source_location": "L334", "id": "stocks_api_query_stocksquerymanager_querylivecotation", "community": 63, "norm_label": ".querylivecotation()" }, + { + "label": "sync_cache.py", + "file_type": "code", + "source_file": "main/app/stocks_api/sync_cache.py", + "source_location": "L1", + "id": "main_app_stocks_api_sync_cache_py", + "community": 511, + "norm_label": "sync_cache.py" + }, + { + "label": "sync_cache()", + "file_type": "code", + "source_file": "main/app/stocks_api/sync_cache.py", + "source_location": "L16", + "id": "stocks_api_sync_cache_sync_cache", + "community": 511, + "norm_label": "sync_cache()" + }, { "label": "util.py", "file_type": "code", @@ -3315,7 +3333,7 @@ "source_file": "main/app/stocks_api/util.py", "source_location": "L18", "id": "stocks_api_util_dedupabbrev", - "community": 256, + "community": 130, "norm_label": "dedupabbrev()" }, { @@ -3324,7 +3342,7 @@ "source_file": "main/app/stocks_api/util.py", "source_location": "L27", "id": "stocks_api_util_autoabbreviate", - "community": 256, + "community": 130, "norm_label": "autoabbreviate()" }, { @@ -3333,7 +3351,7 @@ "source_file": "main/app/stocks_api/util.py", "source_location": "L48", "id": "stocks_api_util_generateabbreviations", - "community": 256, + "community": 130, "norm_label": "generateabbreviations()" }, { @@ -3369,7 +3387,7 @@ "source_file": "main/app/stocks_api/util.py", "source_location": "L97", "id": "stocks_api_util_detectnestedfields", - "community": 256, + "community": 130, "norm_label": "detectnestedfields()" }, { @@ -3502,7 +3520,7 @@ "label": "verifySessionOwnsership()", "file_type": "code", "source_file": "main/controller/prometheus_controller.py", - "source_location": "L26", + "source_location": "L24", "id": "controller_prometheus_controller_verifysessionownsership", "community": 84, "norm_label": "verifysessionownsership()" @@ -3511,7 +3529,7 @@ "label": "health()", "file_type": "code", "source_file": "main/controller/prometheus_controller.py", - "source_location": "L32", + "source_location": "L30", "id": "controller_prometheus_controller_health", "community": 84, "norm_label": "health()" @@ -3520,7 +3538,7 @@ "label": "getSessions()", "file_type": "code", "source_file": "main/controller/prometheus_controller.py", - "source_location": "L37", + "source_location": "L35", "id": "controller_prometheus_controller_getsessions", "community": 84, "norm_label": "getsessions()" @@ -3529,7 +3547,7 @@ "label": "updateSessionTitle()", "file_type": "code", "source_file": "main/controller/prometheus_controller.py", - "source_location": "L56", + "source_location": "L54", "id": "controller_prometheus_controller_updatesessiontitle", "community": 84, "norm_label": "updatesessiontitle()" @@ -3538,7 +3556,7 @@ "label": "getHistory()", "file_type": "code", "source_file": "main/controller/prometheus_controller.py", - "source_location": "L71", + "source_location": "L69", "id": "controller_prometheus_controller_gethistory", "community": 84, "norm_label": "gethistory()" @@ -3547,7 +3565,7 @@ "label": "deleteSession()", "file_type": "code", "source_file": "main/controller/prometheus_controller.py", - "source_location": "L90", + "source_location": "L88", "id": "controller_prometheus_controller_deletesession", "community": 84, "norm_label": "deletesession()" @@ -3556,7 +3574,7 @@ "label": "chat_stream()", "file_type": "code", "source_file": "main/controller/prometheus_controller.py", - "source_location": "L103", + "source_location": "L101", "id": "controller_prometheus_controller_chat_stream", "community": 84, "norm_label": "chat_stream()" @@ -3565,7 +3583,7 @@ "label": "resumeChatStream()", "file_type": "code", "source_file": "main/controller/prometheus_controller.py", - "source_location": "L151", + "source_location": "L149", "id": "controller_prometheus_controller_resumechatstream", "community": 84, "norm_label": "resumechatstream()" @@ -3574,7 +3592,7 @@ "label": "deleteWorkspaceFile()", "file_type": "code", "source_file": "main/controller/prometheus_controller.py", - "source_location": "L165", + "source_location": "L163", "id": "controller_prometheus_controller_deleteworkspacefile", "community": 84, "norm_label": "deleteworkspacefile()" @@ -3583,29 +3601,20 @@ "label": "downloadWorkspaceFile()", "file_type": "code", "source_file": "main/controller/prometheus_controller.py", - "source_location": "L178", + "source_location": "L176", "id": "controller_prometheus_controller_downloadworkspacefile", - "community": 69, + "community": 84, "norm_label": "downloadworkspacefile()" }, { "label": "listWorkspaceFiles()", "file_type": "code", "source_file": "main/controller/prometheus_controller.py", - "source_location": "L194", + "source_location": "L192", "id": "controller_prometheus_controller_listworkspacefiles", "community": 84, "norm_label": "listworkspacefiles()" }, - { - "label": "_forward()", - "file_type": "code", - "source_file": "main/controller/prometheus_controller.py", - "source_location": "L205", - "id": "controller_prometheus_controller_forward", - "community": 84, - "norm_label": "_forward()" - }, { "label": "stocksapi_controller.py", "file_type": "code", @@ -3615,38 +3624,11 @@ "community": 81, "norm_label": "stocksapi_controller.py" }, - { - "label": "JSONBytesResponse", - "file_type": "code", - "source_file": "main/controller/stocksapi_controller.py", - "source_location": "L23", - "id": "controller_stocksapi_controller_jsonbytesresponse", - "community": 81, - "norm_label": "jsonbytesresponse" - }, - { - "label": "FastAPIResponse", - "file_type": "code", - "source_file": "", - "source_location": "", - "id": "fastapiresponse", - "community": 81, - "norm_label": "fastapiresponse" - }, - { - "label": ".render()", - "file_type": "code", - "source_file": "main/controller/stocksapi_controller.py", - "source_location": "L26", - "id": "controller_stocksapi_controller_jsonbytesresponse_render", - "community": 81, - "norm_label": ".render()" - }, { "label": "health()", "file_type": "code", "source_file": "main/controller/stocksapi_controller.py", - "source_location": "L31", + "source_location": "L24", "id": "controller_stocksapi_controller_health", "community": 81, "norm_label": "health()" @@ -3655,7 +3637,7 @@ "label": "listFields()", "file_type": "code", "source_file": "main/controller/stocksapi_controller.py", - "source_location": "L46", + "source_location": "L39", "id": "controller_stocksapi_controller_listfields", "community": 140, "norm_label": "listfields()" @@ -3664,25 +3646,25 @@ "label": "getHistorical()", "file_type": "code", "source_file": "main/controller/stocksapi_controller.py", - "source_location": "L93", + "source_location": "L86", "id": "controller_stocksapi_controller_gethistorical", - "community": 81, + "community": 475, "norm_label": "gethistorical()" }, { "label": "getFundamental()", "file_type": "code", "source_file": "main/controller/stocksapi_controller.py", - "source_location": "L157", + "source_location": "L151", "id": "controller_stocksapi_controller_getfundamental", - "community": 504, + "community": 157, "norm_label": "getfundamental()" }, { "label": "getCotations()", "file_type": "code", "source_file": "main/controller/stocksapi_controller.py", - "source_location": "L226", + "source_location": "L221", "id": "controller_stocksapi_controller_getcotations", "community": 169, "norm_label": "getcotations()" @@ -3691,17 +3673,17 @@ "label": "getLiveCotation()", "file_type": "code", "source_file": "main/controller/stocksapi_controller.py", - "source_location": "L282", + "source_location": "L277", "id": "controller_stocksapi_controller_getlivecotation", - "community": 124, + "community": 81, "norm_label": "getlivecotation()" }, { "label": "Discover available field names before querying /historical or /fundamental.", "file_type": "rationale", "source_file": "main/controller/stocksapi_controller.py", - "source_location": "L47", - "id": "controller_stocksapi_controller_rationale_47", + "source_location": "L40", + "id": "controller_stocksapi_controller_rationale_40", "community": 140, "norm_label": "discover available field names before querying /historical or /fundamental." }, @@ -3709,26 +3691,26 @@ "label": "Get year-based historical financial data for Brazilian B3 stocks. Returns", "file_type": "rationale", "source_file": "main/controller/stocksapi_controller.py", - "source_location": "L103", - "id": "controller_stocksapi_controller_rationale_103", - "community": 81, + "source_location": "L96", + "id": "controller_stocksapi_controller_rationale_96", + "community": 475, "norm_label": "get year-based historical financial data for brazilian b3 stocks. returns" }, { "label": "Get point-in-time fundamental/valuation data for Brazilian B3 stocks. Ret", "file_type": "rationale", "source_file": "main/controller/stocksapi_controller.py", - "source_location": "L167", - "id": "controller_stocksapi_controller_rationale_167", - "community": 504, + "source_location": "L161", + "id": "controller_stocksapi_controller_rationale_161", + "community": 157, "norm_label": "get point-in-time fundamental/valuation data for brazilian b3 stocks. ret" }, { "label": "Get 10-year daily price history (cotation) for Brazilian B3 stocks. Retur", "file_type": "rationale", "source_file": "main/controller/stocksapi_controller.py", - "source_location": "L234", - "id": "controller_stocksapi_controller_rationale_234", + "source_location": "L229", + "id": "controller_stocksapi_controller_rationale_229", "community": 169, "norm_label": "get 10-year daily price history (cotation) for brazilian b3 stocks. retur" }, @@ -3736,9 +3718,9 @@ "label": "Get real-time price quotation for a single Brazilian B3 stock. Returns th", "file_type": "rationale", "source_file": "main/controller/stocksapi_controller.py", - "source_location": "L288", - "id": "controller_stocksapi_controller_rationale_288", - "community": 124, + "source_location": "L283", + "id": "controller_stocksapi_controller_rationale_283", + "community": 81, "norm_label": "get real-time price quotation for a single brazilian b3 stock. returns th" }, { @@ -3747,70 +3729,79 @@ "source_file": "main/controller/user_controller.py", "source_location": "L1", "id": "main_controller_user_controller_py", - "community": 78, + "community": 501, "norm_label": "user_controller.py" }, + { + "label": "sessionToDict()", + "file_type": "code", + "source_file": "main/controller/user_controller.py", + "source_location": "L16", + "id": "controller_user_controller_sessiontodict", + "community": 501, + "norm_label": "sessiontodict()" + }, { "label": "health()", "file_type": "code", "source_file": "main/controller/user_controller.py", - "source_location": "L17", + "source_location": "L33", "id": "controller_user_controller_health", - "community": 78, + "community": 501, "norm_label": "health()" }, { "label": "getMe()", "file_type": "code", "source_file": "main/controller/user_controller.py", - "source_location": "L22", + "source_location": "L38", "id": "controller_user_controller_getme", - "community": 78, + "community": 501, "norm_label": "getme()" }, { "label": "testAdminAccess()", "file_type": "code", "source_file": "main/controller/user_controller.py", - "source_location": "L27", + "source_location": "L43", "id": "controller_user_controller_testadminaccess", - "community": 78, + "community": 501, "norm_label": "testadminaccess()" }, { "label": "getSessions()", "file_type": "code", "source_file": "main/controller/user_controller.py", - "source_location": "L35", + "source_location": "L51", "id": "controller_user_controller_getsessions", - "community": 78, + "community": 501, "norm_label": "getsessions()" }, { "label": "getCurrentSession()", "file_type": "code", "source_file": "main/controller/user_controller.py", - "source_location": "L72", + "source_location": "L78", "id": "controller_user_controller_getcurrentsession", - "community": 78, + "community": 501, "norm_label": "getcurrentsession()" }, { "label": "revokeSession()", "file_type": "code", "source_file": "main/controller/user_controller.py", - "source_location": "L94", + "source_location": "L91", "id": "controller_user_controller_revokesession", - "community": 78, + "community": 501, "norm_label": "revokesession()" }, { "label": "revokeAllSessions()", "file_type": "code", "source_file": "main/controller/user_controller.py", - "source_location": "L115", + "source_location": "L112", "id": "controller_user_controller_revokeallsessions", - "community": 78, + "community": 501, "norm_label": "revokeallsessions()" }, { @@ -3828,7 +3819,7 @@ "source_file": "main/models/memory.py", "source_location": "L1", "id": "main_models_memory_py", - "community": 131, + "community": 146, "norm_label": "memory.py" }, { @@ -3837,7 +3828,7 @@ "source_file": "main/models/memory.py", "source_location": "L7", "id": "models_memory_prometheusmemory", - "community": 131, + "community": 146, "norm_label": "prometheusmemory" }, { @@ -3846,7 +3837,7 @@ "source_file": "", "source_location": "", "id": "base", - "community": 131, + "community": 146, "norm_label": "base" }, { @@ -4008,7 +3999,7 @@ "source_file": "main/service/authentication_service.py", "source_location": "L1", "id": "main_service_authentication_service_py", - "community": 95, + "community": 84, "norm_label": "authentication_service.py" }, { @@ -4017,7 +4008,7 @@ "source_file": "main/service/authentication_service.py", "source_location": "L9", "id": "service_authentication_service_authenticationservice", - "community": 95, + "community": 84, "norm_label": "authenticationservice" }, { @@ -4026,7 +4017,7 @@ "source_file": "main/service/authentication_service.py", "source_location": "L11", "id": "service_authentication_service_initialize", - "community": 95, + "community": 84, "norm_label": "initialize()" }, { @@ -4035,7 +4026,7 @@ "source_file": "main/service/prometheus_service.py", "source_location": "L1", "id": "main_service_prometheus_service_py", - "community": 54, + "community": 84, "norm_label": "prometheus_service.py" }, { @@ -4051,18 +4042,18 @@ "label": "PrometheusService", "file_type": "code", "source_file": "main/service/prometheus_service.py", - "source_location": "L59", + "source_location": "L61", "id": "service_prometheus_service_prometheusservice", - "community": 131, + "community": 146, "norm_label": "prometheusservice" }, { "label": "initialize()", "file_type": "code", "source_file": "main/service/prometheus_service.py", - "source_location": "L61", + "source_location": "L63", "id": "service_prometheus_service_initialize", - "community": 54, + "community": 84, "norm_label": "initialize()" }, { @@ -4107,7 +4098,7 @@ "source_file": "main/service/stocksapi_service.py", "source_location": "L1", "id": "main_service_stocksapi_service_py", - "community": 95, + "community": 84, "norm_label": "stocksapi_service.py" }, { @@ -4116,7 +4107,7 @@ "source_file": "main/service/stocksapi_service.py", "source_location": "L10", "id": "service_stocksapi_service_mcpdetectmiddleware", - "community": 95, + "community": 84, "norm_label": "mcpdetectmiddleware" }, { @@ -4125,7 +4116,7 @@ "source_file": "main/service/stocksapi_service.py", "source_location": "L11", "id": "service_stocksapi_service_mcpdetectmiddleware_init", - "community": 95, + "community": 84, "norm_label": ".__init__()" }, { @@ -4134,7 +4125,7 @@ "source_file": "main/service/stocksapi_service.py", "source_location": "L14", "id": "service_stocksapi_service_mcpdetectmiddleware_call", - "community": 95, + "community": 84, "norm_label": ".__call__()" }, { @@ -4143,7 +4134,7 @@ "source_file": "main/service/stocksapi_service.py", "source_location": "L26", "id": "service_stocksapi_service_stocksapiservice", - "community": 95, + "community": 84, "norm_label": "stocksapiservice" }, { @@ -4152,7 +4143,7 @@ "source_file": "main/service/stocksapi_service.py", "source_location": "L28", "id": "service_stocksapi_service_initialize", - "community": 95, + "community": 84, "norm_label": "initialize()" }, { @@ -4161,7 +4152,7 @@ "source_file": "main/service/user_service.py", "source_location": "L1", "id": "main_service_user_service_py", - "community": 95, + "community": 84, "norm_label": "user_service.py" }, { @@ -4170,7 +4161,7 @@ "source_file": "main/service/user_service.py", "source_location": "L16", "id": "service_user_service_removeinactivesessions", - "community": 95, + "community": 84, "norm_label": "removeinactivesessions()" }, { @@ -4179,7 +4170,7 @@ "source_file": "main/service/user_service.py", "source_location": "L38", "id": "service_user_service_userservice", - "community": 95, + "community": 84, "norm_label": "userservice" }, { @@ -4188,7 +4179,7 @@ "source_file": "main/service/user_service.py", "source_location": "L40", "id": "service_user_service_initialize", - "community": 95, + "community": 84, "norm_label": "initialize()" }, { @@ -4224,32 +4215,14 @@ "source_file": "main/utils/errors.py", "source_location": "L1", "id": "main_utils_errors_py", - "community": 221, - "norm_label": "errors.py" - }, - { - "label": "ErrorResponse", - "file_type": "code", - "source_file": "main/utils/errors.py", - "source_location": "L12", - "id": "utils_errors_errorresponse", - "community": 33, - "norm_label": "errorresponse" - }, - { - "label": "BaseModel", - "file_type": "code", - "source_file": "", - "source_location": "", - "id": "basemodel", "community": 33, - "norm_label": "basemodel" + "norm_label": "errors.py" }, { "label": "RequestContextFilter", "file_type": "code", "source_file": "main/utils/errors.py", - "source_location": "L21", + "source_location": "L10", "id": "utils_errors_requestcontextfilter", "community": 33, "norm_label": "requestcontextfilter" @@ -4258,7 +4231,7 @@ "label": ".filter()", "file_type": "code", "source_file": "main/utils/errors.py", - "source_location": "L22", + "source_location": "L11", "id": "utils_errors_requestcontextfilter_filter", "community": 33, "norm_label": ".filter()" @@ -4267,43 +4240,43 @@ "label": "buildErrorResponse()", "file_type": "code", "source_file": "main/utils/errors.py", - "source_location": "L27", + "source_location": "L16", "id": "utils_errors_builderrorresponse", - "community": 221, + "community": 33, "norm_label": "builderrorresponse()" }, { "label": "httpExceptionHandler()", "file_type": "code", "source_file": "main/utils/errors.py", - "source_location": "L37", + "source_location": "L27", "id": "utils_errors_httpexceptionhandler", - "community": 221, + "community": 33, "norm_label": "httpexceptionhandler()" }, { "label": "validationExceptionHandler()", "file_type": "code", "source_file": "main/utils/errors.py", - "source_location": "L44", + "source_location": "L34", "id": "utils_errors_validationexceptionhandler", - "community": 221, + "community": 33, "norm_label": "validationexceptionhandler()" }, { "label": "genericExceptionHandler()", "file_type": "code", "source_file": "main/utils/errors.py", - "source_location": "L56", + "source_location": "L46", "id": "utils_errors_genericexceptionhandler", - "community": 221, + "community": 33, "norm_label": "genericexceptionhandler()" }, { "label": "registerErrorHandlers()", "file_type": "code", "source_file": "main/utils/errors.py", - "source_location": "L65", + "source_location": "L55", "id": "utils_errors_registererrorhandlers", "community": 120, "norm_label": "registererrorhandlers()" @@ -4332,7 +4305,7 @@ "source_file": "main/utils/logging_config.py", "source_location": "L1", "id": "main_utils_logging_config_py", - "community": 94, + "community": 122, "norm_label": "logging_config.py" }, { @@ -4341,7 +4314,7 @@ "source_file": "main/utils/logging_config.py", "source_location": "L22", "id": "utils_logging_config_setuplogging", - "community": 94, + "community": 122, "norm_label": "setuplogging()" }, { @@ -4350,7 +4323,7 @@ "source_file": "main/utils/logging_config.py", "source_location": "L37", "id": "utils_logging_config_discordhandler", - "community": 94, + "community": 122, "norm_label": "discordhandler" }, { @@ -4359,7 +4332,7 @@ "source_file": "main/utils/logging_config.py", "source_location": "L38", "id": "utils_logging_config_discordhandler_emit", - "community": 94, + "community": 122, "norm_label": ".emit()" }, { @@ -4368,7 +4341,7 @@ "source_file": "main/utils/logging_config.py", "source_location": "L55", "id": "utils_logging_config_setupdiscordhandler", - "community": 94, + "community": 122, "norm_label": "setupdiscordhandler()" }, { @@ -4431,7 +4404,7 @@ "source_file": "main/utils/roles.py", "source_location": "L1", "id": "main_utils_roles_py", - "community": 21, + "community": 115, "norm_label": "roles.py" }, { @@ -4440,7 +4413,7 @@ "source_file": "main/utils/roles.py", "source_location": "L5", "id": "utils_roles_permission", - "community": 131, + "community": 146, "norm_label": "permission" }, { @@ -4476,7 +4449,7 @@ "source_file": "main/utils/roles.py", "source_location": "L29", "id": "utils_roles_checkaccess", - "community": 21, + "community": 115, "norm_label": "checkaccess()" }, { @@ -4485,7 +4458,7 @@ "source_file": "main/utils/roles.py", "source_location": "L42", "id": "utils_roles_requirepermission", - "community": 21, + "community": 115, "norm_label": "requirepermission()" }, { @@ -4494,34 +4467,25 @@ "source_file": "main/utils/service_manager.py", "source_location": "L1", "id": "main_utils_service_manager_py", - "community": 95, + "community": 84, "norm_label": "service_manager.py" }, - { - "label": "ServiceManager", - "file_type": "code", - "source_file": "main/utils/service_manager.py", - "source_location": "L15", - "id": "utils_service_manager_servicemanager", - "community": 95, - "norm_label": "servicemanager" - }, { "label": "getApp()", "file_type": "code", "source_file": "main/utils/service_manager.py", - "source_location": "L19", + "source_location": "L17", "id": "utils_service_manager_getapp", - "community": 95, + "community": 84, "norm_label": "getapp()" }, { "label": "runAll()", "file_type": "code", "source_file": "main/utils/service_manager.py", - "source_location": "L42", + "source_location": "L40", "id": "utils_service_manager_runall", - "community": 95, + "community": 59, "norm_label": "runall()" }, { @@ -4530,7 +4494,7 @@ "source_file": "main/utils/models/loader.py", "source_location": "L1", "id": "main_utils_models_loader_py", - "community": 105, + "community": 84, "norm_label": "loader.py" }, { @@ -4539,7 +4503,7 @@ "source_file": "main/utils/models/loader.py", "source_location": "L12", "id": "models_loader_getembeddingmodel", - "community": 105, + "community": 84, "norm_label": "getembeddingmodel()" }, { @@ -6342,6 +6306,258 @@ "community": 89, "norm_label": "code:bash (git add todo.md)" }, + { + "label": "2026-08-15-stocks-api-perf.md", + "file_type": "document", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L1", + "id": "docs_superpowers_plans_2026_08_15_stocks_api_perf_md", + "community": 124, + "norm_label": "2026-08-15-stocks-api-perf.md" + }, + { + "label": "Stocks API Performance: Pre-Materialized Cache + Sync Handlers Implementation Plan", + "file_type": "document", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L1", + "id": "plans_2026_08_15_stocks_api_perf_stocks_api_performance_pre_materialized_cache_sync_handlers_implementation_plan", + "community": 124, + "norm_label": "stocks api performance: pre-materialized cache + sync handlers implementation plan" + }, + { + "label": "Global Constraints", + "file_type": "document", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L13", + "id": "plans_2026_08_15_stocks_api_perf_global_constraints", + "community": 124, + "norm_label": "global constraints" + }, + { + "label": "File Structure", + "file_type": "document", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L23", + "id": "plans_2026_08_15_stocks_api_perf_file_structure", + "community": 124, + "norm_label": "file structure" + }, + { + "label": "Task 1: TickerPayloadCache \u2014 pre-materialize per-ticker payloads at refresh", + "file_type": "document", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L35", + "id": "plans_2026_08_15_stocks_api_perf_task_1_tickerpayloadcache_pre_materialize_per_ticker_payloads_at_refresh", + "community": 124, + "norm_label": "task 1: tickerpayloadcache \u2014 pre-materialize per-ticker payloads at refresh" + }, + { + "label": "code:python (# tests/test_stocks_payload_cache.py)", + "file_type": "document", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L49", + "id": "plans_2026_08_15_stocks_api_perf_codeblock_1", + "community": 124, + "norm_label": "code:python (# tests/test_stocks_payload_cache.py)" + }, + { + "label": "code:python (def sanitizeNanValues(obj):)", + "file_type": "document", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L88", + "id": "plans_2026_08_15_stocks_api_perf_codeblock_2", + "community": 124, + "norm_label": "code:python (def sanitizenanvalues(obj):)" + }, + { + "label": "code:python (from main.app.stocks_api.util import JSON_COLUMNS, categoriz)", + "file_type": "document", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L118", + "id": "plans_2026_08_15_stocks_api_perf_codeblock_3", + "community": 124, + "norm_label": "code:python (from main.app.stocks_api.util import json_columns, categoriz)" + }, + { + "label": "code:python (def make_df():)", + "file_type": "document", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L131", + "id": "plans_2026_08_15_stocks_api_perf_codeblock_4", + "community": 124, + "norm_label": "code:python (def make_df():)" + }, + { + "label": "code:python (class TickerPayloadCache:)", + "file_type": "document", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L177", + "id": "plans_2026_08_15_stocks_api_perf_codeblock_5", + "community": 124, + "norm_label": "code:python (class tickerpayloadcache:)" + }, + { + "label": "code:python (self.tickerPayloads.refresh(df))", + "file_type": "document", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L228", + "id": "plans_2026_08_15_stocks_api_perf_codeblock_6", + "community": 124, + "norm_label": "code:python (self.tickerpayloads.refresh(df))" + }, + { + "label": "code:bash (git add main/app/stocks_api/util.py main/app/stocks_api/quer)", + "file_type": "document", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L244", + "id": "plans_2026_08_15_stocks_api_perf_codeblock_7", + "community": 124, + "norm_label": "code:bash (git add main/app/stocks_api/util.py main/app/stocks_api/quer)" + }, + { + "label": "Task 2: Fast paths in StocksQueryManager for default-shaped queries", + "file_type": "document", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L251", + "id": "plans_2026_08_15_stocks_api_perf_task_2_fast_paths_in_stocksquerymanager_for_default_shaped_queries", + "community": 124, + "norm_label": "task 2: fast paths in stocksquerymanager for default-shaped queries" + }, + { + "label": "code:python (def _query_manager():)", + "file_type": "document", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L263", + "id": "plans_2026_08_15_stocks_api_perf_codeblock_8", + "community": 124, + "norm_label": "code:python (def _query_manager():)" + }, + { + "label": "code:python (pc = self.cacheManager.tickerPayloads)", + "file_type": "document", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L315", + "id": "plans_2026_08_15_stocks_api_perf_codeblock_9", + "community": 124, + "norm_label": "code:python (pc = self.cachemanager.tickerpayloads)" + }, + { + "label": "code:python (pc = self.cacheManager.tickerPayloads)", + "file_type": "document", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L349", + "id": "plans_2026_08_15_stocks_api_perf_codeblock_10", + "community": 124, + "norm_label": "code:python (pc = self.cachemanager.tickerpayloads)" + }, + { + "label": "Task 3: Convert query handlers to sync def", + "file_type": "document", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L392", + "id": "plans_2026_08_15_stocks_api_perf_task_3_convert_query_handlers_to_sync_def", + "community": 124, + "norm_label": "task 3: convert query handlers to sync def" + }, + { + "label": "code:python (# tests/test_stocks_sync_handlers.py)", + "file_type": "document", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L405", + "id": "plans_2026_08_15_stocks_api_perf_codeblock_11", + "community": 124, + "norm_label": "code:python (# tests/test_stocks_sync_handlers.py)" + }, + { + "label": "code:bash (git add main/controller/stocksapi_controller.py main/app/sto)", + "file_type": "document", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L461", + "id": "plans_2026_08_15_stocks_api_perf_codeblock_12", + "community": 124, + "norm_label": "code:bash (git add main/controller/stocksapi_controller.py main/app/sto)" + }, + { + "label": "Task 4: Pre-parsed cotation date index \u2014 replace filterCotationColumn hot path", + "file_type": "document", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L468", + "id": "plans_2026_08_15_stocks_api_perf_task_4_pre_parsed_cotation_date_index_replace_filtercotationcolumn_hot_path", + "community": 124, + "norm_label": "task 4: pre-parsed cotation date index \u2014 replace filtercotationcolumn hot path" + }, + { + "label": "code:python (def test_payload_cache_cotation_index():)", + "file_type": "document", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L482", + "id": "plans_2026_08_15_stocks_api_perf_codeblock_13", + "community": 124, + "norm_label": "code:python (def test_payload_cache_cotation_index():)" + }, + { + "label": "code:python (self._cotations: dict[str, bytes] = {})", + "file_type": "document", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L512", + "id": "plans_2026_08_15_stocks_api_perf_codeblock_14", + "community": 124, + "norm_label": "code:python (self._cotations: dict[str, bytes] = {})" + }, + { + "label": "code:python (cotationCols = [\"TICKER\", \"NOME\", \"TIME\", \"COTACAO 10Y PADRA)", + "file_type": "document", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L519", + "id": "plans_2026_08_15_stocks_api_perf_codeblock_15", + "community": 124, + "norm_label": "code:python (cotationcols = [\"ticker\", \"nome\", \"time\", \"cotacao 10y padra)" + }, + { + "label": "code:python (self._cotations = cot)", + "file_type": "document", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L539", + "id": "plans_2026_08_15_stocks_api_perf_codeblock_16", + "community": 124, + "norm_label": "code:python (self._cotations = cot)" + }, + { + "label": "code:python (pc = self.cacheManager.tickerPayloads)", + "file_type": "document", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L548", + "id": "plans_2026_08_15_stocks_api_perf_codeblock_17", + "community": 124, + "norm_label": "code:python (pc = self.cachemanager.tickerpayloads)" + }, + { + "label": "code:bash (git add main/app/stocks_api/cache.py main/app/stocks_api/que)", + "file_type": "document", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L606", + "id": "plans_2026_08_15_stocks_api_perf_codeblock_18", + "community": 124, + "norm_label": "code:bash (git add main/app/stocks_api/cache.py main/app/stocks_api/que)" + }, + { + "label": "Task 5: Full verification + graphify update", + "file_type": "document", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L613", + "id": "plans_2026_08_15_stocks_api_perf_task_5_full_verification_graphify_update", + "community": 124, + "norm_label": "task 5: full verification + graphify update" + }, + { + "label": "Self-Review", + "file_type": "document", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L633", + "id": "plans_2026_08_15_stocks_api_perf_self_review", + "community": 124, + "norm_label": "self-review" + }, { "label": "2026-08-15-workspace-endpoints.md", "file_type": "document", @@ -6747,6 +6963,339 @@ "community": 55, "norm_label": "task 4: docker restart + e2e of /prometheus/chat/stream (performed by controller, not a subagent)" }, + { + "label": "_safe_filter()", + "file_type": "code", + "source_file": "main/app/prometheus/agent.py", + "source_location": "L26", + "community": 116, + "norm_label": "_safe_filter()", + "id": "prometheus_agent_safe_filter" + }, + { + "label": "FieldRegistry", + "file_type": "code", + "source_file": "main/app/prometheus/compact.py", + "source_location": "L89", + "community": 178, + "norm_label": "fieldregistry", + "id": "prometheus_compact_fieldregistry" + }, + { + "label": ".buildUrl()", + "file_type": "code", + "source_file": "main/app/prometheus/compact.py", + "source_location": "L94", + "community": 178, + "norm_label": ".buildurl()", + "id": "prometheus_compact_fieldregistry_buildurl" + }, + { + "label": ".fetchFields()", + "file_type": "code", + "source_file": "main/app/prometheus/compact.py", + "source_location": "L99", + "community": 178, + "norm_label": ".fetchfields()", + "id": "prometheus_compact_fieldregistry_fetchfields" + }, + { + "label": ".getFields()", + "file_type": "code", + "source_file": "main/app/prometheus/compact.py", + "source_location": "L120", + "community": 178, + "norm_label": ".getfields()", + "id": "prometheus_compact_fieldregistry_getfields" + }, + { + "label": ".buildMetricRegex()", + "file_type": "code", + "source_file": "main/app/prometheus/compact.py", + "source_location": "L127", + "community": 178, + "norm_label": ".buildmetricregex()", + "id": "prometheus_compact_fieldregistry_buildmetricregex" + }, + { + "label": ".getMetricRegex()", + "file_type": "code", + "source_file": "main/app/prometheus/compact.py", + "source_location": "L134", + "community": 178, + "norm_label": ".getmetricregex()", + "id": "prometheus_compact_fieldregistry_getmetricregex" + }, + { + "label": ".__init__()", + "file_type": "code", + "source_file": "main/app/prometheus/compact.py", + "source_location": "L222", + "community": 178, + "norm_label": ".__init__()", + "id": "prometheus_compact_prometheuscompactor_init" + }, + { + "label": "_getDb()", + "file_type": "code", + "source_file": "main/app/prometheus/tools.py", + "source_location": "L18", + "community": 86, + "norm_label": "_getdb()", + "id": "prometheus_tools_getdb" + }, + { + "label": "Search user's saved memories, preferences, and past analysis context. Use", + "file_type": "rationale", + "source_file": "main/app/prometheus/tools.py", + "source_location": "L27", + "community": 86, + "norm_label": "search user's saved memories, preferences, and past analysis context. use", + "id": "prometheus_tools_rationale_27" + }, + { + "label": "Store a memory about the user's preferences, analysis results, or feedback.", + "file_type": "rationale", + "source_file": "main/app/prometheus/tools.py", + "source_location": "L54", + "community": 86, + "norm_label": "store a memory about the user's preferences, analysis results, or feedback.", + "id": "prometheus_tools_rationale_54" + }, + { + "label": "Execute Python code in an isolated sandbox. Use for quantitative analysis,", + "file_type": "rationale", + "source_file": "main/app/prometheus/tools.py", + "source_location": "L92", + "community": 188, + "norm_label": "execute python code in an isolated sandbox. use for quantitative analysis,", + "id": "prometheus_tools_rationale_92" + }, + { + "label": "Read a file from the workspace. Args: path: Path to the file (e.", + "file_type": "rationale", + "source_file": "main/app/prometheus/tools.py", + "source_location": "L113", + "community": 152, + "norm_label": "read a file from the workspace. args: path: path to the file (e.", + "id": "prometheus_tools_rationale_113" + }, + { + "label": "Write a file to the workspace. Use this to save data files (CSV, JSON, scri", + "file_type": "rationale", + "source_file": "main/app/prometheus/tools.py", + "source_location": "L127", + "community": 152, + "norm_label": "write a file to the workspace. use this to save data files (csv, json, scri", + "id": "prometheus_tools_rationale_127" + }, + { + "label": "List files in the workspace directory. Args: path: Directory pat", + "file_type": "rationale", + "source_file": "main/app/prometheus/tools.py", + "source_location": "L143", + "community": 152, + "norm_label": "list files in the workspace directory. args: path: directory pat", + "id": "prometheus_tools_rationale_143" + }, + { + "label": "Get a download link for a workspace file to share with the user. Use this", + "file_type": "rationale", + "source_file": "main/app/prometheus/tools.py", + "source_location": "L156", + "community": 86, + "norm_label": "get a download link for a workspace file to share with the user. use this", + "id": "prometheus_tools_rationale_156" + }, + { + "label": "._executeQuery()", + "file_type": "code", + "source_file": "main/app/stocks_api/query.py", + "source_location": "L110", + "community": 63, + "norm_label": "._executequery()", + "id": "stocks_api_query_stocksquerymanager_executequery" + }, + { + "label": "Shared query pipeline for historical and fundamental endpoints.", + "file_type": "rationale", + "source_file": "main/app/stocks_api/query.py", + "source_location": "L123", + "community": 63, + "norm_label": "shared query pipeline for historical and fundamental endpoints.", + "id": "stocks_api_query_rationale_123" + }, + { + "label": "JSONBytesResponse", + "file_type": "code", + "source_file": "main/controller/stocksapi_controller.py", + "source_location": "L24", + "community": 81, + "norm_label": "jsonbytesresponse", + "id": "controller_stocksapi_controller_jsonbytesresponse" + }, + { + "label": "FastAPIResponse", + "file_type": "code", + "source_file": "", + "source_location": "", + "community": 81, + "norm_label": "fastapiresponse", + "id": "fastapiresponse" + }, + { + "label": ".render()", + "file_type": "code", + "source_file": "main/controller/stocksapi_controller.py", + "source_location": "L27", + "community": 81, + "norm_label": ".render()", + "id": "controller_stocksapi_controller_jsonbytesresponse_render" + }, + { + "label": "Discover available field names before querying /historical or /fundamental.", + "file_type": "rationale", + "source_file": "main/controller/stocksapi_controller.py", + "source_location": "L48", + "community": 140, + "norm_label": "discover available field names before querying /historical or /fundamental.", + "id": "controller_stocksapi_controller_rationale_48" + }, + { + "label": "Get year-based historical financial data for Brazilian B3 stocks. Returns", + "file_type": "rationale", + "source_file": "main/controller/stocksapi_controller.py", + "source_location": "L104", + "community": 475, + "norm_label": "get year-based historical financial data for brazilian b3 stocks. returns", + "id": "controller_stocksapi_controller_rationale_104" + }, + { + "label": "Get point-in-time fundamental/valuation data for Brazilian B3 stocks. Ret", + "file_type": "rationale", + "source_file": "main/controller/stocksapi_controller.py", + "source_location": "L169", + "community": 157, + "norm_label": "get point-in-time fundamental/valuation data for brazilian b3 stocks. ret", + "id": "controller_stocksapi_controller_rationale_169" + }, + { + "label": "Get 10-year daily price history (cotation) for Brazilian B3 stocks. Retur", + "file_type": "rationale", + "source_file": "main/controller/stocksapi_controller.py", + "source_location": "L237", + "community": 169, + "norm_label": "get 10-year daily price history (cotation) for brazilian b3 stocks. retur", + "id": "controller_stocksapi_controller_rationale_237" + }, + { + "label": "Get real-time price quotation for a single Brazilian B3 stock. Returns th", + "file_type": "rationale", + "source_file": "main/controller/stocksapi_controller.py", + "source_location": "L291", + "community": 81, + "norm_label": "get real-time price quotation for a single brazilian b3 stock. returns th", + "id": "controller_stocksapi_controller_rationale_291" + }, + { + "label": "ErrorResponse", + "file_type": "code", + "source_file": "main/utils/errors.py", + "source_location": "L12", + "community": 33, + "norm_label": "errorresponse", + "id": "utils_errors_errorresponse" + }, + { + "label": "BaseModel", + "file_type": "code", + "source_file": "", + "source_location": "", + "community": 33, + "norm_label": "basemodel", + "id": "basemodel" + }, + { + "label": "ServiceManager", + "file_type": "code", + "source_file": "main/utils/service_manager.py", + "source_location": "L15", + "community": 84, + "norm_label": "servicemanager", + "id": "utils_service_manager_servicemanager" + }, + { + "label": "onExtractionDone()", + "file_type": "code", + "source_file": "main/app/prometheus/agent.py", + "source_location": "L26", + "community": 116, + "norm_label": "onextractiondone()", + "id": "prometheus_agent_onextractiondone" + }, + { + "label": "spawnExtraction()", + "file_type": "code", + "source_file": "main/app/prometheus/agent.py", + "source_location": "L34", + "community": 116, + "norm_label": "spawnextraction()", + "id": "prometheus_agent_spawnextraction" + }, + { + "label": "_forward()", + "file_type": "code", + "source_file": "main/controller/prometheus_controller.py", + "source_location": "L205", + "community": 84, + "norm_label": "_forward()", + "id": "controller_prometheus_controller_forward" + }, + { + "label": "Discover available field names before querying /historical or /fundamental.", + "file_type": "rationale", + "source_file": "main/controller/stocksapi_controller.py", + "source_location": "L47", + "community": 140, + "norm_label": "discover available field names before querying /historical or /fundamental.", + "id": "controller_stocksapi_controller_rationale_47" + }, + { + "label": "Get year-based historical financial data for Brazilian B3 stocks. Returns", + "file_type": "rationale", + "source_file": "main/controller/stocksapi_controller.py", + "source_location": "L103", + "community": 475, + "norm_label": "get year-based historical financial data for brazilian b3 stocks. returns", + "id": "controller_stocksapi_controller_rationale_103" + }, + { + "label": "Get point-in-time fundamental/valuation data for Brazilian B3 stocks. Ret", + "file_type": "rationale", + "source_file": "main/controller/stocksapi_controller.py", + "source_location": "L167", + "community": 157, + "norm_label": "get point-in-time fundamental/valuation data for brazilian b3 stocks. ret", + "id": "controller_stocksapi_controller_rationale_167" + }, + { + "label": "Get 10-year daily price history (cotation) for Brazilian B3 stocks. Retur", + "file_type": "rationale", + "source_file": "main/controller/stocksapi_controller.py", + "source_location": "L234", + "community": 169, + "norm_label": "get 10-year daily price history (cotation) for brazilian b3 stocks. retur", + "id": "controller_stocksapi_controller_rationale_234" + }, + { + "label": "Get real-time price quotation for a single Brazilian B3 stock. Returns th", + "file_type": "rationale", + "source_file": "main/controller/stocksapi_controller.py", + "source_location": "L288", + "community": 81, + "norm_label": "get real-time price quotation for a single brazilian b3 stock. returns th", + "id": "controller_stocksapi_controller_rationale_288" + }, { "label": "uploadWorkspaceFile()", "file_type": "code", @@ -6761,7 +7310,7 @@ "file_type": "code", "source_file": "frontend/src/api.test.js", "source_location": "L1", - "community": 5, + "community": 216, "norm_label": "api.test.js", "id": "frontend_src_api_test_js" }, @@ -6770,7 +7319,7 @@ "file_type": "code", "source_file": "frontend/src/api.test.js", "source_location": "L4", - "community": 5, + "community": 216, "norm_label": "sseresponse()", "id": "src_api_test_sseresponse" }, @@ -6779,7 +7328,7 @@ "file_type": "code", "source_file": "frontend/src/api.test.js", "source_location": "L23", - "community": 5, + "community": 216, "norm_label": "fetchmock", "id": "src_api_test_fetchmock" }, @@ -6788,7 +7337,7 @@ "file_type": "code", "source_file": "frontend/src/api.test.js", "source_location": "L28", - "community": 5, + "community": 216, "norm_label": "onchunk", "id": "src_api_test_onchunk" }, @@ -6797,7 +7346,7 @@ "file_type": "code", "source_file": "frontend/src/api.test.js", "source_location": "L29", - "community": 5, + "community": 216, "norm_label": "ondone", "id": "src_api_test_ondone" }, @@ -6806,7 +7355,7 @@ "file_type": "code", "source_file": "frontend/src/api.test.js", "source_location": "L30", - "community": 5, + "community": 216, "norm_label": "oncursor", "id": "src_api_test_oncursor" }, @@ -6815,7 +7364,7 @@ "file_type": "code", "source_file": "frontend/src/api.test.js", "source_location": "L31", - "community": 5, + "community": 216, "norm_label": "onsession", "id": "src_api_test_onsession" }, @@ -6824,7 +7373,7 @@ "file_type": "code", "source_file": "frontend/src/api.test.js", "source_location": "L113", - "community": 5, + "community": 216, "norm_label": "file", "id": "src_api_test_file" }, @@ -6860,7 +7409,7 @@ "file_type": "rationale", "source_file": "main/app/prometheus/tools.py", "source_location": "L145", - "community": 188, + "community": 86, "norm_label": "get a download link for a workspace file to share with the user. use this", "id": "prometheus_tools_rationale_145" }, @@ -7175,19 +7724,10 @@ "file_type": "rationale", "source_file": "main/controller/stocksapi_controller.py", "source_location": "L105", - "community": 81, + "community": 475, "norm_label": "get year-based historical financial data for brazilian b3 stocks. returns", "id": "controller_stocksapi_controller_rationale_105" }, - { - "label": "Get point-in-time fundamental/valuation data for Brazilian B3 stocks. Ret", - "file_type": "rationale", - "source_file": "main/controller/stocksapi_controller.py", - "source_location": "L169", - "community": 504, - "norm_label": "get point-in-time fundamental/valuation data for brazilian b3 stocks. ret", - "id": "controller_stocksapi_controller_rationale_169" - }, { "label": "Get 10-year daily price history (cotation) for Brazilian B3 stocks. Retur", "file_type": "rationale", @@ -7202,7 +7742,7 @@ "file_type": "rationale", "source_file": "main/controller/stocksapi_controller.py", "source_location": "L290", - "community": 124, + "community": 81, "norm_label": "get real-time price quotation for a single brazilian b3 stock. returns th", "id": "controller_stocksapi_controller_rationale_290" }, @@ -7220,7 +7760,7 @@ "file_type": "code", "source_file": "frontend/src/components/AgentLoop.jsx", "source_location": "L3", - "community": 5, + "community": 211, "norm_label": "toolchip()", "id": "components_agentloop_toolchip" }, @@ -7238,7 +7778,7 @@ "file_type": "code", "source_file": "main/app/stocks_api/response_cache.py", "source_location": "L1", - "community": 63, + "community": 518, "norm_label": "response_cache.py", "id": "main_app_stocks_api_response_cache_py" }, @@ -7247,7 +7787,7 @@ "file_type": "code", "source_file": "main/app/stocks_api/response_cache.py", "source_location": "L19", - "community": 63, + "community": 518, "norm_label": "responsecache", "id": "stocks_api_response_cache_responsecache" }, @@ -7256,7 +7796,7 @@ "file_type": "code", "source_file": "main/app/stocks_api/response_cache.py", "source_location": "L20", - "community": 63, + "community": 518, "norm_label": ".__init__()", "id": "stocks_api_response_cache_responsecache_init" }, @@ -7265,7 +7805,7 @@ "file_type": "code", "source_file": "main/app/stocks_api/response_cache.py", "source_location": "L29", - "community": 63, + "community": 518, "norm_label": ".makekey()", "id": "stocks_api_response_cache_responsecache_makekey" }, @@ -7274,7 +7814,7 @@ "file_type": "code", "source_file": "main/app/stocks_api/response_cache.py", "source_location": "L34", - "community": 63, + "community": 518, "norm_label": ".get()", "id": "stocks_api_response_cache_responsecache_get" }, @@ -7296,21 +7836,12 @@ "norm_label": "createsession()", "id": "controller_prometheus_controller_createsession" }, - { - "label": "Discover available field names before querying /historical or /fundamental.", - "file_type": "rationale", - "source_file": "main/controller/stocksapi_controller.py", - "source_location": "L40", - "community": 140, - "norm_label": "discover available field names before querying /historical or /fundamental.", - "id": "controller_stocksapi_controller_rationale_40" - }, { "label": "Get year-based historical financial data for Brazilian B3 stocks. Returns", "file_type": "rationale", "source_file": "main/controller/stocksapi_controller.py", "source_location": "L95", - "community": 81, + "community": 475, "norm_label": "get year-based historical financial data for brazilian b3 stocks. returns", "id": "controller_stocksapi_controller_rationale_95" }, @@ -7319,7 +7850,7 @@ "file_type": "rationale", "source_file": "main/controller/stocksapi_controller.py", "source_location": "L165", - "community": 504, + "community": 157, "norm_label": "get point-in-time fundamental/valuation data for brazilian b3 stocks. ret", "id": "controller_stocksapi_controller_rationale_165" }, @@ -7337,7 +7868,7 @@ "file_type": "rationale", "source_file": "main/controller/stocksapi_controller.py", "source_location": "L296", - "community": 124, + "community": 81, "norm_label": "get real-time price quotation for a single brazilian b3 stock. returns th", "id": "controller_stocksapi_controller_rationale_296" }, @@ -7364,7 +7895,7 @@ "file_type": "rationale", "source_file": "main/controller/stocksapi_controller.py", "source_location": "L85", - "community": 81, + "community": 475, "norm_label": "get year-based historical financial data for brazilian b3 stocks. returns", "id": "controller_stocksapi_controller_rationale_85" }, @@ -7373,7 +7904,7 @@ "file_type": "rationale", "source_file": "main/controller/stocksapi_controller.py", "source_location": "L155", - "community": 504, + "community": 157, "norm_label": "get point-in-time fundamental/valuation data for brazilian b3 stocks. ret", "id": "controller_stocksapi_controller_rationale_155" }, @@ -7391,7 +7922,7 @@ "file_type": "rationale", "source_file": "main/controller/stocksapi_controller.py", "source_location": "L286", - "community": 124, + "community": 81, "norm_label": "get real-time price quotation for a single brazilian b3 stock. returns th", "id": "controller_stocksapi_controller_rationale_286" }, @@ -8138,7 +8669,7 @@ "file_type": "code", "source_file": "main/controller/user_controller.py", "source_location": "L26", - "community": 78, + "community": 501, "norm_label": "upgradetodeveloperstarter()", "id": "controller_user_controller_upgradetodeveloperstarter" }, @@ -8147,7 +8678,7 @@ "file_type": "code", "source_file": "main/controller/user_controller.py", "source_location": "L38", - "community": 78, + "community": 501, "norm_label": "upgradetodeveloperenterprise()", "id": "controller_user_controller_upgradetodeveloperenterprise" }, @@ -9128,7 +9659,7 @@ "file_type": "code", "source_file": "main/app/prometheus/state.py", "source_location": "L14", - "community": 497, + "community": 63, "norm_label": ".set()", "id": "prometheus_state_harnessstate_set" }, @@ -9191,7 +9722,7 @@ "file_type": "code", "source_file": "main/app/prometheus/tools.py", "source_location": "L104", - "community": 100, + "community": 188, "norm_label": "set_state()", "id": "prometheus_tools_set_state" }, @@ -9200,7 +9731,7 @@ "file_type": "rationale", "source_file": "main/app/prometheus/tools.py", "source_location": "L105", - "community": 100, + "community": 188, "norm_label": "store a value in the harness state for this session. use this to save inter", "id": "prometheus_tools_rationale_105" }, @@ -9209,7 +9740,7 @@ "file_type": "rationale", "source_file": "main/app/prometheus/tools.py", "source_location": "L123", - "community": 490, + "community": 188, "norm_label": "execute python code in an isolated sandbox. use for quantitative analysis,", "id": "prometheus_tools_rationale_123" }, @@ -9533,7 +10064,7 @@ "file_type": "rationale", "source_file": "main/controller/stocksapi_controller.py", "source_location": "L82", - "community": 81, + "community": 475, "norm_label": "get year-based historical financial data for brazilian b3 stocks. returns", "id": "controller_stocksapi_controller_rationale_82" }, @@ -9542,7 +10073,7 @@ "file_type": "rationale", "source_file": "main/controller/stocksapi_controller.py", "source_location": "L144", - "community": 504, + "community": 157, "norm_label": "get point-in-time fundamental/valuation data for brazilian b3 stocks. ret", "id": "controller_stocksapi_controller_rationale_144" }, @@ -9560,7 +10091,7 @@ "file_type": "rationale", "source_file": "main/controller/stocksapi_controller.py", "source_location": "L261", - "community": 124, + "community": 81, "norm_label": "get real-time price quotation for a single brazilian b3 stock. returns th", "id": "controller_stocksapi_controller_rationale_261" }, @@ -9686,7 +10217,7 @@ "file_type": "code", "source_file": "main/app/prometheus/memory.py", "source_location": "L48", - "community": 53, + "community": 115, "norm_label": "applyupdate()", "id": "prometheus_memory_applyupdate" }, @@ -9785,7 +10316,7 @@ "file_type": "code", "source_file": "main/app/prometheus/tokenizer.py", "source_location": "L1", - "community": 495, + "community": 80, "norm_label": "tokenizer.py", "id": "main_app_prometheus_tokenizer_py" }, @@ -9794,7 +10325,7 @@ "file_type": "code", "source_file": "main/app/prometheus/tokenizer.py", "source_location": "L10", - "community": 495, + "community": 80, "norm_label": "_get_tokenizer()", "id": "prometheus_tokenizer_get_tokenizer" }, @@ -9803,7 +10334,7 @@ "file_type": "code", "source_file": "main/app/prometheus/tokenizer.py", "source_location": "L17", - "community": 495, + "community": 80, "norm_label": "counttokens()", "id": "prometheus_tokenizer_counttokens" }, @@ -9812,7 +10343,7 @@ "file_type": "rationale", "source_file": "main/app/prometheus/tokenizer.py", "source_location": "L18", - "community": 495, + "community": 80, "norm_label": "count tokens using gemini's local tokenizer. accurate for portuguese.", "id": "prometheus_tokenizer_rationale_18" }, @@ -10595,7 +11126,7 @@ "file_type": "rationale", "source_file": "main/app/prometheus/tools.py", "source_location": "L18", - "community": 486, + "community": 86, "norm_label": "search user's saved memories, preferences, and past analysis context. use", "id": "prometheus_tools_rationale_18" }, @@ -10604,7 +11135,7 @@ "file_type": "rationale", "source_file": "main/app/prometheus/tools.py", "source_location": "L44", - "community": 491, + "community": 86, "norm_label": "store a memory about the user's preferences, analysis results, or feedback.", "id": "prometheus_tools_rationale_44" }, @@ -10622,7 +11153,7 @@ "file_type": "rationale", "source_file": "main/app/prometheus/tools.py", "source_location": "L96", - "community": 100, + "community": 188, "norm_label": "store a value in the harness state for this session. use this to save inter", "id": "prometheus_tools_rationale_96" }, @@ -10631,7 +11162,7 @@ "file_type": "rationale", "source_file": "main/app/prometheus/tools.py", "source_location": "L114", - "community": 490, + "community": 188, "norm_label": "execute python code in an isolated sandbox. use for quantitative analysis,", "id": "prometheus_tools_rationale_114" }, @@ -11360,7 +11891,7 @@ "file_type": "rationale", "source_file": "main/controller/stocksapi_controller.py", "source_location": "L66", - "community": 81, + "community": 475, "norm_label": "get year-based historical financial data for brazilian b3 stocks. returns", "id": "controller_stocksapi_controller_rationale_66" }, @@ -11369,7 +11900,7 @@ "file_type": "rationale", "source_file": "main/controller/stocksapi_controller.py", "source_location": "L124", - "community": 504, + "community": 157, "norm_label": "get point-in-time fundamental/valuation data for brazilian b3 stocks. ret", "id": "controller_stocksapi_controller_rationale_124" }, @@ -11387,7 +11918,7 @@ "file_type": "rationale", "source_file": "main/controller/stocksapi_controller.py", "source_location": "L233", - "community": 124, + "community": 81, "norm_label": "get real-time price quotation for a single brazilian b3 stock. returns th", "id": "controller_stocksapi_controller_rationale_233" }, @@ -11612,7 +12143,7 @@ "file_type": "code", "source_file": "frontend/tests/api.test.js", "source_location": "L1", - "community": 5, + "community": 505, "norm_label": "api.test.js", "id": "frontend_tests_api_test_js" }, @@ -11621,7 +12152,7 @@ "file_type": "code", "source_file": "frontend/tests/api.test.js", "source_location": "L4", - "community": 5, + "community": 505, "norm_label": "createmockreadablestream()", "id": "tests_api_test_createmockreadablestream" }, @@ -11630,7 +12161,7 @@ "file_type": "code", "source_file": "frontend/tests/api.test.js", "source_location": "L22", - "community": 5, + "community": 505, "norm_label": "onchunk", "id": "tests_api_test_onchunk" }, @@ -11639,7 +12170,7 @@ "file_type": "code", "source_file": "frontend/tests/api.test.js", "source_location": "L23", - "community": 5, + "community": 505, "norm_label": "ondone", "id": "tests_api_test_ondone" }, @@ -11648,7 +12179,7 @@ "file_type": "code", "source_file": "frontend/tests/api.test.js", "source_location": "L24", - "community": 5, + "community": 505, "norm_label": "onerror", "id": "tests_api_test_onerror" }, @@ -11657,7 +12188,7 @@ "file_type": "code", "source_file": "frontend/tests/api.test.js", "source_location": "L117", - "community": 5, + "community": 505, "norm_label": "events", "id": "tests_api_test_events" }, @@ -11666,7 +12197,7 @@ "file_type": "code", "source_file": "frontend/tests/App.test.jsx", "source_location": "L1", - "community": 5, + "community": 506, "norm_label": "app.test.jsx", "id": "frontend_tests_app_test_jsx" }, @@ -11675,7 +12206,7 @@ "file_type": "code", "source_file": "frontend/tests/App.test.jsx", "source_location": "L40", - "community": 5, + "community": 506, "norm_label": "chunks", "id": "tests_app_test_chunks" }, @@ -11684,7 +12215,7 @@ "file_type": "code", "source_file": "frontend/tests/App.test.jsx", "source_location": "L66", - "community": 5, + "community": 506, "norm_label": "receivedchunks", "id": "tests_app_test_receivedchunks" }, @@ -11693,7 +12224,7 @@ "file_type": "code", "source_file": "frontend/tests/App.test.jsx", "source_location": "L68", - "community": 5, + "community": 506, "norm_label": "events", "id": "tests_app_test_events" }, @@ -11702,7 +12233,7 @@ "file_type": "code", "source_file": "frontend/tests/App.test.jsx", "source_location": "L84", - "community": 5, + "community": 506, "norm_label": "onchunk", "id": "tests_app_test_onchunk" }, @@ -11711,7 +12242,7 @@ "file_type": "code", "source_file": "frontend/tests/App.test.jsx", "source_location": "L85", - "community": 5, + "community": 506, "norm_label": "ondone", "id": "tests_app_test_ondone" }, @@ -11720,7 +12251,7 @@ "file_type": "code", "source_file": "frontend/tests/App.test.jsx", "source_location": "L92", - "community": 5, + "community": 506, "norm_label": "fulltext", "id": "tests_app_test_fulltext" }, @@ -11729,7 +12260,7 @@ "file_type": "code", "source_file": "frontend/tests/MdocMessage.test.jsx", "source_location": "L1", - "community": 5, + "community": 211, "norm_label": "mdocmessage.test.jsx", "id": "frontend_tests_mdocmessage_test_jsx" }, @@ -11738,7 +12269,7 @@ "file_type": "code", "source_file": "frontend/tests/MdocMessage.test.jsx", "source_location": "L7", - "community": 5, + "community": 211, "norm_label": "nodes", "id": "tests_mdocmessage_test_nodes" }, @@ -11747,7 +12278,7 @@ "file_type": "code", "source_file": "frontend/tests/MdocMessage.test.jsx", "source_location": "L22", - "community": 5, + "community": 211, "norm_label": "{ container }", "id": "tests_mdocmessage_test_container" }, @@ -11756,7 +12287,7 @@ "file_type": "code", "source_file": "frontend/tests/MdocMessage.test.jsx", "source_location": "L40", - "community": 5, + "community": 211, "norm_label": "{ rerender }", "id": "tests_mdocmessage_test_rerender" }, @@ -16886,7 +17417,7 @@ "file_type": "code", "source_file": "tests/conftest.py", "source_location": "L81", - "community": 99, + "community": 527, "norm_label": "stocks_http_client()", "id": "tests_conftest_stocks_http_client" }, @@ -16895,7 +17426,7 @@ "file_type": "code", "source_file": "tests/conftest.py", "source_location": "L106", - "community": 99, + "community": 527, "norm_label": "client()", "id": "tests_conftest_client" }, @@ -16922,7 +17453,7 @@ "file_type": "rationale", "source_file": "tests/conftest.py", "source_location": "L82", - "community": 99, + "community": 527, "norm_label": "testclient with stocks router + verifyapikey + getcurrentuser overrides.", "id": "tests_conftest_rationale_82" }, @@ -16931,7 +17462,7 @@ "file_type": "rationale", "source_file": "tests/conftest.py", "source_location": "L107", - "community": 99, + "community": 527, "norm_label": "testclient with all routers mounted \u2014 no lifespan (no db/service init). o", "id": "tests_conftest_rationale_107" }, @@ -17039,7 +17570,7 @@ "file_type": "code", "source_file": "tests/test_agent_state_integration.py", "source_location": "L7", - "community": 186, + "community": 99, "norm_label": "testbuildsystempromptstate", "id": "tests_test_agent_state_integration_testbuildsystempromptstate" }, @@ -17048,7 +17579,7 @@ "file_type": "code", "source_file": "tests/test_agent_state_integration.py", "source_location": "L8", - "community": 186, + "community": 99, "norm_label": ".test_build_system_prompt_no_state()", "id": "tests_test_agent_state_integration_testbuildsystempromptstate_test_build_system_prompt_no_state" }, @@ -17057,7 +17588,7 @@ "file_type": "code", "source_file": "tests/test_agent_state_integration.py", "source_location": "L13", - "community": 186, + "community": 99, "norm_label": ".test_build_system_prompt_with_state()", "id": "tests_test_agent_state_integration_testbuildsystempromptstate_test_build_system_prompt_with_state" }, @@ -17066,7 +17597,7 @@ "file_type": "code", "source_file": "tests/test_agent_state_integration.py", "source_location": "L21", - "community": 186, + "community": 99, "norm_label": ".test_build_system_prompt_empty_state()", "id": "tests_test_agent_state_integration_testbuildsystempromptstate_test_build_system_prompt_empty_state" }, @@ -17075,7 +17606,7 @@ "file_type": "code", "source_file": "tests/test_agent_state_integration.py", "source_location": "L27", - "community": 186, + "community": 99, "norm_label": ".test_build_system_prompt_state_after_memories()", "id": "tests_test_agent_state_integration_testbuildsystempromptstate_test_build_system_prompt_state_after_memories" }, @@ -17084,7 +17615,7 @@ "file_type": "code", "source_file": "tests/test_agent_state_integration.py", "source_location": "L37", - "community": 186, + "community": 99, "norm_label": ".test_build_system_prompt_multiple_state_entries()", "id": "tests_test_agent_state_integration_testbuildsystempromptstate_test_build_system_prompt_multiple_state_entries" }, @@ -17165,7 +17696,7 @@ "file_type": "rationale", "source_file": "tests/test_agent_state_integration.py", "source_location": "L9", - "community": 186, + "community": 99, "norm_label": "system prompt should work without state parameter.", "id": "tests_test_agent_state_integration_rationale_9" }, @@ -17174,7 +17705,7 @@ "file_type": "rationale", "source_file": "tests/test_agent_state_integration.py", "source_location": "L14", - "community": 186, + "community": 99, "norm_label": "system prompt should include state context when provided.", "id": "tests_test_agent_state_integration_rationale_14" }, @@ -17183,7 +17714,7 @@ "file_type": "rationale", "source_file": "tests/test_agent_state_integration.py", "source_location": "L22", - "community": 186, + "community": 99, "norm_label": "system prompt should not include state section when empty.", "id": "tests_test_agent_state_integration_rationale_22" }, @@ -17192,7 +17723,7 @@ "file_type": "rationale", "source_file": "tests/test_agent_state_integration.py", "source_location": "L28", - "community": 186, + "community": 99, "norm_label": "state section should appear after memories section.", "id": "tests_test_agent_state_integration_rationale_28" }, @@ -17201,7 +17732,7 @@ "file_type": "rationale", "source_file": "tests/test_agent_state_integration.py", "source_location": "L38", - "community": 186, + "community": 99, "norm_label": "all state entries should appear in the prompt.", "id": "tests_test_agent_state_integration_rationale_38" }, @@ -17543,7 +18074,7 @@ "file_type": "code", "source_file": "tests/test_auth_util.py", "source_location": "L1", - "community": 43, + "community": 498, "norm_label": "test_auth_util.py", "id": "tests_test_auth_util_py" }, @@ -17615,7 +18146,7 @@ "file_type": "code", "source_file": "tests/test_auth_util.py", "source_location": "L43", - "community": 58, + "community": 43, "norm_label": ".test_create_access_token_default_expiry()", "id": "tests_test_auth_util_testauthutil_test_create_access_token_default_expiry" }, @@ -17633,7 +18164,7 @@ "file_type": "code", "source_file": "tests/test_auth_util.py", "source_location": "L61", - "community": 58, + "community": 43, "norm_label": ".test_create_access_token_contains_data()", "id": "tests_test_auth_util_testauthutil_test_create_access_token_contains_data" }, @@ -17732,7 +18263,7 @@ "file_type": "code", "source_file": "tests/test_config.py", "source_location": "L1", - "community": 102, + "community": 500, "norm_label": "test_config.py", "id": "tests_test_config_py" }, @@ -18164,7 +18695,7 @@ "file_type": "code", "source_file": "tests/test_controllers_coverage.py", "source_location": "L257", - "community": 120, + "community": 21, "norm_label": "testlogoutendpoint", "id": "tests_test_controllers_coverage_testlogoutendpoint" }, @@ -18497,7 +19028,7 @@ "file_type": "code", "source_file": "tests/test_controllers_coverage.py", "source_location": "L805", - "community": 21, + "community": 221, "norm_label": "testrevokeallsessions", "id": "tests_test_controllers_coverage_testrevokeallsessions" }, @@ -18506,7 +19037,7 @@ "file_type": "code", "source_file": "tests/test_controllers_coverage.py", "source_location": "L808", - "community": 120, + "community": 221, "norm_label": ".test_revoke_all_sessions()", "id": "tests_test_controllers_coverage_testrevokeallsessions_test_revoke_all_sessions" }, @@ -18794,7 +19325,7 @@ "file_type": "code", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1229", - "community": 213, + "community": 137, "norm_label": "testaddroletouser", "id": "tests_test_controllers_coverage_testaddroletouser" }, @@ -18803,7 +19334,7 @@ "file_type": "code", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1232", - "community": 214, + "community": 137, "norm_label": ".test_add_role_success()", "id": "tests_test_controllers_coverage_testaddroletouser_test_add_role_success" }, @@ -18812,7 +19343,7 @@ "file_type": "code", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1249", - "community": 215, + "community": 493, "norm_label": ".test_add_role_already_has_role()", "id": "tests_test_controllers_coverage_testaddroletouser_test_add_role_already_has_role" }, @@ -18857,7 +19388,7 @@ "file_type": "code", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1307", - "community": 216, + "community": 493, "norm_label": ".test_get_current_user_session_revoked()", "id": "tests_test_controllers_coverage_testgetcurrentuser_test_get_current_user_session_revoked" }, @@ -18866,7 +19397,7 @@ "file_type": "code", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1323", - "community": 146, + "community": 493, "norm_label": ".test_get_current_user_not_found()", "id": "tests_test_controllers_coverage_testgetcurrentuser_test_get_current_user_not_found" }, @@ -18875,7 +19406,7 @@ "file_type": "code", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1340", - "community": 197, + "community": 493, "norm_label": ".test_get_current_user_generic_exception()", "id": "tests_test_controllers_coverage_testgetcurrentuser_test_get_current_user_generic_exception" }, @@ -18884,7 +19415,7 @@ "file_type": "code", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1357", - "community": 208, + "community": 493, "norm_label": ".test_get_current_user_no_session_id()", "id": "tests_test_controllers_coverage_testgetcurrentuser_test_get_current_user_no_session_id" }, @@ -18893,7 +19424,7 @@ "file_type": "code", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1381", - "community": 263, + "community": 78, "norm_label": "testhashpasswordempty", "id": "tests_test_controllers_coverage_testhashpasswordempty" }, @@ -18902,7 +19433,7 @@ "file_type": "code", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1384", - "community": 263, + "community": 78, "norm_label": ".test_empty_password_raises()", "id": "tests_test_controllers_coverage_testhashpasswordempty_test_empty_password_raises" }, @@ -18911,7 +19442,7 @@ "file_type": "code", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1391", - "community": 263, + "community": 78, "norm_label": "testverifyaccesstoken", "id": "tests_test_controllers_coverage_testverifyaccesstoken" }, @@ -18920,7 +19451,7 @@ "file_type": "code", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1394", - "community": 263, + "community": 78, "norm_label": ".test_expired_token()", "id": "tests_test_controllers_coverage_testverifyaccesstoken_test_expired_token" }, @@ -18929,7 +19460,7 @@ "file_type": "code", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1410", - "community": 78, + "community": 131, "norm_label": ".test_invalid_token()", "id": "tests_test_controllers_coverage_testverifyaccesstoken_test_invalid_token" }, @@ -19109,7 +19640,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L258", - "community": 120, + "community": 21, "norm_label": "covers lines 107, 109-130, 133: logout token extraction and revocation.", "id": "tests_test_controllers_coverage_rationale_258" }, @@ -19127,7 +19658,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L281", - "community": 120, + "community": 21, "norm_label": "covers lines 111-113: token extracted from authorization bearer header.", "id": "tests_test_controllers_coverage_rationale_281" }, @@ -19370,7 +19901,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L806", - "community": 21, + "community": 221, "norm_label": "covers lines 143, 145, 147-148: post /user/sessions/revoke-all.", "id": "tests_test_controllers_coverage_rationale_806" }, @@ -19379,7 +19910,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L809", - "community": 120, + "community": 221, "norm_label": "covers lines 143, 145, 147-148.", "id": "tests_test_controllers_coverage_rationale_809" }, @@ -19613,7 +20144,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1230", - "community": 213, + "community": 137, "norm_label": "covers lines 13, 17, 19-20, 22-27: usermanager.addroletouser.", "id": "tests_test_controllers_coverage_rationale_1230" }, @@ -19622,7 +20153,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1233", - "community": 214, + "community": 137, "norm_label": "covers lines 17, 22-27: user found, role not present, role added.", "id": "tests_test_controllers_coverage_rationale_1233" }, @@ -19631,7 +20162,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1250", - "community": 215, + "community": 493, "norm_label": "covers line 27: user already has the role.", "id": "tests_test_controllers_coverage_rationale_1250" }, @@ -19667,7 +20198,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1308", - "community": 216, + "community": 493, "norm_label": "covers lines 42-44: session validation fails.", "id": "tests_test_controllers_coverage_rationale_1308" }, @@ -19676,7 +20207,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1324", - "community": 146, + "community": 493, "norm_label": "covers lines 48-49: user not in db.", "id": "tests_test_controllers_coverage_rationale_1324" }, @@ -19685,7 +20216,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1341", - "community": 197, + "community": 493, "norm_label": "covers lines 65-67: unexpected exception.", "id": "tests_test_controllers_coverage_rationale_1341" }, @@ -19694,7 +20225,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1358", - "community": 208, + "community": 493, "norm_label": "covers lines 37-38, 46, 51, 58 (sessionid is none): skips session validation.", "id": "tests_test_controllers_coverage_rationale_1358" }, @@ -19703,7 +20234,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1382", - "community": 263, + "community": 78, "norm_label": "covers line 16: empty password raises valueerror.", "id": "tests_test_controllers_coverage_rationale_1382" }, @@ -19712,7 +20243,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1392", - "community": 263, + "community": 78, "norm_label": "covers lines 45-51: verifyaccesstoken with expired and invalid tokens.", "id": "tests_test_controllers_coverage_rationale_1392" }, @@ -19721,7 +20252,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1395", - "community": 263, + "community": 78, "norm_label": "covers lines 48-49: jwt.expiredsignatureerror.", "id": "tests_test_controllers_coverage_rationale_1395" }, @@ -19730,7 +20261,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1411", - "community": 78, + "community": 131, "norm_label": "covers lines 50-51: jwt.invalidtokenerror.", "id": "tests_test_controllers_coverage_rationale_1411" }, @@ -21170,7 +21701,7 @@ "file_type": "code", "source_file": "tests/test_logging_config_coverage.py", "source_location": "L103", - "community": 94, + "community": 122, "norm_label": "testsetuplogging", "id": "tests_test_logging_config_coverage_testsetuplogging" }, @@ -21179,7 +21710,7 @@ "file_type": "code", "source_file": "tests/test_logging_config_coverage.py", "source_location": "L105", - "community": 94, + "community": 122, "norm_label": "test_setup_discord_handler_enabled()", "id": "tests_test_logging_config_coverage_test_setup_discord_handler_enabled" }, @@ -21188,7 +21719,7 @@ "file_type": "code", "source_file": "tests/test_logging_config_coverage.py", "source_location": "L114", - "community": 94, + "community": 122, "norm_label": "test_setup_discord_handler_disabled()", "id": "tests_test_logging_config_coverage_test_setup_discord_handler_disabled" }, @@ -21206,7 +21737,7 @@ "file_type": "code", "source_file": "tests/test_memory_dedup.py", "source_location": "L1", - "community": 131, + "community": 146, "norm_label": "test_memory_dedup.py", "id": "tests_test_memory_dedup_py" }, @@ -21215,7 +21746,7 @@ "file_type": "code", "source_file": "tests/test_memory_dedup.py", "source_location": "L8", - "community": 131, + "community": 146, "norm_label": "_create_memory()", "id": "tests_test_memory_dedup_create_memory" }, @@ -21224,7 +21755,7 @@ "file_type": "code", "source_file": "tests/test_memory_dedup.py", "source_location": "L12", - "community": 131, + "community": 146, "norm_label": "_count_memories()", "id": "tests_test_memory_dedup_count_memories" }, @@ -21233,7 +21764,7 @@ "file_type": "code", "source_file": "tests/test_memory_dedup.py", "source_location": "L20", - "community": 131, + "community": 146, "norm_label": "_get_memory()", "id": "tests_test_memory_dedup_get_memory" }, @@ -21242,7 +21773,7 @@ "file_type": "code", "source_file": "tests/test_memory_dedup.py", "source_location": "L28", - "community": 131, + "community": 146, "norm_label": "testexactsamekeyupdates", "id": "tests_test_memory_dedup_testexactsamekeyupdates" }, @@ -21251,7 +21782,7 @@ "file_type": "code", "source_file": "tests/test_memory_dedup.py", "source_location": "L29", - "community": 131, + "community": 146, "norm_label": ".test_exact_same_key_updates()", "id": "tests_test_memory_dedup_testexactsamekeyupdates_test_exact_same_key_updates" }, @@ -21260,7 +21791,7 @@ "file_type": "code", "source_file": "tests/test_memory_dedup.py", "source_location": "L36", - "community": 131, + "community": 146, "norm_label": "testsimilarkeymerges", "id": "tests_test_memory_dedup_testsimilarkeymerges" }, @@ -21269,7 +21800,7 @@ "file_type": "code", "source_file": "tests/test_memory_dedup.py", "source_location": "L37", - "community": 131, + "community": 146, "norm_label": ".test_similar_key_merges()", "id": "tests_test_memory_dedup_testsimilarkeymerges_test_similar_key_merges" }, @@ -21278,7 +21809,7 @@ "file_type": "code", "source_file": "tests/test_memory_dedup.py", "source_location": "L46", - "community": 131, + "community": 146, "norm_label": "testdifferentkeysnomerge", "id": "tests_test_memory_dedup_testdifferentkeysnomerge" }, @@ -21287,7 +21818,7 @@ "file_type": "code", "source_file": "tests/test_memory_dedup.py", "source_location": "L47", - "community": 131, + "community": 146, "norm_label": ".test_different_keys_no_merge()", "id": "tests_test_memory_dedup_testdifferentkeysnomerge_test_different_keys_no_merge" }, @@ -21296,7 +21827,7 @@ "file_type": "code", "source_file": "tests/test_memory_dedup.py", "source_location": "L55", - "community": 131, + "community": 146, "norm_label": "testmergeboostsscore", "id": "tests_test_memory_dedup_testmergeboostsscore" }, @@ -21305,7 +21836,7 @@ "file_type": "code", "source_file": "tests/test_memory_dedup.py", "source_location": "L56", - "community": 131, + "community": 146, "norm_label": ".test_merge_boosts_score()", "id": "tests_test_memory_dedup_testmergeboostsscore_test_merge_boosts_score" }, @@ -21314,7 +21845,7 @@ "file_type": "code", "source_file": "tests/test_memory_dedup.py", "source_location": "L64", - "community": 131, + "community": 146, "norm_label": "testmergeincrementsaccess", "id": "tests_test_memory_dedup_testmergeincrementsaccess" }, @@ -21323,7 +21854,7 @@ "file_type": "code", "source_file": "tests/test_memory_dedup.py", "source_location": "L65", - "community": 131, + "community": 146, "norm_label": ".test_merge_increments_access()", "id": "tests_test_memory_dedup_testmergeincrementsaccess_test_merge_increments_access" }, @@ -21332,7 +21863,7 @@ "file_type": "code", "source_file": "tests/test_memory_dedup.py", "source_location": "L73", - "community": 131, + "community": 146, "norm_label": "testthresholdboundary", "id": "tests_test_memory_dedup_testthresholdboundary" }, @@ -21341,7 +21872,7 @@ "file_type": "code", "source_file": "tests/test_memory_dedup.py", "source_location": "L74", - "community": 131, + "community": 146, "norm_label": ".test_threshold_boundary()", "id": "tests_test_memory_dedup_testthresholdboundary_test_threshold_boundary" }, @@ -21350,7 +21881,7 @@ "file_type": "rationale", "source_file": "tests/test_memory_dedup.py", "source_location": "L38", - "community": 131, + "community": 146, "norm_label": "keys with jaccard > 0.8 should merge.", "id": "tests_test_memory_dedup_rationale_38" }, @@ -21359,7 +21890,7 @@ "file_type": "rationale", "source_file": "tests/test_memory_dedup.py", "source_location": "L48", - "community": 131, + "community": 146, "norm_label": "keys with low similarity should not merge.", "id": "tests_test_memory_dedup_rationale_48" }, @@ -21368,7 +21899,7 @@ "file_type": "rationale", "source_file": "tests/test_memory_dedup.py", "source_location": "L75", - "community": 131, + "community": 146, "norm_label": "keys with jaccard <= 0.8 should not merge.", "id": "tests_test_memory_dedup_rationale_75" }, @@ -21458,7 +21989,7 @@ "file_type": "code", "source_file": "tests/test_memory_maintenance.py", "source_location": "L84", - "community": 54, + "community": 146, "norm_label": "testarchive", "id": "tests_test_memory_maintenance_testarchive" }, @@ -21575,7 +22106,7 @@ "file_type": "code", "source_file": "tests/test_memory_maintenance.py", "source_location": "L170", - "community": 131, + "community": 146, "norm_label": "testemptydatabase", "id": "tests_test_memory_maintenance_testemptydatabase" }, @@ -21692,7 +22223,7 @@ "file_type": "code", "source_file": "tests/test_memory_manager.py", "source_location": "L1", - "community": 131, + "community": 146, "norm_label": "test_memory_manager.py", "id": "tests_test_memory_manager_py" }, @@ -21701,7 +22232,7 @@ "file_type": "code", "source_file": "tests/test_memory_manager.py", "source_location": "L8", - "community": 131, + "community": 146, "norm_label": "testgetmemorylimit", "id": "tests_test_memory_manager_testgetmemorylimit" }, @@ -21710,7 +22241,7 @@ "file_type": "code", "source_file": "tests/test_memory_manager.py", "source_location": "L9", - "community": 131, + "community": 146, "norm_label": ".test_basic_user()", "id": "tests_test_memory_manager_testgetmemorylimit_test_basic_user" }, @@ -21719,7 +22250,7 @@ "file_type": "code", "source_file": "tests/test_memory_manager.py", "source_location": "L12", - "community": 131, + "community": 146, "norm_label": ".test_premium_user()", "id": "tests_test_memory_manager_testgetmemorylimit_test_premium_user" }, @@ -21728,7 +22259,7 @@ "file_type": "code", "source_file": "tests/test_memory_manager.py", "source_location": "L15", - "community": 131, + "community": 146, "norm_label": ".test_admin_user()", "id": "tests_test_memory_manager_testgetmemorylimit_test_admin_user" }, @@ -21737,7 +22268,7 @@ "file_type": "code", "source_file": "tests/test_memory_manager.py", "source_location": "L19", - "community": 131, + "community": 146, "norm_label": "testupsertmemory", "id": "tests_test_memory_manager_testupsertmemory" }, @@ -21746,7 +22277,7 @@ "file_type": "code", "source_file": "tests/test_memory_manager.py", "source_location": "L20", - "community": 131, + "community": 146, "norm_label": ".test_create()", "id": "tests_test_memory_manager_testupsertmemory_test_create" }, @@ -21755,7 +22286,7 @@ "file_type": "code", "source_file": "tests/test_memory_manager.py", "source_location": "L33", - "community": 131, + "community": 146, "norm_label": ".test_update()", "id": "tests_test_memory_manager_testupsertmemory_test_update" }, @@ -21764,7 +22295,7 @@ "file_type": "code", "source_file": "tests/test_memory_manager.py", "source_location": "L40", - "community": 131, + "community": 146, "norm_label": ".test_unchanged()", "id": "tests_test_memory_manager_testupsertmemory_test_unchanged" }, @@ -21773,7 +22304,7 @@ "file_type": "code", "source_file": "tests/test_memory_manager.py", "source_location": "L45", - "community": 131, + "community": 146, "norm_label": ".test_limit_enforcement()", "id": "tests_test_memory_manager_testupsertmemory_test_limit_enforcement" }, @@ -21782,7 +22313,7 @@ "file_type": "code", "source_file": "tests/test_memory_manager.py", "source_location": "L59", - "community": 131, + "community": 146, "norm_label": ".test_limit_not_enforced_without_roles()", "id": "tests_test_memory_manager_testupsertmemory_test_limit_not_enforced_without_roles" }, @@ -21791,7 +22322,7 @@ "file_type": "code", "source_file": "tests/test_memory_manager.py", "source_location": "L66", - "community": 131, + "community": 146, "norm_label": ".test_upsert_with_embedding()", "id": "tests_test_memory_manager_testupsertmemory_test_upsert_with_embedding" }, @@ -21800,7 +22331,7 @@ "file_type": "code", "source_file": "tests/test_memory_manager.py", "source_location": "L80", - "community": 131, + "community": 146, "norm_label": "testcountmemories", "id": "tests_test_memory_manager_testcountmemories" }, @@ -21809,7 +22340,7 @@ "file_type": "code", "source_file": "tests/test_memory_manager.py", "source_location": "L81", - "community": 131, + "community": 146, "norm_label": ".test_counts_active()", "id": "tests_test_memory_manager_testcountmemories_test_counts_active" }, @@ -21818,7 +22349,7 @@ "file_type": "code", "source_file": "tests/test_memory_manager.py", "source_location": "L86", - "community": 131, + "community": 146, "norm_label": ".test_excludes_archived()", "id": "tests_test_memory_manager_testcountmemories_test_excludes_archived" }, @@ -21827,7 +22358,7 @@ "file_type": "code", "source_file": "tests/test_memory_manager.py", "source_location": "L94", - "community": 131, + "community": 146, "norm_label": ".test_counts_per_user()", "id": "tests_test_memory_manager_testcountmemories_test_counts_per_user" }, @@ -21836,7 +22367,7 @@ "file_type": "code", "source_file": "tests/test_memory_manager.py", "source_location": "L101", - "community": 131, + "community": 146, "norm_label": "testgetusermemories", "id": "tests_test_memory_manager_testgetusermemories" }, @@ -21845,7 +22376,7 @@ "file_type": "code", "source_file": "tests/test_memory_manager.py", "source_location": "L102", - "community": 131, + "community": 146, "norm_label": ".test_returns_memories()", "id": "tests_test_memory_manager_testgetusermemories_test_returns_memories" }, @@ -21854,7 +22385,7 @@ "file_type": "code", "source_file": "tests/test_memory_manager.py", "source_location": "L109", - "community": 131, + "community": 146, "norm_label": ".test_pagination()", "id": "tests_test_memory_manager_testgetusermemories_test_pagination" }, @@ -21863,7 +22394,7 @@ "file_type": "code", "source_file": "tests/test_memory_manager.py", "source_location": "L115", - "community": 131, + "community": 146, "norm_label": ".test_excludes_archived()", "id": "tests_test_memory_manager_testgetusermemories_test_excludes_archived" }, @@ -21872,7 +22403,7 @@ "file_type": "code", "source_file": "tests/test_memory_manager.py", "source_location": "L125", - "community": 131, + "community": 146, "norm_label": "testdeletememory", "id": "tests_test_memory_manager_testdeletememory" }, @@ -21881,7 +22412,7 @@ "file_type": "code", "source_file": "tests/test_memory_manager.py", "source_location": "L126", - "community": 131, + "community": 146, "norm_label": ".test_soft_delete()", "id": "tests_test_memory_manager_testdeletememory_test_soft_delete" }, @@ -21890,7 +22421,7 @@ "file_type": "code", "source_file": "tests/test_memory_manager.py", "source_location": "L132", - "community": 131, + "community": 146, "norm_label": ".test_delete_nonexistent()", "id": "tests_test_memory_manager_testdeletememory_test_delete_nonexistent" }, @@ -21899,7 +22430,7 @@ "file_type": "code", "source_file": "tests/test_memory_manager.py", "source_location": "L135", - "community": 131, + "community": 146, "norm_label": ".test_delete_wrong_user()", "id": "tests_test_memory_manager_testdeletememory_test_delete_wrong_user" }, @@ -21908,7 +22439,7 @@ "file_type": "code", "source_file": "tests/test_memory_manager.py", "source_location": "L142", - "community": 131, + "community": 146, "norm_label": "testsearchfulltext", "id": "tests_test_memory_manager_testsearchfulltext" }, @@ -21917,7 +22448,7 @@ "file_type": "code", "source_file": "tests/test_memory_manager.py", "source_location": "L143", - "community": 131, + "community": 146, "norm_label": ".test_search_after_create()", "id": "tests_test_memory_manager_testsearchfulltext_test_search_after_create" }, @@ -22016,7 +22547,7 @@ "file_type": "code", "source_file": "tests/test_memory_tools_wiring.py", "source_location": "L64", - "community": 497, + "community": 49, "norm_label": "testtoolregistry", "id": "tests_test_memory_tools_wiring_testtoolregistry" }, @@ -22025,7 +22556,7 @@ "file_type": "code", "source_file": "tests/test_memory_tools_wiring.py", "source_location": "L67", - "community": 497, + "community": 49, "norm_label": ".test_registry_contains_memory_tools()", "id": "tests_test_memory_tools_wiring_testtoolregistry_test_registry_contains_memory_tools" }, @@ -22034,7 +22565,7 @@ "file_type": "code", "source_file": "tests/test_memory_tools_wiring.py", "source_location": "L71", - "community": 497, + "community": 49, "norm_label": ".test_registry_values_are_callable()", "id": "tests_test_memory_tools_wiring_testtoolregistry_test_registry_values_are_callable" }, @@ -22043,7 +22574,7 @@ "file_type": "code", "source_file": "tests/test_memory_tools_wiring.py", "source_location": "L75", - "community": 497, + "community": 49, "norm_label": ".test_registry_matches_tool_names()", "id": "tests_test_memory_tools_wiring_testtoolregistry_test_registry_matches_tool_names" }, @@ -22052,7 +22583,7 @@ "file_type": "code", "source_file": "tests/test_memory_tools_wiring.py", "source_location": "L79", - "community": 474, + "community": 49, "norm_label": "testmakechatincludesmemorytools", "id": "tests_test_memory_tools_wiring_testmakechatincludesmemorytools" }, @@ -22070,7 +22601,7 @@ "file_type": "code", "source_file": "tests/test_memory_tools_wiring.py", "source_location": "L112", - "community": 512, + "community": 49, "norm_label": "testdispatchroutesmemorytools", "id": "tests_test_memory_tools_wiring_testdispatchroutesmemorytools" }, @@ -22124,7 +22655,7 @@ "file_type": "rationale", "source_file": "tests/test_memory_tools_wiring.py", "source_location": "L65", - "community": 497, + "community": 49, "norm_label": "tool_registry pattern must work correctly.", "id": "tests_test_memory_tools_wiring_rationale_65" }, @@ -22133,7 +22664,7 @@ "file_type": "rationale", "source_file": "tests/test_memory_tools_wiring.py", "source_location": "L80", - "community": 474, + "community": 49, "norm_label": "makechat must include memory_tools alongside mcp sessions.", "id": "tests_test_memory_tools_wiring_rationale_80" }, @@ -22142,7 +22673,7 @@ "file_type": "rationale", "source_file": "tests/test_memory_tools_wiring.py", "source_location": "L113", - "community": 512, + "community": 49, "norm_label": "dispatchtoolcall must route memory tool names via tool_registry.", "id": "tests_test_memory_tools_wiring_rationale_113" }, @@ -22727,7 +23258,7 @@ "file_type": "code", "source_file": "tests/test_pagination.py", "source_location": "L39", - "community": 157, + "community": 490, "norm_label": "testinlinepagination", "id": "tests_test_pagination_testinlinepagination" }, @@ -22736,7 +23267,7 @@ "file_type": "code", "source_file": "tests/test_pagination.py", "source_location": "L40", - "community": 157, + "community": 490, "norm_label": ".test_defaults()", "id": "tests_test_pagination_testinlinepagination_test_defaults" }, @@ -22745,7 +23276,7 @@ "file_type": "code", "source_file": "tests/test_pagination.py", "source_location": "L48", - "community": 157, + "community": 490, "norm_label": ".test_custom_limit()", "id": "tests_test_pagination_testinlinepagination_test_custom_limit" }, @@ -22754,7 +23285,7 @@ "file_type": "code", "source_file": "tests/test_pagination.py", "source_location": "L54", - "community": 157, + "community": 490, "norm_label": ".test_custom_offset()", "id": "tests_test_pagination_testinlinepagination_test_custom_offset" }, @@ -22763,7 +23294,7 @@ "file_type": "code", "source_file": "tests/test_pagination.py", "source_location": "L61", - "community": 157, + "community": 490, "norm_label": ".test_limit_and_offset()", "id": "tests_test_pagination_testinlinepagination_test_limit_and_offset" }, @@ -22772,7 +23303,7 @@ "file_type": "code", "source_file": "tests/test_pagination.py", "source_location": "L69", - "community": 157, + "community": 490, "norm_label": ".test_limit_exceeds_max_rejected()", "id": "tests_test_pagination_testinlinepagination_test_limit_exceeds_max_rejected" }, @@ -22781,7 +23312,7 @@ "file_type": "code", "source_file": "tests/test_pagination.py", "source_location": "L73", - "community": 157, + "community": 490, "norm_label": ".test_limit_zero_rejected()", "id": "tests_test_pagination_testinlinepagination_test_limit_zero_rejected" }, @@ -22790,7 +23321,7 @@ "file_type": "code", "source_file": "tests/test_pagination.py", "source_location": "L77", - "community": 157, + "community": 490, "norm_label": ".test_negative_offset_rejected()", "id": "tests_test_pagination_testinlinepagination_test_negative_offset_rejected" }, @@ -22799,7 +23330,7 @@ "file_type": "code", "source_file": "tests/test_pagination.py", "source_location": "L81", - "community": 157, + "community": 490, "norm_label": ".test_offset_beyond_total()", "id": "tests_test_pagination_testinlinepagination_test_offset_beyond_total" }, @@ -22808,7 +23339,7 @@ "file_type": "code", "source_file": "tests/test_pagination.py", "source_location": "L86", - "community": 157, + "community": 490, "norm_label": ".test_limit_equals_max()", "id": "tests_test_pagination_testinlinepagination_test_limit_equals_max" }, @@ -23546,7 +24077,7 @@ "file_type": "code", "source_file": "tests/test_prometheus_tools.py", "source_location": "L44", - "community": 211, + "community": 100, "norm_label": "testmemorytoolfunctions", "id": "tests_test_prometheus_tools_testmemorytoolfunctions" }, @@ -23555,7 +24086,7 @@ "file_type": "code", "source_file": "tests/test_prometheus_tools.py", "source_location": "L45", - "community": 211, + "community": 100, "norm_label": ".test_search_memory_has_docstring()", "id": "tests_test_prometheus_tools_testmemorytoolfunctions_test_search_memory_has_docstring" }, @@ -23564,7 +24095,7 @@ "file_type": "code", "source_file": "tests/test_prometheus_tools.py", "source_location": "L49", - "community": 211, + "community": 100, "norm_label": ".test_save_memory_has_docstring()", "id": "tests_test_prometheus_tools_testmemorytoolfunctions_test_save_memory_has_docstring" }, @@ -23573,7 +24104,7 @@ "file_type": "code", "source_file": "tests/test_prometheus_tools.py", "source_location": "L53", - "community": 211, + "community": 100, "norm_label": ".test_search_memory_signature()", "id": "tests_test_prometheus_tools_testmemorytoolfunctions_test_search_memory_signature" }, @@ -23582,7 +24113,7 @@ "file_type": "code", "source_file": "tests/test_prometheus_tools.py", "source_location": "L59", - "community": 211, + "community": 100, "norm_label": ".test_save_memory_signature()", "id": "tests_test_prometheus_tools_testmemorytoolfunctions_test_save_memory_signature" }, @@ -23591,7 +24122,7 @@ "file_type": "code", "source_file": "tests/test_prometheus_tools.py", "source_location": "L66", - "community": 211, + "community": 100, "norm_label": ".test_search_memory_has_type_hints()", "id": "tests_test_prometheus_tools_testmemorytoolfunctions_test_search_memory_has_type_hints" }, @@ -23600,7 +24131,7 @@ "file_type": "code", "source_file": "tests/test_prometheus_tools.py", "source_location": "L71", - "community": 211, + "community": 100, "norm_label": ".test_save_memory_has_type_hints()", "id": "tests_test_prometheus_tools_testmemorytoolfunctions_test_save_memory_has_type_hints" }, @@ -23609,7 +24140,7 @@ "file_type": "code", "source_file": "tests/test_prometheus_tools.py", "source_location": "L77", - "community": 211, + "community": 100, "norm_label": ".test_memory_tools_is_list_of_callables()", "id": "tests_test_prometheus_tools_testmemorytoolfunctions_test_memory_tools_is_list_of_callables" }, @@ -23618,7 +24149,7 @@ "file_type": "code", "source_file": "tests/test_prometheus_tools.py", "source_location": "L83", - "community": 211, + "community": 100, "norm_label": ".test_memory_tool_names_unchanged()", "id": "tests_test_prometheus_tools_testmemorytoolfunctions_test_memory_tool_names_unchanged" }, @@ -23708,7 +24239,7 @@ "file_type": "code", "source_file": "tests/test_prometheus_tools.py", "source_location": "L126", - "community": 518, + "community": 100, "norm_label": "testgeminicompatibility", "id": "tests_test_prometheus_tools_testgeminicompatibility" }, @@ -23726,7 +24257,7 @@ "file_type": "code", "source_file": "tests/test_prometheus_tools.py", "source_location": "L135", - "community": 518, + "community": 100, "norm_label": ".test_no_harnessstate_in_any_signature()", "id": "tests_test_prometheus_tools_testgeminicompatibility_test_no_harnessstate_in_any_signature" }, @@ -23780,7 +24311,7 @@ "file_type": "rationale", "source_file": "tests/test_prometheus_tools.py", "source_location": "L127", - "community": 518, + "community": 100, "norm_label": "every function in tool_registry must have gemini-safe signatures. custom cl", "id": "tests_test_prometheus_tools_rationale_127" }, @@ -23789,7 +24320,7 @@ "file_type": "rationale", "source_file": "tests/test_prometheus_tools.py", "source_location": "L136", - "community": 518, + "community": 100, "norm_label": "regression: harnessstate must never leak into tool signatures.", "id": "tests_test_prometheus_tools_rationale_136" }, @@ -24059,7 +24590,7 @@ "file_type": "code", "source_file": "tests/test_request_id.py", "source_location": "L1", - "community": 150, + "community": 33, "norm_label": "test_request_id.py", "id": "tests_test_request_id_py" }, @@ -24068,7 +24599,7 @@ "file_type": "code", "source_file": "tests/test_request_id.py", "source_location": "L14", - "community": 150, + "community": 33, "norm_label": "app()", "id": "tests_test_request_id_app" }, @@ -24077,7 +24608,7 @@ "file_type": "code", "source_file": "tests/test_request_id.py", "source_location": "L30", - "community": 150, + "community": 33, "norm_label": "client()", "id": "tests_test_request_id_client" }, @@ -24086,7 +24617,7 @@ "file_type": "code", "source_file": "tests/test_request_id.py", "source_location": "L34", - "community": 150, + "community": 33, "norm_label": "testrequestidmiddleware", "id": "tests_test_request_id_testrequestidmiddleware" }, @@ -24095,7 +24626,7 @@ "file_type": "code", "source_file": "tests/test_request_id.py", "source_location": "L35", - "community": 150, + "community": 33, "norm_label": ".test_generates_uuid_when_no_header()", "id": "tests_test_request_id_testrequestidmiddleware_test_generates_uuid_when_no_header" }, @@ -24104,7 +24635,7 @@ "file_type": "code", "source_file": "tests/test_request_id.py", "source_location": "L44", - "community": 150, + "community": 33, "norm_label": ".test_returns_generated_uuid_in_body()", "id": "tests_test_request_id_testrequestidmiddleware_test_returns_generated_uuid_in_body" }, @@ -24113,7 +24644,7 @@ "file_type": "code", "source_file": "tests/test_request_id.py", "source_location": "L51", - "community": 150, + "community": 33, "norm_label": ".test_uses_client_provided_request_id()", "id": "tests_test_request_id_testrequestidmiddleware_test_uses_client_provided_request_id" }, @@ -24122,7 +24653,7 @@ "file_type": "code", "source_file": "tests/test_request_id.py", "source_location": "L57", - "community": 150, + "community": 33, "norm_label": ".test_response_header_matches_request()", "id": "tests_test_request_id_testrequestidmiddleware_test_response_header_matches_request" }, @@ -24131,7 +24662,7 @@ "file_type": "code", "source_file": "tests/test_request_id.py", "source_location": "L62", - "community": 150, + "community": 33, "norm_label": ".test_different_requests_get_different_ids()", "id": "tests_test_request_id_testrequestidmiddleware_test_different_requests_get_different_ids" }, @@ -24140,7 +24671,7 @@ "file_type": "code", "source_file": "tests/test_request_id.py", "source_location": "L67", - "community": 150, + "community": 33, "norm_label": ".test_context_var_available_in_route()", "id": "tests_test_request_id_testrequestidmiddleware_test_context_var_available_in_route" }, @@ -24149,7 +24680,7 @@ "file_type": "code", "source_file": "tests/test_request_id.py", "source_location": "L72", - "community": 150, + "community": 33, "norm_label": ".test_empty_x_request_id_header_generates_uuid()", "id": "tests_test_request_id_testrequestidmiddleware_test_empty_x_request_id_header_generates_uuid" }, @@ -24158,7 +24689,7 @@ "file_type": "code", "source_file": "tests/test_request_id.py", "source_location": "L81", - "community": 150, + "community": 33, "norm_label": ".test_middleware_preserves_response_body()", "id": "tests_test_request_id_testrequestidmiddleware_test_middleware_preserves_response_body" }, @@ -24770,7 +25301,7 @@ "file_type": "code", "source_file": "tests/test_sandbox_persistence.py", "source_location": "L1", - "community": 86, + "community": 4, "norm_label": "test_sandbox_persistence.py", "id": "tests_test_sandbox_persistence_py" }, @@ -24779,7 +25310,7 @@ "file_type": "code", "source_file": "tests/test_sandbox_persistence.py", "source_location": "L9", - "community": 86, + "community": 4, "norm_label": "_mock_forgevm()", "id": "tests_test_sandbox_persistence_mock_forgevm" }, @@ -24824,7 +25355,7 @@ "file_type": "code", "source_file": "tests/test_sandbox_persistence.py", "source_location": "L62", - "community": 86, + "community": 4, "norm_label": "testsandboxpersistence", "id": "tests_test_sandbox_persistence_testsandboxpersistence" }, @@ -24833,7 +25364,7 @@ "file_type": "code", "source_file": "tests/test_sandbox_persistence.py", "source_location": "L65", - "community": 86, + "community": 4, "norm_label": "test_get_or_create_creates_new_when_no_existing()", "id": "tests_test_sandbox_persistence_test_get_or_create_creates_new_when_no_existing" }, @@ -24842,7 +25373,7 @@ "file_type": "code", "source_file": "tests/test_sandbox_persistence.py", "source_location": "L77", - "community": 86, + "community": 4, "norm_label": "test_get_or_create_reuses_existing()", "id": "tests_test_sandbox_persistence_test_get_or_create_reuses_existing" }, @@ -24860,7 +25391,7 @@ "file_type": "code", "source_file": "tests/test_sandbox_persistence.py", "source_location": "L126", - "community": 86, + "community": 4, "norm_label": "test_sync_to_sandbox()", "id": "tests_test_sandbox_persistence_test_sync_to_sandbox" }, @@ -24869,7 +25400,7 @@ "file_type": "code", "source_file": "tests/test_sandbox_persistence.py", "source_location": "L145", - "community": 86, + "community": 4, "norm_label": "test_sync_from_sandbox()", "id": "tests_test_sandbox_persistence_test_sync_from_sandbox" }, @@ -24878,7 +25409,7 @@ "file_type": "code", "source_file": "tests/test_sandbox_persistence.py", "source_location": "L165", - "community": 86, + "community": 4, "norm_label": "test_sync_to_sandbox_empty_workspace()", "id": "tests_test_sandbox_persistence_test_sync_to_sandbox_empty_workspace" }, @@ -24887,7 +25418,7 @@ "file_type": "rationale", "source_file": "tests/test_sandbox_persistence.py", "source_location": "L10", - "community": 86, + "community": 4, "norm_label": "wire up mock forgevm asyncclient that returns sandbox with all methods.", "id": "tests_test_sandbox_persistence_rationale_10" }, @@ -25571,7 +26102,7 @@ "file_type": "code", "source_file": "tests/test_state_tools.py", "source_location": "L97", - "community": 100, + "community": 188, "norm_label": "test_set_state_no_state()", "id": "tests_test_state_tools_test_set_state_no_state" }, @@ -26129,7 +26660,7 @@ "file_type": "code", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L433", - "community": 212, + "community": 3, "norm_label": ".test_deserialize_non_nan_float()", "id": "tests_test_stocks_api_coverage_testdeserializejsoncolumns_test_deserialize_non_nan_float" }, @@ -26282,7 +26813,7 @@ "file_type": "code", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L591", - "community": 509, + "community": 28, "norm_label": ".test_historical_with_fields()", "id": "tests_test_stocks_api_coverage_testqueryhistorical_test_historical_with_fields" }, @@ -26381,7 +26912,7 @@ "file_type": "code", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L686", - "community": 28, + "community": 504, "norm_label": ".test_historical_with_date_range()", "id": "tests_test_stocks_api_coverage_testqueryhistorical_test_historical_with_date_range" }, @@ -26480,7 +27011,7 @@ "file_type": "code", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L766", - "community": 17, + "community": 39, "norm_label": ".test_fundamental_with_invalid_date()", "id": "tests_test_stocks_api_coverage_testqueryfundamental_test_fundamental_with_invalid_date" }, @@ -26534,7 +27065,7 @@ "file_type": "code", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L819", - "community": 17, + "community": 39, "norm_label": ".test_fundamental_empty_search_string_no_dedup()", "id": "tests_test_stocks_api_coverage_testqueryfundamental_test_fundamental_empty_search_string_no_dedup" }, @@ -26543,7 +27074,7 @@ "file_type": "code", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L828", - "community": 17, + "community": 39, "norm_label": ".test_fundamental_no_time_column()", "id": "tests_test_stocks_api_coverage_testqueryfundamental_test_fundamental_no_time_column" }, @@ -26588,7 +27119,7 @@ "file_type": "code", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L890", - "community": 39, + "community": 17, "norm_label": ".test_fundamental_search_fallback_string_match()", "id": "tests_test_stocks_api_coverage_testqueryfundamental_test_fundamental_search_fallback_string_match" }, @@ -26606,7 +27137,7 @@ "file_type": "code", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L913", - "community": 519, + "community": 197, "norm_label": ".test_fundamental_excludes_cotacao_10y()", "id": "tests_test_stocks_api_coverage_testqueryfundamental_test_fundamental_excludes_cotacao_10y" }, @@ -26786,7 +27317,7 @@ "file_type": "code", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L1139", - "community": 501, + "community": 503, "norm_label": ".test_cotations_http_route()", "id": "tests_test_stocks_api_coverage_testquerycotations_test_cotations_http_route" }, @@ -27083,7 +27614,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L434", - "community": 212, + "community": 3, "norm_label": "non-json-dict/list string is left as-is.", "id": "tests_test_stocks_api_coverage_rationale_434" }, @@ -27137,7 +27668,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L592", - "community": 509, + "community": 28, "norm_label": "pass field name without year (how categorizecolumns returns them).", "id": "tests_test_stocks_api_coverage_rationale_592" }, @@ -27182,7 +27713,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L687", - "community": 28, + "community": 504, "norm_label": "historical query with a year range.", "id": "tests_test_stocks_api_coverage_rationale_687" }, @@ -27218,7 +27749,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L767", - "community": 17, + "community": 39, "norm_label": "invalid date -> inner 400 passes through (not wrapped as 500).", "id": "tests_test_stocks_api_coverage_rationale_767" }, @@ -27227,7 +27758,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L820", - "community": 17, + "community": 39, "norm_label": "search.strip() == '' should still dedup (line 181).", "id": "tests_test_stocks_api_coverage_rationale_820" }, @@ -27236,7 +27767,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L829", - "community": 17, + "community": 39, "norm_label": "dataframe without time column.", "id": "tests_test_stocks_api_coverage_rationale_829" }, @@ -27272,7 +27803,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L883", - "community": 17, + "community": 39, "norm_label": "multiple search terms with tickerindex.", "id": "tests_test_stocks_api_coverage_rationale_883" }, @@ -27281,7 +27812,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L891", - "community": 39, + "community": 17, "norm_label": "search with no index match falls back to string startswith.", "id": "tests_test_stocks_api_coverage_rationale_891" }, @@ -27299,7 +27830,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L914", - "community": 519, + "community": 197, "norm_label": "cotacao 10y padrao and cotacao 10y ajustada belong to /cotations, not /fundament", "id": "tests_test_stocks_api_coverage_rationale_914" }, @@ -27353,7 +27884,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L1140", - "community": 501, + "community": 503, "norm_label": "hit the actual /stocks/cotations http endpoint with adjusted=false.", "id": "tests_test_stocks_api_coverage_rationale_1140" }, @@ -29072,7 +29603,7 @@ "file_type": "code", "source_file": "frontend/src/components/AgentLoop.jsx", "source_location": "L3", - "community": 5, + "community": 211, "norm_label": "toolcard()", "id": "components_agentloop_toolcard" }, @@ -30359,7 +30890,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1223", - "community": 213, + "community": 137, "norm_label": "covers lines 13, 17, 19-20, 22-27: usermanager.addroletouser.", "id": "tests_test_controllers_coverage_rationale_1223" }, @@ -30368,7 +30899,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1226", - "community": 214, + "community": 137, "norm_label": "covers lines 17, 22-27: user found, role not present, role added.", "id": "tests_test_controllers_coverage_rationale_1226" }, @@ -30377,7 +30908,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1243", - "community": 215, + "community": 493, "norm_label": "covers line 27: user already has the role.", "id": "tests_test_controllers_coverage_rationale_1243" }, @@ -30404,7 +30935,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1301", - "community": 216, + "community": 493, "norm_label": "covers lines 42-44: session validation fails.", "id": "tests_test_controllers_coverage_rationale_1301" }, @@ -30413,7 +30944,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1317", - "community": 146, + "community": 493, "norm_label": "covers lines 48-49: user not in db.", "id": "tests_test_controllers_coverage_rationale_1317" }, @@ -30422,7 +30953,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1334", - "community": 197, + "community": 493, "norm_label": "covers lines 65-67: unexpected exception.", "id": "tests_test_controllers_coverage_rationale_1334" }, @@ -30431,7 +30962,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1351", - "community": 208, + "community": 493, "norm_label": "covers lines 37-38, 46, 51, 58 (sessionid is none): skips session validation.", "id": "tests_test_controllers_coverage_rationale_1351" }, @@ -30440,7 +30971,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1375", - "community": 263, + "community": 78, "norm_label": "covers line 16: empty password raises valueerror.", "id": "tests_test_controllers_coverage_rationale_1375" }, @@ -30449,7 +30980,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1385", - "community": 263, + "community": 78, "norm_label": "covers lines 45-51: verifyaccesstoken with expired and invalid tokens.", "id": "tests_test_controllers_coverage_rationale_1385" }, @@ -30458,7 +30989,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1388", - "community": 263, + "community": 78, "norm_label": "covers lines 48-49: jwt.expiredsignatureerror.", "id": "tests_test_controllers_coverage_rationale_1388" }, @@ -30467,7 +30998,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1404", - "community": 78, + "community": 131, "norm_label": "covers lines 50-51: jwt.invalidtokenerror.", "id": "tests_test_controllers_coverage_rationale_1404" }, @@ -30593,7 +31124,7 @@ "file_type": "rationale", "source_file": "main/app/prometheus/tools.py", "source_location": "L16", - "community": 486, + "community": 86, "norm_label": "search user's saved memories, preferences, and past analysis context. use", "id": "prometheus_tools_rationale_16" }, @@ -30602,7 +31133,7 @@ "file_type": "rationale", "source_file": "main/app/prometheus/tools.py", "source_location": "L42", - "community": 491, + "community": 86, "norm_label": "store a memory about the user's preferences, analysis results, or feedback.", "id": "prometheus_tools_rationale_42" }, @@ -30620,7 +31151,7 @@ "file_type": "rationale", "source_file": "main/app/prometheus/tools.py", "source_location": "L94", - "community": 100, + "community": 188, "norm_label": "store a value in the harness state for this session. use this to save inter", "id": "prometheus_tools_rationale_94" }, @@ -30629,7 +31160,7 @@ "file_type": "rationale", "source_file": "main/app/prometheus/tools.py", "source_location": "L112", - "community": 490, + "community": 188, "norm_label": "execute python code in an isolated sandbox. use for quantitative analysis,", "id": "prometheus_tools_rationale_112" }, @@ -30665,7 +31196,7 @@ "file_type": "rationale", "source_file": "tests/test_memory_dedup.py", "source_location": "L30", - "community": 131, + "community": 146, "norm_label": "keys with jaccard > 0.8 should merge.", "id": "tests_test_memory_dedup_rationale_30" }, @@ -30674,7 +31205,7 @@ "file_type": "rationale", "source_file": "tests/test_memory_dedup.py", "source_location": "L40", - "community": 131, + "community": 146, "norm_label": "keys with low similarity should not merge.", "id": "tests_test_memory_dedup_rationale_40" }, @@ -30683,7 +31214,7 @@ "file_type": "rationale", "source_file": "tests/test_memory_dedup.py", "source_location": "L67", - "community": 131, + "community": 146, "norm_label": "keys with jaccard <= 0.8 should not merge.", "id": "tests_test_memory_dedup_rationale_67" }, @@ -30692,7 +31223,7 @@ "file_type": "rationale", "source_file": "tests/test_sandbox_persistence.py", "source_location": "L9", - "community": 86, + "community": 4, "norm_label": "wire up mock forgevm asyncclient that returns sandbox with all methods.", "id": "tests_test_sandbox_persistence_rationale_9" }, @@ -30800,7 +31331,7 @@ "file_type": "code", "source_file": "tests/test_sandbox_persistence.py", "source_location": "L164", - "community": 86, + "community": 4, "norm_label": "testsandboxcleanup", "id": "tests_test_sandbox_persistence_testsandboxcleanup" }, @@ -30845,7 +31376,7 @@ "file_type": "code", "source_file": "main/models/memory.py", "source_location": "L7", - "community": 131, + "community": 146, "norm_label": "prometheusmemory", "id": "models_memory_usermemory" }, @@ -31052,7 +31583,7 @@ "file_type": "code", "source_file": "tests/test_sandbox_persistence.py", "source_location": "L114", - "community": 86, + "community": 4, "norm_label": "test_sync_workspace()", "id": "tests_test_sandbox_persistence_test_sync_workspace" }, @@ -31061,7 +31592,7 @@ "file_type": "code", "source_file": "tests/test_sandbox_persistence.py", "source_location": "L132", - "community": 86, + "community": 4, "norm_label": "test_restore_workspace()", "id": "tests_test_sandbox_persistence_test_restore_workspace" }, @@ -31070,7 +31601,7 @@ "file_type": "rationale", "source_file": "tests/test_sandbox_persistence.py", "source_location": "L8", - "community": 86, + "community": 4, "norm_label": "wire up mock forgevm asyncclient that returns sandbox with all methods.", "id": "tests_test_sandbox_persistence_rationale_8" }, @@ -31155,15 +31686,6 @@ "norm_label": "read a file from the sandbox filesystem. args: path: absolute pa", "id": "prometheus_tools_rationale_130" }, - { - "label": "Write a file to the sandbox filesystem. Use this to push data files (CSV, J", - "file_type": "rationale", - "source_file": "main/app/prometheus/tools.py", - "source_location": "L143", - "community": 152, - "norm_label": "write a file to the sandbox filesystem. use this to push data files (csv, j", - "id": "prometheus_tools_rationale_143" - }, { "label": "TestAgentSandboxIntegration", "file_type": "code", @@ -31286,7 +31808,7 @@ "file_type": "rationale", "source_file": "main/app/prometheus/tools.py", "source_location": "L15", - "community": 486, + "community": 86, "norm_label": "search user's saved memories, preferences, and past analysis context. use", "id": "prometheus_tools_rationale_15" }, @@ -31295,7 +31817,7 @@ "file_type": "rationale", "source_file": "main/app/prometheus/tools.py", "source_location": "L41", - "community": 491, + "community": 86, "norm_label": "store a memory about the user's preferences, analysis results, or feedback.", "id": "prometheus_tools_rationale_41" }, @@ -31313,7 +31835,7 @@ "file_type": "rationale", "source_file": "main/app/prometheus/tools.py", "source_location": "L93", - "community": 100, + "community": 188, "norm_label": "store a value in the harness state for this session. use this to save inter", "id": "prometheus_tools_rationale_93" }, @@ -33500,7 +34022,7 @@ "file_type": "code", "source_file": "tests/test_prometheus_tools.py", "source_location": "L114", - "community": 8, + "community": 100, "norm_label": "test_get_state_no_state_returns_error()", "id": "tests_test_prometheus_tools_test_get_state_no_state_returns_error" }, @@ -33527,7 +34049,7 @@ "file_type": "rationale", "source_file": "tests/test_prometheus_tools.py", "source_location": "L128", - "community": 518, + "community": 100, "norm_label": "every function in tool_registry must have gemini-safe signatures. custom cl", "id": "tests_test_prometheus_tools_rationale_128" }, @@ -33536,7 +34058,7 @@ "file_type": "rationale", "source_file": "tests/test_prometheus_tools.py", "source_location": "L137", - "community": 518, + "community": 100, "norm_label": "regression: harnessstate must never leak into tool signatures.", "id": "tests_test_prometheus_tools_rationale_137" }, @@ -33545,7 +34067,7 @@ "file_type": "code", "source_file": "main/app/prometheus/cache.py", "source_location": "L1", - "community": 234, + "community": 186, "norm_label": "cache.py", "id": "main_app_prometheus_cache_py" }, @@ -33554,7 +34076,7 @@ "file_type": "code", "source_file": "main/app/prometheus/cache.py", "source_location": "L7", - "community": 234, + "community": 186, "norm_label": "resultcache", "id": "prometheus_cache_resultcache" }, @@ -33563,7 +34085,7 @@ "file_type": "code", "source_file": "main/app/prometheus/cache.py", "source_location": "L8", - "community": 234, + "community": 186, "norm_label": ".__init__()", "id": "prometheus_cache_resultcache_init" }, @@ -33572,7 +34094,7 @@ "file_type": "code", "source_file": "main/app/prometheus/cache.py", "source_location": "L11", - "community": 234, + "community": 186, "norm_label": ".cachepath()", "id": "prometheus_cache_resultcache_cachepath" }, @@ -33581,7 +34103,7 @@ "file_type": "code", "source_file": "main/app/prometheus/cache.py", "source_location": "L15", - "community": 234, + "community": 186, "norm_label": ".get()", "id": "prometheus_cache_resultcache_get" }, @@ -33590,7 +34112,7 @@ "file_type": "code", "source_file": "main/app/prometheus/cache.py", "source_location": "L21", - "community": 234, + "community": 186, "norm_label": ".set()", "id": "prometheus_cache_resultcache_set" }, @@ -33599,7 +34121,7 @@ "file_type": "code", "source_file": "main/app/prometheus/cache.py", "source_location": "L31", - "community": 234, + "community": 186, "norm_label": ".invalidate()", "id": "prometheus_cache_resultcache_invalidate" }, @@ -33608,7 +34130,7 @@ "file_type": "code", "source_file": "main/app/prometheus/cache.py", "source_location": "L38", - "community": 234, + "community": 186, "norm_label": ".exists()", "id": "prometheus_cache_resultcache_exists" }, @@ -33653,7 +34175,7 @@ "file_type": "code", "source_file": "main/app/prometheus/tools.py", "source_location": "L139", - "community": 188, + "community": 86, "norm_label": "read_sandbox_file()", "id": "prometheus_tools_read_sandbox_file" }, @@ -33662,7 +34184,7 @@ "file_type": "code", "source_file": "main/app/prometheus/tools.py", "source_location": "L151", - "community": 188, + "community": 86, "norm_label": "upload_to_sandbox()", "id": "prometheus_tools_upload_to_sandbox" }, @@ -33671,7 +34193,7 @@ "file_type": "code", "source_file": "main/app/prometheus/tools.py", "source_location": "L165", - "community": 188, + "community": 86, "norm_label": "check_cache()", "id": "prometheus_tools_check_cache" }, @@ -33680,25 +34202,16 @@ "file_type": "rationale", "source_file": "main/app/prometheus/tools.py", "source_location": "L17", - "community": 486, + "community": 86, "norm_label": "search user's saved memories, preferences, and past analysis context. use", "id": "prometheus_tools_rationale_17" }, - { - "label": "Store a value in the harness state for this session. Use this to save inter", - "file_type": "rationale", - "source_file": "main/app/prometheus/tools.py", - "source_location": "L92", - "community": 100, - "norm_label": "store a value in the harness state for this session. use this to save inter", - "id": "prometheus_tools_rationale_92" - }, { "label": "Execute Python code in an isolated sandbox. Use for quantitative analysis,", "file_type": "rationale", "source_file": "main/app/prometheus/tools.py", "source_location": "L109", - "community": 490, + "community": 188, "norm_label": "execute python code in an isolated sandbox. use for quantitative analysis,", "id": "prometheus_tools_rationale_109" }, @@ -33707,7 +34220,7 @@ "file_type": "rationale", "source_file": "main/app/prometheus/tools.py", "source_location": "L140", - "community": 188, + "community": 86, "norm_label": "read a file from the sandbox filesystem. args: path: absolute pa", "id": "prometheus_tools_rationale_140" }, @@ -33716,7 +34229,7 @@ "file_type": "rationale", "source_file": "main/app/prometheus/tools.py", "source_location": "L152", - "community": 188, + "community": 86, "norm_label": "upload a file to the sandbox filesystem. use this to push data files (csv,", "id": "prometheus_tools_rationale_152" }, @@ -33725,7 +34238,7 @@ "file_type": "rationale", "source_file": "main/app/prometheus/tools.py", "source_location": "L166", - "community": 188, + "community": 86, "norm_label": "check if a computed result exists in the cache. use before executing expens", "id": "prometheus_tools_rationale_166" }, @@ -33950,7 +34463,7 @@ "file_type": "code", "source_file": "tests/test_config_sandbox.py", "source_location": "L1", - "community": 102, + "community": 500, "norm_label": "test_config_sandbox.py", "id": "tests_test_config_sandbox_py" }, @@ -34409,7 +34922,7 @@ "file_type": "rationale", "source_file": "main/app/prometheus/tools.py", "source_location": "L142", - "community": 188, + "community": 86, "norm_label": "read a file from the sandbox filesystem. args: path: absolute pa", "id": "prometheus_tools_rationale_142" }, @@ -34616,7 +35129,7 @@ "file_type": "code", "source_file": "main/app/prometheus/cache.py", "source_location": "L19", - "community": 234, + "community": 186, "norm_label": "._cache_path()", "id": "prometheus_cache_resultcache_cache_path" }, @@ -34625,7 +35138,7 @@ "file_type": "rationale", "source_file": "main/app/prometheus/cache.py", "source_location": "L1", - "community": 234, + "community": 186, "norm_label": "resultcache \u2014 sha256-keyed file-based cache for computed results.", "id": "prometheus_cache_rationale_1" }, @@ -34634,7 +35147,7 @@ "file_type": "rationale", "source_file": "main/app/prometheus/cache.py", "source_location": "L10", - "community": 234, + "community": 186, "norm_label": "file-based cache keyed by sha256 of code. stores results as json under:", "id": "prometheus_cache_rationale_10" }, @@ -34643,7 +35156,7 @@ "file_type": "rationale", "source_file": "main/app/prometheus/cache.py", "source_location": "L24", - "community": 234, + "community": 186, "norm_label": "return cached result dict or none if miss.", "id": "prometheus_cache_rationale_24" }, @@ -34652,7 +35165,7 @@ "file_type": "rationale", "source_file": "main/app/prometheus/cache.py", "source_location": "L31", - "community": 234, + "community": 186, "norm_label": "store result with timestamp.", "id": "prometheus_cache_rationale_31" }, @@ -34661,7 +35174,7 @@ "file_type": "rationale", "source_file": "main/app/prometheus/cache.py", "source_location": "L42", - "community": 234, + "community": 186, "norm_label": "delete all cached results for a session.", "id": "prometheus_cache_rationale_42" }, @@ -34670,7 +35183,7 @@ "file_type": "rationale", "source_file": "main/app/prometheus/cache.py", "source_location": "L50", - "community": 234, + "community": 186, "norm_label": "check if a result exists for the given code.", "id": "prometheus_cache_rationale_50" }, @@ -35021,7 +35534,7 @@ "file_type": "rationale", "source_file": "main/app/prometheus/tools.py", "source_location": "L91", - "community": 100, + "community": 188, "norm_label": "store a value in the harness state for this session. use this to save interm", "id": "prometheus_tools_rationale_91" }, @@ -35093,7 +35606,7 @@ "file_type": "rationale", "source_file": "main/app/prometheus/tools.py", "source_location": "L13", - "community": 486, + "community": 86, "norm_label": "search user's saved memories, preferences, and past analysis context. use t", "id": "prometheus_tools_rationale_13" }, @@ -35102,7 +35615,7 @@ "file_type": "rationale", "source_file": "main/app/prometheus/tools.py", "source_location": "L39", - "community": 491, + "community": 86, "norm_label": "store a memory about the user's preferences, analysis results, or feedback.", "id": "prometheus_tools_rationale_39" }, @@ -35165,7 +35678,7 @@ "file_type": "rationale", "source_file": "main/app/prometheus/state.py", "source_location": "L22", - "community": 497, + "community": 63, "norm_label": "store a value in state. marks state as changed for context injection.", "id": "prometheus_state_rationale_22" }, @@ -35219,7 +35732,7 @@ "file_type": "rationale", "source_file": "main/app/prometheus/tools.py", "source_location": "L12", - "community": 486, + "community": 86, "norm_label": "search user's saved memories, preferences, and past analysis context. use t", "id": "prometheus_tools_rationale_12" }, @@ -35228,7 +35741,7 @@ "file_type": "rationale", "source_file": "main/app/prometheus/tools.py", "source_location": "L38", - "community": 491, + "community": 86, "norm_label": "store a memory about the user's preferences, analysis results, or feedback.", "id": "prometheus_tools_rationale_38" }, @@ -35282,7 +35795,7 @@ "file_type": "code", "source_file": "main/app/prometheus/tools.py", "source_location": "L46", - "community": 105, + "community": 53, "norm_label": "executememorytool()", "id": "prometheus_tools_executememorytool" }, @@ -35291,7 +35804,7 @@ "file_type": "rationale", "source_file": "main/app/prometheus/tools.py", "source_location": "L29", - "community": 491, + "community": 86, "norm_label": "store a memory about the user's preferences, analysis results, or feedback.", "id": "prometheus_tools_rationale_29" }, @@ -35300,7 +35813,7 @@ "file_type": "rationale", "source_file": "tests/test_memory_dedup.py", "source_location": "L52", - "community": 131, + "community": 146, "norm_label": "keys with low similarity should not merge.", "id": "tests_test_memory_dedup_rationale_52" }, @@ -35309,7 +35822,7 @@ "file_type": "rationale", "source_file": "tests/test_memory_dedup.py", "source_location": "L85", - "community": 131, + "community": 146, "norm_label": "keys with jaccard <= 0.8 should not merge.", "id": "tests_test_memory_dedup_rationale_85" }, @@ -35426,7 +35939,7 @@ "file_type": "rationale", "source_file": "tests/test_memory_tools_wiring.py", "source_location": "L52", - "community": 474, + "community": 49, "norm_label": "makechat must include memory_tools alongside mcp sessions.", "id": "tests_test_memory_tools_wiring_rationale_52" }, @@ -35435,7 +35948,7 @@ "file_type": "rationale", "source_file": "tests/test_memory_tools_wiring.py", "source_location": "L89", - "community": 512, + "community": 49, "norm_label": "dispatchtoolcall must route memory tool names to executememorytool.", "id": "tests_test_memory_tools_wiring_rationale_89" }, @@ -35462,7 +35975,7 @@ "file_type": "rationale", "source_file": "tests/test_memory_tools_wiring.py", "source_location": "L57", - "community": 474, + "community": 49, "norm_label": "makechat must include memory_tools alongside mcp sessions.", "id": "tests_test_memory_tools_wiring_rationale_57" }, @@ -35471,7 +35984,7 @@ "file_type": "rationale", "source_file": "tests/test_memory_tools_wiring.py", "source_location": "L92", - "community": 512, + "community": 49, "norm_label": "dispatchtoolcall must route memory tool names to executememorytool.", "id": "tests_test_memory_tools_wiring_rationale_92" }, @@ -35588,7 +36101,7 @@ "file_type": "code", "source_file": "main/utils/models/loader.py", "source_location": "L23", - "community": 105, + "community": 84, "norm_label": "embed()", "id": "models_loader_embed" }, @@ -35786,7 +36299,7 @@ "file_type": "code", "source_file": "main/utils/models/loader.py", "source_location": "L11", - "community": 105, + "community": 84, "norm_label": "_downloadmodel()", "id": "models_loader_downloadmodel" }, @@ -35795,7 +36308,7 @@ "file_type": "code", "source_file": "frontend/src/api.js", "source_location": "L10", - "community": 5, + "community": 150, "norm_label": "getcookie()", "id": "src_api_getcookie" }, @@ -35921,7 +36434,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1277", - "community": 213, + "community": 493, "norm_label": "covers lines 36-38, 40-44, 46, 48-49, 51, 58-59, 61: successful user retrieval.", "id": "tests_test_controllers_coverage_rationale_1277" }, @@ -35930,7 +36443,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1302", - "community": 216, + "community": 493, "norm_label": "covers lines 42-44: session validation fails.", "id": "tests_test_controllers_coverage_rationale_1302" }, @@ -35939,7 +36452,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1318", - "community": 146, + "community": 493, "norm_label": "covers lines 48-49: user not in db.", "id": "tests_test_controllers_coverage_rationale_1318" }, @@ -35948,7 +36461,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1335", - "community": 197, + "community": 493, "norm_label": "covers lines 65-67: unexpected exception.", "id": "tests_test_controllers_coverage_rationale_1335" }, @@ -35957,7 +36470,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1352", - "community": 208, + "community": 493, "norm_label": "covers lines 37-38, 46, 51, 58 (sessionid is none): skips session validation.", "id": "tests_test_controllers_coverage_rationale_1352" }, @@ -35966,7 +36479,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1376", - "community": 263, + "community": 78, "norm_label": "covers line 16: empty password raises valueerror.", "id": "tests_test_controllers_coverage_rationale_1376" }, @@ -35975,7 +36488,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1386", - "community": 263, + "community": 78, "norm_label": "covers lines 45-51: verifyaccesstoken with expired and invalid tokens.", "id": "tests_test_controllers_coverage_rationale_1386" }, @@ -35984,7 +36497,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1389", - "community": 197, + "community": 493, "norm_label": "covers lines 48-49: jwt.expiredsignatureerror.", "id": "tests_test_controllers_coverage_rationale_1389" }, @@ -35993,7 +36506,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1405", - "community": 78, + "community": 131, "norm_label": "covers lines 50-51: jwt.invalidtokenerror.", "id": "tests_test_controllers_coverage_rationale_1405" }, @@ -36245,7 +36758,7 @@ "file_type": "rationale", "source_file": "tests/test_memory_tools_wiring.py", "source_location": "L56", - "community": 474, + "community": 49, "norm_label": "makechat must include memory_tools alongside mcp sessions.", "id": "tests_test_memory_tools_wiring_rationale_56" }, @@ -36254,7 +36767,7 @@ "file_type": "rationale", "source_file": "tests/test_memory_tools_wiring.py", "source_location": "L91", - "community": 512, + "community": 49, "norm_label": "dispatchtoolcall must route memory tool names to executememorytool.", "id": "tests_test_memory_tools_wiring_rationale_91" }, @@ -36578,7 +37091,7 @@ "file_type": "rationale", "source_file": "tests/test_memory_tools_wiring.py", "source_location": "L48", - "community": 474, + "community": 49, "norm_label": "makechat must include memory_tools alongside mcp sessions.", "id": "tests_test_memory_tools_wiring_rationale_48" }, @@ -36587,7 +37100,7 @@ "file_type": "rationale", "source_file": "tests/test_memory_tools_wiring.py", "source_location": "L76", - "community": 512, + "community": 49, "norm_label": "dispatchtoolcall must route memory tool names to executememorytool.", "id": "tests_test_memory_tools_wiring_rationale_76" }, @@ -36659,7 +37172,7 @@ "file_type": "code", "source_file": "main/app/prometheus/memory.py", "source_location": "L20", - "community": 131, + "community": 146, "norm_label": "memorymanager", "id": "prometheus_memory_memorymanager" }, @@ -36677,7 +37190,7 @@ "file_type": "code", "source_file": "main/controller/prometheus_controller.py", "source_location": "L177", - "community": 105, + "community": 84, "norm_label": "creatememory()", "id": "controller_prometheus_controller_creatememory" }, @@ -37271,7 +37784,7 @@ "file_type": "rationale", "source_file": "main/app/prometheus/memory.py", "source_location": "L14", - "community": 131, + "community": 146, "norm_label": "all memory operations. stateless class methods.", "id": "prometheus_memory_rationale_14" }, @@ -37487,7 +38000,7 @@ "file_type": "code", "source_file": "main/controller/prometheus_controller.py", "source_location": "L177", - "community": 105, + "community": 84, "norm_label": "create_memory()", "id": "controller_prometheus_controller_create_memory" }, @@ -37712,7 +38225,7 @@ "file_type": "rationale", "source_file": "tests/test_memory_manager.py", "source_location": "L11", - "community": 131, + "community": 146, "norm_label": "non-extended role gets basic limit.", "id": "tests_test_memory_manager_rationale_11" }, @@ -37721,7 +38234,7 @@ "file_type": "rationale", "source_file": "tests/test_memory_manager.py", "source_location": "L15", - "community": 131, + "community": 146, "norm_label": "premium user gets extended limit.", "id": "tests_test_memory_manager_rationale_15" }, @@ -37730,7 +38243,7 @@ "file_type": "rationale", "source_file": "tests/test_memory_manager.py", "source_location": "L19", - "community": 131, + "community": 146, "norm_label": "admin gets extended limit (has all permissions).", "id": "tests_test_memory_manager_rationale_19" }, @@ -37739,7 +38252,7 @@ "file_type": "rationale", "source_file": "tests/test_memory_manager.py", "source_location": "L25", - "community": 131, + "community": 146, "norm_label": "creates a new memory.", "id": "tests_test_memory_manager_rationale_25" }, @@ -37748,7 +38261,7 @@ "file_type": "rationale", "source_file": "tests/test_memory_manager.py", "source_location": "L35", - "community": 131, + "community": 146, "norm_label": "updates existing memory when value changes.", "id": "tests_test_memory_manager_rationale_35" }, @@ -37757,7 +38270,7 @@ "file_type": "rationale", "source_file": "tests/test_memory_manager.py", "source_location": "L43", - "community": 131, + "community": 146, "norm_label": "returns unchanged when value is identical.", "id": "tests_test_memory_manager_rationale_43" }, @@ -37766,7 +38279,7 @@ "file_type": "rationale", "source_file": "tests/test_memory_manager.py", "source_location": "L49", - "community": 131, + "community": 146, "norm_label": "rejects new memory when limit reached.", "id": "tests_test_memory_manager_rationale_49" }, @@ -37775,7 +38288,7 @@ "file_type": "rationale", "source_file": "tests/test_memory_manager.py", "source_location": "L61", - "community": 131, + "community": 146, "norm_label": "no role check when user_roles not provided.", "id": "tests_test_memory_manager_rationale_61" }, @@ -37784,7 +38297,7 @@ "file_type": "rationale", "source_file": "tests/test_memory_manager.py", "source_location": "L69", - "community": 131, + "community": 146, "norm_label": "stores embedding alongside memory.", "id": "tests_test_memory_manager_rationale_69" }, @@ -37793,7 +38306,7 @@ "file_type": "rationale", "source_file": "tests/test_memory_manager.py", "source_location": "L82", - "community": 131, + "community": 146, "norm_label": "counts only non-archived memories.", "id": "tests_test_memory_manager_rationale_82" }, @@ -37802,7 +38315,7 @@ "file_type": "rationale", "source_file": "tests/test_memory_manager.py", "source_location": "L88", - "community": 131, + "community": 146, "norm_label": "archived memories not counted.", "id": "tests_test_memory_manager_rationale_88" }, @@ -37811,7 +38324,7 @@ "file_type": "rationale", "source_file": "tests/test_memory_manager.py", "source_location": "L107", - "community": 131, + "community": 146, "norm_label": "returns paginated memories.", "id": "tests_test_memory_manager_rationale_107" }, @@ -37820,7 +38333,7 @@ "file_type": "rationale", "source_file": "tests/test_memory_manager.py", "source_location": "L115", - "community": 131, + "community": 146, "norm_label": "offset and limit work.", "id": "tests_test_memory_manager_rationale_115" }, @@ -37829,7 +38342,7 @@ "file_type": "rationale", "source_file": "tests/test_memory_manager.py", "source_location": "L122", - "community": 131, + "community": 146, "norm_label": "archived memories excluded.", "id": "tests_test_memory_manager_rationale_122" }, @@ -37838,7 +38351,7 @@ "file_type": "rationale", "source_file": "tests/test_memory_manager.py", "source_location": "L135", - "community": 131, + "community": 146, "norm_label": "soft-deletes a memory.", "id": "tests_test_memory_manager_rationale_135" }, @@ -37847,7 +38360,7 @@ "file_type": "rationale", "source_file": "tests/test_memory_manager.py", "source_location": "L142", - "community": 131, + "community": 146, "norm_label": "returns false for non-existent memory.", "id": "tests_test_memory_manager_rationale_142" }, @@ -37856,7 +38369,7 @@ "file_type": "rationale", "source_file": "tests/test_memory_manager.py", "source_location": "L146", - "community": 131, + "community": 146, "norm_label": "cannot delete another user's memory.", "id": "tests_test_memory_manager_rationale_146" }, @@ -37865,7 +38378,7 @@ "file_type": "rationale", "source_file": "tests/test_memory_manager.py", "source_location": "L155", - "community": 131, + "community": 146, "norm_label": "fulltext search finds matching memories (mysql only).", "id": "tests_test_memory_manager_rationale_155" }, @@ -39008,7 +39521,7 @@ "file_type": "rationale", "source_file": "main/controller/stocksapi_controller.py", "source_location": "L65", - "community": 81, + "community": 475, "norm_label": "get year-based historical financial data for brazilian b3 stocks. returns", "id": "controller_stocksapi_controller_rationale_65" }, @@ -39017,7 +39530,7 @@ "file_type": "rationale", "source_file": "main/controller/stocksapi_controller.py", "source_location": "L123", - "community": 504, + "community": 157, "norm_label": "get point-in-time fundamental/valuation data for brazilian b3 stocks. ret", "id": "controller_stocksapi_controller_rationale_123" }, @@ -39035,7 +39548,7 @@ "file_type": "rationale", "source_file": "main/controller/stocksapi_controller.py", "source_location": "L232", - "community": 124, + "community": 81, "norm_label": "get real-time price quotation for a single brazilian b3 stock. returns th", "id": "controller_stocksapi_controller_rationale_232" }, @@ -39080,7 +39593,7 @@ "file_type": "rationale", "source_file": "tests/conftest.py", "source_location": "L74", - "community": 99, + "community": 527, "norm_label": "testclient with stocks router + verifyapikey + getcurrentuser overrides.", "id": "tests_conftest_rationale_74" }, @@ -39089,7 +39602,7 @@ "file_type": "rationale", "source_file": "tests/conftest.py", "source_location": "L99", - "community": 99, + "community": 527, "norm_label": "testclient with all routers mounted \u2014 no lifespan (no db/service init). o", "id": "tests_conftest_rationale_99" }, @@ -39224,7 +39737,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L802", - "community": 21, + "community": 221, "norm_label": "covers lines 143, 145, 147-148: post /user/sessions/revoke-all.", "id": "tests_test_controllers_coverage_rationale_802" }, @@ -39233,7 +39746,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L805", - "community": 120, + "community": 221, "norm_label": "covers lines 143, 145, 147-148.", "id": "tests_test_controllers_coverage_rationale_805" }, @@ -39467,7 +39980,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1219", - "community": 213, + "community": 137, "norm_label": "covers lines 13, 17, 19-20, 22-27: usermanager.addroletouser.", "id": "tests_test_controllers_coverage_rationale_1219" }, @@ -39476,7 +39989,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1222", - "community": 214, + "community": 137, "norm_label": "covers lines 17, 22-27: user found, role not present, role added.", "id": "tests_test_controllers_coverage_rationale_1222" }, @@ -39485,7 +39998,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1239", - "community": 215, + "community": 493, "norm_label": "covers line 27: user already has the role.", "id": "tests_test_controllers_coverage_rationale_1239" }, @@ -39521,7 +40034,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1298", - "community": 216, + "community": 493, "norm_label": "covers lines 42-44: session validation fails.", "id": "tests_test_controllers_coverage_rationale_1298" }, @@ -39530,7 +40043,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1314", - "community": 146, + "community": 493, "norm_label": "covers lines 48-49: user not in db.", "id": "tests_test_controllers_coverage_rationale_1314" }, @@ -39539,7 +40052,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1331", - "community": 197, + "community": 493, "norm_label": "covers lines 65-67: unexpected exception.", "id": "tests_test_controllers_coverage_rationale_1331" }, @@ -39548,7 +40061,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1348", - "community": 208, + "community": 493, "norm_label": "covers lines 37-38, 46, 51, 58 (sessionid is none): skips session validation.", "id": "tests_test_controllers_coverage_rationale_1348" }, @@ -39557,7 +40070,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1372", - "community": 146, + "community": 493, "norm_label": "covers line 16: empty password raises valueerror.", "id": "tests_test_controllers_coverage_rationale_1372" }, @@ -39566,7 +40079,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1401", - "community": 78, + "community": 131, "norm_label": "covers lines 50-51: jwt.invalidtokenerror.", "id": "tests_test_controllers_coverage_rationale_1401" }, @@ -39836,7 +40349,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L800", - "community": 21, + "community": 221, "norm_label": "covers lines 143, 145, 147-148: post /user/sessions/revoke-all.", "id": "tests_test_controllers_coverage_rationale_800" }, @@ -39845,7 +40358,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L803", - "community": 120, + "community": 221, "norm_label": "covers lines 143, 145, 147-148.", "id": "tests_test_controllers_coverage_rationale_803" }, @@ -40070,7 +40583,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1218", - "community": 213, + "community": 137, "norm_label": "covers lines 13, 17, 19-20, 22-27: usermanager.addroletouser.", "id": "tests_test_controllers_coverage_rationale_1218" }, @@ -40079,7 +40592,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1221", - "community": 214, + "community": 137, "norm_label": "covers lines 17, 22-27: user found, role not present, role added.", "id": "tests_test_controllers_coverage_rationale_1221" }, @@ -40088,7 +40601,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1238", - "community": 215, + "community": 493, "norm_label": "covers line 27: user already has the role.", "id": "tests_test_controllers_coverage_rationale_1238" }, @@ -40124,7 +40637,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1297", - "community": 215, + "community": 493, "norm_label": "covers lines 42-44: session validation fails.", "id": "tests_test_controllers_coverage_rationale_1297" }, @@ -40133,7 +40646,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1313", - "community": 146, + "community": 493, "norm_label": "covers lines 48-49: user not in db.", "id": "tests_test_controllers_coverage_rationale_1313" }, @@ -40142,7 +40655,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1330", - "community": 197, + "community": 493, "norm_label": "covers lines 65-67: unexpected exception.", "id": "tests_test_controllers_coverage_rationale_1330" }, @@ -40151,7 +40664,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1347", - "community": 208, + "community": 493, "norm_label": "covers lines 37-38, 46, 51, 58 (sessionid is none): skips session validation.", "id": "tests_test_controllers_coverage_rationale_1347" }, @@ -40160,7 +40673,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1371", - "community": 263, + "community": 78, "norm_label": "covers line 16: empty password raises valueerror.", "id": "tests_test_controllers_coverage_rationale_1371" }, @@ -40169,7 +40682,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1381", - "community": 263, + "community": 78, "norm_label": "covers lines 45-51: verifyaccesstoken with expired and invalid tokens.", "id": "tests_test_controllers_coverage_rationale_1381" }, @@ -40178,7 +40691,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1384", - "community": 263, + "community": 78, "norm_label": "covers lines 48-49: jwt.expiredsignatureerror.", "id": "tests_test_controllers_coverage_rationale_1384" }, @@ -40187,7 +40700,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1400", - "community": 78, + "community": 131, "norm_label": "covers lines 50-51: jwt.invalidtokenerror.", "id": "tests_test_controllers_coverage_rationale_1400" }, @@ -40313,7 +40826,7 @@ "file_type": "code", "source_file": "tests/test_cache.py", "source_location": "L14", - "community": 234, + "community": 105, "norm_label": "testcachelrueviction", "id": "tests_test_cache_testcachelrueviction" }, @@ -40322,7 +40835,7 @@ "file_type": "code", "source_file": "tests/test_cache.py", "source_location": "L17", - "community": 234, + "community": 105, "norm_label": "._make_manager()", "id": "tests_test_cache_testcachelrueviction_make_manager" }, @@ -40331,7 +40844,7 @@ "file_type": "code", "source_file": "tests/test_cache.py", "source_location": "L22", - "community": 234, + "community": 105, "norm_label": ".test_query_cache_starts_empty()", "id": "tests_test_cache_testcachelrueviction_test_query_cache_starts_empty" }, @@ -40340,7 +40853,7 @@ "file_type": "code", "source_file": "tests/test_cache.py", "source_location": "L26", - "community": 234, + "community": 105, "norm_label": ".test_query_cache_max_size_constant()", "id": "tests_test_cache_testcachelrueviction_test_query_cache_max_size_constant" }, @@ -40349,7 +40862,7 @@ "file_type": "code", "source_file": "tests/test_cache.py", "source_location": "L29", - "community": 234, + "community": 105, "norm_label": ".test_lru_eviction_when_over_limit()", "id": "tests_test_cache_testcachelrueviction_test_lru_eviction_when_over_limit" }, @@ -40358,7 +40871,7 @@ "file_type": "code", "source_file": "tests/test_cache.py", "source_location": "L50", - "community": 234, + "community": 105, "norm_label": ".test_move_to_end_on_cache_hit()", "id": "tests_test_cache_testcachelrueviction_test_move_to_end_on_cache_hit" }, @@ -40367,7 +40880,7 @@ "file_type": "code", "source_file": "tests/test_cache.py", "source_location": "L68", - "community": 234, + "community": 105, "norm_label": ".test_clear_query_cache()", "id": "tests_test_cache_testcachelrueviction_test_clear_query_cache" }, @@ -40376,7 +40889,7 @@ "file_type": "code", "source_file": "tests/test_cache.py", "source_location": "L77", - "community": 234, + "community": 105, "norm_label": ".test_none_columns_key_is_none()", "id": "tests_test_cache_testcachelrueviction_test_none_columns_key_is_none" }, @@ -40385,7 +40898,7 @@ "file_type": "code", "source_file": "tests/test_cache.py", "source_location": "L83", - "community": 234, + "community": 105, "norm_label": ".test_columns_key_is_tuple()", "id": "tests_test_cache_testcachelrueviction_test_columns_key_is_tuple" }, @@ -40430,7 +40943,7 @@ "file_type": "code", "source_file": "tests/test_cache.py", "source_location": "L107", - "community": 234, + "community": 105, "norm_label": "testcachettllogic", "id": "tests_test_cache_testcachettllogic" }, @@ -40439,7 +40952,7 @@ "file_type": "code", "source_file": "tests/test_cache.py", "source_location": "L108", - "community": 234, + "community": 105, "norm_label": "._make_manager()", "id": "tests_test_cache_testcachettllogic_make_manager" }, @@ -40448,7 +40961,7 @@ "file_type": "code", "source_file": "tests/test_cache.py", "source_location": "L112", - "community": 234, + "community": 105, "norm_label": ".test_expired_entry_detected()", "id": "tests_test_cache_testcachettllogic_test_expired_entry_detected" }, @@ -40457,7 +40970,7 @@ "file_type": "code", "source_file": "tests/test_cache.py", "source_location": "L123", - "community": 234, + "community": 105, "norm_label": ".test_fresh_entry_detected()", "id": "tests_test_cache_testcachettllogic_test_fresh_entry_detected" }, @@ -40466,7 +40979,7 @@ "file_type": "rationale", "source_file": "tests/test_cache.py", "source_location": "L15", - "community": 234, + "community": 105, "norm_label": "tests for stockscachemanager querycache lru eviction.", "id": "tests_test_cache_rationale_15" }, @@ -40475,7 +40988,7 @@ "file_type": "rationale", "source_file": "tests/test_cache.py", "source_location": "L18", - "community": 234, + "community": 105, "norm_label": "create a stockscachemanager with a mock db engine.", "id": "tests_test_cache_rationale_18" }, @@ -40484,7 +40997,7 @@ "file_type": "rationale", "source_file": "tests/test_cache.py", "source_location": "L78", - "community": 234, + "community": 105, "norm_label": "when columns is none, cache key should be none.", "id": "tests_test_cache_rationale_78" }, @@ -40664,7 +41177,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L510", - "community": 212, + "community": 3, "norm_label": "non-json-dict/list string is left as-is.", "id": "tests_test_stocks_api_coverage_rationale_510" }, @@ -40718,7 +41231,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L668", - "community": 509, + "community": 28, "norm_label": "pass field name without year (how categorizecolumns returns them).", "id": "tests_test_stocks_api_coverage_rationale_668" }, @@ -40790,7 +41303,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L843", - "community": 17, + "community": 39, "norm_label": "invalid date -> inner 400 passes through (not wrapped as 500).", "id": "tests_test_stocks_api_coverage_rationale_843" }, @@ -40808,7 +41321,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L905", - "community": 17, + "community": 39, "norm_label": "dataframe without time column.", "id": "tests_test_stocks_api_coverage_rationale_905" }, @@ -40853,7 +41366,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L967", - "community": 39, + "community": 17, "norm_label": "search with no index match falls back to string startswith.", "id": "tests_test_stocks_api_coverage_rationale_967" }, @@ -40871,7 +41384,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L990", - "community": 519, + "community": 197, "norm_label": "cotacao 10y padrao and cotacao 10y ajustada belong to /cotations, not /fundament", "id": "tests_test_stocks_api_coverage_rationale_990" }, @@ -40925,7 +41438,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L1216", - "community": 501, + "community": 503, "norm_label": "hit the actual /stocks/cotations http endpoint with adjusted=false.", "id": "tests_test_stocks_api_coverage_rationale_1216" }, @@ -41429,7 +41942,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L509", - "community": 212, + "community": 3, "norm_label": "non-json-dict/list string is left as-is.", "id": "tests_test_stocks_api_coverage_rationale_509" }, @@ -41483,7 +41996,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L667", - "community": 509, + "community": 28, "norm_label": "pass field name without year (how categorizecolumns returns them).", "id": "tests_test_stocks_api_coverage_rationale_667" }, @@ -41528,7 +42041,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L762", - "community": 28, + "community": 504, "norm_label": "historical query with a year range.", "id": "tests_test_stocks_api_coverage_rationale_762" }, @@ -41564,7 +42077,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L895", - "community": 17, + "community": 39, "norm_label": "search.strip() == '' should still dedup (line 181).", "id": "tests_test_stocks_api_coverage_rationale_895" }, @@ -41573,7 +42086,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L904", - "community": 17, + "community": 39, "norm_label": "dataframe without time column.", "id": "tests_test_stocks_api_coverage_rationale_904" }, @@ -41609,7 +42122,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L964", - "community": 39, + "community": 17, "norm_label": "search with no index match falls back to string startswith.", "id": "tests_test_stocks_api_coverage_rationale_964" }, @@ -41627,7 +42140,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L986", - "community": 519, + "community": 197, "norm_label": "cotacao 10y padrao and cotacao 10y ajustada belong to /cotations, not /fundament", "id": "tests_test_stocks_api_coverage_rationale_986" }, @@ -41681,7 +42194,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L1212", - "community": 501, + "community": 503, "norm_label": "hit the actual /stocks/cotations http endpoint with adjusted=false.", "id": "tests_test_stocks_api_coverage_rationale_1212" }, @@ -41825,7 +42338,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L1210", - "community": 501, + "community": 503, "norm_label": "hit the actual /stocks/cotations http endpoint with adjusted=false.", "id": "tests_test_stocks_api_coverage_rationale_1210" }, @@ -41843,7 +42356,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L832", - "community": 17, + "community": 39, "norm_label": "invalid date -> inner 400 caught by outer except -> 500.", "id": "tests_test_stocks_api_coverage_rationale_832" }, @@ -41852,7 +42365,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L885", - "community": 17, + "community": 39, "norm_label": "search.strip() == '' should still dedup (line 181).", "id": "tests_test_stocks_api_coverage_rationale_885" }, @@ -41861,7 +42374,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L894", - "community": 17, + "community": 39, "norm_label": "dataframe without time column.", "id": "tests_test_stocks_api_coverage_rationale_894" }, @@ -41897,7 +42410,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L954", - "community": 39, + "community": 17, "norm_label": "search with no index match falls back to string startswith.", "id": "tests_test_stocks_api_coverage_rationale_954" }, @@ -41915,7 +42428,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L976", - "community": 519, + "community": 197, "norm_label": "cotacao 10y padrao and cotacao 10y ajustada belong to /cotations, not /fundament", "id": "tests_test_stocks_api_coverage_rationale_976" }, @@ -41969,7 +42482,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L1191", - "community": 501, + "community": 503, "norm_label": "hit the actual /stocks/cotations http endpoint with adjusted=false.", "id": "tests_test_stocks_api_coverage_rationale_1191" }, @@ -42500,7 +43013,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L1170", - "community": 501, + "community": 503, "norm_label": "hit the actual /stocks/cotations http endpoint with adjusted=false.", "id": "tests_test_stocks_api_coverage_rationale_1170" }, @@ -42545,7 +43058,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L1141", - "community": 501, + "community": 503, "norm_label": "hit the actual /stocks/cotations http endpoint with adjusted=false.", "id": "tests_test_stocks_api_coverage_rationale_1141" }, @@ -42626,7 +43139,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L1148", - "community": 501, + "community": 503, "norm_label": "hit the actual /stocks/cotations http endpoint with adjusted=false.", "id": "tests_test_stocks_api_coverage_rationale_1148" }, @@ -42824,7 +43337,7 @@ "file_type": "rationale", "source_file": "tests/conftest.py", "source_location": "L75", - "community": 99, + "community": 527, "norm_label": "testclient with all routers mounted \u2014 no lifespan (no db/service init). o", "id": "tests_conftest_rationale_75" }, @@ -43337,7 +43850,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L845", - "community": 21, + "community": 221, "norm_label": "covers lines 143, 145, 147-148: post /user/sessions/revoke-all.", "id": "tests_test_controllers_coverage_rationale_845" }, @@ -43346,7 +43859,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L848", - "community": 120, + "community": 221, "norm_label": "covers lines 143, 145, 147-148.", "id": "tests_test_controllers_coverage_rationale_848" }, @@ -43580,7 +44093,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1280", - "community": 214, + "community": 137, "norm_label": "covers lines 17, 22-27: user found, role not present, role added.", "id": "tests_test_controllers_coverage_rationale_1280" }, @@ -43598,7 +44111,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1356", - "community": 216, + "community": 493, "norm_label": "covers lines 42-44: session validation fails.", "id": "tests_test_controllers_coverage_rationale_1356" }, @@ -43607,7 +44120,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1406", - "community": 208, + "community": 493, "norm_label": "covers lines 37-38, 46, 51, 58 (sessionid is none): skips session validation.", "id": "tests_test_controllers_coverage_rationale_1406" }, @@ -43616,7 +44129,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1430", - "community": 263, + "community": 78, "norm_label": "covers line 16: empty password raises valueerror.", "id": "tests_test_controllers_coverage_rationale_1430" }, @@ -43625,7 +44138,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1440", - "community": 263, + "community": 78, "norm_label": "covers lines 45-51: verifyaccesstoken with expired and invalid tokens.", "id": "tests_test_controllers_coverage_rationale_1440" }, @@ -43634,7 +44147,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1443", - "community": 263, + "community": 78, "norm_label": "covers lines 48-49: jwt.expiredsignatureerror.", "id": "tests_test_controllers_coverage_rationale_1443" }, @@ -43643,7 +44156,7 @@ "file_type": "rationale", "source_file": "tests/test_controllers_coverage.py", "source_location": "L1459", - "community": 78, + "community": 131, "norm_label": "covers lines 50-51: jwt.invalidtokenerror.", "id": "tests_test_controllers_coverage_rationale_1459" }, @@ -44255,7 +44768,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L508", - "community": 212, + "community": 3, "norm_label": "non-json-dict/list string is left as-is.", "id": "tests_test_stocks_api_coverage_rationale_508" }, @@ -44309,7 +44822,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L666", - "community": 509, + "community": 28, "norm_label": "pass field name without year (how categorizecolumns returns them).", "id": "tests_test_stocks_api_coverage_rationale_666" }, @@ -44354,7 +44867,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L761", - "community": 28, + "community": 504, "norm_label": "historical query with a year range.", "id": "tests_test_stocks_api_coverage_rationale_761" }, @@ -44372,7 +44885,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L831", - "community": 17, + "community": 39, "norm_label": "invalid date -> inner 400 caught by outer except -> 500.", "id": "tests_test_stocks_api_coverage_rationale_831" }, @@ -44390,7 +44903,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L893", - "community": 17, + "community": 39, "norm_label": "dataframe without time column.", "id": "tests_test_stocks_api_coverage_rationale_893" }, @@ -44426,7 +44939,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L945", - "community": 39, + "community": 17, "norm_label": "multiple search terms with tickerindex.", "id": "tests_test_stocks_api_coverage_rationale_945" }, @@ -44435,7 +44948,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L953", - "community": 39, + "community": 17, "norm_label": "search with no index match falls back to string startswith.", "id": "tests_test_stocks_api_coverage_rationale_953" }, @@ -44615,7 +45128,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L757", - "community": 28, + "community": 504, "norm_label": "historical query with a year range.", "id": "tests_test_stocks_api_coverage_rationale_757" }, @@ -44642,7 +45155,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L827", - "community": 17, + "community": 39, "norm_label": "invalid date -> inner 400 caught by outer except -> 500.", "id": "tests_test_stocks_api_coverage_rationale_827" }, @@ -44651,7 +45164,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L876", - "community": 17, + "community": 39, "norm_label": "search.strip() == '' should still dedup (line 181).", "id": "tests_test_stocks_api_coverage_rationale_876" }, @@ -44714,7 +45227,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L756", - "community": 28, + "community": 504, "norm_label": "historical query with a year range.", "id": "tests_test_stocks_api_coverage_rationale_756" }, @@ -44732,7 +45245,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L826", - "community": 17, + "community": 39, "norm_label": "invalid date -> inner 400 caught by outer except -> 500.", "id": "tests_test_stocks_api_coverage_rationale_826" }, @@ -44768,7 +45281,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L943", - "community": 39, + "community": 17, "norm_label": "search with no index match falls back to string startswith.", "id": "tests_test_stocks_api_coverage_rationale_943" }, @@ -44804,7 +45317,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L620", - "community": 509, + "community": 28, "norm_label": "pass field name without year (how categorizecolumns returns them).", "id": "tests_test_stocks_api_coverage_rationale_620" }, @@ -44849,7 +45362,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L710", - "community": 28, + "community": 504, "norm_label": "historical query with a year range.", "id": "tests_test_stocks_api_coverage_rationale_710" }, @@ -44867,7 +45380,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L780", - "community": 17, + "community": 39, "norm_label": "invalid date -> inner 400 caught by outer except -> 500.", "id": "tests_test_stocks_api_coverage_rationale_780" }, @@ -44876,7 +45389,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L828", - "community": 17, + "community": 39, "norm_label": "search.strip() == '' should still dedup (line 181).", "id": "tests_test_stocks_api_coverage_rationale_828" }, @@ -44885,7 +45398,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L837", - "community": 17, + "community": 39, "norm_label": "dataframe without time column.", "id": "tests_test_stocks_api_coverage_rationale_837" }, @@ -44921,7 +45434,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L897", - "community": 39, + "community": 17, "norm_label": "search with no index match falls back to string startswith.", "id": "tests_test_stocks_api_coverage_rationale_897" }, @@ -44975,7 +45488,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L621", - "community": 509, + "community": 28, "norm_label": "pass field name without year (how categorizecolumns returns them).", "id": "tests_test_stocks_api_coverage_rationale_621" }, @@ -45020,7 +45533,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L711", - "community": 28, + "community": 504, "norm_label": "historical query with a year range.", "id": "tests_test_stocks_api_coverage_rationale_711" }, @@ -45038,7 +45551,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L781", - "community": 17, + "community": 39, "norm_label": "invalid date -> inner 400 caught by outer except -> 500.", "id": "tests_test_stocks_api_coverage_rationale_781" }, @@ -45047,7 +45560,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L838", - "community": 17, + "community": 39, "norm_label": "dataframe without time column.", "id": "tests_test_stocks_api_coverage_rationale_838" }, @@ -45110,7 +45623,7 @@ "file_type": "code", "source_file": "main/utils/errors.py", "source_location": "L27", - "community": 221, + "community": 33, "norm_label": "_build_error_response()", "id": "utils_errors_build_error_response" }, @@ -45119,7 +45632,7 @@ "file_type": "code", "source_file": "main/utils/errors.py", "source_location": "L37", - "community": 221, + "community": 33, "norm_label": "http_exception_handler()", "id": "utils_errors_http_exception_handler" }, @@ -45128,7 +45641,7 @@ "file_type": "code", "source_file": "main/utils/errors.py", "source_location": "L44", - "community": 221, + "community": 33, "norm_label": "validation_exception_handler()", "id": "utils_errors_validation_exception_handler" }, @@ -45137,7 +45650,7 @@ "file_type": "code", "source_file": "main/utils/errors.py", "source_location": "L56", - "community": 221, + "community": 33, "norm_label": "generic_exception_handler()", "id": "utils_errors_generic_exception_handler" }, @@ -45605,7 +46118,7 @@ "file_type": "code", "source_file": "main/service/user_service.py", "source_location": "L35", - "community": 95, + "community": 84, "norm_label": "inactivesessionsscheduler()", "id": "service_user_service_inactivesessionsscheduler" }, @@ -46055,7 +46568,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L503", - "community": 212, + "community": 3, "norm_label": "non-json-dict/list string is left as-is.", "id": "tests_test_stocks_api_coverage_rationale_503" }, @@ -46091,7 +46604,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L615", - "community": 509, + "community": 28, "norm_label": "pass field name without year (how categorizecolumns returns them).", "id": "tests_test_stocks_api_coverage_rationale_615" }, @@ -46127,7 +46640,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L705", - "community": 28, + "community": 504, "norm_label": "historical query with a year range.", "id": "tests_test_stocks_api_coverage_rationale_705" }, @@ -46154,7 +46667,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L775", - "community": 17, + "community": 39, "norm_label": "invalid date -> inner 400 caught by outer except -> 500.", "id": "tests_test_stocks_api_coverage_rationale_775" }, @@ -46163,7 +46676,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L823", - "community": 17, + "community": 39, "norm_label": "search.strip() == '' should still dedup (line 181).", "id": "tests_test_stocks_api_coverage_rationale_823" }, @@ -46199,7 +46712,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_api_coverage.py", "source_location": "L892", - "community": 39, + "community": 17, "norm_label": "search with no index match falls back to string startswith.", "id": "tests_test_stocks_api_coverage_rationale_892" }, @@ -46217,7 +46730,7 @@ "file_type": "rationale", "source_file": "tests/conftest.py", "source_location": "L62", - "community": 99, + "community": 527, "norm_label": "testclient with all routers mounted \u2014 no lifespan (no db/service init). o", "id": "tests_conftest_rationale_62" }, @@ -46226,7 +46739,7 @@ "file_type": "rationale", "source_file": "tests/conftest.py", "source_location": "L61", - "community": 99, + "community": 527, "norm_label": "testclient with all routers mounted \u2014 no lifespan (no db/service init). o", "id": "tests_conftest_rationale_61" }, @@ -46235,7 +46748,7 @@ "file_type": "rationale", "source_file": "tests/conftest.py", "source_location": "L57", - "community": 99, + "community": 527, "norm_label": "testclient with all routers mounted \u2014 no lifespan (no db/service init). o", "id": "tests_conftest_rationale_57" }, @@ -46244,7 +46757,7 @@ "file_type": "rationale", "source_file": "tests/conftest.py", "source_location": "L49", - "community": 99, + "community": 527, "norm_label": "testclient with all routers mounted \u2014 no lifespan (no db/service init). o", "id": "tests_conftest_rationale_49" }, @@ -46910,7 +47423,7 @@ "file_type": "code", "source_file": "tests/test_stocks_cache.py", "source_location": "L299", - "community": 502, + "community": 509, "norm_label": "testfilterbysearchterms", "id": "tests_test_stocks_cache_testfilterbysearchterms" }, @@ -46919,7 +47432,7 @@ "file_type": "code", "source_file": "tests/test_stocks_cache.py", "source_location": "L302", - "community": 502, + "community": 509, "norm_label": ".test_filter_with_tickerindex()", "id": "tests_test_stocks_cache_testfilterbysearchterms_test_filter_with_tickerindex" }, @@ -46928,7 +47441,7 @@ "file_type": "code", "source_file": "tests/test_stocks_cache.py", "source_location": "L308", - "community": 475, + "community": 502, "norm_label": "testqueryperformance", "id": "tests_test_stocks_cache_testqueryperformance" }, @@ -46937,7 +47450,7 @@ "file_type": "code", "source_file": "tests/test_stocks_cache.py", "source_location": "L311", - "community": 475, + "community": 502, "norm_label": ".test_query_response_time_under_1_second()", "id": "tests_test_stocks_cache_testqueryperformance_test_query_response_time_under_1_second" }, @@ -47180,7 +47693,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_cache.py", "source_location": "L300", - "community": 502, + "community": 509, "norm_label": "tests for optimized search filtering", "id": "tests_test_stocks_cache_rationale_300" }, @@ -47189,7 +47702,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_cache.py", "source_location": "L303", - "community": 502, + "community": 509, "norm_label": "filter should use ticker index for o(1) lookup", "id": "tests_test_stocks_cache_rationale_303" }, @@ -47198,7 +47711,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_cache.py", "source_location": "L309", - "community": 475, + "community": 502, "norm_label": "performance tests for query operations", "id": "tests_test_stocks_cache_rationale_309" }, @@ -47207,7 +47720,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_cache.py", "source_location": "L312", - "community": 475, + "community": 502, "norm_label": "query should respond within 1 second", "id": "tests_test_stocks_cache_rationale_312" }, @@ -47468,7 +47981,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_cache.py", "source_location": "L302", - "community": 502, + "community": 509, "norm_label": "tests for optimized search filtering", "id": "tests_test_stocks_cache_rationale_302" }, @@ -47477,7 +47990,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_cache.py", "source_location": "L305", - "community": 502, + "community": 509, "norm_label": "filter should use ticker index for o(1) lookup", "id": "tests_test_stocks_cache_rationale_305" }, @@ -47486,7 +47999,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_cache.py", "source_location": "L311", - "community": 475, + "community": 502, "norm_label": "performance tests for query operations", "id": "tests_test_stocks_cache_rationale_311" }, @@ -47495,7 +48008,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_cache.py", "source_location": "L314", - "community": 475, + "community": 502, "norm_label": "query should respond within 1 second", "id": "tests_test_stocks_cache_rationale_314" }, @@ -47567,7 +48080,7 @@ "file_type": "code", "source_file": "tests/test_stocks_cache.py", "source_location": "L304", - "community": 502, + "community": 509, "norm_label": ".test_filter_with_tickerindex()", "id": "tests_test_stocks_cache_testfilterbysearchterms_test_filter_with_tickerIndex" }, @@ -47576,7 +48089,7 @@ "file_type": "code", "source_file": "tests/test_stocks_optimization.py", "source_location": "L1", - "community": 259, + "community": 488, "norm_label": "test_stocks_optimization.py", "id": "tests_test_stocks_optimization_py" }, @@ -47693,7 +48206,7 @@ "file_type": "code", "source_file": "tests/test_stocks_optimization.py", "source_location": "L111", - "community": 259, + "community": 488, "norm_label": "testconnectionpool", "id": "tests_test_stocks_optimization_testconnectionpool" }, @@ -47702,7 +48215,7 @@ "file_type": "code", "source_file": "tests/test_stocks_optimization.py", "source_location": "L114", - "community": 259, + "community": 488, "norm_label": ".test_stocks_engine_has_pool_configuration()", "id": "tests_test_stocks_optimization_testconnectionpool_test_stocks_engine_has_pool_configuration" }, @@ -47711,7 +48224,7 @@ "file_type": "code", "source_file": "tests/test_stocks_optimization.py", "source_location": "L123", - "community": 259, + "community": 488, "norm_label": "testlazydeserialization", "id": "tests_test_stocks_optimization_testlazydeserialization" }, @@ -47720,7 +48233,7 @@ "file_type": "code", "source_file": "tests/test_stocks_optimization.py", "source_location": "L126", - "community": 259, + "community": 488, "norm_label": ".test_query_manager_has_deserialize_method()", "id": "tests_test_stocks_optimization_testlazydeserialization_test_query_manager_has_deserialize_method" }, @@ -47837,7 +48350,7 @@ "file_type": "code", "source_file": "tests/test_stocks_optimization.py", "source_location": "L310", - "community": 259, + "community": 488, "norm_label": "testqueryperformance", "id": "tests_test_stocks_optimization_testqueryperformance" }, @@ -47846,7 +48359,7 @@ "file_type": "code", "source_file": "tests/test_stocks_optimization.py", "source_location": "L313", - "community": 259, + "community": 488, "norm_label": ".test_query_response_time_under_1_second()", "id": "tests_test_stocks_optimization_testqueryperformance_test_query_response_time_under_1_second" }, @@ -47963,7 +48476,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_optimization.py", "source_location": "L112", - "community": 259, + "community": 488, "norm_label": "tests for connection pool configuration", "id": "tests_test_stocks_optimization_rationale_112" }, @@ -47972,7 +48485,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_optimization.py", "source_location": "L115", - "community": 259, + "community": 488, "norm_label": "stocks engine should have optimized pool settings", "id": "tests_test_stocks_optimization_rationale_115" }, @@ -47981,7 +48494,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_optimization.py", "source_location": "L124", - "community": 259, + "community": 488, "norm_label": "tests for lazy json deserialization", "id": "tests_test_stocks_optimization_rationale_124" }, @@ -47990,7 +48503,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_optimization.py", "source_location": "L127", - "community": 259, + "community": 488, "norm_label": "query manager should have deserialize method", "id": "tests_test_stocks_optimization_rationale_127" }, @@ -48107,7 +48620,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_optimization.py", "source_location": "L311", - "community": 259, + "community": 488, "norm_label": "performance tests for query operations", "id": "tests_test_stocks_optimization_rationale_311" }, @@ -48116,7 +48629,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_optimization.py", "source_location": "L314", - "community": 259, + "community": 488, "norm_label": "query should respond within 1 second", "id": "tests_test_stocks_optimization_rationale_314" }, @@ -48152,7 +48665,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_optimization.py", "source_location": "L182", - "community": 259, + "community": 488, "norm_label": "performance tests for query operations", "id": "tests_test_stocks_optimization_rationale_182" }, @@ -48161,7 +48674,7 @@ "file_type": "rationale", "source_file": "tests/test_stocks_optimization.py", "source_location": "L185", - "community": 259, + "community": 488, "norm_label": "query should respond within 1 second", "id": "tests_test_stocks_optimization_rationale_185" }, @@ -48484,7 +48997,7 @@ "label": "Authentication System", "file_type": "document", "source_file": "docs/authentication.md", - "community": 43, + "community": 498, "norm_label": "authentication system", "id": "authentication" }, @@ -48492,7 +49005,7 @@ "label": "JWT Authentication", "file_type": "rationale", "source_file": "docs/authentication.md", - "community": 43, + "community": 498, "norm_label": "jwt authentication", "id": "jwt" }, @@ -48500,7 +49013,7 @@ "label": "Google OAuth", "file_type": "rationale", "source_file": "docs/authentication.md", - "community": 43, + "community": 498, "norm_label": "google oauth", "id": "google_oauth" }, @@ -49216,16 +49729,6 @@ "source": "server_config_config", "target": "prometheus_agent_prometheus" }, - { - "relation": "uses", - "confidence": "INFERRED", - "source_file": "main/app/prometheus/compact.py", - "source_location": "L53", - "weight": 0.8, - "confidence_score": 0.5, - "source": "prometheus_compact_fieldregistry", - "target": "server_config_config" - }, { "relation": "uses", "confidence": "INFERRED", @@ -49306,6 +49809,16 @@ "source": "server_config_config", "target": "utils_logging_config_discordhandler" }, + { + "relation": "uses", + "confidence": "INFERRED", + "source_file": "main/app/prometheus/compact.py", + "source_location": "L53", + "weight": 0.8, + "confidence_score": 0.5, + "source": "prometheus_compact_fieldregistry", + "target": "server_config_config" + }, { "relation": "uses", "confidence": "INFERRED", @@ -49461,6 +49974,17 @@ "source": "server_run_lifespan", "target": "utils_connectivity_checkserviceconnection" }, + { + "relation": "calls", + "context": "call", + "confidence": "INFERRED", + "confidence_score": 0.8, + "source_file": "run.py", + "source_location": "L66", + "weight": 1.0, + "source": "server_run_lifespan", + "target": "utils_service_manager_runall" + }, { "relation": "calls", "context": "call", @@ -50654,6 +51178,36 @@ "source": "frontend_src_app_jsx", "target": "src_app_clearresume" }, + { + "relation": "contains", + "confidence": "EXTRACTED", + "source_file": "frontend/src/App.jsx", + "source_location": "L59", + "weight": 1.0, + "confidence_score": 1.0, + "source": "frontend_src_app_jsx", + "target": "src_app_clearlastsession" + }, + { + "relation": "contains", + "confidence": "EXTRACTED", + "source_file": "frontend/src/App.jsx", + "source_location": "L63", + "weight": 1.0, + "confidence_score": 1.0, + "source": "frontend_src_app_jsx", + "target": "src_app_readlastsession" + }, + { + "relation": "contains", + "confidence": "EXTRACTED", + "source_file": "frontend/src/App.jsx", + "source_location": "L71", + "weight": 1.0, + "confidence_score": 1.0, + "source": "frontend_src_app_jsx", + "target": "src_app_savelastsession" + }, { "relation": "contains", "confidence": "EXTRACTED", @@ -50826,9 +51380,9 @@ "source_file": "frontend/src/components/MdocMessage.jsx", "source_location": "L61", "weight": 1.0, + "confidence_score": 1.0, "source": "frontend_src_components_mdocmessage_jsx", - "target": "components_mdocmessage_workspacelink", - "confidence_score": 1.0 + "target": "components_mdocmessage_workspacelink" }, { "relation": "contains", @@ -52847,61 +53401,71 @@ "relation": "contains", "confidence": "EXTRACTED", "source_file": "main/app/prometheus/agent.py", - "source_location": "L27", + "source_location": "L26", + "weight": 1.0, + "source": "main_app_prometheus_agent_py", + "target": "prometheus_agent_safefilter", + "confidence_score": 1.0 + }, + { + "relation": "contains", + "confidence": "EXTRACTED", + "source_file": "main/app/prometheus/agent.py", + "source_location": "L58", "weight": 1.0, "confidence_score": 1.0, "source": "main_app_prometheus_agent_py", - "target": "prometheus_agent_onextractiondone" + "target": "prometheus_agent_getclient" }, { "relation": "contains", "confidence": "EXTRACTED", "source_file": "main/app/prometheus/agent.py", - "source_location": "L35", + "source_location": "L134", "weight": 1.0, "confidence_score": 1.0, "source": "main_app_prometheus_agent_py", - "target": "prometheus_agent_spawnextraction" + "target": "prometheus_agent_prometheus" }, { "relation": "contains", "confidence": "EXTRACTED", "source_file": "main/app/prometheus/agent.py", - "source_location": "L21", + "source_location": "L139", "weight": 1.0, "confidence_score": 1.0, "source": "main_app_prometheus_agent_py", - "target": "prometheus_agent_safe_filter" + "target": "prometheus_agent_buildsystemprompt" }, { "relation": "contains", "confidence": "EXTRACTED", "source_file": "main/app/prometheus/agent.py", - "source_location": "L58", + "source_location": "L21", "weight": 1.0, "confidence_score": 1.0, "source": "main_app_prometheus_agent_py", - "target": "prometheus_agent_getclient" + "target": "prometheus_agent_safe_filter" }, { "relation": "contains", "confidence": "EXTRACTED", "source_file": "main/app/prometheus/agent.py", - "source_location": "L134", + "source_location": "L27", "weight": 1.0, "confidence_score": 1.0, "source": "main_app_prometheus_agent_py", - "target": "prometheus_agent_prometheus" + "target": "prometheus_agent_onextractiondone" }, { "relation": "contains", "confidence": "EXTRACTED", "source_file": "main/app/prometheus/agent.py", - "source_location": "L139", + "source_location": "L35", "weight": 1.0, "confidence_score": 1.0, "source": "main_app_prometheus_agent_py", - "target": "prometheus_agent_buildsystemprompt" + "target": "prometheus_agent_spawnextraction" }, { "relation": "contains", @@ -52973,17 +53537,6 @@ "source": "main_app_prometheus_agent_py", "target": "prometheus_agent_chatsession" }, - { - "relation": "calls", - "context": "call", - "confidence": "EXTRACTED", - "source_file": "main/app/prometheus/agent.py", - "source_location": "L272", - "weight": 1.0, - "confidence_score": 1.0, - "source": "prometheus_agent_prometheus_streammessage", - "target": "prometheus_agent_spawnextraction" - }, { "relation": "calls", "context": "call", @@ -53484,6 +54037,17 @@ "source": "prometheus_agent_prometheus_makechat", "target": "prometheus_agent_get_memory_tools" }, + { + "relation": "calls", + "context": "call", + "confidence": "INFERRED", + "confidence_score": 0.8, + "source_file": "main/app/prometheus/agent.py", + "source_location": "L251", + "weight": 1.0, + "source": "prometheus_agent_prometheus_streammessage", + "target": "prometheus_compact_loadfielddata" + }, { "relation": "calls", "context": "call", @@ -53501,10 +54065,10 @@ "confidence": "INFERRED", "confidence_score": 0.8, "source_file": "main/app/prometheus/agent.py", - "source_location": "L231", + "source_location": "L252", "weight": 1.0, "source": "prometheus_agent_prometheus_streammessage", - "target": "prometheus_tools_dispatchtoolcall" + "target": "prometheus_memory_extract" }, { "relation": "calls", @@ -53512,10 +54076,21 @@ "confidence": "INFERRED", "confidence_score": 0.8, "source_file": "main/app/prometheus/agent.py", - "source_location": "L202", + "source_location": "L231", "weight": 1.0, "source": "prometheus_agent_prometheus_streammessage", - "target": "prometheus_events_looplogger" + "target": "prometheus_tools_dispatchtoolcall" + }, + { + "relation": "calls", + "context": "call", + "confidence": "EXTRACTED", + "source_file": "main/app/prometheus/agent.py", + "source_location": "L272", + "weight": 1.0, + "confidence_score": 1.0, + "source": "prometheus_agent_prometheus_streammessage", + "target": "prometheus_agent_spawnextraction" }, { "relation": "calls", @@ -53523,10 +54098,10 @@ "confidence": "INFERRED", "confidence_score": 0.8, "source_file": "main/app/prometheus/agent.py", - "source_location": "L252", + "source_location": "L202", "weight": 1.0, "source": "prometheus_agent_prometheus_streammessage", - "target": "prometheus_memory_extract" + "target": "prometheus_events_looplogger" }, { "relation": "calls", @@ -53893,11 +54468,51 @@ "relation": "contains", "confidence": "EXTRACTED", "source_file": "main/app/prometheus/compact.py", - "source_location": "L41", + "source_location": "L93", "weight": 1.0, - "confidence_score": 1.0, "source": "main_app_prometheus_compact_py", - "target": "prometheus_compact_fieldregistry" + "target": "prometheus_compact_loadfielddata", + "confidence_score": 1.0 + }, + { + "relation": "contains", + "confidence": "EXTRACTED", + "source_file": "main/app/prometheus/compact.py", + "source_location": "L119", + "weight": 1.0, + "source": "main_app_prometheus_compact_py", + "target": "prometheus_compact_gethistoricalfields", + "confidence_score": 1.0 + }, + { + "relation": "contains", + "confidence": "EXTRACTED", + "source_file": "main/app/prometheus/compact.py", + "source_location": "L123", + "weight": 1.0, + "source": "main_app_prometheus_compact_py", + "target": "prometheus_compact_getfundamentalcolumns", + "confidence_score": 1.0 + }, + { + "relation": "contains", + "confidence": "EXTRACTED", + "source_file": "main/app/prometheus/compact.py", + "source_location": "L127", + "weight": 1.0, + "source": "main_app_prometheus_compact_py", + "target": "prometheus_compact_invalidatefielddata", + "confidence_score": 1.0 + }, + { + "relation": "contains", + "confidence": "EXTRACTED", + "source_file": "main/app/prometheus/compact.py", + "source_location": "L133", + "weight": 1.0, + "source": "main_app_prometheus_compact_py", + "target": "prometheus_compact_getmetricregex", + "confidence_score": 1.0 }, { "relation": "contains", @@ -53969,6 +54584,16 @@ "source": "main_app_prometheus_compact_py", "target": "prometheus_compact_prometheuscompactor" }, + { + "relation": "contains", + "confidence": "EXTRACTED", + "source_file": "main/app/prometheus/compact.py", + "source_location": "L41", + "weight": 1.0, + "confidence_score": 1.0, + "source": "main_app_prometheus_compact_py", + "target": "prometheus_compact_fieldregistry" + }, { "relation": "contains", "confidence": "EXTRACTED", @@ -54023,151 +54648,71 @@ "source": "prometheus_compact_charcount", "target": "prometheus_compact_counttokens" }, - { - "relation": "method", - "confidence": "EXTRACTED", - "source_file": "main/app/prometheus/compact.py", - "source_location": "L52", - "weight": 1.0, - "confidence_score": 1.0, - "source": "prometheus_compact_fieldregistry", - "target": "prometheus_compact_fieldregistry_buildurl" - }, - { - "relation": "method", - "confidence": "EXTRACTED", - "source_file": "main/app/prometheus/compact.py", - "source_location": "L58", - "weight": 1.0, - "confidence_score": 1.0, - "source": "prometheus_compact_fieldregistry", - "target": "prometheus_compact_fieldregistry_fetchfields" - }, - { - "relation": "method", - "confidence": "EXTRACTED", - "source_file": "main/app/prometheus/compact.py", - "source_location": "L79", - "weight": 1.0, - "confidence_score": 1.0, - "source": "prometheus_compact_fieldregistry", - "target": "prometheus_compact_fieldregistry_getfields" - }, - { - "relation": "method", - "confidence": "EXTRACTED", - "source_file": "main/app/prometheus/compact.py", - "source_location": "L86", - "weight": 1.0, - "confidence_score": 1.0, - "source": "prometheus_compact_fieldregistry", - "target": "prometheus_compact_fieldregistry_buildmetricregex" - }, - { - "relation": "method", - "confidence": "EXTRACTED", - "source_file": "main/app/prometheus/compact.py", - "source_location": "L93", - "weight": 1.0, - "confidence_score": 1.0, - "source": "prometheus_compact_fieldregistry", - "target": "prometheus_compact_fieldregistry_getmetricregex" - }, - { - "relation": "method", - "confidence": "EXTRACTED", - "source_file": "main/app/prometheus/compact.py", - "source_location": "L98", - "weight": 1.0, - "confidence_score": 1.0, - "source": "prometheus_compact_fieldregistry", - "target": "prometheus_compact_fieldregistry_invalidate" - }, - { - "relation": "method", - "confidence": "EXTRACTED", - "source_file": "main/app/prometheus/compact.py", - "source_location": "L152", - "weight": 1.0, - "confidence_score": 1.0, - "source": "prometheus_compact_fieldregistry", - "target": "prometheus_compact_fieldregistry_warmup" - }, - { - "relation": "method", - "confidence": "EXTRACTED", - "source_file": "main/app/prometheus/compact.py", - "source_location": "L47", - "weight": 1.0, - "confidence_score": 1.0, - "source": "prometheus_compact_fieldregistry", - "target": "prometheus_compact_fieldregistry_new" - }, { "relation": "calls", "context": "call", "confidence": "EXTRACTED", "source_file": "main/app/prometheus/compact.py", - "source_location": "L188", + "source_location": "L120", "weight": 1.0, - "confidence_score": 1.0, - "source": "prometheus_compact_prometheuscompactor_init", - "target": "prometheus_compact_fieldregistry" + "source": "prometheus_compact_gethistoricalfields", + "target": "prometheus_compact_loadfielddata", + "confidence_score": 1.0 }, { "relation": "calls", "context": "call", "confidence": "EXTRACTED", "source_file": "main/app/prometheus/compact.py", - "source_location": "L60", + "source_location": "L124", "weight": 1.0, - "confidence_score": 1.0, - "source": "prometheus_compact_fieldregistry_fetchfields", - "target": "prometheus_compact_fieldregistry_buildurl" + "source": "prometheus_compact_getfundamentalcolumns", + "target": "prometheus_compact_loadfielddata", + "confidence_score": 1.0 }, { "relation": "calls", "context": "call", "confidence": "EXTRACTED", "source_file": "main/app/prometheus/compact.py", - "source_location": "L82", + "source_location": "L136", "weight": 1.0, - "confidence_score": 1.0, - "source": "prometheus_compact_fieldregistry_getfields", - "target": "prometheus_compact_fieldregistry_fetchfields" + "source": "prometheus_compact_getmetricregex", + "target": "prometheus_compact_loadfielddata", + "confidence_score": 1.0 }, { "relation": "calls", "context": "call", "confidence": "EXTRACTED", "source_file": "main/app/prometheus/compact.py", - "source_location": "L153", + "source_location": "L151", "weight": 1.0, - "confidence_score": 1.0, - "source": "prometheus_compact_fieldregistry_warmup", - "target": "prometheus_compact_fieldregistry_fetchfields" + "source": "prometheus_compact_extractmetrics", + "target": "prometheus_compact_getmetricregex", + "confidence_score": 1.0 }, { "relation": "calls", "context": "call", "confidence": "EXTRACTED", "source_file": "main/app/prometheus/compact.py", - "source_location": "L87", + "source_location": "L212", "weight": 1.0, "confidence_score": 1.0, - "source": "prometheus_compact_fieldregistry_buildmetricregex", - "target": "prometheus_compact_fieldregistry_getfields" + "source": "prometheus_compact_prometheuscompactor_extractepisode", + "target": "prometheus_compact_extracttickers" }, { "relation": "calls", "context": "call", "confidence": "EXTRACTED", "source_file": "main/app/prometheus/compact.py", - "source_location": "L95", + "source_location": "L213", "weight": 1.0, "confidence_score": 1.0, - "source": "prometheus_compact_fieldregistry_getmetricregex", - "target": "prometheus_compact_fieldregistry_buildmetricregex" + "source": "prometheus_compact_prometheuscompactor_extractepisode", + "target": "prometheus_compact_extractmetrics" }, { "relation": "calls", @@ -54180,28 +54725,6 @@ "source": "prometheus_compact_extractmetrics", "target": "prometheus_compact_fieldregistry_getmetricregex" }, - { - "relation": "calls", - "context": "call", - "confidence": "EXTRACTED", - "source_file": "main/app/prometheus/compact.py", - "source_location": "L212", - "weight": 1.0, - "confidence_score": 1.0, - "source": "prometheus_compact_prometheuscompactor_extractepisode", - "target": "prometheus_compact_extracttickers" - }, - { - "relation": "calls", - "context": "call", - "confidence": "EXTRACTED", - "source_file": "main/app/prometheus/compact.py", - "source_location": "L213", - "weight": 1.0, - "confidence_score": 1.0, - "source": "prometheus_compact_prometheuscompactor_extractepisode", - "target": "prometheus_compact_extractmetrics" - }, { "relation": "calls", "context": "call", @@ -54246,16 +54769,6 @@ "source": "prometheus_compact_prometheuscompactor_extractepisode", "target": "prometheus_compact_buildsummary" }, - { - "relation": "method", - "confidence": "EXTRACTED", - "source_file": "main/app/prometheus/compact.py", - "source_location": "L187", - "weight": 1.0, - "confidence_score": 1.0, - "source": "prometheus_compact_prometheuscompactor", - "target": "prometheus_compact_prometheuscompactor_init" - }, { "relation": "method", "confidence": "EXTRACTED", @@ -54316,6 +54829,16 @@ "source": "prometheus_compact_prometheuscompactor", "target": "prometheus_compact_prometheuscompactor_getepisodes" }, + { + "relation": "method", + "confidence": "EXTRACTED", + "source_file": "main/app/prometheus/compact.py", + "source_location": "L187", + "weight": 1.0, + "confidence_score": 1.0, + "source": "prometheus_compact_prometheuscompactor", + "target": "prometheus_compact_prometheuscompactor_init" + }, { "relation": "calls", "context": "call", @@ -56471,6 +56994,16 @@ "source": "prometheus_stream_bus_streambus", "target": "prometheus_stream_bus_streambus_startrun" }, + { + "relation": "method", + "confidence": "EXTRACTED", + "source_file": "main/app/prometheus/stream_bus.py", + "source_location": "L83", + "weight": 1.0, + "confidence_score": 1.0, + "source": "prometheus_stream_bus_streambus", + "target": "prometheus_stream_bus_streambus_forward" + }, { "relation": "calls", "context": "call", @@ -56493,6 +57026,28 @@ "source": "prometheus_stream_bus_streambus_startrun", "target": "prometheus_stream_bus_streambus_getorcreate" }, + { + "relation": "calls", + "context": "call", + "confidence": "EXTRACTED", + "source_file": "main/app/prometheus/stream_bus.py", + "source_location": "L84", + "weight": 1.0, + "confidence_score": 1.0, + "source": "prometheus_stream_bus_streambus_forward", + "target": "prometheus_stream_bus_streambus_subscribe" + }, + { + "relation": "calls", + "context": "call", + "confidence": "EXTRACTED", + "source_file": "main/app/prometheus/stream_bus.py", + "source_location": "L105", + "weight": 1.0, + "confidence_score": 1.0, + "source": "prometheus_stream_bus_streambus_forward", + "target": "prometheus_stream_bus_streambus_unsubscribe" + }, { "relation": "contains", "confidence": "EXTRACTED", @@ -56573,6 +57128,16 @@ "source": "main_app_prometheus_tools_py", "target": "prometheus_tools_dispatchtoolcall" }, + { + "relation": "contains", + "confidence": "EXTRACTED", + "source_file": "main/app/prometheus/tools.py", + "source_location": "L18", + "weight": 1.0, + "confidence_score": 1.0, + "source": "main_app_prometheus_tools_py", + "target": "prometheus_tools_getdb" + }, { "relation": "contains", "confidence": "EXTRACTED", @@ -56653,6 +57218,27 @@ "source": "prometheus_tools_rationale_19", "target": "prometheus_tools_search_memory" }, + { + "relation": "calls", + "context": "call", + "confidence": "EXTRACTED", + "source_file": "main/app/prometheus/tools.py", + "source_location": "L39", + "weight": 1.0, + "confidence_score": 1.0, + "source": "prometheus_tools_search_memory", + "target": "prometheus_tools_getdb" + }, + { + "relation": "rationale_for", + "confidence": "EXTRACTED", + "source_file": "main/app/prometheus/tools.py", + "source_location": "L27", + "weight": 1.0, + "confidence_score": 1.0, + "source": "prometheus_tools_rationale_27", + "target": "prometheus_tools_search_memory" + }, { "relation": "rationale_for", "confidence": "EXTRACTED", @@ -56734,6 +57320,27 @@ "source": "prometheus_tools_save_memory", "target": "prometheus_vector_embed" }, + { + "relation": "calls", + "context": "call", + "confidence": "EXTRACTED", + "source_file": "main/app/prometheus/tools.py", + "source_location": "L67", + "weight": 1.0, + "confidence_score": 1.0, + "source": "prometheus_tools_save_memory", + "target": "prometheus_tools_getdb" + }, + { + "relation": "rationale_for", + "confidence": "EXTRACTED", + "source_file": "main/app/prometheus/tools.py", + "source_location": "L54", + "weight": 1.0, + "confidence_score": 1.0, + "source": "prometheus_tools_rationale_54", + "target": "prometheus_tools_save_memory" + }, { "relation": "rationale_for", "confidence": "EXTRACTED", @@ -56804,6 +57411,16 @@ "source": "prometheus_tools_rationale_90", "target": "prometheus_tools_execute_code" }, + { + "relation": "rationale_for", + "confidence": "EXTRACTED", + "source_file": "main/app/prometheus/tools.py", + "source_location": "L92", + "weight": 1.0, + "confidence_score": 1.0, + "source": "prometheus_tools_rationale_92", + "target": "prometheus_tools_execute_code" + }, { "relation": "rationale_for", "confidence": "EXTRACTED", @@ -56864,6 +57481,16 @@ "source": "prometheus_tools_rationale_111", "target": "prometheus_tools_read_file" }, + { + "relation": "rationale_for", + "confidence": "EXTRACTED", + "source_file": "main/app/prometheus/tools.py", + "source_location": "L113", + "weight": 1.0, + "confidence_score": 1.0, + "source": "prometheus_tools_rationale_113", + "target": "prometheus_tools_read_file" + }, { "relation": "rationale_for", "confidence": "EXTRACTED", @@ -56924,6 +57551,16 @@ "source": "prometheus_tools_rationale_125", "target": "prometheus_tools_write_file" }, + { + "relation": "rationale_for", + "confidence": "EXTRACTED", + "source_file": "main/app/prometheus/tools.py", + "source_location": "L127", + "weight": 1.0, + "confidence_score": 1.0, + "source": "prometheus_tools_rationale_127", + "target": "prometheus_tools_write_file" + }, { "relation": "rationale_for", "confidence": "EXTRACTED", @@ -56994,6 +57631,16 @@ "source": "prometheus_tools_rationale_141", "target": "prometheus_tools_list_files" }, + { + "relation": "rationale_for", + "confidence": "EXTRACTED", + "source_file": "main/app/prometheus/tools.py", + "source_location": "L143", + "weight": 1.0, + "confidence_score": 1.0, + "source": "prometheus_tools_rationale_143", + "target": "prometheus_tools_list_files" + }, { "relation": "rationale_for", "confidence": "EXTRACTED", @@ -57054,6 +57701,16 @@ "source": "prometheus_tools_rationale_154", "target": "prometheus_tools_serve_file" }, + { + "relation": "rationale_for", + "confidence": "EXTRACTED", + "source_file": "main/app/prometheus/tools.py", + "source_location": "L156", + "weight": 1.0, + "confidence_score": 1.0, + "source": "prometheus_tools_rationale_156", + "target": "prometheus_tools_serve_file" + }, { "relation": "rationale_for", "confidence": "EXTRACTED", @@ -57262,6 +57919,16 @@ "source": "prometheus_tools_dispatchtoolcall", "target": "tests_test_memory_tools_wiring_test_non_memory_tool_not_routed_to_executememorytool" }, + { + "relation": "rationale_for", + "confidence": "EXTRACTED", + "source_file": "main/app/prometheus/tools.py", + "source_location": "L19", + "weight": 1.0, + "confidence_score": 1.0, + "source": "prometheus_tools_rationale_19", + "target": "prometheus_tools_getdb" + }, { "relation": "rationale_for", "confidence": "EXTRACTED", @@ -59914,6 +60581,16 @@ "source": "stocks_api_query_stocksquerymanager", "target": "stocks_api_query_stocksquerymanager_querylivecotation" }, + { + "relation": "method", + "confidence": "EXTRACTED", + "source_file": "main/app/stocks_api/query.py", + "source_location": "L110", + "weight": 1.0, + "confidence_score": 1.0, + "source": "stocks_api_query_stocksquerymanager", + "target": "stocks_api_query_stocksquerymanager_executequery" + }, { "relation": "uses", "confidence": "INFERRED", @@ -60338,6 +61015,17 @@ "source": "stocks_api_query_stocksquerymanager_deserializejsoncolumns", "target": "stocks_api_query_stocksquerymanager_querycotations" }, + { + "relation": "calls", + "context": "call", + "confidence": "EXTRACTED", + "source_file": "main/app/stocks_api/query.py", + "source_location": "L153", + "weight": 1.0, + "confidence_score": 1.0, + "source": "stocks_api_query_stocksquerymanager_executequery", + "target": "stocks_api_query_stocksquerymanager_deserializejsoncolumns" + }, { "relation": "calls", "context": "call", @@ -60371,6 +61059,17 @@ "source": "stocks_api_query_stocksquerymanager_filterbysearchterms", "target": "stocks_api_query_stocksquerymanager_querycotations" }, + { + "relation": "calls", + "context": "call", + "confidence": "EXTRACTED", + "source_file": "main/app/stocks_api/query.py", + "source_location": "L131", + "weight": 1.0, + "confidence_score": 1.0, + "source": "stocks_api_query_stocksquerymanager_executequery", + "target": "stocks_api_query_stocksquerymanager_filterbysearchterms" + }, { "relation": "calls", "context": "call", @@ -60393,6 +61092,17 @@ "source": "stocks_api_query_stocksquerymanager_queryhistorical", "target": "stocks_api_util_parsedaterange" }, + { + "relation": "calls", + "context": "call", + "confidence": "EXTRACTED", + "source_file": "main/app/stocks_api/query.py", + "source_location": "L204", + "weight": 1.0, + "confidence_score": 1.0, + "source": "stocks_api_query_stocksquerymanager_queryhistorical", + "target": "stocks_api_query_stocksquerymanager_executequery" + }, { "relation": "calls", "context": "call", @@ -60448,6 +61158,17 @@ "source": "stocks_api_query_stocksquerymanager_queryfundamental", "target": "stocks_api_util_parsedaterange" }, + { + "relation": "calls", + "context": "call", + "confidence": "EXTRACTED", + "source_file": "main/app/stocks_api/query.py", + "source_location": "L277", + "weight": 1.0, + "confidence_score": 1.0, + "source": "stocks_api_query_stocksquerymanager_queryfundamental", + "target": "stocks_api_query_stocksquerymanager_executequery" + }, { "relation": "calls", "context": "call", @@ -60503,6 +61224,16 @@ "source": "stocks_api_query_stocksquerymanager_querycotations", "target": "stocks_api_query_filtercotationbydate" }, + { + "relation": "contains", + "confidence": "EXTRACTED", + "source_file": "main/app/stocks_api/sync_cache.py", + "source_location": "L16", + "weight": 1.0, + "confidence_score": 1.0, + "source": "main_app_stocks_api_sync_cache_py", + "target": "stocks_api_sync_cache_sync_cache" + }, { "relation": "imports_from", "context": "import", @@ -62328,16 +63059,6 @@ "source": "main_controller_stocksapi_controller_py", "target": "fastapi" }, - { - "relation": "contains", - "confidence": "EXTRACTED", - "source_file": "main/controller/stocksapi_controller.py", - "source_location": "L23", - "weight": 1.0, - "confidence_score": 1.0, - "source": "main_controller_stocksapi_controller_py", - "target": "controller_stocksapi_controller_jsonbytesresponse" - }, { "relation": "contains", "confidence": "EXTRACTED", @@ -62402,61 +63123,61 @@ "relation": "contains", "confidence": "EXTRACTED", "source_file": "main/controller/stocksapi_controller.py", - "source_location": "L46", + "source_location": "L23", "weight": 1.0, "confidence_score": 1.0, "source": "main_controller_stocksapi_controller_py", - "target": "controller_stocksapi_controller_generatekey" + "target": "controller_stocksapi_controller_jsonbytesresponse" }, { "relation": "contains", "confidence": "EXTRACTED", "source_file": "main/controller/stocksapi_controller.py", - "source_location": "L63", + "source_location": "L46", "weight": 1.0, "confidence_score": 1.0, "source": "main_controller_stocksapi_controller_py", - "target": "controller_stocksapi_controller_getrealtimecotation" + "target": "controller_stocksapi_controller_generatekey" }, { "relation": "contains", "confidence": "EXTRACTED", "source_file": "main/controller/stocksapi_controller.py", - "source_location": "L20", + "source_location": "L63", "weight": 1.0, "confidence_score": 1.0, "source": "main_controller_stocksapi_controller_py", - "target": "controller_stocksapi_controller_apikeytest" + "target": "controller_stocksapi_controller_getrealtimecotation" }, { - "relation": "inherits", + "relation": "contains", "confidence": "EXTRACTED", "source_file": "main/controller/stocksapi_controller.py", - "source_location": "L23", + "source_location": "L20", "weight": 1.0, "confidence_score": 1.0, - "source": "controller_stocksapi_controller_jsonbytesresponse", - "target": "fastapiresponse" + "source": "main_controller_stocksapi_controller_py", + "target": "controller_stocksapi_controller_apikeytest" }, { - "relation": "method", + "relation": "rationale_for", "confidence": "EXTRACTED", "source_file": "main/controller/stocksapi_controller.py", - "source_location": "L28", + "source_location": "L40", "weight": 1.0, "confidence_score": 1.0, - "source": "controller_stocksapi_controller_jsonbytesresponse", - "target": "controller_stocksapi_controller_jsonbytesresponse_render" + "source": "controller_stocksapi_controller_rationale_40", + "target": "controller_stocksapi_controller_listfields" }, { "relation": "rationale_for", "confidence": "EXTRACTED", "source_file": "main/controller/stocksapi_controller.py", - "source_location": "L24", + "source_location": "L48", "weight": 1.0, "confidence_score": 1.0, - "source": "controller_stocksapi_controller_rationale_24", - "target": "controller_stocksapi_controller_jsonbytesresponse" + "source": "controller_stocksapi_controller_rationale_48", + "target": "controller_stocksapi_controller_listfields" }, { "relation": "rationale_for", @@ -62478,16 +63199,6 @@ "source": "controller_stocksapi_controller_rationale_49", "target": "controller_stocksapi_controller_listfields" }, - { - "relation": "rationale_for", - "confidence": "EXTRACTED", - "source_file": "main/controller/stocksapi_controller.py", - "source_location": "L40", - "weight": 1.0, - "confidence_score": 1.0, - "source": "controller_stocksapi_controller_rationale_40", - "target": "controller_stocksapi_controller_listfields" - }, { "relation": "rationale_for", "confidence": "EXTRACTED", @@ -62529,6 +63240,26 @@ "source": "controller_stocksapi_controller_listfields", "target": "controller_stocksapi_controller_rationale_26" }, + { + "relation": "rationale_for", + "confidence": "EXTRACTED", + "source_file": "main/controller/stocksapi_controller.py", + "source_location": "L96", + "weight": 1.0, + "source": "controller_stocksapi_controller_rationale_96", + "target": "controller_stocksapi_controller_gethistorical", + "confidence_score": 1.0 + }, + { + "relation": "rationale_for", + "confidence": "EXTRACTED", + "source_file": "main/controller/stocksapi_controller.py", + "source_location": "L104", + "weight": 1.0, + "confidence_score": 1.0, + "source": "controller_stocksapi_controller_rationale_104", + "target": "controller_stocksapi_controller_gethistorical" + }, { "relation": "rationale_for", "confidence": "EXTRACTED", @@ -62614,11 +63345,11 @@ "relation": "rationale_for", "confidence": "EXTRACTED", "source_file": "main/controller/stocksapi_controller.py", - "source_location": "L167", + "source_location": "L161", "weight": 1.0, - "confidence_score": 1.0, - "source": "controller_stocksapi_controller_rationale_167", - "target": "controller_stocksapi_controller_getfundamental" + "source": "controller_stocksapi_controller_rationale_161", + "target": "controller_stocksapi_controller_getfundamental", + "confidence_score": 1.0 }, { "relation": "rationale_for", @@ -62630,6 +63361,16 @@ "source": "controller_stocksapi_controller_rationale_169", "target": "controller_stocksapi_controller_getfundamental" }, + { + "relation": "rationale_for", + "confidence": "EXTRACTED", + "source_file": "main/controller/stocksapi_controller.py", + "source_location": "L167", + "weight": 1.0, + "confidence_score": 1.0, + "source": "controller_stocksapi_controller_rationale_167", + "target": "controller_stocksapi_controller_getfundamental" + }, { "relation": "rationale_for", "confidence": "EXTRACTED", @@ -62691,6 +63432,26 @@ "source": "controller_stocksapi_controller_getfundamental", "target": "controller_stocksapi_controller_rationale_123" }, + { + "relation": "rationale_for", + "confidence": "EXTRACTED", + "source_file": "main/controller/stocksapi_controller.py", + "source_location": "L229", + "weight": 1.0, + "source": "controller_stocksapi_controller_rationale_229", + "target": "controller_stocksapi_controller_getcotations", + "confidence_score": 1.0 + }, + { + "relation": "rationale_for", + "confidence": "EXTRACTED", + "source_file": "main/controller/stocksapi_controller.py", + "source_location": "L237", + "weight": 1.0, + "confidence_score": 1.0, + "source": "controller_stocksapi_controller_rationale_237", + "target": "controller_stocksapi_controller_getcotations" + }, { "relation": "rationale_for", "confidence": "EXTRACTED", @@ -62772,6 +63533,26 @@ "source": "controller_stocksapi_controller_getcotations", "target": "controller_stocksapi_controller_rationale_184" }, + { + "relation": "rationale_for", + "confidence": "EXTRACTED", + "source_file": "main/controller/stocksapi_controller.py", + "source_location": "L283", + "weight": 1.0, + "source": "controller_stocksapi_controller_rationale_283", + "target": "controller_stocksapi_controller_getlivecotation", + "confidence_score": 1.0 + }, + { + "relation": "rationale_for", + "confidence": "EXTRACTED", + "source_file": "main/controller/stocksapi_controller.py", + "source_location": "L291", + "weight": 1.0, + "confidence_score": 1.0, + "source": "controller_stocksapi_controller_rationale_291", + "target": "controller_stocksapi_controller_getlivecotation" + }, { "relation": "rationale_for", "confidence": "EXTRACTED", @@ -62864,6 +63645,16 @@ "source": "main_controller_user_controller_py", "target": "fastapi" }, + { + "relation": "contains", + "confidence": "EXTRACTED", + "source_file": "main/controller/user_controller.py", + "source_location": "L16", + "weight": 1.0, + "source": "main_controller_user_controller_py", + "target": "controller_user_controller_sessiontodict", + "confidence_score": 1.0 + }, { "relation": "contains", "confidence": "EXTRACTED", @@ -62954,6 +63745,28 @@ "source": "main_controller_user_controller_py", "target": "controller_user_controller_upgradetodeveloperenterprise" }, + { + "relation": "calls", + "context": "call", + "confidence": "EXTRACTED", + "source_file": "main/controller/user_controller.py", + "source_location": "L67", + "weight": 1.0, + "source": "controller_user_controller_getsessions", + "target": "controller_user_controller_sessiontodict", + "confidence_score": 1.0 + }, + { + "relation": "calls", + "context": "call", + "confidence": "EXTRACTED", + "source_file": "main/controller/user_controller.py", + "source_location": "L87", + "weight": 1.0, + "source": "controller_user_controller_getcurrentsession", + "target": "controller_user_controller_sessiontodict", + "confidence_score": 1.0 + }, { "relation": "contains", "confidence": "EXTRACTED", @@ -64436,6 +65249,17 @@ "source": "service_authentication_service_authenticationservice", "target": "utils_service_manager_servicemanager" }, + { + "relation": "calls", + "context": "call", + "confidence": "INFERRED", + "confidence_score": 0.8, + "source_file": "main/service/authentication_service.py", + "source_location": "L12", + "weight": 1.0, + "source": "service_authentication_service_initialize", + "target": "utils_service_manager_getapp" + }, { "relation": "contains", "confidence": "EXTRACTED", @@ -64750,6 +65574,17 @@ "source": "service_prometheus_service_prometheusservice", "target": "models_memory_usermemory" }, + { + "relation": "calls", + "context": "call", + "confidence": "INFERRED", + "confidence_score": 0.8, + "source_file": "main/service/prometheus_service.py", + "source_location": "L64", + "weight": 1.0, + "source": "service_prometheus_service_initialize", + "target": "utils_service_manager_getapp" + }, { "relation": "calls", "context": "call", @@ -64861,6 +65696,17 @@ "source": "service_stocksapi_service_stocksapiservice", "target": "utils_service_manager_servicemanager" }, + { + "relation": "calls", + "context": "call", + "confidence": "INFERRED", + "confidence_score": 0.8, + "source_file": "main/service/stocksapi_service.py", + "source_location": "L29", + "weight": 1.0, + "source": "service_stocksapi_service_initialize", + "target": "utils_service_manager_getapp" + }, { "relation": "contains", "confidence": "EXTRACTED", @@ -64911,6 +65757,17 @@ "source": "service_user_service_userservice", "target": "utils_service_manager_servicemanager" }, + { + "relation": "calls", + "context": "call", + "confidence": "INFERRED", + "confidence_score": 0.8, + "source_file": "main/service/user_service.py", + "source_location": "L42", + "weight": 1.0, + "source": "service_user_service_initialize", + "target": "utils_service_manager_getapp" + }, { "relation": "contains", "confidence": "EXTRACTED", @@ -65061,16 +65918,6 @@ "source": "main_utils_errors_py", "target": "fastapi" }, - { - "relation": "contains", - "confidence": "EXTRACTED", - "source_file": "main/utils/errors.py", - "source_location": "L13", - "weight": 1.0, - "confidence_score": 1.0, - "source": "main_utils_errors_py", - "target": "utils_errors_errorresponse" - }, { "relation": "contains", "confidence": "EXTRACTED", @@ -65131,6 +65978,16 @@ "source": "main_utils_errors_py", "target": "utils_errors_registererrorhandlers" }, + { + "relation": "contains", + "confidence": "EXTRACTED", + "source_file": "main/utils/errors.py", + "source_location": "L13", + "weight": 1.0, + "confidence_score": 1.0, + "source": "main_utils_errors_py", + "target": "utils_errors_errorresponse" + }, { "relation": "contains", "confidence": "EXTRACTED", @@ -65181,140 +66038,6 @@ "source": "main_utils_errors_py", "target": "utils_errors_register_error_handlers" }, - { - "relation": "inherits", - "confidence": "EXTRACTED", - "source_file": "main/utils/errors.py", - "source_location": "L13", - "weight": 1.0, - "confidence_score": 1.0, - "source": "utils_errors_errorresponse", - "target": "basemodel" - }, - { - "relation": "calls", - "context": "call", - "confidence": "EXTRACTED", - "source_file": "main/utils/errors.py", - "source_location": "L28", - "weight": 1.0, - "confidence_score": 1.0, - "source": "utils_errors_errorresponse", - "target": "utils_errors_builderrorresponse" - }, - { - "relation": "uses", - "confidence": "INFERRED", - "source_file": "tests/test_error_handlers.py", - "source_location": "L12", - "weight": 0.8, - "confidence_score": 0.5, - "source": "utils_errors_errorresponse", - "target": "tests_test_error_handlers_samplebody" - }, - { - "relation": "uses", - "confidence": "INFERRED", - "source_file": "tests/test_error_handlers.py", - "source_location": "L12", - "weight": 0.8, - "confidence_score": 0.5, - "source": "utils_errors_errorresponse", - "target": "tests_test_error_handlers_testerrorresponsemodel" - }, - { - "relation": "uses", - "confidence": "INFERRED", - "source_file": "tests/test_error_handlers.py", - "source_location": "L12", - "weight": 0.8, - "confidence_score": 0.5, - "source": "utils_errors_errorresponse", - "target": "tests_test_error_handlers_testrequestcontextfilter" - }, - { - "relation": "uses", - "confidence": "INFERRED", - "source_file": "tests/test_error_handlers.py", - "source_location": "L12", - "weight": 0.8, - "confidence_score": 0.5, - "source": "utils_errors_errorresponse", - "target": "tests_test_error_handlers_testhttpexceptionhandler" - }, - { - "relation": "uses", - "confidence": "INFERRED", - "source_file": "tests/test_error_handlers.py", - "source_location": "L12", - "weight": 0.8, - "confidence_score": 0.5, - "source": "utils_errors_errorresponse", - "target": "tests_test_error_handlers_testvalidationexceptionhandler" - }, - { - "relation": "uses", - "confidence": "INFERRED", - "source_file": "tests/test_error_handlers.py", - "source_location": "L12", - "weight": 0.8, - "confidence_score": 0.5, - "source": "utils_errors_errorresponse", - "target": "tests_test_error_handlers_testgenericexceptionhandler" - }, - { - "relation": "uses", - "confidence": "INFERRED", - "source_file": "tests/test_error_handlers.py", - "source_location": "L12", - "weight": 0.8, - "confidence_score": 0.5, - "source": "utils_errors_errorresponse", - "target": "tests_test_error_handlers_testsuccesspassthrough" - }, - { - "relation": "calls", - "context": "call", - "confidence": "INFERRED", - "confidence_score": 0.8, - "source_file": "tests/test_error_handlers.py", - "source_location": "L56", - "weight": 1.0, - "source": "utils_errors_errorresponse", - "target": "tests_test_error_handlers_testerrorresponsemodel_test_error_response_structure" - }, - { - "relation": "calls", - "context": "call", - "confidence": "INFERRED", - "confidence_score": 0.8, - "source_file": "tests/test_error_handlers.py", - "source_location": "L65", - "weight": 1.0, - "source": "utils_errors_errorresponse", - "target": "tests_test_error_handlers_testerrorresponsemodel_test_error_response_with_detail_and_request_id" - }, - { - "relation": "calls", - "context": "call", - "confidence": "EXTRACTED", - "source_file": "main/utils/errors.py", - "source_location": "L30", - "weight": 1.0, - "confidence_score": 1.0, - "source": "utils_errors_errorresponse", - "target": "utils_errors_build_error_response" - }, - { - "relation": "inherits", - "confidence": "EXTRACTED", - "source_file": "tests/test_error_handlers.py", - "source_location": "L20", - "weight": 1.0, - "confidence_score": 1.0, - "source": "basemodel", - "target": "tests_test_error_handlers_samplebody" - }, { "relation": "method", "confidence": "EXTRACTED", @@ -65481,6 +66204,17 @@ "source": "utils_errors_builderrorresponse", "target": "utils_errors_genericexceptionhandler" }, + { + "relation": "calls", + "context": "call", + "confidence": "EXTRACTED", + "source_file": "main/utils/errors.py", + "source_location": "L28", + "weight": 1.0, + "confidence_score": 1.0, + "source": "utils_errors_errorresponse", + "target": "utils_errors_builderrorresponse" + }, { "relation": "calls", "context": "call", @@ -67116,31 +67850,31 @@ "relation": "contains", "confidence": "EXTRACTED", "source_file": "main/utils/service_manager.py", - "source_location": "L16", + "source_location": "L21", "weight": 1.0, "confidence_score": 1.0, "source": "main_utils_service_manager_py", - "target": "utils_service_manager_servicemanager" + "target": "utils_service_manager_getapp" }, { "relation": "contains", "confidence": "EXTRACTED", "source_file": "main/utils/service_manager.py", - "source_location": "L21", + "source_location": "L48", "weight": 1.0, "confidence_score": 1.0, "source": "main_utils_service_manager_py", - "target": "utils_service_manager_getapp" + "target": "utils_service_manager_runall" }, { "relation": "contains", "confidence": "EXTRACTED", "source_file": "main/utils/service_manager.py", - "source_location": "L48", + "source_location": "L16", "weight": 1.0, "confidence_score": 1.0, "source": "main_utils_service_manager_py", - "target": "utils_service_manager_runall" + "target": "utils_service_manager_servicemanager" }, { "relation": "contains", @@ -69076,6 +69810,276 @@ "source": "plans_2026_08_09_sse_resume_task_5_full_verification_todo_check_off", "target": "plans_2026_08_09_sse_resume_codeblock_16" }, + { + "relation": "contains", + "confidence": "EXTRACTED", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L1", + "weight": 1.0, + "confidence_score": 1.0, + "source": "docs_superpowers_plans_2026_08_15_stocks_api_perf_md", + "target": "plans_2026_08_15_stocks_api_perf_stocks_api_performance_pre_materialized_cache_sync_handlers_implementation_plan" + }, + { + "relation": "contains", + "confidence": "EXTRACTED", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L13", + "weight": 1.0, + "confidence_score": 1.0, + "source": "plans_2026_08_15_stocks_api_perf_stocks_api_performance_pre_materialized_cache_sync_handlers_implementation_plan", + "target": "plans_2026_08_15_stocks_api_perf_global_constraints" + }, + { + "relation": "contains", + "confidence": "EXTRACTED", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L23", + "weight": 1.0, + "confidence_score": 1.0, + "source": "plans_2026_08_15_stocks_api_perf_stocks_api_performance_pre_materialized_cache_sync_handlers_implementation_plan", + "target": "plans_2026_08_15_stocks_api_perf_file_structure" + }, + { + "relation": "contains", + "confidence": "EXTRACTED", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L633", + "weight": 1.0, + "confidence_score": 1.0, + "source": "plans_2026_08_15_stocks_api_perf_stocks_api_performance_pre_materialized_cache_sync_handlers_implementation_plan", + "target": "plans_2026_08_15_stocks_api_perf_self_review" + }, + { + "relation": "contains", + "confidence": "EXTRACTED", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L35", + "weight": 1.0, + "confidence_score": 1.0, + "source": "plans_2026_08_15_stocks_api_perf_file_structure", + "target": "plans_2026_08_15_stocks_api_perf_task_1_tickerpayloadcache_pre_materialize_per_ticker_payloads_at_refresh" + }, + { + "relation": "contains", + "confidence": "EXTRACTED", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L251", + "weight": 1.0, + "confidence_score": 1.0, + "source": "plans_2026_08_15_stocks_api_perf_file_structure", + "target": "plans_2026_08_15_stocks_api_perf_task_2_fast_paths_in_stocksquerymanager_for_default_shaped_queries" + }, + { + "relation": "contains", + "confidence": "EXTRACTED", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L392", + "weight": 1.0, + "confidence_score": 1.0, + "source": "plans_2026_08_15_stocks_api_perf_file_structure", + "target": "plans_2026_08_15_stocks_api_perf_task_3_convert_query_handlers_to_sync_def" + }, + { + "relation": "contains", + "confidence": "EXTRACTED", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L468", + "weight": 1.0, + "confidence_score": 1.0, + "source": "plans_2026_08_15_stocks_api_perf_file_structure", + "target": "plans_2026_08_15_stocks_api_perf_task_4_pre_parsed_cotation_date_index_replace_filtercotationcolumn_hot_path" + }, + { + "relation": "contains", + "confidence": "EXTRACTED", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L613", + "weight": 1.0, + "confidence_score": 1.0, + "source": "plans_2026_08_15_stocks_api_perf_file_structure", + "target": "plans_2026_08_15_stocks_api_perf_task_5_full_verification_graphify_update" + }, + { + "relation": "contains", + "confidence": "EXTRACTED", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L49", + "weight": 1.0, + "confidence_score": 1.0, + "source": "plans_2026_08_15_stocks_api_perf_task_1_tickerpayloadcache_pre_materialize_per_ticker_payloads_at_refresh", + "target": "plans_2026_08_15_stocks_api_perf_codeblock_1" + }, + { + "relation": "contains", + "confidence": "EXTRACTED", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L88", + "weight": 1.0, + "confidence_score": 1.0, + "source": "plans_2026_08_15_stocks_api_perf_task_1_tickerpayloadcache_pre_materialize_per_ticker_payloads_at_refresh", + "target": "plans_2026_08_15_stocks_api_perf_codeblock_2" + }, + { + "relation": "contains", + "confidence": "EXTRACTED", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L118", + "weight": 1.0, + "confidence_score": 1.0, + "source": "plans_2026_08_15_stocks_api_perf_task_1_tickerpayloadcache_pre_materialize_per_ticker_payloads_at_refresh", + "target": "plans_2026_08_15_stocks_api_perf_codeblock_3" + }, + { + "relation": "contains", + "confidence": "EXTRACTED", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L131", + "weight": 1.0, + "confidence_score": 1.0, + "source": "plans_2026_08_15_stocks_api_perf_task_1_tickerpayloadcache_pre_materialize_per_ticker_payloads_at_refresh", + "target": "plans_2026_08_15_stocks_api_perf_codeblock_4" + }, + { + "relation": "contains", + "confidence": "EXTRACTED", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L177", + "weight": 1.0, + "confidence_score": 1.0, + "source": "plans_2026_08_15_stocks_api_perf_task_1_tickerpayloadcache_pre_materialize_per_ticker_payloads_at_refresh", + "target": "plans_2026_08_15_stocks_api_perf_codeblock_5" + }, + { + "relation": "contains", + "confidence": "EXTRACTED", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L228", + "weight": 1.0, + "confidence_score": 1.0, + "source": "plans_2026_08_15_stocks_api_perf_task_1_tickerpayloadcache_pre_materialize_per_ticker_payloads_at_refresh", + "target": "plans_2026_08_15_stocks_api_perf_codeblock_6" + }, + { + "relation": "contains", + "confidence": "EXTRACTED", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L244", + "weight": 1.0, + "confidence_score": 1.0, + "source": "plans_2026_08_15_stocks_api_perf_task_1_tickerpayloadcache_pre_materialize_per_ticker_payloads_at_refresh", + "target": "plans_2026_08_15_stocks_api_perf_codeblock_7" + }, + { + "relation": "contains", + "confidence": "EXTRACTED", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L263", + "weight": 1.0, + "confidence_score": 1.0, + "source": "plans_2026_08_15_stocks_api_perf_task_2_fast_paths_in_stocksquerymanager_for_default_shaped_queries", + "target": "plans_2026_08_15_stocks_api_perf_codeblock_8" + }, + { + "relation": "contains", + "confidence": "EXTRACTED", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L315", + "weight": 1.0, + "confidence_score": 1.0, + "source": "plans_2026_08_15_stocks_api_perf_task_2_fast_paths_in_stocksquerymanager_for_default_shaped_queries", + "target": "plans_2026_08_15_stocks_api_perf_codeblock_9" + }, + { + "relation": "contains", + "confidence": "EXTRACTED", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L349", + "weight": 1.0, + "confidence_score": 1.0, + "source": "plans_2026_08_15_stocks_api_perf_task_2_fast_paths_in_stocksquerymanager_for_default_shaped_queries", + "target": "plans_2026_08_15_stocks_api_perf_codeblock_10" + }, + { + "relation": "contains", + "confidence": "EXTRACTED", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L405", + "weight": 1.0, + "confidence_score": 1.0, + "source": "plans_2026_08_15_stocks_api_perf_task_3_convert_query_handlers_to_sync_def", + "target": "plans_2026_08_15_stocks_api_perf_codeblock_11" + }, + { + "relation": "contains", + "confidence": "EXTRACTED", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L461", + "weight": 1.0, + "confidence_score": 1.0, + "source": "plans_2026_08_15_stocks_api_perf_task_3_convert_query_handlers_to_sync_def", + "target": "plans_2026_08_15_stocks_api_perf_codeblock_12" + }, + { + "relation": "contains", + "confidence": "EXTRACTED", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L482", + "weight": 1.0, + "confidence_score": 1.0, + "source": "plans_2026_08_15_stocks_api_perf_task_4_pre_parsed_cotation_date_index_replace_filtercotationcolumn_hot_path", + "target": "plans_2026_08_15_stocks_api_perf_codeblock_13" + }, + { + "relation": "contains", + "confidence": "EXTRACTED", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L512", + "weight": 1.0, + "confidence_score": 1.0, + "source": "plans_2026_08_15_stocks_api_perf_task_4_pre_parsed_cotation_date_index_replace_filtercotationcolumn_hot_path", + "target": "plans_2026_08_15_stocks_api_perf_codeblock_14" + }, + { + "relation": "contains", + "confidence": "EXTRACTED", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L519", + "weight": 1.0, + "confidence_score": 1.0, + "source": "plans_2026_08_15_stocks_api_perf_task_4_pre_parsed_cotation_date_index_replace_filtercotationcolumn_hot_path", + "target": "plans_2026_08_15_stocks_api_perf_codeblock_15" + }, + { + "relation": "contains", + "confidence": "EXTRACTED", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L539", + "weight": 1.0, + "confidence_score": 1.0, + "source": "plans_2026_08_15_stocks_api_perf_task_4_pre_parsed_cotation_date_index_replace_filtercotationcolumn_hot_path", + "target": "plans_2026_08_15_stocks_api_perf_codeblock_16" + }, + { + "relation": "contains", + "confidence": "EXTRACTED", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L548", + "weight": 1.0, + "confidence_score": 1.0, + "source": "plans_2026_08_15_stocks_api_perf_task_4_pre_parsed_cotation_date_index_replace_filtercotationcolumn_hot_path", + "target": "plans_2026_08_15_stocks_api_perf_codeblock_17" + }, + { + "relation": "contains", + "confidence": "EXTRACTED", + "source_file": "docs/superpowers/plans/2026-08-15-stocks-api-perf.md", + "source_location": "L606", + "weight": 1.0, + "confidence_score": 1.0, + "source": "plans_2026_08_15_stocks_api_perf_task_4_pre_parsed_cotation_date_index_replace_filtercotationcolumn_hot_path", + "target": "plans_2026_08_15_stocks_api_perf_codeblock_18" + }, { "relation": "contains", "confidence": "EXTRACTED", @@ -69506,6 +70510,325 @@ "source": "plans_2026_08_15_workspace_frontend_task_3_drag_drop_file_upload_in_the_promptbox_inputbar_jsx", "target": "plans_2026_08_15_workspace_frontend_codeblock_10" }, + { + "relation": "method", + "confidence": "EXTRACTED", + "source_file": "main/app/prometheus/compact.py", + "source_location": "L52", + "weight": 1.0, + "confidence_score": 1.0, + "source": "prometheus_compact_fieldregistry", + "target": "prometheus_compact_fieldregistry_buildurl" + }, + { + "relation": "method", + "confidence": "EXTRACTED", + "source_file": "main/app/prometheus/compact.py", + "source_location": "L58", + "weight": 1.0, + "confidence_score": 1.0, + "source": "prometheus_compact_fieldregistry", + "target": "prometheus_compact_fieldregistry_fetchfields" + }, + { + "relation": "method", + "confidence": "EXTRACTED", + "source_file": "main/app/prometheus/compact.py", + "source_location": "L79", + "weight": 1.0, + "confidence_score": 1.0, + "source": "prometheus_compact_fieldregistry", + "target": "prometheus_compact_fieldregistry_getfields" + }, + { + "relation": "method", + "confidence": "EXTRACTED", + "source_file": "main/app/prometheus/compact.py", + "source_location": "L86", + "weight": 1.0, + "confidence_score": 1.0, + "source": "prometheus_compact_fieldregistry", + "target": "prometheus_compact_fieldregistry_buildmetricregex" + }, + { + "relation": "method", + "confidence": "EXTRACTED", + "source_file": "main/app/prometheus/compact.py", + "source_location": "L93", + "weight": 1.0, + "confidence_score": 1.0, + "source": "prometheus_compact_fieldregistry", + "target": "prometheus_compact_fieldregistry_getmetricregex" + }, + { + "relation": "method", + "confidence": "EXTRACTED", + "source_file": "main/app/prometheus/compact.py", + "source_location": "L98", + "weight": 1.0, + "confidence_score": 1.0, + "source": "prometheus_compact_fieldregistry", + "target": "prometheus_compact_fieldregistry_invalidate" + }, + { + "relation": "method", + "confidence": "EXTRACTED", + "source_file": "main/app/prometheus/compact.py", + "source_location": "L152", + "weight": 1.0, + "confidence_score": 1.0, + "source": "prometheus_compact_fieldregistry", + "target": "prometheus_compact_fieldregistry_warmup" + }, + { + "relation": "method", + "confidence": "EXTRACTED", + "source_file": "main/app/prometheus/compact.py", + "source_location": "L47", + "weight": 1.0, + "confidence_score": 1.0, + "source": "prometheus_compact_fieldregistry", + "target": "prometheus_compact_fieldregistry_new" + }, + { + "relation": "calls", + "context": "call", + "confidence": "EXTRACTED", + "source_file": "main/app/prometheus/compact.py", + "source_location": "L188", + "weight": 1.0, + "confidence_score": 1.0, + "source": "prometheus_compact_prometheuscompactor_init", + "target": "prometheus_compact_fieldregistry" + }, + { + "relation": "calls", + "context": "call", + "confidence": "EXTRACTED", + "source_file": "main/app/prometheus/compact.py", + "source_location": "L60", + "weight": 1.0, + "confidence_score": 1.0, + "source": "prometheus_compact_fieldregistry_fetchfields", + "target": "prometheus_compact_fieldregistry_buildurl" + }, + { + "relation": "calls", + "context": "call", + "confidence": "EXTRACTED", + "source_file": "main/app/prometheus/compact.py", + "source_location": "L82", + "weight": 1.0, + "confidence_score": 1.0, + "source": "prometheus_compact_fieldregistry_getfields", + "target": "prometheus_compact_fieldregistry_fetchfields" + }, + { + "relation": "calls", + "context": "call", + "confidence": "EXTRACTED", + "source_file": "main/app/prometheus/compact.py", + "source_location": "L153", + "weight": 1.0, + "confidence_score": 1.0, + "source": "prometheus_compact_fieldregistry_warmup", + "target": "prometheus_compact_fieldregistry_fetchfields" + }, + { + "relation": "calls", + "context": "call", + "confidence": "EXTRACTED", + "source_file": "main/app/prometheus/compact.py", + "source_location": "L87", + "weight": 1.0, + "confidence_score": 1.0, + "source": "prometheus_compact_fieldregistry_buildmetricregex", + "target": "prometheus_compact_fieldregistry_getfields" + }, + { + "relation": "calls", + "context": "call", + "confidence": "EXTRACTED", + "source_file": "main/app/prometheus/compact.py", + "source_location": "L95", + "weight": 1.0, + "confidence_score": 1.0, + "source": "prometheus_compact_fieldregistry_getmetricregex", + "target": "prometheus_compact_fieldregistry_buildmetricregex" + }, + { + "relation": "rationale_for", + "confidence": "EXTRACTED", + "source_file": "main/app/prometheus/tools.py", + "source_location": "L92", + "weight": 1.0, + "confidence_score": 1.0, + "source": "prometheus_tools_set_state", + "target": "prometheus_tools_rationale_92" + }, + { + "relation": "rationale_for", + "confidence": "EXTRACTED", + "source_file": "main/app/stocks_api/query.py", + "source_location": "L123", + "weight": 1.0, + "confidence_score": 1.0, + "source": "stocks_api_query_rationale_123", + "target": "stocks_api_query_stocksquerymanager_executequery" + }, + { + "relation": "inherits", + "confidence": "EXTRACTED", + "source_file": "main/controller/stocksapi_controller.py", + "source_location": "L23", + "weight": 1.0, + "confidence_score": 1.0, + "source": "controller_stocksapi_controller_jsonbytesresponse", + "target": "fastapiresponse" + }, + { + "relation": "method", + "confidence": "EXTRACTED", + "source_file": "main/controller/stocksapi_controller.py", + "source_location": "L28", + "weight": 1.0, + "confidence_score": 1.0, + "source": "controller_stocksapi_controller_jsonbytesresponse", + "target": "controller_stocksapi_controller_jsonbytesresponse_render" + }, + { + "relation": "rationale_for", + "confidence": "EXTRACTED", + "source_file": "main/controller/stocksapi_controller.py", + "source_location": "L24", + "weight": 1.0, + "confidence_score": 1.0, + "source": "controller_stocksapi_controller_rationale_24", + "target": "controller_stocksapi_controller_jsonbytesresponse" + }, + { + "relation": "inherits", + "confidence": "EXTRACTED", + "source_file": "main/utils/errors.py", + "source_location": "L13", + "weight": 1.0, + "confidence_score": 1.0, + "source": "utils_errors_errorresponse", + "target": "basemodel" + }, + { + "relation": "uses", + "confidence": "INFERRED", + "source_file": "tests/test_error_handlers.py", + "source_location": "L12", + "weight": 0.8, + "confidence_score": 0.5, + "source": "utils_errors_errorresponse", + "target": "tests_test_error_handlers_samplebody" + }, + { + "relation": "uses", + "confidence": "INFERRED", + "source_file": "tests/test_error_handlers.py", + "source_location": "L12", + "weight": 0.8, + "confidence_score": 0.5, + "source": "utils_errors_errorresponse", + "target": "tests_test_error_handlers_testerrorresponsemodel" + }, + { + "relation": "uses", + "confidence": "INFERRED", + "source_file": "tests/test_error_handlers.py", + "source_location": "L12", + "weight": 0.8, + "confidence_score": 0.5, + "source": "utils_errors_errorresponse", + "target": "tests_test_error_handlers_testrequestcontextfilter" + }, + { + "relation": "uses", + "confidence": "INFERRED", + "source_file": "tests/test_error_handlers.py", + "source_location": "L12", + "weight": 0.8, + "confidence_score": 0.5, + "source": "utils_errors_errorresponse", + "target": "tests_test_error_handlers_testhttpexceptionhandler" + }, + { + "relation": "uses", + "confidence": "INFERRED", + "source_file": "tests/test_error_handlers.py", + "source_location": "L12", + "weight": 0.8, + "confidence_score": 0.5, + "source": "utils_errors_errorresponse", + "target": "tests_test_error_handlers_testvalidationexceptionhandler" + }, + { + "relation": "uses", + "confidence": "INFERRED", + "source_file": "tests/test_error_handlers.py", + "source_location": "L12", + "weight": 0.8, + "confidence_score": 0.5, + "source": "utils_errors_errorresponse", + "target": "tests_test_error_handlers_testgenericexceptionhandler" + }, + { + "relation": "uses", + "confidence": "INFERRED", + "source_file": "tests/test_error_handlers.py", + "source_location": "L12", + "weight": 0.8, + "confidence_score": 0.5, + "source": "utils_errors_errorresponse", + "target": "tests_test_error_handlers_testsuccesspassthrough" + }, + { + "relation": "calls", + "context": "call", + "confidence": "INFERRED", + "confidence_score": 0.8, + "source_file": "tests/test_error_handlers.py", + "source_location": "L56", + "weight": 1.0, + "source": "utils_errors_errorresponse", + "target": "tests_test_error_handlers_testerrorresponsemodel_test_error_response_structure" + }, + { + "relation": "calls", + "context": "call", + "confidence": "INFERRED", + "confidence_score": 0.8, + "source_file": "tests/test_error_handlers.py", + "source_location": "L65", + "weight": 1.0, + "source": "utils_errors_errorresponse", + "target": "tests_test_error_handlers_testerrorresponsemodel_test_error_response_with_detail_and_request_id" + }, + { + "relation": "calls", + "context": "call", + "confidence": "EXTRACTED", + "source_file": "main/utils/errors.py", + "source_location": "L30", + "weight": 1.0, + "confidence_score": 1.0, + "source": "utils_errors_errorresponse", + "target": "utils_errors_build_error_response" + }, + { + "relation": "inherits", + "confidence": "EXTRACTED", + "source_file": "tests/test_error_handlers.py", + "source_location": "L20", + "weight": 1.0, + "confidence_score": 1.0, + "source": "basemodel", + "target": "tests_test_error_handlers_samplebody" + }, { "relation": "imports", "context": "import", @@ -73846,16 +75169,6 @@ "source": "prometheus_tools_set_state", "target": "tests_test_prometheus_tools_test_set_state_no_state_returns_error" }, - { - "relation": "rationale_for", - "confidence": "EXTRACTED", - "source_file": "main/app/prometheus/tools.py", - "source_location": "L92", - "weight": 1.0, - "confidence_score": 1.0, - "source": "prometheus_tools_set_state", - "target": "prometheus_tools_rationale_92" - }, { "relation": "rationale_for", "confidence": "EXTRACTED", @@ -123019,5 +124332,5 @@ "label": "User Authentication & Authorization" } ], - "built_at_commit": "733e8a8d08cf552370a4d1d9cc0494c471157153" + "built_at_commit": "5f72f66a6069e4eab04233b2f63287165e3c6e2e" } \ No newline at end of file diff --git a/graphify-out/manifest.json b/graphify-out/manifest.json index c34f206..1750976 100644 --- a/graphify-out/manifest.json +++ b/graphify-out/manifest.json @@ -10,13 +10,13 @@ "semantic_hash": "15d0716e706e3b84ad409efb247b485d" }, "D:\\Repositories\\server\\config.py": { - "mtime": 1786768590.5836227, + "mtime": 1786906805.9709556, "ast_hash": "8a3cb8faa46fcdbec1f60a953922d88a", "semantic_hash": "" }, "D:\\Repositories\\server\\run.py": { - "mtime": 1785518621.025705, - "ast_hash": "a69a0edf127343d048dfb0b99e8316d2", + "mtime": 1786910439.2384806, + "ast_hash": "8856c087c4c66080621d00487e4bc52c", "semantic_hash": "" }, "D:\\Repositories\\server\\frontend\\components.json": { @@ -45,8 +45,8 @@ "semantic_hash": "" }, "D:\\Repositories\\server\\frontend\\src\\App.jsx": { - "mtime": 1786815932.4997418, - "ast_hash": "bade3f9c54c62868817bfa5fa282e403", + "mtime": 1786832610.472853, + "ast_hash": "d4881ac3307fa1da25ddd87d238888d9", "semantic_hash": "" }, "D:\\Repositories\\server\\frontend\\src\\App.resume.test.jsx": { @@ -80,8 +80,8 @@ "semantic_hash": "" }, "D:\\Repositories\\server\\frontend\\src\\components\\MessageList.jsx": { - "mtime": 1785643884.1822786, - "ast_hash": "df3b45d04e7c9ea28e96275bc69ef1fd", + "mtime": 1786821222.7263086, + "ast_hash": "b452605e7bc482488e4d63a8dc241f78", "semantic_hash": "" }, "D:\\Repositories\\server\\frontend\\src\\components\\SessionSidebar.jsx": { @@ -90,8 +90,8 @@ "semantic_hash": "" }, "D:\\Repositories\\server\\frontend\\src\\components\\SettingsDialog.jsx": { - "mtime": 1786772885.0458639, - "ast_hash": "32c50d55395cd1a0a7a932b3c2150b74", + "mtime": 1786820946.0218458, + "ast_hash": "3f7f8fe1c78422e051c31e0b77833db5", "semantic_hash": "" }, "D:\\Repositories\\server\\frontend\\src\\components\\ui\\alert-dialog.jsx": { @@ -165,8 +165,8 @@ "semantic_hash": "" }, "D:\\Repositories\\server\\main\\app\\prometheus\\agent.py": { - "mtime": 1786818060.5129879, - "ast_hash": "de5913d8d5a0cdb2c969af8c998e18bc", + "mtime": 1786911668.173201, + "ast_hash": "e745fed9187a711f2470513cf32ee5c1", "semantic_hash": "" }, "D:\\Repositories\\server\\main\\app\\prometheus\\chat.py": { @@ -175,32 +175,32 @@ "semantic_hash": "" }, "D:\\Repositories\\server\\main\\app\\prometheus\\compact.py": { - "mtime": 1785703175.538699, - "ast_hash": "6809695afa66a3db4b47b92a4dda6888", + "mtime": 1786911619.4646873, + "ast_hash": "18157a3dbab303c03c11bc87643a6137", "semantic_hash": "" }, "D:\\Repositories\\server\\main\\app\\prometheus\\mcp.py": { - "mtime": 1785590230.8001673, - "ast_hash": "dfab26b6d240bbd4e77d3229034e3b5d", + "mtime": 1786897540.6096563, + "ast_hash": "89338f55a6fcc783e0f7bf3d9179a307", "semantic_hash": "" }, "D:\\Repositories\\server\\main\\app\\prometheus\\memory.py": { - "mtime": 1785590225.834715, - "ast_hash": "e70ae113b3677625b279117ede199e75", + "mtime": 1786897540.9170341, + "ast_hash": "d416e2ae2c12da02d0aaf2baabd709c4", "semantic_hash": "" }, "D:\\Repositories\\server\\main\\app\\prometheus\\sandbox.py": { - "mtime": 1786768212.6670675, + "mtime": 1786906805.9719558, "ast_hash": "2e36e0b848f09359bee8078c78eb970b", "semantic_hash": "" }, "D:\\Repositories\\server\\main\\app\\prometheus\\stream_bus.py": { - "mtime": 1786300943.613942, - "ast_hash": "1eb1d7bfc9bf6b5ea8719cde83dae8d6", + "mtime": 1786911622.373986, + "ast_hash": "6a80c42ab84489b8a70c1cd4e855c8e5", "semantic_hash": "" }, "D:\\Repositories\\server\\main\\app\\prometheus\\tools.py": { - "mtime": 1786771290.662009, + "mtime": 1786906805.9734619, "ast_hash": "39a7952d9fc6ce047e1e5800cd48f269", "semantic_hash": "" }, @@ -210,8 +210,8 @@ "semantic_hash": "" }, "D:\\Repositories\\server\\main\\app\\scraper_b3\\scraper.py": { - "mtime": 1785703925.0877438, - "ast_hash": "febb18ede2e34e554d8ed8184733c3c4", + "mtime": 1786906805.9759822, + "ast_hash": "9fc12a2e3982aa28fe9dc29ac082b67b", "semantic_hash": "" }, "D:\\Repositories\\server\\main\\app\\scraper_b3\\xango.py": { @@ -220,8 +220,8 @@ "semantic_hash": "0cbeed2304027b45b74b36f17b47cca7" }, "D:\\Repositories\\server\\main\\app\\stocks_api\\cache.py": { - "mtime": 1786491940.2229466, - "ast_hash": "bc4e7359f6e0e5fc44314d045001f062", + "mtime": 1786910244.3779006, + "ast_hash": "ea3f33c05d084fd6dd5cbc2e90827d9c", "semantic_hash": "" }, "D:\\Repositories\\server\\main\\app\\stocks_api\\compress.py": { @@ -235,12 +235,17 @@ "semantic_hash": "" }, "D:\\Repositories\\server\\main\\app\\stocks_api\\query.py": { - "mtime": 1785703925.0907328, - "ast_hash": "6c2d3fcf98784d8c50694d26fec68c9c", + "mtime": 1786906805.9779794, + "ast_hash": "0652cdbd830c3882a9b14291745ad5fb", + "semantic_hash": "" + }, + "D:\\Repositories\\server\\main\\app\\stocks_api\\sync_cache.py": { + "mtime": 1786897269.308236, + "ast_hash": "552746cc2b8399a52148fb811e352e27", "semantic_hash": "" }, "D:\\Repositories\\server\\main\\app\\stocks_api\\util.py": { - "mtime": 1785703925.0917397, + "mtime": 1786897651.6305304, "ast_hash": "c6d7b43581bbf065579cbc870f532b6d", "semantic_hash": "" }, @@ -255,18 +260,18 @@ "semantic_hash": "" }, "D:\\Repositories\\server\\main\\controller\\prometheus_controller.py": { - "mtime": 1786815835.338288, - "ast_hash": "5b91096c7b98ed3cb15fee3bdc4bd0da", + "mtime": 1786819455.8181014, + "ast_hash": "1b32c35cadbd166be60080af053e1fbc", "semantic_hash": "" }, "D:\\Repositories\\server\\main\\controller\\stocksapi_controller.py": { - "mtime": 1785695453.1617672, - "ast_hash": "aa4b7bfe47ace93dff52ec3ebbc76baf", + "mtime": 1786910450.1948988, + "ast_hash": "d8d6cef9351c99f43baf1f82795ec851", "semantic_hash": "" }, "D:\\Repositories\\server\\main\\controller\\user_controller.py": { - "mtime": 1785703931.6236646, - "ast_hash": "90f773bea9b5f44ce4f9836345e13c8f", + "mtime": 1786911618.0717938, + "ast_hash": "e1f57a197fe0949c592edf3fa1734fe4", "semantic_hash": "" }, "D:\\Repositories\\server\\main\\models\\base.py": { @@ -315,13 +320,13 @@ "semantic_hash": "646d1cc2f6a33ca9acfa8cf3e3b84531" }, "D:\\Repositories\\server\\main\\service\\authentication_service.py": { - "mtime": 1785622645.1873093, - "ast_hash": "a752470c722076944e8c4be1c483e61f", + "mtime": 1786910439.2364678, + "ast_hash": "68127fe1d44a44242ce3a5ed2bf4d464", "semantic_hash": "" }, "D:\\Repositories\\server\\main\\service\\prometheus_service.py": { - "mtime": 1785590689.9648468, - "ast_hash": "ed83f3dd138f56fd510d32d87f6577c1", + "mtime": 1786910439.237477, + "ast_hash": "620e625c8fca8ea37317df2ecd9de3fb", "semantic_hash": "" }, "D:\\Repositories\\server\\main\\service\\scraper_service.py": { @@ -330,13 +335,13 @@ "semantic_hash": "" }, "D:\\Repositories\\server\\main\\service\\stocksapi_service.py": { - "mtime": 1785695713.9659114, - "ast_hash": "296a5fb028c220b1abdb7cbd582f5cf7", + "mtime": 1786910439.2364678, + "ast_hash": "e80fad33af579abeccb25589703be3ad", "semantic_hash": "" }, "D:\\Repositories\\server\\main\\service\\user_service.py": { - "mtime": 1785590719.971278, - "ast_hash": "5e9f8746a29c4c37e1cc5e5a2622a873", + "mtime": 1786910439.237477, + "ast_hash": "8e127deee33d6ddd16040af24609ac1a", "semantic_hash": "" }, "D:\\Repositories\\server\\main\\utils\\connectivity.py": { @@ -345,8 +350,8 @@ "semantic_hash": "" }, "D:\\Repositories\\server\\main\\utils\\errors.py": { - "mtime": 1784738121.6744492, - "ast_hash": "22b2b4a5f0a7f1e659f2e3a2449b9f3f", + "mtime": 1786910321.3720095, + "ast_hash": "ec4e3edafb614b6fe5d36ad03a1a46ab", "semantic_hash": "" }, "D:\\Repositories\\server\\main\\utils\\http_session.py": { @@ -355,8 +360,8 @@ "semantic_hash": "0837b2c1f6a7f9e678f96844d4d1aadc" }, "D:\\Repositories\\server\\main\\utils\\logging_config.py": { - "mtime": 1785186140.7313354, - "ast_hash": "22b5bb5591c046f7e897be8f0ae7df3b", + "mtime": 1786897540.611656, + "ast_hash": "8f7c2f17ff2d4f0f94116fb8c1bcfe64", "semantic_hash": "" }, "D:\\Repositories\\server\\main\\utils\\migrator.py": { @@ -375,13 +380,13 @@ "semantic_hash": "" }, "D:\\Repositories\\server\\main\\utils\\service_manager.py": { - "mtime": 1785635297.01323, - "ast_hash": "e9021803ec60d4d52af9d21d6b0aad24", + "mtime": 1786910424.6665003, + "ast_hash": "2a191eb6030e1cb5327c50f43dce1b87", "semantic_hash": "" }, "D:\\Repositories\\server\\main\\utils\\models\\loader.py": { - "mtime": 1784695823.6144185, - "ast_hash": "5e25428347cd1e946ee54360b9031213", + "mtime": 1786897539.3964214, + "ast_hash": "53d7f85c943e3cac2acb81fb5ebe5a79", "semantic_hash": "" }, "D:\\Repositories\\server\\main\\utils\\models\\__init__.py": { @@ -470,7 +475,7 @@ "semantic_hash": "" }, "D:\\Repositories\\server\\TODO.md": { - "mtime": 1786310103.9541347, + "mtime": 1786897268.9688492, "ast_hash": "13818cf4bbf70ee14fe0d647c7e27c97", "semantic_hash": "" }, @@ -504,6 +509,11 @@ "ast_hash": "6dea783c1c379b193b0234febff9ed28", "semantic_hash": "" }, + "D:\\Repositories\\server\\docs\\superpowers\\plans\\2026-08-15-stocks-api-perf.md": { + "mtime": 1786832710.0980358, + "ast_hash": "cba293f917148b27cd7319e358a71a63", + "semantic_hash": "" + }, "D:\\Repositories\\server\\docs\\superpowers\\plans\\2026-08-15-workspace-endpoints.md": { "mtime": 1786767787.344132, "ast_hash": "b7a3455fd151d32d6fcc9577e8926105", @@ -518,5 +528,10 @@ "mtime": 1785641936.6961534, "ast_hash": "7bbc5e5a7693a5828d34f9f4d7eb8125", "semantic_hash": "" + }, + "D:\\Repositories\\server\\latency_benchmark.png": { + "mtime": 1786899358.7689898, + "ast_hash": "ed293a820c45972b2fc172cd513c0bc0", + "semantic_hash": "" } } \ No newline at end of file diff --git a/main/app/prometheus/agent.py b/main/app/prometheus/agent.py index 8597bc0..591f59e 100644 --- a/main/app/prometheus/agent.py +++ b/main/app/prometheus/agent.py @@ -13,23 +13,23 @@ from main.models.prometheus import PrometheusSession from main.app.prometheus.memory import PrometheusMemory from main.app.prometheus.chat import PrometheusChatManager -from main.app.prometheus.compact import PrometheusCompactor, fieldRegistry +from main.app.prometheus.compact import PrometheusCompactor, loadFieldData from main.app.prometheus.mcp import clientPool from main.app.prometheus.sandbox import SandboxManager from main.app.prometheus.tools import TOOL_REGISTRY, dispatchToolCall -_original_filter = _mcp._filter_to_supported_schema +originalFilter = _mcp._filter_to_supported_schema pendingExtractions: set[asyncio.Task] = set() -def _safe_filter(schema): +def safeFilter(schema): if not isinstance(schema, dict): return schema - return _original_filter(schema) + return originalFilter(schema) -_mcp._filter_to_supported_schema = _safe_filter +_mcp._filter_to_supported_schema = safeFilter logger = logging.getLogger(__name__) @@ -248,7 +248,7 @@ async def streamMessage(self, query=None, sessionId=None, db=None, user=None, fi if clientPool.clients is None: try: await clientPool.initialize() - fieldRegistry.getFields() + loadFieldData() except Exception as e: logger.warning("Pool/registry startup failed: %s", e) @@ -259,10 +259,15 @@ async def streamMessage(self, query=None, sessionId=None, db=None, user=None, fi if session and user: try: + async def extract() -> None: try: await asyncio.to_thread( - PrometheusMemory.extract, None, user.get("userId"), str(sessionId), user.get("roles", []) + PrometheusMemory.extract, + None, + user.get("userId"), + str(sessionId), + user.get("roles", []), ) except Exception as e: logger.debug("Memory extraction failed: %s", e) diff --git a/main/app/prometheus/compact.py b/main/app/prometheus/compact.py index 92f2d83..b45e946 100644 --- a/main/app/prometheus/compact.py +++ b/main/app/prometheus/compact.py @@ -52,7 +52,7 @@ def countTokens(text: str) -> int: result = tok.count_tokens(text) return result.total_tokens except Exception: - pass + pass # nosec: B110 best-effort token estimation, fallback to len//3 return len(text) // 3 @@ -86,67 +86,69 @@ def countTokens(text: str) -> int: ] -class FieldRegistry: - fields: list[str] | None = None - fetchedAt: float = 0 - ttl: float = 3600 +fieldData: dict | None = None +metricRegex: re.Pattern | None = None - def buildUrl(self) -> str: - host = Config.STOCKS_API.HOST - port = Config.STOCKS_API.PORT - return f"http://{host}:{port}/stocks/fields" - def fetchFields(self) -> list[str]: - try: - url = self.buildUrl() - req = Request(url, headers={"X-MCP": "true"}) - with urlopen(req, timeout=5) as resp: - data = json.loads(resp.read().decode("utf-8")) - - fields: list[str] = [] - historical = data.get("historical", {}) - if isinstance(historical, dict): - fields.extend(historical.keys()) - fundamental = data.get("fundamental", []) - if isinstance(fundamental, list): - fields.extend(fundamental) - - logger.info("FieldRegistry: fetched %d fields from Stocks API", len(fields)) - return list(dict.fromkeys(fields)) - except Exception as e: - logger.warning("FieldRegistry: failed to fetch fields, using fallback: %s", e) - return list(FALLBACK_FIELDS) - - def getFields(self) -> list[str]: - now = time.time() - if self.fields is None or (now - self.fetchedAt) > self.ttl: - self.fields = self.fetchFields() - self.fetchedAt = now - return self.fields - - def buildMetricRegex(self) -> re.Pattern: - fields = self.getFields() - escaped = [re.escape(f) for f in fields if len(f) > 1] - escaped.sort(key=len, reverse=True) - pattern = r"\b(" + "|".join(escaped) + r")\b" - return re.compile(pattern) +def loadFieldData() -> dict: + global fieldData + if fieldData is None: + from config import stocksEngine + from main.app.stocks_api.cache import stocksCache + + fieldData = {"historical": [], "fundamental": []} + if stocksCache.STOCKS_CACHE is None: + return fieldData + + cols = stocksCache.STOCKS_CACHE.columns.tolist() + historicalFields = {} + fundamentalCols = [] + for col in cols: + parts = col.split() + if len(parts) >= 2 and parts[-1].isdigit(): + field = " ".join(parts[:-1]) + historicalFields[field] = True + elif col not in ["TICKER", "NOME", "TIME"]: + fundamentalCols.append(col) + + fieldData["historical"] = list(historicalFields.keys()) + fieldData["fundamental"] = fundamentalCols + return fieldData + - def getMetricRegex(self) -> re.Pattern: - if not hasattr(self, "metricRegex") or self.fields is None: - self.metricRegex = self.buildMetricRegex() - return self.metricRegex +def getHistoricalFields() -> list[str]: + return loadFieldData()["historical"] -fieldRegistry = FieldRegistry() +def getFundamentalColumns() -> list[str]: + return loadFieldData()["fundamental"] + + +def invalidateFieldData(): + global fieldData, metricRegex + fieldData = None + metricRegex = None + + +def getMetricRegex() -> re.Pattern: + global metricRegex + if metricRegex is None: + data = loadFieldData() + fields = data["historical"] + data["fundamental"] + escaped = [re.escape(f) for f in fields if len(f) > 1] + escaped.sort(key=len, reverse=True) + pattern = r"\b(" + "|".join(escaped) + r")\b" + metricRegex = re.compile(pattern) + return metricRegex def extractTickers(text: str) -> list[str]: return list(dict.fromkeys(TICKER_RE.findall(text))) -def extractMetrics(text: str, registry: FieldRegistry | None = None) -> list[str]: - if registry is not None: - regex = registry.getMetricRegex() +def extractMetrics(text: str, useRegistry: bool = False) -> list[str]: + if useRegistry: + regex = getMetricRegex() else: escaped = [re.escape(f) for f in FALLBACK_FIELDS if len(f) > 1] escaped.sort(key=len, reverse=True) @@ -219,9 +221,6 @@ def buildSummary( class PrometheusCompactor: - def __init__(self): - self.registry = fieldRegistry - def shouldCompact(self, history: list) -> bool: if not history: return False @@ -245,7 +244,7 @@ def extractEpisode(self, chunk: list[dict]) -> dict: allText = " ".join(m.get("content", "") for m in chunk if m.get("content")) tickers = extractTickers(allText) - metrics = extractMetrics(allText, registry=self.registry) + metrics = extractMetrics(allText, useRegistry=True) decisions = extractDecisions(userMessages) snapshots = extractSnapshots(toolResults) tools = extractToolCalls(loopEvents) diff --git a/main/app/prometheus/mcp.py b/main/app/prometheus/mcp.py index 3c23a7f..aeeca73 100644 --- a/main/app/prometheus/mcp.py +++ b/main/app/prometheus/mcp.py @@ -93,7 +93,7 @@ async def close(self): try: await client.__aexit__(None, None, None) except Exception: - pass + pass # nosec: B110 best-effort per-client cleanup self.clients = None diff --git a/main/app/prometheus/memory.py b/main/app/prometheus/memory.py index bf9d3e5..8673512 100644 --- a/main/app/prometheus/memory.py +++ b/main/app/prometheus/memory.py @@ -28,7 +28,6 @@ "feedback": 10.0, # medium - sticky "context": 3.0, # ephemeral - forgets fast } -DEFAULT_INITIAL_STABILITY = 7.0 MEMORY_EXTRACTION_TOKEN_BUDGET = 32000 MEMORY_EXTRACT_FREE_CAP = 5 @@ -157,7 +156,7 @@ def upsertMemory( source=source, embedding=embedding, contentHash=contentHash(value), - score=INITIAL_STABILITY.get(str(memoryType), DEFAULT_INITIAL_STABILITY), + score=INITIAL_STABILITY.get(str(memoryType)), lastAccessedAt=datetime.now(), ) db.add(memory) @@ -337,7 +336,9 @@ def extract(db: Session | None = None, userId=None, sessionId=None, userRoles=No if ownSession: db = SessionLocal() try: - assert db is not None + if db is None: + logger.error("Failed to acquire DB session for memory search") + return [] if not Roles.checkAccess(userRoles, Permission.USE_PROMETHEUS): return [] cap = ( diff --git a/main/app/prometheus/stream_bus.py b/main/app/prometheus/stream_bus.py index 710cbd5..25a94b4 100644 --- a/main/app/prometheus/stream_bus.py +++ b/main/app/prometheus/stream_bus.py @@ -28,20 +28,20 @@ def publish(self, event: dict) -> None: class StreamBus: def __init__(self) -> None: - self._channels: dict[str, StreamChannel] = {} + self.channels: dict[str, StreamChannel] = {} def getOrCreate(self, sessionId: str) -> StreamChannel: - ch = self._channels.get(sessionId) + ch = self.channels.get(sessionId) if ch is None: ch = StreamChannel() - self._channels[sessionId] = ch + self.channels[sessionId] = ch return ch def publish(self, sessionId: str, event: dict) -> None: self.getOrCreate(sessionId).publish(event) def subscribe(self, sessionId: str, cursor: int = 0) -> tuple[asyncio.Queue, StreamChannel] | None: - ch = self._channels.get(sessionId) + ch = self.channels.get(sessionId) if ch is None: return None q: asyncio.Queue = asyncio.Queue(maxsize=1000) @@ -54,7 +54,7 @@ def subscribe(self, sessionId: str, cursor: int = 0) -> tuple[asyncio.Queue, Str return q, ch def unsubscribe(self, sessionId: str, q: asyncio.Queue) -> None: - ch = self._channels.get(sessionId) + ch = self.channels.get(sessionId) if ch: ch.subscribers.discard(q) @@ -65,7 +65,7 @@ def startRun(self, sessionId: str, runner_factory: Callable[[], AsyncIterator[di ch.events.clear() ch.finished = False - async def _run() -> None: + async def run() -> None: try: async for event in runner_factory(): ch.publish(event) @@ -78,7 +78,7 @@ async def _run() -> None: ch.finished = True ch.publish({"type": "done"}) - ch.task = asyncio.get_running_loop().create_task(_run()) + ch.task = asyncio.get_running_loop().create_task(run()) async def forward(self, sessionId: str, cursor: int = 0) -> AsyncIterator[str]: sub = self.subscribe(sessionId, cursor) diff --git a/main/app/scraper_b3/scraper.py b/main/app/scraper_b3/scraper.py index 0955750..c16d346 100644 --- a/main/app/scraper_b3/scraper.py +++ b/main/app/scraper_b3/scraper.py @@ -25,6 +25,11 @@ warnings.filterwarnings("ignore", category=RuntimeWarning) +# Allowlist for column names interpolated into SQL (defense in depth: +# column names come from the live DB schema, not user input, but a +# strict pattern prevents any future source from breaking the query) +SAFE_COLUMN_RE = re.compile(r"^[A-Za-z0-9][A-Za-z0-9 _]*$") + def getCurrentSelic(): selic = pd.DataFrame( @@ -611,6 +616,7 @@ def exportMysql(self, df): for col in existingCols if any(pattern in col for pattern in historicalPatterns) and col not in JSON_COLUMNS ] + historicalCols = [col for col in historicalCols if SAFE_COLUMN_RE.match(col) is not None] if historicalCols: conn.execute( @@ -626,7 +632,8 @@ def exportMysql(self, df): for col in historicalCols: conn.execute( - text(f""" + text( + f""" INSERT INTO tmp_prev_historical (TICKER, COL_NAME, VAL) SELECT t1.TICKER, :col, t1.`{col}` FROM b3_stocks t1 @@ -637,7 +644,8 @@ def exportMysql(self, df): GROUP BY TICKER ) latest ON t1.TICKER = latest.TICKER AND t1.TIME = latest.MAX_TIME WHERE t1.`{col}` IS NOT NULL - """), + """ # nosec: B608 + ), {"col": col, "currentDate": currentDate}, ) @@ -648,7 +656,7 @@ def exportMysql(self, df): SET s.`{col}` = COALESCE(s.`{col}`, prev.VAL) WHERE s.`{col}` IS NULL AND s.TIME >= :currentDate; - """ + """ # nosec: B608 conn.execute(text(mergeSql), {"col": col, "currentDate": currentDate}) conn.execute(text("DROP TEMPORARY TABLE tmp_prev_historical")) diff --git a/main/app/stocks_api/cache.py b/main/app/stocks_api/cache.py index 8db1884..215982d 100644 --- a/main/app/stocks_api/cache.py +++ b/main/app/stocks_api/cache.py @@ -12,14 +12,13 @@ from apscheduler.schedulers.background import BackgroundScheduler import os -import subprocess +import subprocess # nosec: B404 used only with constant args, see line 302 import sys import time import zstandard as zstd from datetime import datetime, timezone from pathlib import Path from typing import Any -import sys fcntl: Any = None if sys.platform != "win32": @@ -132,7 +131,7 @@ def buildFeatherCache(): try: result.close() except Exception: - pass + pass # nosec: B110 best-effort writer/sink close, retried next refresh finally: if writer is not None: writer.close() @@ -229,7 +228,7 @@ def getCachedStocks(self, force_refresh: bool = False): "from main.app.stocks_api.cache import buildFeatherCache; buildFeatherCache()", ], check=True, - ) + ) # nosec: B603 constant args, no untrusted input finally: lockFile.close() finally: diff --git a/main/app/stocks_api/query.py b/main/app/stocks_api/query.py index e39b32c..02624d0 100644 --- a/main/app/stocks_api/query.py +++ b/main/app/stocks_api/query.py @@ -107,7 +107,7 @@ def filterBySearchTerms(self, df: pd.DataFrame, search: str) -> pd.DataFrame: mask = df["TICKER"].str.upper().apply(lambda t: any(t.startswith(term) for term in searchTerms)) return df[mask] - async def queryHistorical( + def queryHistorical( self, search: str | None = None, fields: str | None = None, @@ -183,11 +183,13 @@ async def queryHistorical( "count": len(df), "data": sanitizeNanValues(df.to_dict(orient="records")), } + except HTTPException: + raise except Exception as e: logger.exception("Cached historical query failed") raise HTTPException(status_code=500, detail="Internal server error while processing historical data") - async def queryFundamental( + def queryFundamental( self, search: str | None = None, fields: str | None = None, @@ -276,7 +278,7 @@ async def queryFundamental( logger.exception("Cached fundamental query failed") raise HTTPException(status_code=500, detail="Internal server error while processing fundamental data") - async def queryCotations( + def queryCotations( self, search: str | None = None, dates: str | None = None, @@ -329,7 +331,7 @@ async def queryCotations( logger.exception("Cached cotations query failed") raise HTTPException(status_code=500, detail="Internal server error while processing cotations data") - async def queryLiveCotation(self, search: str): + def queryLiveCotation(self, search: str): try: resp = getSession().get( f"https://cotacao.b3.com.br/mds/api/v1/instrumentQuotation/{search.upper()}", diff --git a/main/app/stocks_api/sync_cache.py b/main/app/stocks_api/sync_cache.py new file mode 100644 index 0000000..8cc99b2 --- /dev/null +++ b/main/app/stocks_api/sync_cache.py @@ -0,0 +1,30 @@ +import asyncio +from functools import wraps +from typing import Any, Callable, TypeVar + +from cashews import cache +from cashews.key import get_cache_key + +try: + from cashews.defaults import _empty as _MISS +except ImportError: # pragma: no cover - private import fallback + _MISS = object() + +F = TypeVar("F", bound=Callable[..., Any]) + + +def sync_cache(ttl: str, key: str) -> Callable[[F], F]: + def decorator(func: F) -> F: + @wraps(func) + def wrapper(*args: Any, **kwargs: Any) -> Any: + cache_key = get_cache_key(func, key, args, kwargs) + cached = asyncio.run(cache.get(cache_key, default=_MISS)) + if cached is not _MISS: + return cached + result = func(*args, **kwargs) + asyncio.run(cache.set(cache_key, result, expire=ttl)) + return result + + return wrapper # type: ignore[return-value] + + return decorator diff --git a/main/controller/stocksapi_controller.py b/main/controller/stocksapi_controller.py index dd26f74..325f657 100644 --- a/main/controller/stocksapi_controller.py +++ b/main/controller/stocksapi_controller.py @@ -1,10 +1,9 @@ from datetime import datetime, timezone import logging -import orjson + from cashews import cache from fastapi import APIRouter, Depends, Query, HTTPException, Response -from fastapi.responses import Response as FastAPIResponse from main.app.stocks_api.query import stocksQuery @@ -12,6 +11,7 @@ from main.app.stocks_api.util import categorizeColumns, generateAbbreviations from main.app.stocks_api.compress import compressResponse, getNest from main.app.stocks_api.cache import stocksCache +from main.app.stocks_api.sync_cache import sync_cache logger = logging.getLogger(__name__) @@ -20,13 +20,6 @@ router = APIRouter(prefix="/stocks", tags=["Stocks API"]) -class JSONBytesResponse(FastAPIResponse): - media_type = "application/json" - - def render(self, content): - return content if isinstance(content, bytes) else str(content).encode(self.charset) - - @router.get("/health") def health(): updatedAt = stocksCache.lastCacheUpdate @@ -88,9 +81,9 @@ def listFields(): return {"historical": historical, "fundamental": fundamental, "abbreviations": abbreviations, "nested": nested} -@router.get("/historical", operation_id="get_historical", response_class=JSONBytesResponse) -@cache(ttl="1h", key="stocks:historical:{search}:{fields}:{dates}:{orderBy}:{limit}:{compact}") -async def getHistorical( +@router.get("/historical", operation_id="get_historical") +@sync_cache(ttl="1h", key="stocks:historical:{search}:{fields}:{dates}:{orderBy}:{limit}:{compact}") +def getHistorical( response: Response, search: str = Query(None, max_length=3780, pattern=r"^[A-Za-z0-9,\s]*$"), fields: str = Query(None, max_length=500, pattern=r"^[A-Za-z0-9,\s/.-]+$"), @@ -110,7 +103,8 @@ async def getHistorical( - `search` (optional): Comma-separated ticker symbols to filter. Examples: "PETR4", "PETR4,VALE3", "ITUB4,BBDC4". Case-insensitive. Supports prefix matching (e.g. "PET" matches PETR4, PETR3). - If omitted, returns all stocks in the database. + If omitted, returns all stocks in the database. An empty request (no + search/fields/dates) returns HTTP 400. - `fields` (optional): Comma-separated metric names (WITHOUT year suffix). Examples: "LUCRO LIQUIDO", "LUCRO LIQUIDO,RECEITA LIQUIDA,EBITDA". @@ -145,16 +139,16 @@ async def getHistorical( - Get PETR4 net income 2022-2024: search="PETR4", fields="LUCRO LIQUIDO", dates="2022,2024" - Get all revenue data for VALE3: search="VALE3", fields="RECEITA LIQUIDA" - Compare top 10 by EBITDA: fields="EBITDA", orderBy="EBITDA", limit=10""" - result = await stocksQuery.queryHistorical(search, fields, dates, orderBy, limit) + response.headers["Cache-Control"] = "public, max-age=300" + result = stocksQuery.queryHistorical(search, fields, dates, orderBy, limit) if compact: result = compressResponse(result, "get_historical", {"search": search, "fields": fields, "dates": dates}) - response.headers["Cache-Control"] = "public, max-age=300" - return orjson.dumps(result) + return result -@router.get("/fundamental", operation_id="get_fundamental", response_class=JSONBytesResponse) -@cache(ttl="5m", key="stocks:fundamental:{search}:{fields}:{dates}:{orderBy}:{limit}:{compact}") -async def getFundamental( +@router.get("/fundamental", operation_id="get_fundamental") +@sync_cache(ttl="5m", key="stocks:fundamental:{search}:{fields}:{dates}:{orderBy}:{limit}:{compact}") +def getFundamental( response: Response, search: str = Query(None, max_length=3780, pattern=r"^[A-Za-z0-9,\s]*$"), fields: str = Query(None, max_length=500, pattern=r"^[A-Za-z0-9,\s/.-]+$"), @@ -189,7 +183,8 @@ async def getFundamental( Example: "2024-01-15" → closest snapshot to Jan 15, 2024. * "START,END" → range: returns all snapshots between START and END dates. Example: "2024-01-01,2024-06-30" → all Q1-Q2 2024 snapshots. - If omitted, returns the most recent snapshot for each stock. + If omitted, returns the most recent snapshot for each stock. An empty + request (no search/fields/dates) returns HTTP 400. - `orderBy` (optional): Sort results by a column name (descending). - `limit` (optional): Maximum number of stocks to return (1-1000). @@ -214,16 +209,16 @@ async def getFundamental( - Get all stocks' dividend yield latest: fields="DY" - Compare P/L across tickers: search="PETR4,VALE3,ITUB4", fields="P/L", orderBy="P/L" - Q1 2024 fundamental snapshot: fields="P/L,ROE", dates="2024-01-01,2024-03-31" """ - result = await stocksQuery.queryFundamental(search, fields, dates, orderBy, limit) + response.headers["Cache-Control"] = "public, max-age=300" + result = stocksQuery.queryFundamental(search, fields, dates, orderBy, limit) if compact: result = compressResponse(result, "get_fundamental", {"search": search, "fields": fields, "dates": dates}) - response.headers["Cache-Control"] = "public, max-age=300" - return orjson.dumps(result) + return result -@router.get("/cotations", operation_id="get_cotations", response_class=JSONBytesResponse) -@cache(ttl="5m", key="stocks:cotations:{search}:{dates}:{adjusted}:{compact}") -async def getCotations( +@router.get("/cotations", operation_id="get_cotations") +@sync_cache(ttl="5m", key="stocks:cotations:{search}:{dates}:{adjusted}:{compact}") +def getCotations( response: Response, search: str = Query(..., min_length=1, max_length=3780, pattern=r"^[A-Za-z0-9,\s]*$"), dates: str = Query(None, max_length=21), @@ -270,16 +265,16 @@ async def getCotations( - Get PETR4 full price history: search="PETR4" - Get PETR4 + VALE3 2023 prices: search="PETR4,VALE3", dates="2023-01-01,2023-12-31" - Get inflation-adjusted prices: search="ITUB4", adjusted=true""" - result = await stocksQuery.queryCotations(search, dates, adjusted) + response.headers["Cache-Control"] = "public, max-age=300" + result = stocksQuery.queryCotations(search, dates, adjusted) if compact: result = compressResponse(result, "get_cotations", {"search": search, "dates": dates}) - response.headers["Cache-Control"] = "public, max-age=300" - return orjson.dumps(result) + return result -@router.get("/cotations/live", operation_id="get_live_price", response_class=JSONBytesResponse) -@cache(ttl="15s", key="stocks:live:{search}:{compact}") -async def getLiveCotation( +@router.get("/cotations/live", operation_id="get_live_price") +@sync_cache(ttl="15s", key="stocks:live:{search}:{compact}") +def getLiveCotation( response: Response, search: str = Query(..., min_length=1, max_length=7, pattern=r"^[A-Za-z0-9,\s]*$"), compact: bool = Query(False), @@ -315,8 +310,8 @@ async def getLiveCotation( - Only one ticker per request (max 7 chars for the search param). - Real-time data is only available during B3 market hours (10:00-17:30 BRT). - Outside market hours, returns the last available closing price.""" - result = await stocksQuery.queryLiveCotation(search) + response.headers["Cache-Control"] = "public, max-age=15" + result = stocksQuery.queryLiveCotation(search) if compact: result = compressResponse(result, "get_live_price", {"search": search}) - response.headers["Cache-Control"] = "public, max-age=15" - return orjson.dumps(result) + return result diff --git a/main/controller/user_controller.py b/main/controller/user_controller.py index 6b9e78c..1124357 100644 --- a/main/controller/user_controller.py +++ b/main/controller/user_controller.py @@ -13,6 +13,22 @@ router = APIRouter(prefix="/user", tags=["User"]) +def sessionToDict(s, isCurrent=False): + return { + "sessionId": s.sessionId, + "deviceName": SessionManager.getDeviceName(s), + "browser": s.browser, + "os": s.operatingSystem, + "deviceType": s.deviceType, + "lastActiveAt": s.lastActivityAt.isoformat() if s.lastActivityAt else None, + "createdAt": s.createdAt.isoformat() if s.createdAt else None, + "isActive": s.isActive, + "isCurrent": isCurrent, + "userAgent": s.userAgent, + } + + + @router.get("/health") def health(request: Request): return {"status": "ok", "service": "user"} @@ -48,17 +64,7 @@ def getSessions( return { "sessions": [ - { - "sessionId": s.sessionId, - "deviceName": SessionManager.getDeviceName(s), - "browser": s.browser, - "os": s.operatingSystem, - "deviceType": s.deviceType, - "lastActiveAt": s.lastActivityAt.isoformat() if s.lastActivityAt else None, - "createdAt": s.createdAt.isoformat() if s.createdAt else None, - "isActive": s.isActive, - "isCurrent": s.sessionId == currentSessionId if currentSessionId else False, - } + sessionToDict(s, s.sessionId == currentSessionId if currentSessionId else False) for s in paginatedSessions ], "total": total, @@ -78,16 +84,7 @@ def getCurrentSession( if not session: raise HTTPException(status_code=404, detail="Current session not found") - return { - "sessionId": session.sessionId, - "deviceName": SessionManager.getDeviceName(session), - "browser": session.browser, - "os": session.operatingSystem, - "deviceType": session.deviceType, - "userAgent": session.userAgent, - "lastActiveAt": session.lastActivityAt.isoformat() if session.lastActivityAt else None, - "createdAt": session.createdAt.isoformat() if session.createdAt else None, - } + return sessionToDict(session) @router.delete("/sessions/{sessionId}") diff --git a/main/service/authentication_service.py b/main/service/authentication_service.py index 4a635ff..340c053 100644 --- a/main/service/authentication_service.py +++ b/main/service/authentication_service.py @@ -2,14 +2,14 @@ from starlette.middleware.sessions import SessionMiddleware -from main.utils.service_manager import ServiceManager +from main.utils.service_manager import getApp from main.controller.authentication_controller import router as authenticationRouter class AuthenticationService: @staticmethod def initialize(port: int): - service = ServiceManager.getApp(port) + service = getApp(port) service.add_middleware( SessionMiddleware, secret_key=Config.USER.SESSION_SECRET_KEY, same_site="lax", https_only=False diff --git a/main/service/prometheus_service.py b/main/service/prometheus_service.py index 177033b..be216f3 100644 --- a/main/service/prometheus_service.py +++ b/main/service/prometheus_service.py @@ -5,7 +5,7 @@ from sqlalchemy.orm import Session from apscheduler.schedulers.background import BackgroundScheduler -from main.utils.service_manager import ServiceManager +from main.utils.service_manager import getApp from main.models.memory import PrometheusMemory @@ -22,7 +22,9 @@ def memoryMaintenance(db: Session | None = None): if ownSession: db = SessionLocal() try: - assert db is not None + if db is None: + logger.error("Failed to acquire DB session for memory maintenance") + return nowNaive = datetime.now().replace(tzinfo=None) active = db.query(PrometheusMemory).filter(PrometheusMemory.archivedAt.is_(None)).all() @@ -59,7 +61,7 @@ def memoryMaintenance(db: Session | None = None): class PrometheusService: @staticmethod def initialize(port: int): - service = ServiceManager.getApp(port) + service = getApp(port) service.include_router(prometheusRouter) getEmbeddingModel() diff --git a/main/service/stocksapi_service.py b/main/service/stocksapi_service.py index 205ae2c..690f1cc 100644 --- a/main/service/stocksapi_service.py +++ b/main/service/stocksapi_service.py @@ -1,7 +1,7 @@ from fastapi_mcp import FastApiMCP from fastapi.middleware.gzip import GZipMiddleware -from main.utils.service_manager import ServiceManager +from main.utils.service_manager import getApp from main.controller.stocksapi_controller import router as stocksRouter from main.app.stocks_api.cache import stocksCache @@ -26,7 +26,7 @@ async def __call__(self, scope, receive, send): class StocksAPIService: @staticmethod def initialize(port: int): - service = ServiceManager.getApp(port) + service = getApp(port) service.add_middleware(MCPDetectMiddleware) service.include_router(stocksRouter) service.add_middleware(GZipMiddleware, minimum_size=4096, compresslevel=3) diff --git a/main/service/user_service.py b/main/service/user_service.py index 2852bef..d1b1315 100644 --- a/main/service/user_service.py +++ b/main/service/user_service.py @@ -7,7 +7,7 @@ from main.models.user_session import UserSession from main.app.authentication.constants import SESSION_EXPIRY_DAYS -from main.utils.service_manager import ServiceManager +from main.utils.service_manager import getApp from main.controller.user_controller import router as userRouter logger = logging.getLogger(__name__) @@ -39,7 +39,7 @@ class UserService: @staticmethod def initialize(port: int): global scheduler - service = ServiceManager.getApp(port) + service = getApp(port) service.include_router(userRouter) scheduler = BackgroundScheduler() diff --git a/main/utils/errors.py b/main/utils/errors.py index 1f084cf..c72f9ac 100644 --- a/main/utils/errors.py +++ b/main/utils/errors.py @@ -5,7 +5,6 @@ from fastapi.exceptions import RequestValidationError from fastapi.responses import JSONResponse from pydantic import BaseModel - from main.utils.request_id import requestIdVar diff --git a/main/utils/logging_config.py b/main/utils/logging_config.py index 9cfac00..78d4abf 100644 --- a/main/utils/logging_config.py +++ b/main/utils/logging_config.py @@ -68,7 +68,7 @@ def sender(): try: requests.post(Config.DISCORD.WEBHOOK_URL, json={"content": msg}, timeout=10) except Exception: - pass + pass # nosec: B110 per-message send failure swallowed, retried on next tick time.sleep(0.45) # ~5 msgs/2s, under discord rate limit t = threading.Thread(target=sender, daemon=True, name="discord-sender") diff --git a/main/utils/models/loader.py b/main/utils/models/loader.py index 4c97432..680ae6b 100644 --- a/main/utils/models/loader.py +++ b/main/utils/models/loader.py @@ -13,10 +13,13 @@ def getEmbeddingModel() -> SentenceTransformer: global model if model is None: if not (MODEL_DIR / "model.safetensors").exists(): + # Revision pinned to a verified commit for supply-chain reproducibility + # (bandit B615: "main" is a moving target). Bump deliberately when + # intentionally updating the embedding model. snapshot_download( MODEL_ID, local_dir=str(MODEL_DIR), - revision="main", + revision="1110a243fdf4706b3f48f1d95db1a4f5529b4d41", ignore_patterns=["*.bin", "*.h5", "*.ot", "*.onnx", "*.openvino*"], ) model = SentenceTransformer(str(MODEL_DIR)) diff --git a/main/utils/service_manager.py b/main/utils/service_manager.py index 716faef..3037d6c 100644 --- a/main/utils/service_manager.py +++ b/main/utils/service_manager.py @@ -11,42 +11,39 @@ logger = logging.getLogger(__name__) +_instances: dict[int, FastAPI] = {} -class ServiceManager: - instances: dict[int, FastAPI] = {} - @classmethod - def getApp(cls, port: int) -> FastAPI: - if port in cls.instances: - return cls.instances[port] +def getApp(port: int) -> FastAPI: + if port in _instances: + return _instances[port] - app = FastAPI(title=f"Mansa Service {port}") - app.state.limiter = limiter + app = FastAPI(title=f"Mansa Service {port}") + app.state.limiter = limiter - @app.exception_handler(RateLimitExceeded) - async def rateLimitExceededHandler(request: Request, exc: RateLimitExceeded): - return JSONResponse(status_code=429, content={"detail": "Too many requests", "error": str(exc.detail)}) + @app.exception_handler(RateLimitExceeded) + async def rateLimitExceededHandler(request: Request, exc: RateLimitExceeded): + return JSONResponse(status_code=429, content={"detail": "Too many requests", "error": str(exc.detail)}) - app.add_middleware( - CORSMiddleware, - allow_origin_regex=r"https?://(localhost|127\.0\.0\.1|0\.0\.0\.0)(:\d+)?", - allow_credentials=True, - allow_methods=["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"], - allow_headers=["*"], - ) + app.add_middleware( + CORSMiddleware, + allow_origin_regex=r"https?://(localhost|127\.0\.0\.1|0\.0\.0\.0)(:\d+)?", + allow_credentials=True, + allow_methods=["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"], + allow_headers=["*"], + ) - cls.instances[port] = app - return app + _instances[port] = app + return app - @classmethod - def runAll(cls): - logLevel = "error" if Config.DEBUG_MODE else "critical" - def runUvicorn(app: FastAPI, port: int, logLevel: str): - uvicorn.run(app, host="0.0.0.0", port=port, log_level=logLevel) # nosec: B104 +def runAll(): + logLevel = "error" if Config.DEBUG_MODE else "critical" - for port, app in cls.instances.items(): - thread = threading.Thread(target=runUvicorn, args=(app, port, logLevel), daemon=True) - thread.start() + def runUvicorn(app: FastAPI, port: int, logLevel: str): + uvicorn.run(app, host="0.0.0.0", port=port, log_level=logLevel) # nosec: B104 - logger.info(f"Service running on port {port}") + for port, app in _instances.items(): + thread = threading.Thread(target=runUvicorn, args=(app, port, logLevel), daemon=True) + thread.start() + logger.info(f"Service running on port {port}") diff --git a/run.py b/run.py index f0f248d..8b37298 100644 --- a/run.py +++ b/run.py @@ -7,7 +7,7 @@ from config import Config, LOCALHOST_ADDRESSES from main.utils.connectivity import checkDatabaseConnection, checkServiceConnection -from main.utils.service_manager import ServiceManager +from main.utils.service_manager import runAll from main.utils.migrator import runMigrations from main.utils.request_id import RequestIDMiddleware from main.utils.errors import registerErrorHandlers @@ -63,7 +63,7 @@ async def lifespan(app: FastAPI): if Config.SCRAPER.ENABLED: ScraperService.initialize() - ServiceManager.runAll() + runAll() logger.info("All services initialized!") yield diff --git a/tests/test_compact.py b/tests/test_compact.py index 06635d8..21b67a9 100644 --- a/tests/test_compact.py +++ b/tests/test_compact.py @@ -10,10 +10,10 @@ buildSummary, countTokens, getTokenizer, - FieldRegistry, FALLBACK_FIELDS, PrometheusCompactor, EPISODE_CAP, + getMetricRegex, ) @@ -61,54 +61,6 @@ def test_uses_fallback_when_no_registry(self): assert "P/L" in result -class TestFieldRegistry: - def test_module_level_instance_is_shared(self): - from main.app.prometheus.compact import fieldRegistry - - compactor = PrometheusCompactor() - assert compactor.registry is fieldRegistry - - def test_new_instances_are_distinct(self): - r1 = FieldRegistry() - r2 = FieldRegistry() - assert r1 is not r2 - - def test_fallback_fields_on_api_failure(self): - registry = FieldRegistry() - fields = registry.fetchFields() - assert "P/L" in fields - assert "ROE" in fields - assert len(fields) >= 20 - - def test_build_metric_regex(self): - registry = FieldRegistry() - registry.fields = ["P/L", "ROE", "DY", "CAGR LUCROS 10 ANOS"] - regex = registry.buildMetricRegex() - assert "P/L" in regex.pattern - assert "ROE" in regex.pattern - idx_cagr = regex.pattern.find("CAGR LUCROS 10 ANOS") - idx_pl = regex.pattern.find("P/L") - assert idx_cagr < idx_pl - - def test_get_fields_refetches_when_ttl_expired(self): - registry = FieldRegistry() - registry.fields = ["P/L"] - registry.fetchedAt = 0 - with patch.object(registry, "fetchFields", return_value=["ROE"]): - fields = registry.getFields() - assert fields == ["ROE"] - assert registry.fetchedAt > 0 - - def test_get_fields_caches_within_ttl(self): - registry = FieldRegistry() - registry.fields = ["P/L"] - registry.fetchedAt = time.time() - with patch.object(registry, "fetchFields") as mockFetch: - fields = registry.getFields() - assert fields == ["P/L"] - mockFetch.assert_not_called() - - class TestExtractDecisions: def test_preference(self): msgs = [{"content": "Prefiro ações de dividendos"}] @@ -240,7 +192,7 @@ def test_extract_uses_field_registry(self): result = self.compactor.extractEpisode(chunk) mockExtract.assert_called_once() callArgs = mockExtract.call_args - assert callArgs[1].get("registry") is not None or callArgs[0][1] is not None + assert callArgs[1].get("useRegistry") is True or callArgs[0][1] is True def test_consolidate_under_cap(self): episodes = [{"id": f"ep_{i}", "summary": f"Episode {i}"} for i in range(5)] @@ -261,10 +213,6 @@ def test_consolidate_preserves_decisions(self): merged = result[0] assert len(merged["keyDecisions"]) == 5 - def test_has_field_registry(self): - assert self.compactor.registry is not None - assert isinstance(self.compactor.registry, FieldRegistry) - def test_get_episodes_empty_session(self): mockDb = MagicMock() mockDb.query.return_value.filter.return_value.first.return_value = None diff --git a/tests/test_controllers_coverage.py b/tests/test_controllers_coverage.py index 5fe5ef0..bfe7457 100644 --- a/tests/test_controllers_coverage.py +++ b/tests/test_controllers_coverage.py @@ -1105,7 +1105,7 @@ class TestStocksApiHistorical: def test_get_historical(self): """Covers line 35.""" with patch("main.controller.stocksapi_controller.stocksQuery") as mock_query: - mock_query.queryHistorical = AsyncMock(return_value={"data": [{"ticker": "PETR4", "price": 30.0}]}) + mock_query.queryHistorical = MagicMock(return_value={"data": [{"ticker": "PETR4", "price": 30.0}]}) client, _, _ = _make_stocksapi_client(mock_api_key="key") resp = client.get("/stocks/historical?search=PETR4&limit=10") @@ -1119,7 +1119,7 @@ class TestStocksApiFundamental: def test_get_fundamental(self): """Covers line 47.""" with patch("main.controller.stocksapi_controller.stocksQuery") as mock_query: - mock_query.queryFundamental = AsyncMock(return_value={"data": [{"ticker": "VALE3", "pl": 5.0}]}) + mock_query.queryFundamental = MagicMock(return_value={"data": [{"ticker": "VALE3", "pl": 5.0}]}) client, _, _ = _make_stocksapi_client(mock_api_key="key") resp = client.get("/stocks/fundamental?search=VALE3&limit=5") diff --git a/tests/test_mcp_pool.py b/tests/test_mcp_pool.py index 8d23585..aaeff29 100644 --- a/tests/test_mcp_pool.py +++ b/tests/test_mcp_pool.py @@ -1,5 +1,10 @@ -import pytest -from unittest.mock import patch, AsyncMock +import asyncio +import copy +import time + +from unittest.mock import ANY, AsyncMock, patch + +import main.app.prometheus.mcp as mcp from main.app.prometheus.mcp import MCPClientPool, clientPool @@ -17,3 +22,277 @@ def test_not_initialized(self): pool = MCPClientPool() pool.clients = None assert pool.clients is None + + +class _FakeSession: + """Deterministic stand-in for a fastmcp client session.""" + + def __init__(self, tools_error=None): + self.tools_error = tools_error + self.tools_calls = 0 + + async def list_tools(self): + self.tools_calls += 1 + if self.tools_error is not None: + raise self.tools_error + return ["tools"] + + +class _FakeClient: + """Deterministic stand-in for a fastmcp Client with async enter/exit.""" + + def __init__(self, name="fake", session=None, aenter_error=None, aexit_error=None): + self.name = name + self.session = session if session is not None else _FakeSession() + self.aenter_error = aenter_error + self.aexit_error = aexit_error + self.entered = 0 + self.exited = 0 + + async def __aenter__(self): + self.entered += 1 + if self.aenter_error is not None: + raise self.aenter_error + return self + + async def __aexit__(self, *args): + self.exited += 1 + if self.aexit_error is not None: + raise self.aexit_error + + +async def _getClientsAndYield(pool): + result = await pool.getClients() + await asyncio.sleep(0) # let a scheduled healthCheck task complete + return result + + +async def _runHealthCheckTwice(pool): + await asyncio.gather(pool.healthCheck(), pool.healthCheck()) + + +class TestBuildClient: + def test_with_headers_builds_streamable_transport(self): + server = {"name": "stocks", "url": "http://host:8000/stocks/mcp", "headers": {"X-MCP": "true"}} + with patch.object(mcp, "Client") as mock_client, patch.object(mcp, "StreamableHttpTransport") as mock_transport: + result = mcp.buildClient(server) + mock_transport.assert_called_once_with("http://host:8000/stocks/mcp", headers={"X-MCP": "true"}) + mock_client.assert_called_once_with(transport=mock_transport.return_value) + assert result is mock_client.return_value + + def test_without_headers_builds_plain_url(self): + server = {"name": "searxng", "url": "http://searxng:8080/mcp/"} + with patch.object(mcp, "Client") as mock_client, patch.object(mcp, "StreamableHttpTransport") as mock_transport: + result = mcp.buildClient(server) + mock_client.assert_called_once_with("http://searxng:8080/mcp/") + mock_transport.assert_not_called() + assert result is mock_client.return_value + + +class TestInitialize: + def test_connects_all_servers(self): + fakes = {name: _FakeClient(name) for name in ("stocks", "searxng")} + pool = MCPClientPool() + with ( + patch.object(mcp, "buildClient", side_effect=lambda s: fakes[s["name"]]), + patch.object(mcp, "logger") as mock_logger, + ): + asyncio.run(pool.initialize()) + assert set(pool.clients) == {"stocks", "searxng"} + assert pool.clients["stocks"] is fakes["stocks"] + assert pool.clients["searxng"] is fakes["searxng"] + assert all(c.entered == 1 for c in fakes.values()) + assert pool.lastHealthCheck > 0 + # deepcopy monkeypatch applied to session types without raising + assert copy.deepcopy(fakes["stocks"].session) is fakes["stocks"].session + mock_logger.info.assert_any_call("MCPClientPool: initialized with %s", ["stocks", "searxng"]) + + def test_continues_on_connect_error(self): + bad = _FakeClient("stocks", aenter_error=RuntimeError("boom")) + good = _FakeClient("searxng") + fakes = {"stocks": bad, "searxng": good} + pool = MCPClientPool() + with ( + patch.object(mcp, "buildClient", side_effect=lambda s: fakes[s["name"]]), + patch.object(mcp, "logger") as mock_logger, + ): + asyncio.run(pool.initialize()) + assert "stocks" not in pool.clients + assert pool.clients["searxng"] is good + assert pool.lastHealthCheck > 0 + mock_logger.error.assert_called_once_with("MCPClientPool: %s connect failed: %s", "stocks", ANY) + + +class TestGetClients: + def test_initializes_when_clients_none(self): + pool = MCPClientPool() + pool.clients = None + fake = _FakeClient("stocks") + + async def _initialize(): + pool.clients = {"stocks": fake} + pool.lastHealthCheck = time.time() + + with ( + patch.object(pool, "initialize", new=AsyncMock(side_effect=_initialize)) as mock_init, + patch.object(pool, "healthCheck", new=AsyncMock()) as mock_hc, + ): + clients, sessions = asyncio.run(pool.getClients()) + mock_init.assert_awaited_once() + mock_hc.assert_not_awaited() + assert clients == {"stocks": fake} + assert sessions == [fake.session] + + def test_no_health_check_when_interval_fresh(self): + pool = MCPClientPool() + fake = _FakeClient("stocks") + pool.clients = {"stocks": fake} + pool.lastHealthCheck = time.time() + with patch.object(pool, "healthCheck", new=AsyncMock()) as mock_hc: + clients, sessions = asyncio.run(pool.getClients()) + mock_hc.assert_not_awaited() + assert clients == {"stocks": fake} + assert sessions == [fake.session] + + def test_schedules_health_check_when_interval_elapsed(self): + pool = MCPClientPool() + fake = _FakeClient("stocks") + pool.clients = {"stocks": fake} + pool.lastHealthCheck = 0.0 + with patch.object(pool, "healthCheck", new=AsyncMock()) as mock_hc: + clients, sessions = asyncio.run(_getClientsAndYield(pool)) + mock_hc.assert_awaited_once() + assert clients == {"stocks": fake} + assert sessions == [fake.session] + + +class TestHealthCheck: + def test_returns_early_when_recently_checked(self): + pool = MCPClientPool() + fake = _FakeClient("stocks") + pool.clients = {"stocks": fake} + pool.lastHealthCheck = time.time() + with patch.object(pool, "reconnect", new=AsyncMock()) as mock_reconnect: + asyncio.run(pool.healthCheck()) + assert fake.session.tools_calls == 0 + mock_reconnect.assert_not_awaited() + + def test_double_check_guard_skips_second_call(self): + pool = MCPClientPool() + fake = _FakeClient("stocks") + pool.clients = {"stocks": fake} + pool.lastHealthCheck = 0.0 + with patch.object(pool, "reconnect", new=AsyncMock()) as mock_reconnect: + asyncio.run(_runHealthCheckTwice(pool)) + assert fake.session.tools_calls == 1 # only the first call ran the tool check + mock_reconnect.assert_not_awaited() + + def test_all_healthy_no_reconnect(self): + pool = MCPClientPool() + s1, s2 = _FakeClient("stocks"), _FakeClient("searxng") + pool.clients = {"stocks": s1, "searxng": s2} + pool.lastHealthCheck = 0.0 + with patch.object(pool, "reconnect", new=AsyncMock()) as mock_reconnect: + asyncio.run(pool.healthCheck()) + assert s1.session.tools_calls == 1 + assert s2.session.tools_calls == 1 + mock_reconnect.assert_not_awaited() + assert pool.lastHealthCheck > 0 + + def test_unhealthy_reconnects(self): + pool = MCPClientPool() + good = _FakeClient("stocks") + bad = _FakeClient("searxng", session=_FakeSession(tools_error=RuntimeError("timeout"))) + pool.clients = {"stocks": good, "searxng": bad} + pool.lastHealthCheck = 0.0 + with ( + patch.object(pool, "reconnect", new=AsyncMock()) as mock_reconnect, + patch.object(mcp, "logger") as mock_logger, + ): + asyncio.run(pool.healthCheck()) + assert good.session.tools_calls == 1 + assert bad.session.tools_calls == 1 + mock_reconnect.assert_awaited_once_with("searxng") + mock_logger.warning.assert_called_once_with("MCPClientPool: %s unhealthy, reconnecting: %s", "searxng", ANY) + + +class TestReconnect: + def test_unknown_server_logs_error(self): + pool = MCPClientPool() + fake = _FakeClient("stocks") + pool.clients = {"stocks": fake} + with patch.object(mcp, "buildClient") as mock_build, patch.object(mcp, "logger") as mock_logger: + asyncio.run(pool.reconnect("ghost")) + mock_build.assert_not_called() + mock_logger.error.assert_called_once_with("MCPClientPool: %s not found in MCP_SERVERS", "ghost") + assert pool.clients == {"stocks": fake} + assert fake.exited == 0 + + def test_replaces_existing_client(self): + pool = MCPClientPool() + old = _FakeClient("stocks") + new = _FakeClient("stocks") + pool.clients = {"stocks": old} + server = mcp.MCP_SERVERS[0] + with ( + patch.object(mcp, "buildClient", return_value=new) as mock_build, + patch.object(mcp, "logger") as mock_logger, + ): + asyncio.run(pool.reconnect("stocks")) + assert old.exited == 1 + assert new.entered == 1 + assert pool.clients["stocks"] is new + mock_build.assert_called_once_with(server) + mock_logger.info.assert_called_once_with("MCPClientPool: %s reconnected", "stocks") + + def test_adds_missing_client(self): + pool = MCPClientPool() + new = _FakeClient("searxng") + pool.clients = {} + with patch.object(mcp, "buildClient", return_value=new) as mock_build: + asyncio.run(pool.reconnect("searxng")) + assert pool.clients["searxng"] is new + assert new.entered == 1 + mock_build.assert_called_once() + + def test_build_error_keeps_old_client(self): + pool = MCPClientPool() + old = _FakeClient("stocks") + bad = _FakeClient("stocks", aenter_error=RuntimeError("boom")) + pool.clients = {"stocks": old} + with ( + patch.object(mcp, "buildClient", return_value=bad) as mock_build, + patch.object(mcp, "logger") as mock_logger, + ): + asyncio.run(pool.reconnect("stocks")) + assert old.exited == 1 # old client torn down before the failed rebuild + assert pool.clients["stocks"] is old + mock_build.assert_called_once() + mock_logger.error.assert_called_once_with("MCPClientPool: %s reconnect failed: %s", "stocks", ANY) + + +class TestClose: + def test_exits_all_clients(self): + pool = MCPClientPool() + f1, f2 = _FakeClient("stocks"), _FakeClient("searxng") + pool.clients = {"stocks": f1, "searxng": f2} + asyncio.run(pool.close()) + assert f1.exited == 1 + assert f2.exited == 1 + assert pool.clients is None + + def test_swallows_exit_errors(self): + pool = MCPClientPool() + f1 = _FakeClient("stocks", aexit_error=RuntimeError("boom")) + f2 = _FakeClient("searxng") + pool.clients = {"stocks": f1, "searxng": f2} + asyncio.run(pool.close()) + assert f1.exited == 1 + assert f2.exited == 1 + assert pool.clients is None + + def test_noop_when_no_clients(self): + pool = MCPClientPool() + pool.clients = None + asyncio.run(pool.close()) + assert pool.clients is None diff --git a/tests/test_prometheus_auth_coverage.py b/tests/test_prometheus_auth_coverage.py index 293e285..cd791c2 100644 --- a/tests/test_prometheus_auth_coverage.py +++ b/tests/test_prometheus_auth_coverage.py @@ -117,13 +117,12 @@ async def fake_stream(*args, **kwargs): assert results[-1]["text"] == "Reply with history" @pytest.mark.anyio - @patch("main.app.prometheus.agent.fieldRegistry") @patch("main.app.prometheus.agent.clientPool") @patch("main.app.prometheus.agent.PrometheusChatManager") @patch("main.app.prometheus.agent.Config") @patch("main.app.prometheus.agent.genai") async def test_stream_message_yields_text_chunks( - self, mock_genai, mock_config, mock_chat, mock_pool_cls, mock_field_cls + self, mock_genai, mock_config, mock_chat, mock_pool_cls ): """streamMessage must yield dict chunks from async iterator.""" mock_config.PROMETHEUS = MagicMock(GEMINI_API_KEY="key") @@ -167,13 +166,12 @@ async def fake_aiter(): assert results[1] == {"type": "text", "text": "world"} @pytest.mark.anyio - @patch("main.app.prometheus.agent.fieldRegistry") @patch("main.app.prometheus.agent.clientPool") @patch("main.app.prometheus.agent.PrometheusChatManager") @patch("main.app.prometheus.agent.Config") @patch("main.app.prometheus.agent.genai") async def test_stream_message_handles_function_calls( - self, mock_genai, mock_config, mock_chat, mock_pool_cls, mock_field_cls + self, mock_genai, mock_config, mock_chat, mock_pool_cls ): """streamMessage must handle function_calls as a list (not dict).""" mock_config.PROMETHEUS = MagicMock(GEMINI_API_KEY="key") diff --git a/tests/test_prometheus_resume.py b/tests/test_prometheus_resume.py index d06cc10..597d77f 100644 --- a/tests/test_prometheus_resume.py +++ b/tests/test_prometheus_resume.py @@ -21,9 +21,9 @@ async def streamMessage(self, query=None, sessionId=None, db=None, user=None, fi @pytest.fixture(autouse=True) def _isolate_bus(): - streamBus._channels.clear() + streamBus.channels.clear() yield - streamBus._channels.clear() + streamBus.channels.clear() @pytest.fixture(autouse=True) diff --git a/tests/test_stocks_api_coverage.py b/tests/test_stocks_api_coverage.py index 68e8fdd..b5c4d78 100644 --- a/tests/test_stocks_api_coverage.py +++ b/tests/test_stocks_api_coverage.py @@ -509,13 +509,13 @@ def test_cache_not_initialized_raises_503(self): from fastapi import HTTPException with pytest.raises(HTTPException) as exc_info: - asyncio.run(mgr.queryHistorical(search="TEST0")) + mgr.queryHistorical(search="TEST0") assert exc_info.value.status_code == 503 def test_basic_historical_query(self): df = _make_stocks_df() mgr = self._make_manager(cache_df=df) - result = asyncio.run(mgr.queryHistorical(search="TEST0")) + result = mgr.queryHistorical(search="TEST0") assert result["type"] == "historical" assert result["count"] > 0 assert "data" in result @@ -525,7 +525,7 @@ def test_historical_with_search(self): df = _make_stocks_df() mgr = self._make_manager(cache_df=df) mgr.cacheManager.tickerIndex = {"TEST0": 0} - result = asyncio.run(mgr.queryHistorical(search="TEST0")) + result = mgr.queryHistorical(search="TEST0") assert result["search"] == "TEST0" assert result["count"] == 1 @@ -534,49 +534,49 @@ def test_historical_with_fields(self): df = _make_stocks_df() mgr = self._make_manager(cache_df=df) # categorizeColumns returns key="LUCRO LIQUIDO", not "LUCRO LIQUIDO 2023" - result = asyncio.run(mgr.queryHistorical(fields="LUCRO LIQUIDO")) + result = mgr.queryHistorical(fields="LUCRO LIQUIDO") assert "LUCRO LIQUIDO" in result["fields"] def test_historical_with_dates(self): df = _make_stocks_df() mgr = self._make_manager(cache_df=df) - result = asyncio.run(mgr.queryHistorical(dates="2023")) + result = mgr.queryHistorical(dates="2023") assert result["dates"] == [2023, 2023] def test_historical_with_order_by(self): df = _make_stocks_df() mgr = self._make_manager(cache_df=df) - result = asyncio.run(mgr.queryHistorical(search="TEST0", orderBy="PRECO")) + result = mgr.queryHistorical(search="TEST0", orderBy="PRECO") assert result["type"] == "historical" def test_historical_with_limit(self): df = _make_stocks_df(rows=5) mgr = self._make_manager(cache_df=df) - result = asyncio.run(mgr.queryHistorical(search="TEST", limit=2)) + result = mgr.queryHistorical(search="TEST", limit=2) assert result["count"] == 2 def test_historical_no_historical_fields(self): - """No historical data columns -> inner 400 caught by outer except -> 500.""" + """No historical data columns -> 400 propagates (HTTPException is re-raised).""" df = pd.DataFrame({"TICKER": ["A"], "NOME": ["X"], "PRECO": [10.0]}) mgr = self._make_manager(cache_df=df) from fastapi import HTTPException with pytest.raises(HTTPException) as exc_info: - asyncio.run(mgr.queryHistorical(search="TEST0")) - # The 400 is raised inside try, caught by the outer except -> 500 - assert exc_info.value.status_code == 500 + mgr.queryHistorical(search="TEST0") + # HTTPException raised inside try is re-raised as-is (client error, not 500) + assert exc_info.value.status_code == 400 def test_historical_sorts_by_time(self): df = _make_stocks_df(rows=3) mgr = self._make_manager(cache_df=df) - result = asyncio.run(mgr.queryHistorical(search="TEST0")) + result = mgr.queryHistorical(search="TEST0") assert result["type"] == "historical" def test_historical_deduplicates_by_ticker(self): df = _make_stocks_df(rows=3) df = pd.concat([df, df.iloc[[0]]], ignore_index=True) mgr = self._make_manager(cache_df=df) - result = asyncio.run(mgr.queryHistorical(search="TEST0")) + result = mgr.queryHistorical(search="TEST0") tickers = [d["TICKER"] for d in result["data"]] assert len(tickers) == len(set(tickers)) @@ -595,7 +595,7 @@ def columns(self): from fastapi import HTTPException with pytest.raises(HTTPException) as exc_info: - asyncio.run(mgr.queryHistorical(search="TEST0")) + mgr.queryHistorical(search="TEST0") assert exc_info.value.status_code == 500 def test_historical_with_invalid_dates(self): @@ -605,30 +605,30 @@ def test_historical_with_invalid_dates(self): from fastapi import HTTPException with pytest.raises(HTTPException): - asyncio.run(mgr.queryHistorical(dates="2020,2021,2022")) + mgr.queryHistorical(dates="2020,2021,2022") def test_historical_search_with_no_results(self): df = _make_stocks_df() mgr = self._make_manager(cache_df=df) mgr.cacheManager.tickerIndex = {} - result = asyncio.run(mgr.queryHistorical(search="ZZZZ")) + result = mgr.queryHistorical(search="ZZZZ") assert result["count"] == 0 def test_historical_no_fields_collected(self): - """No historical columns at all -> inner 400 caught by outer except -> 500.""" + """No historical columns at all -> inner 400 propagates (not swallowed as 500).""" df = pd.DataFrame({"TICKER": ["A"], "NOME": ["X"]}) mgr = self._make_manager(cache_df=df) from fastapi import HTTPException with pytest.raises(HTTPException) as exc_info: - asyncio.run(mgr.queryHistorical(fields="NONEXISTENT_FIELD")) - assert exc_info.value.status_code == 500 + mgr.queryHistorical(fields="NONEXISTENT_FIELD") + assert exc_info.value.status_code == 400 def test_historical_with_date_range(self): """Historical query with a year range.""" df = _make_stocks_df() mgr = self._make_manager(cache_df=df) - result = asyncio.run(mgr.queryHistorical(dates="2022,2023")) + result = mgr.queryHistorical(dates="2022,2023") assert result["dates"] == [2022, 2023] def test_historical_search_multiple_terms_index(self): @@ -636,7 +636,7 @@ def test_historical_search_multiple_terms_index(self): df = _make_stocks_df(rows=5) mgr = self._make_manager(cache_df=df) mgr.cacheManager.tickerIndex = {"TEST0": 0, "TEST2": 2, "TEST4": 4} - result = asyncio.run(mgr.queryHistorical(search="TEST0,TEST2,TEST4")) + result = mgr.queryHistorical(search="TEST0,TEST2,TEST4") assert result["count"] == 3 def test_historical_requires_search_fields_or_dates(self): @@ -646,7 +646,7 @@ def test_historical_requires_search_fields_or_dates(self): from fastapi import HTTPException with pytest.raises(HTTPException) as exc_info: - asyncio.run(mgr.queryHistorical()) + mgr.queryHistorical() assert exc_info.value.status_code == 400 @@ -668,13 +668,13 @@ def test_cache_not_initialized_raises_503(self): from fastapi import HTTPException with pytest.raises(HTTPException) as exc_info: - asyncio.run(mgr.queryFundamental(search="TEST0")) + mgr.queryFundamental(search="TEST0") assert exc_info.value.status_code == 503 def test_basic_fundamental_query(self): df = _make_stocks_df() mgr = self._make_manager(cache_df=df) - result = asyncio.run(mgr.queryFundamental(search="TEST0")) + result = mgr.queryFundamental(search="TEST0") assert result["type"] == "fundamental" assert result["count"] > 0 assert "data" in result @@ -683,25 +683,25 @@ def test_fundamental_with_search(self): df = _make_stocks_df() mgr = self._make_manager(cache_df=df) mgr.cacheManager.tickerIndex = {"TEST0": 0} - result = asyncio.run(mgr.queryFundamental(search="TEST0")) + result = mgr.queryFundamental(search="TEST0") assert result["search"] == "TEST0" def test_fundamental_with_fields(self): df = _make_stocks_df() mgr = self._make_manager(cache_df=df) - result = asyncio.run(mgr.queryFundamental(fields="PRECO,P/L")) + result = mgr.queryFundamental(fields="PRECO,P/L") assert "PRECO" in result["fields"] def test_fundamental_with_date_range(self): df = _make_stocks_df() mgr = self._make_manager(cache_df=df) - result = asyncio.run(mgr.queryFundamental(dates="2024-01-01,2024-12-31")) + result = mgr.queryFundamental(dates="2024-01-01,2024-12-31") assert result["type"] == "fundamental" def test_fundamental_with_single_date(self): df = _make_stocks_df() mgr = self._make_manager(cache_df=df) - result = asyncio.run(mgr.queryFundamental(dates="2024-01-15")) + result = mgr.queryFundamental(dates="2024-01-15") assert result["type"] == "fundamental" def test_fundamental_with_invalid_date(self): @@ -711,33 +711,33 @@ def test_fundamental_with_invalid_date(self): from fastapi import HTTPException with pytest.raises(HTTPException) as exc_info: - asyncio.run(mgr.queryFundamental(dates="not-a-date,also-not-a-date")) + mgr.queryFundamental(dates="not-a-date,also-not-a-date") assert exc_info.value.status_code == 400 def test_fundamental_with_order_by(self): df = _make_stocks_df() mgr = self._make_manager(cache_df=df) - result = asyncio.run(mgr.queryFundamental(search="TEST0", orderBy="PRECO")) + result = mgr.queryFundamental(search="TEST0", orderBy="PRECO") assert result["type"] == "fundamental" def test_fundamental_with_limit(self): df = _make_stocks_df(rows=5) mgr = self._make_manager(cache_df=df) - result = asyncio.run(mgr.queryFundamental(fields="PRECO", limit=2)) + result = mgr.queryFundamental(fields="PRECO", limit=2) assert result["count"] == 2 def test_fundamental_deduplicates_without_search(self): df = _make_stocks_df(rows=3) df = pd.concat([df, df.iloc[[0]]], ignore_index=True) mgr = self._make_manager(cache_df=df) - result = asyncio.run(mgr.queryFundamental(fields="PRECO")) + result = mgr.queryFundamental(fields="PRECO") tickers = [d["TICKER"] for d in result["data"]] assert len(tickers) == len(set(tickers)) def test_fundamental_with_search_no_dedup(self): df = _make_stocks_df() mgr = self._make_manager(cache_df=df) - result = asyncio.run(mgr.queryFundamental(search="TEST")) + result = mgr.queryFundamental(search="TEST") assert result["type"] == "fundamental" def test_fundamental_exception_returns_500(self): @@ -754,7 +754,7 @@ def columns(self): from fastapi import HTTPException with pytest.raises(HTTPException) as exc_info: - asyncio.run(mgr.queryFundamental(search="TEST0")) + mgr.queryFundamental(search="TEST0") assert exc_info.value.status_code == 500 def test_fundamental_empty_search_string_no_dedup(self): @@ -762,7 +762,7 @@ def test_fundamental_empty_search_string_no_dedup(self): df = _make_stocks_df(rows=3) df = pd.concat([df, df.iloc[[0]]], ignore_index=True) mgr = self._make_manager(cache_df=df) - result = asyncio.run(mgr.queryFundamental(search=" ")) + result = mgr.queryFundamental(search=" ") tickers = [d["TICKER"] for d in result["data"]] assert len(tickers) == len(set(tickers)) @@ -776,7 +776,7 @@ def test_fundamental_no_time_column(self): } ) mgr = self._make_manager(cache_df=df) - result = asyncio.run(mgr.queryFundamental(search="TEST0")) + result = mgr.queryFundamental(search="TEST0") assert result["type"] == "fundamental" def test_fundamental_date_range_two_dates(self): @@ -790,7 +790,7 @@ def test_fundamental_date_range_two_dates(self): } ) mgr = self._make_manager(cache_df=df) - result = asyncio.run(mgr.queryFundamental(dates="2024-01-01,2024-06-30")) + result = mgr.queryFundamental(dates="2024-01-01,2024-06-30") assert result["count"] >= 1 def test_fundamental_with_invalid_single_date(self): @@ -800,7 +800,7 @@ def test_fundamental_with_invalid_single_date(self): from fastapi import HTTPException with pytest.raises(HTTPException) as exc_info: - asyncio.run(mgr.queryFundamental(dates="not-a-date")) + mgr.queryFundamental(dates="not-a-date") assert exc_info.value.status_code == 400 def test_fundamental_fields_not_in_columns(self): @@ -815,7 +815,7 @@ def test_fundamental_fields_not_in_columns(self): ) mgr = self._make_manager(cache_df=df) with pytest.raises(HTTPException) as exc_info: - asyncio.run(mgr.queryFundamental(fields="NONEXISTENT,P/L")) + mgr.queryFundamental(fields="NONEXISTENT,P/L") assert exc_info.value.status_code == 400 assert "NONEXISTENT" in exc_info.value.detail assert "/stocks/fields" in exc_info.value.detail @@ -825,7 +825,7 @@ def test_fundamental_search_multiple_terms(self): df = _make_stocks_df(rows=5) mgr = self._make_manager(cache_df=df) mgr.cacheManager.tickerIndex = {"TEST0": 0, "TEST3": 3} - result = asyncio.run(mgr.queryFundamental(search="TEST0,TEST3")) + result = mgr.queryFundamental(search="TEST0,TEST3") assert result["count"] == 2 def test_fundamental_search_fallback_string_match(self): @@ -833,7 +833,7 @@ def test_fundamental_search_fallback_string_match(self): df = _make_stocks_df(rows=3) mgr = self._make_manager(cache_df=df) mgr.cacheManager.tickerIndex = {} - result = asyncio.run(mgr.queryFundamental(search="TEST")) + result = mgr.queryFundamental(search="TEST") assert result["count"] == 3 def test_fundamental_dates_one_date(self): @@ -847,7 +847,7 @@ def test_fundamental_dates_one_date(self): } ) mgr = self._make_manager(cache_df=df) - result = asyncio.run(mgr.queryFundamental(dates="2024-01-15")) + result = mgr.queryFundamental(dates="2024-01-15") # Per-ticker: each gets its closest snapshot (A→2024-01-15, B→2024-06-15) assert result["count"] == 2 @@ -871,7 +871,7 @@ def test_fundamental_excludes_cotacao_10y(self): } ) mgr = self._make_manager(cache_df=df) - result = asyncio.run(mgr.queryFundamental(search="TEST0")) + result = mgr.queryFundamental(search="TEST0") assert "COTACAO 10Y PADRAO" not in result["fields"] assert "COTACAO 10Y AJUSTADA" not in result["fields"] for d in result["data"]: @@ -898,7 +898,7 @@ def test_fundamental_does_not_mutate_cache_time_dtype(self): mgr = StocksQueryManager(cache) original_dtype = cache.STOCKS_CACHE["TIME"].dtype - asyncio.run(mgr.queryFundamental(search="TEST0")) + mgr.queryFundamental(search="TEST0") assert cache.STOCKS_CACHE["TIME"].dtype == original_dtype def test_fundamental_requires_search_fields_or_dates(self): @@ -907,7 +907,7 @@ def test_fundamental_requires_search_fields_or_dates(self): from fastapi import HTTPException with pytest.raises(HTTPException) as exc_info: - asyncio.run(mgr.queryFundamental()) + mgr.queryFundamental() assert exc_info.value.status_code == 400 @@ -955,14 +955,14 @@ def test_cotations_cache_not_initialized_raises_503(self): from fastapi import HTTPException with pytest.raises(HTTPException) as exc_info: - asyncio.run(mgr.queryCotations(adjusted=False)) + mgr.queryCotations(adjusted=False) assert exc_info.value.status_code == 503 # --- adjusted=False -> PADRAO --- def test_cotations_adjusted_false_returns_padrao(self): df = self._make_cotations_df() mgr = self._make_manager(cache_df=df) - result = asyncio.run(mgr.queryCotations(adjusted=False)) + result = mgr.queryCotations(adjusted=False) assert result["type"] == "cotations" assert result["fields"] == ["COTACAO 10Y PADRAO"] assert "COTACAO 10Y PADRAO" in result["data"][0] @@ -972,7 +972,7 @@ def test_cotations_adjusted_false_returns_padrao(self): def test_cotations_adjusted_true_returns_ajustada(self): df = self._make_cotations_df() mgr = self._make_manager(cache_df=df) - result = asyncio.run(mgr.queryCotations(adjusted=True)) + result = mgr.queryCotations(adjusted=True) assert result["type"] == "cotations" assert result["fields"] == ["COTACAO 10Y AJUSTADA"] assert "COTACAO 10Y AJUSTADA" in result["data"][0] @@ -983,7 +983,7 @@ def test_cotations_returns_most_recent_per_ticker(self): """4 rows for 2 tickers -> 2 results, one per ticker, both with latest TIME.""" df = self._make_cotations_df() mgr = self._make_manager(cache_df=df) - result = asyncio.run(mgr.queryCotations(adjusted=False)) + result = mgr.queryCotations(adjusted=False) assert result["count"] == 2 tickers = {d["TICKER"] for d in result["data"]} assert tickers == {"TEST0", "TEST1"} @@ -995,7 +995,7 @@ def test_cotations_dates_filter_inner_json_data(self): """dates="2016-12-02" should keep only the 02-12-2016 entry in each JSON list.""" df = self._make_cotations_df() mgr = self._make_manager(cache_df=df) - result = asyncio.run(mgr.queryCotations(adjusted=False, dates="2016-12-02,2016-12-02")) + result = mgr.queryCotations(adjusted=False, dates="2016-12-02,2016-12-02") assert result["count"] == 2 for d in result["data"]: cotation = d["COTACAO 10Y PADRAO"] @@ -1006,7 +1006,7 @@ def test_cotations_dates_filter_inner_json_data(self): def test_cotations_dates_range_keeps_all_inner_entries(self): df = self._make_cotations_df() mgr = self._make_manager(cache_df=df) - result = asyncio.run(mgr.queryCotations(adjusted=False, dates="2016-12-01,2016-12-31")) + result = mgr.queryCotations(adjusted=False, dates="2016-12-01,2016-12-31") assert result["count"] == 2 for d in result["data"]: assert len(d["COTACAO 10Y PADRAO"]) == 2 @@ -1014,7 +1014,7 @@ def test_cotations_dates_range_keeps_all_inner_entries(self): def test_cotations_no_dates_keeps_all_inner_entries(self): df = self._make_cotations_df() mgr = self._make_manager(cache_df=df) - result = asyncio.run(mgr.queryCotations(adjusted=False)) + result = mgr.queryCotations(adjusted=False) for d in result["data"]: assert len(d["COTACAO 10Y PADRAO"]) == 2 @@ -1023,7 +1023,7 @@ def test_cotations_with_search_filter(self): df = self._make_cotations_df() mgr = self._make_manager(cache_df=df) mgr.cacheManager.tickerIndex = {"TEST0": 0, "TEST1": 2} - result = asyncio.run(mgr.queryCotations(adjusted=False, search="TEST0")) + result = mgr.queryCotations(adjusted=False, search="TEST0") assert result["search"] == "TEST0" assert result["count"] == 1 assert result["data"][0]["TICKER"] == "TEST0" @@ -1032,14 +1032,14 @@ def test_cotations_with_search_multiple_terms(self): df = self._make_cotations_df() mgr = self._make_manager(cache_df=df) mgr.cacheManager.tickerIndex = {"TEST0": 0, "TEST1": 2} - result = asyncio.run(mgr.queryCotations(adjusted=True, search="TEST0,TEST1")) + result = mgr.queryCotations(adjusted=True, search="TEST0,TEST1") assert result["count"] == 2 # --- missing column -> empty --- def test_cotations_missing_column_returns_empty(self): df = self._make_cotations_df(with_padrao=False, with_ajustada=False) mgr = self._make_manager(cache_df=df) - result = asyncio.run(mgr.queryCotations(adjusted=False)) + result = mgr.queryCotations(adjusted=False) assert result["count"] == 0 assert result["data"] == [] assert result["fields"] == ["COTACAO 10Y PADRAO"] @@ -1049,20 +1049,20 @@ def test_cotations_missing_column_returns_empty(self): def test_cotations_dates_param_stored(self): df = self._make_cotations_df() mgr = self._make_manager(cache_df=df) - result = asyncio.run(mgr.queryCotations(adjusted=False, dates="2020-01-01,2024-12-31")) + result = mgr.queryCotations(adjusted=False, dates="2020-01-01,2024-12-31") assert result["dates"] == "2020-01-01,2024-12-31" def test_cotations_dates_default_none(self): df = self._make_cotations_df() mgr = self._make_manager(cache_df=df) - result = asyncio.run(mgr.queryCotations(adjusted=False)) + result = mgr.queryCotations(adjusted=False) assert result["dates"] is None # --- default search --- def test_cotations_default_search_all(self): df = self._make_cotations_df() mgr = self._make_manager(cache_df=df) - result = asyncio.run(mgr.queryCotations(adjusted=False)) + result = mgr.queryCotations(adjusted=False) assert result["search"] == "all" # --- exception -> 500 --- @@ -1073,7 +1073,7 @@ def test_cotations_exception_returns_500(self): from fastapi import HTTPException with pytest.raises(HTTPException) as exc_info: - asyncio.run(mgr.queryCotations(adjusted=False)) + mgr.queryCotations(adjusted=False) assert exc_info.value.status_code == 500 # --- HTTP integration: /stocks/cotations route (one test, parametrized conceptually) --- @@ -1155,7 +1155,7 @@ def _patch_session(self, response=None, side_effect=None): def test_success_returns_correct_shape(self): mgr = self._make_manager() with self._patch_session(): - result = asyncio.run(mgr.queryLiveCotation("WEGE3")) + result = mgr.queryLiveCotation("WEGE3") assert result["type"] == "realtime-cotation" assert result["search"] == "WEGE3" assert result["count"] == 1 @@ -1172,7 +1172,7 @@ def test_success_returns_correct_shape(self): def test_lowercase_ticker_uppercased(self): mgr = self._make_manager() with self._patch_session(): - result = asyncio.run(mgr.queryLiveCotation("wege3")) + result = mgr.queryLiveCotation("wege3") assert result["search"] == "WEGE3" assert result["data"][0]["TICKER"] == "WEGE3" @@ -1217,7 +1217,7 @@ def test_b3_unavailable_returns_503(self): mgr = self._make_manager() with self._patch_session(side_effect=Exception("connection refused")): with pytest.raises(HTTPException) as exc_info: - asyncio.run(mgr.queryLiveCotation("WEGE3")) + mgr.queryLiveCotation("WEGE3") assert exc_info.value.status_code == 503 def test_b3_bad_status_returns_404(self): @@ -1227,7 +1227,7 @@ def test_b3_bad_status_returns_404(self): payload = {"BizSts": {"cd": "ERR"}, "Trad": []} with self._patch_session(response=payload): with pytest.raises(HTTPException) as exc_info: - asyncio.run(mgr.queryLiveCotation("WEGE3")) + mgr.queryLiveCotation("WEGE3") assert exc_info.value.status_code == 404 def test_http_route_returns_200(self, stocks_http_client): diff --git a/tests/test_stocks_compress.py b/tests/test_stocks_compress.py new file mode 100644 index 0000000..126de1a --- /dev/null +++ b/tests/test_stocks_compress.py @@ -0,0 +1,522 @@ +"""Unit tests for main/app/stocks_api/compress.py. + +Covers the payload-compaction helpers used by the stocks MCP tools: +compactValue suffix/date logic, toColumnar, fixHeaders, compactRow, +compactCotations, the compressResponse pipeline, and the lazy +abbr/nest caches (getAbbr/getNest/rebuildAbbrevs). + +Pure unit tests: no MySQL required. Cache-dependent functions are +exercised by patching stocksCache attributes; the module-level +abbr/nest globals are reset before and after every test so the +suite is order-independent. +""" + +from unittest.mock import patch + +import pandas as pd +import pytest + +from main.app.stocks_api.cache import stocksCache +from main.app.stocks_api.compress import ( + compactCotations, + compactRow, + compactValue, + compressResponse, + fixHeaders, + getAbbr, + getNest, + rebuildAbbrevs, + toColumnar, + walk, +) + +# Stub abbreviation/nesting tables for direct compactRow tests. +ABBR_STUB = { + "meta": {"TICKER": "TK", "NOME": "NM", "TIME": "TI"}, + "historical": {"LUCRO LIQUIDO": "LL"}, + "fundamental": {"P/L": "PL"}, +} + +NEST_STUB = { + "NOTICIAS": { + "subfields": {"TITULO": "T", "LINK": "L"}, + "dropped_in_compact": ["LINK"], + "max_items_compact": 2, + } +} + +ABBR_FALLBACK = { + "meta": {"TICKER": "TK", "NOME": "NM", "TIME": "TI"}, + "historical": {}, + "fundamental": {}, +} + + +@pytest.fixture(autouse=True) +def _reset_abbrev_globals(): + """compress.py caches abbr/nest in module globals; reset before and after each test.""" + rebuildAbbrevs() + yield + rebuildAbbrevs() + + +class TestCompactValue: + """compactValue: float rounding, int suffixes, date compaction, passthroughs.""" + + def test_float_rounds_to_10_significant_digits(self): + assert compactValue(3.14159265358979) == 3.141592654 + + def test_int_trillion_suffix(self): + assert compactValue(1_234_567_890_123) == "1.2T" + + def test_int_billion_suffix(self): + assert compactValue(1_234_567_890) == "1.2B" + + def test_int_million_suffix_exact(self): + assert compactValue(1_000_000) == "1M" + + def test_int_thousand_suffix(self): + assert compactValue(2_500) == "2.5K" + + def test_int_below_thousand_unchanged(self): + assert compactValue(999) == 999 + + def test_negative_int_suffix(self): + assert compactValue(-1_000_000) == "-1M" + + def test_bool_untouched(self): + assert compactValue(True) is True + assert compactValue(False) is False + + def test_df_date_compacts_to_mm_yy(self): + assert compactValue("15-06-2026") == "06-15" + + def test_di_date_compacts_to_mm_dd(self): + assert compactValue("2026-06-15") == "06-15" + + def test_non_matching_string_unchanged(self): + assert compactValue("hello") == "hello" + assert compactValue("15-06-202") == "15-06-202" + + +class TestWalk: + """walk: recursive dict/list transform.""" + + def test_recurses_dicts_and_lists(self): + assert walk({"a": [1, {"b": 2}], "c": 3}, lambda v: v * 2) == {"a": [2, {"b": 4}], "c": 6} + + def test_scalar_leaf(self): + assert walk("x", lambda v: v.upper()) == "X" + + +class TestToColumnar: + """toColumnar: passthrough guards + happy-path columnar output.""" + + def test_empty_list_unchanged(self): + assert toColumnar([]) == [] + + def test_single_row_unchanged(self): + data = [{"a": 1}] + assert toColumnar(data) == data + + def test_first_row_not_dict_unchanged(self): + data = [[1, 2], [3, 4]] + assert toColumnar(data) == data + + def test_mismatched_keys_unchanged(self): + data = [{"a": 1}, {"b": 2}] + assert toColumnar(data) == data + + def test_happy_path(self): + data = [{"a": 1, "b": "x"}, {"a": 2, "b": "y"}] + assert toColumnar(data) == {"h": "a,b", "d": ["1|x", "2|y"]} + + +class TestFixHeaders: + """fixHeaders: in-place COT remap of "h" headers.""" + + def test_remaps_cot_headers(self): + obj = {"h": "DATA,PRECO"} + fixHeaders(obj) + assert obj == {"h": "D,P"} + + def test_unknown_pieces_passthrough(self): + obj = {"h": "DATA,FOO"} + fixHeaders(obj) + assert obj == {"h": "D,FOO"} + + def test_nested_dict_value(self): + obj = {"inner": {"h": "PRECO"}} + fixHeaders(obj) + assert obj == {"inner": {"h": "P"}} + + def test_list_of_dicts_not_traversed(self): + # edge case: fixHeaders only recurses into dict values whose values + # are dicts; a list value is handed to fixHeaders, which is a no-op + # because the top-level isinstance(obj, dict) guard fails. + obj = {"rows": [{"h": "DATA"}]} + fixHeaders(obj) + assert obj == {"rows": [{"h": "DATA"}]} + + def test_non_str_h_value_untouched(self): + obj = {"h": 5} + fixHeaders(obj) + assert obj == {"h": 5} + + +class TestCompactRow: + """compactRow: meta/historical/fundamental abbreviation + nested handling.""" + + def test_meta_keys_abbreviated(self): + row = {"TICKER": "PETR4", "NOME": "PETROBRAS PN", "TIME": "2026-06-15"} + assert compactRow(row, "get_fundamental", ABBR_STUB, {}) == { + "TK": "PETR4", + "NM": "PETROBRAS PN", + "TI": "2026-06-15", + } + + def test_historical_year_col(self): + row = {"TICKER": "PETR4", "LUCRO LIQUIDO 2024": 50000} + assert compactRow(row, "get_historical", ABBR_STUB, {}) == {"TK": "PETR4", "LL.24": 50000} + + def test_historical_fallback_first_letters(self): + row = {"RECEITA LIQUIDA 2023": 100000} + assert compactRow(row, "get_historical", ABBR_STUB, {}) == {"RL.23": 100000} + + def test_historical_space_key_without_year_passthrough(self): + row = {"LUCRO LIQUIDO": 1} + assert compactRow(row, "get_historical", ABBR_STUB, {}) == {"LUCRO LIQUIDO": 1} + + def test_fundamental_keys_abbreviated(self): + row = {"P/L": 5.2} + assert compactRow(row, "get_fundamental", ABBR_STUB, {}) == {"PL": 5.2} + + def test_unknown_key_passthrough(self): + row = {"FOO": 1, "P/L": 2} + assert compactRow(row, "get_fundamental", ABBR_STUB, {}) == {"FOO": 1, "PL": 2} + + def test_nested_rename_drop_cap(self): + row = { + "NOTICIAS": [ + {"TITULO": "a", "LINK": "http://x", "EXTRA": "e"}, + {"TITULO": "b", "LINK": "http://y"}, + {"TITULO": "c", "LINK": "http://z"}, + ] + } + assert compactRow(row, "get_fundamental", ABBR_STUB, NEST_STUB) == { + "NOTICIAS": [{"T": "a", "EXTRA": "e"}, {"T": "b"}] + } + + def test_nested_defaults_when_spec_omits_options(self): + nests = {"NOTICIAS": {"subfields": {"TITULO": "T"}}} + row = {"NOTICIAS": [{"TITULO": "a", "LINK": "x"}]} + assert compactRow(row, "get_fundamental", ABBR_STUB, nests) == {"NOTICIAS": [{"T": "a", "LINK": "x"}]} + + def test_nested_field_not_list_untouched(self): + row = {"NOTICIAS": "x"} + assert compactRow(row, "get_fundamental", ABBR_STUB, NEST_STUB) == {"NOTICIAS": "x"} + + def test_nested_non_dict_items_kept(self): + row = {"NOTICIAS": [1, 2]} + assert compactRow(row, "get_fundamental", ABBR_STUB, NEST_STUB) == {"NOTICIAS": [1, 2]} + + +class TestCompactCotations: + """compactCotations: single/multi entry compaction + passthroughs.""" + + def test_non_list_data_unchanged(self): + result = {"data": "x", "count": 1} + assert compactCotations(result) == {"data": "x", "count": 1} + + def test_missing_data_unchanged(self): + result = {"count": 1} + assert compactCotations(result) == {"count": 1} + + def test_single_entry(self): + result = { + "data": [ + { + "TICKER": "PETR4", + "NOME": "PETROBRAS PN", + "TIME": "2026-06-15", + "COTACAO 10Y PADRAO": [{"DATA": "15-06-2026", "PRECO": 28.5}], + } + ] + } + out = compactCotations(result) + assert out == { + "TK": "PETR4", + "NM": "PETROBRAS PN", + "TI": "06-15", + "C10": {"h": "D,P", "d": ["06-15|28.5"]}, + } + assert "data" not in out + + def test_single_entry_non_10y_key_name(self): + result = {"data": [{"TICKER": "PETR4", "COTACAO PADRAO": [{"DATA": "15-06-2026", "PRECO": 1.0}]}]} + out = compactCotations(result) + assert out == { + "TK": "PETR4", + "NM": "", + "TI": "", + "COTA": {"h": "D,P", "d": ["06-15|1.0"]}, + } + + def test_single_entry_missing_nome_time_default_empty(self): + result = {"data": [{"TICKER": "PETR4", "COTACAO 10Y PADRAO": [{"DATA": "15-06-2026", "PRECO": 1.0}]}]} + out = compactCotations(result) + assert out == {"TK": "PETR4", "NM": "", "TI": "", "C10": {"h": "D,P", "d": ["06-15|1.0"]}} + + def test_single_entry_no_cotation_key_unchanged(self): + result = {"data": [{"TICKER": "PETR4"}]} + assert compactCotations(result) == result + + def test_single_entry_empty_cotation_list_unchanged(self): + result = {"data": [{"TICKER": "PETR4", "COTACAO 10Y PADRAO": []}]} + assert compactCotations(result) == result + + def test_multi_entry(self): + result = { + "data": [ + {"TICKER": "PETR4", "COTACAO 10Y PADRAO": [{"DATA": "15-06-2026", "PRECO": 1.0}]}, + {"TICKER": "VALE3", "COTACAO 10Y PADRAO": [{"DATA": "16-06-2026", "PRECO": 2.0}]}, + ] + } + out = compactCotations(result) + assert out["data"][0] == { + "TICKER": "PETR4", + "COTACAO 10Y PADRAO": {"h": "D,P", "d": ["06-15|1.0"]}, + } + assert out["data"][1] == { + "TICKER": "VALE3", + "COTACAO 10Y PADRAO": {"h": "D,P", "d": ["06-16|2.0"]}, + } + + def test_multi_entry_non_dict_entries_unchanged(self): + result = {"data": [1, 2]} + assert compactCotations(result) == result + + def test_to_col_non_dict_rows(self): + result = {"data": [{"TICKER": "PETR4", "COTACAO 10Y PADRAO": [["a", "b"], ["c", "d"]]}]} + out = compactCotations(result) + assert out["C10"] == {"h": "v", "d": ["a|b", "c|d"]} + + +class TestAbbrevCaches: + """getAbbr/getNest/rebuildAbbrevs: fallbacks, cache-present discovery, resets.""" + + def test_get_abbr_cache_absent_fallback(self): + with patch.object(stocksCache, "STOCKS_CACHE", None): + rebuildAbbrevs() + assert getAbbr() == ABBR_FALLBACK + + def test_get_nest_cache_absent_fallback(self): + with patch.object(stocksCache, "STOCKS_CACHE", None): + rebuildAbbrevs() + assert getNest() == {} + + def test_get_abbr_cache_present(self): + df = pd.DataFrame( + { + "TICKER": ["PETR4"], + "NOME": ["PETROBRAS PN"], + "TIME": ["2026-06-15"], + "LUCRO LIQUIDO 2024": [50000], + "P/L": [5.2], + } + ) + with patch.object(stocksCache, "STOCKS_CACHE", df): + rebuildAbbrevs() + abbr = getAbbr() + assert abbr["meta"] == {"TICKER": "TK", "NOME": "NM", "TIME": "TI"} + assert abbr["historical"] == {"LUCRO LIQUIDO": "LL"} + assert abbr["fundamental"] == {"P/L": "PL"} + + def test_get_nest_cache_present_merges_nested_sample(self): + df = pd.DataFrame({"TICKER": ["PETR4"], "NOTICIAS": ['[{"TITULO": "a", "LINK": "http://x"}]']}) + nested = pd.DataFrame( + { + "NOTICIAS": ['[{"TITULO": "a", "LINK": "http://x"}]'], + "DIVIDENDOS": ['[{"DATA": "01-01-2024"}]'], + } + ) + with ( + patch.object(stocksCache, "STOCKS_CACHE", df), + patch.object(stocksCache, "nestedSample", nested), + ): + rebuildAbbrevs() + nest = getNest() + assert set(nest["NOTICIAS"]["subfields"]) >= {"TITULO", "LINK"} + assert nest["NOTICIAS"]["dropped_in_compact"] == ["LINK"] + assert nest["NOTICIAS"]["max_items_compact"] == 5 + # nestedSample-only column merged in via setdefault + assert "DIVIDENDOS" in nest + + def test_get_abbr_cached_across_calls(self): + df = pd.DataFrame({"TICKER": ["X"]}) + with patch.object(stocksCache, "STOCKS_CACHE", df): + rebuildAbbrevs() + assert getAbbr() is getAbbr() + + def test_rebuild_abbrevs_resets_globals(self): + df = pd.DataFrame({"TICKER": ["PETR4"], "LUCRO LIQUIDO 2024": [1]}) + with patch.object(stocksCache, "STOCKS_CACHE", df): + rebuildAbbrevs() + assert getAbbr()["historical"] != {} + rebuildAbbrevs() + with patch.object(stocksCache, "STOCKS_CACHE", None): + assert getAbbr() == ABBR_FALLBACK + assert getNest() == {} + + +class TestCompressResponse: + """compressResponse: pipeline orchestration across tools.""" + + def test_pops_metadata_present_in_args(self): + raw = { + "count": 2, + "search": "PETR4", + "fields": ["P/L"], + "dates": "2024", + "type": "get_fundamental", + "data": [], + } + out = compressResponse(raw, "get_fundamental", {"search": "PETR4", "fields": ["P/L"], "dates": "2024"}) + assert out == {"data": []} + + def test_keeps_metadata_not_in_args(self): + raw = {"count": 1, "search": "PETR4", "type": "get_fundamental", "data": []} + assert compressResponse(raw, "get_fundamental", {}) == {"search": "PETR4", "data": []} + + def test_empty_data_list_passthrough(self): + raw = {"count": 0, "type": "get_fundamental", "data": []} + assert compressResponse(raw, "get_fundamental", {}) == {"data": []} + + def test_data_not_list_passthrough(self): + raw = {"type": "get_fundamental", "data": {"foo": 1}} + assert compressResponse(raw, "get_fundamental", {}) == {"data": {"foo": 1}} + + def test_data_non_dict_entries_passthrough(self): + raw = {"data": [1, 2]} + assert compressResponse(raw, "get_fundamental", {}) == {"data": [1, 2]} + + def test_get_cotations_branch(self): + raw = { + "count": 1, + "search": "PETR4", + "type": "get_cotations", + "data": [ + { + "TICKER": "PETR4", + "NOME": "PETROBRAS PN", + "TIME": "2026-06-15", + "COTACAO 10Y PADRAO": [{"DATA": "15-06-2026", "PRECO": 28.5}], + } + ], + } + out = compressResponse(raw, "get_cotations", {"search": "PETR4"}) + assert out == { + "TK": "PETR4", + "NM": "PETROBRAS PN", + "TI": "06-15", + "C10": {"h": "D,P", "d": ["06-15|28.5"]}, + } + + def test_get_cotations_data_not_list(self): + raw = {"type": "get_cotations", "data": "x"} + assert compressResponse(raw, "get_cotations", {}) == {"data": "x"} + + def test_get_live_price_remaps_price_keys(self): + raw = { + "count": 1, + "search": "PETR4", + "type": "get_live_price", + "data": [ + { + "TICKER": "PETR4", + "PRECO ATUAL": 28.5, + "PRECO ORIGINAL": 28.3, + "PRECO MINIMO": 28.0, + "PRECO MAXIMO": 28.8, + "PRECO MEDIO": 28.45, + } + ], + } + out = compressResponse(raw, "get_live_price", {"search": "PETR4"}) + # the single row is unwrapped from a list but stays under the "data" key + assert out == { + "data": { + "TK": "PETR4", + "PA": 28.5, + "PO": 28.3, + "PMN": 28.0, + "PMX": 28.8, + "PMD": 28.45, + } + } + + def test_get_live_price_data_not_list(self): + raw = {"type": "get_live_price", "data": {"TICKER": "PETR4"}} + assert compressResponse(raw, "get_live_price", {}) == {"data": {"TICKER": "PETR4"}} + + def test_multi_row_columnar_with_fallback_abbrs(self): + # cache absent: fallback abbrs have empty historical/fundamental, + # so "P/L" passes through unabbreviated. + raw = { + "count": 2, + "type": "get_fundamental", + "data": [ + {"TICKER": "PETR4", "P/L": 5.2}, + {"TICKER": "VALE3", "P/L": 6.5}, + ], + } + out = compressResponse(raw, "get_fundamental", {}) + assert out == {"data": {"h": "TK,P/L", "d": ["PETR4|5.2", "VALE3|6.5"]}} + + def test_single_row_unwrapped_with_cache_abbrevs(self): + df = pd.DataFrame({"TICKER": ["PETR4"], "P/L": [5.2]}) + raw = {"data": [{"TICKER": "PETR4", "P/L": 5.2}]} + with patch.object(stocksCache, "STOCKS_CACHE", df): + rebuildAbbrevs() + out = compressResponse(raw, "get_fundamental", {}) + assert out == {"data": {"TK": "PETR4", "PL": 5.2}} + + def test_get_historical_year_cols_with_cache_abbrevs(self): + df = pd.DataFrame( + { + "TICKER": ["PETR4"], + "NOME": ["PETROBRAS PN"], + "TIME": ["2026-06-15"], + "LUCRO LIQUIDO 2024": [50000], + "RECEITA LIQUIDA 2023": [100000], + } + ) + raw = { + "count": 1, + "search": "PETR4", + "type": "get_historical", + "dates": "2023,2024", + "data": [ + { + "TICKER": "PETR4", + "NOME": "PETROBRAS PN", + "TIME": "2026-06-15", + "LUCRO LIQUIDO 2024": 50000, + "RECEITA LIQUIDA 2023": 100000, + } + ], + } + with patch.object(stocksCache, "STOCKS_CACHE", df): + rebuildAbbrevs() + out = compressResponse(raw, "get_historical", {"search": "PETR4", "dates": "2023,2024"}) + # note: walk(compactValue) suffixes int leaves, so year values become "50K"/"100K"; + # the single row is unwrapped from a list but stays under the "data" key + assert out == { + "data": { + "TK": "PETR4", + "NM": "PETROBRAS PN", + "TI": "06-15", + "LL.24": "50K", + "RL.23": "100K", + } + } diff --git a/tests/test_stocks_mcp_middleware.py b/tests/test_stocks_mcp_middleware.py new file mode 100644 index 0000000..2065434 --- /dev/null +++ b/tests/test_stocks_mcp_middleware.py @@ -0,0 +1,99 @@ +"""Tests for MCPDetectMiddleware and StocksAPIService.initialize in stocksapi_service.py. + +Covers the ASGI middleware's compact-flag injection (x-mcp header -> compressed +state + compact=true query param) and the service bootstrap wiring (router, +middleware, MCP mount) without starting background schedulers. +""" + +import asyncio +import os +import sys +from unittest import mock + +sys.path.insert(0, os.path.dirname(os.path.dirname(__file__))) + +from fastapi import FastAPI + +from main.app.stocks_api.cache import stocksCache +from main.service.stocksapi_service import MCPDetectMiddleware, StocksAPIService + + +def _run_through(scope): + """Run MCPDetectMiddleware over scope with a mocked async downstream app.""" + downstream = mock.AsyncMock() + middleware = MCPDetectMiddleware(downstream) + receive = mock.Mock() + send = mock.Mock() + asyncio.run(middleware(scope, receive, send)) + return downstream + + +class TestMCPDetectMiddleware: + """MCPDetectMiddleware: x-mcp header forces compressed state + compact query.""" + + def test_mcp_header_appends_compact_to_nonempty_query(self): + scope = {"type": "http", "headers": [(b"x-mcp", b"true")], "query_string": b"a=1", "state": {}} + downstream = _run_through(scope) + + assert scope["state"]["compressed"] is True + assert scope["query_string"] == b"a=1&compact=true" + downstream.assert_awaited_once() + + def test_mcp_header_with_empty_query_string(self): + scope = {"type": "http", "headers": [(b"x-mcp", b"true")], "query_string": b""} + assert "state" not in scope + + _run_through(scope) + + assert scope["state"]["compressed"] is True + assert scope["query_string"] == b"compact=true" + + def test_mcp_header_existing_compact_not_duplicated(self): + scope = {"type": "http", "headers": [(b"x-mcp", b"true")], "query_string": b"compact=false", "state": {}} + + _run_through(scope) + + assert scope["state"]["compressed"] is True + assert scope["query_string"] == b"compact=false" + + def test_no_mcp_header_leaves_scope_untouched(self): + scope = {"type": "http", "headers": [(b"user-agent", b"test")], "query_string": b"a=1", "state": {}} + + _run_through(scope) + + assert "compressed" not in scope["state"] + assert scope["query_string"] == b"a=1" + + def test_non_http_scope_passes_through_untouched(self): + scope = {"type": "websocket", "headers": [(b"x-mcp", b"true")], "query_string": b"a=1"} + + _run_through(scope) + + assert scope.get("state", {}).get("compressed") is None + assert scope["query_string"] == b"a=1" + + +class TestStocksAPIServiceInitialize: + """StocksAPIService.initialize: wires router, middleware and MCP mount.""" + + def test_initialize_wires_router_middleware_and_mcp_mount(self): + app = FastAPI() + with ( + mock.patch("main.service.stocksapi_service.getApp", return_value=app) as mock_get_app, + mock.patch.object(stocksCache, "cacheScheduler") as mock_scheduler, + ): + StocksAPIService.initialize(39999) + + mock_get_app.assert_called_once_with(39999) + mock_scheduler.assert_called_once() + + # Stocks router registered + assert any(getattr(r, "path", "").startswith("/stocks/") for r in app.routes) + + # Middleware stack + middleware_names = [m.cls.__name__ for m in app.user_middleware] + assert "MCPDetectMiddleware" in middleware_names + assert "GZipMiddleware" in middleware_names + + # MCP mount registered + assert any(getattr(r, "path", None) == "/stocks/mcp" for r in app.routes) diff --git a/tests/test_sync_cache.py b/tests/test_sync_cache.py new file mode 100644 index 0000000..fd609d4 --- /dev/null +++ b/tests/test_sync_cache.py @@ -0,0 +1,73 @@ +import asyncio +import orjson +import pytest + +from cashews import cache + +from main.app.stocks_api.sync_cache import sync_cache + + +@pytest.fixture(scope="module", autouse=True) +def _setup_cache(): + cache.setup("mem://") + yield + asyncio.run(cache.clear()) + + +def test_hit_returns_cached_value_without_calling_func(): + calls = [] + + @sync_cache(ttl="1h", key="test:simple:{x}") + def fn(x): + calls.append(x) + return orjson.dumps({"x": x}) + + first = fn(x=1) + second = fn(x=1) + + assert first == second == orjson.dumps({"x": 1}) + assert calls == [1] # computed once, second call is a cache hit + + +def test_distinct_args_get_distinct_cache_entries(): + calls = [] + + @sync_cache(ttl="1h", key="test:distinct:{x}") + def fn(x): + calls.append(x) + return orjson.dumps({"x": x}) + + fn(x=1) + fn(x=2) + + assert calls == [1, 2] + + +def test_params_not_in_template_are_excluded_from_key(): + calls = [] + + @sync_cache(ttl="1h", key="test:exclude:{x}") + def fn(x, junk="ignored"): + calls.append(x) + return orjson.dumps({"x": x}) + + fn(x=1, junk="a") + fn(x=1, junk="b") # junk must not change the key + + assert calls == [1] + + +def test_exceptions_propagate_and_are_not_cached(): + calls = [] + + @sync_cache(ttl="1h", key="test:exc:{x}") + def fn(x): + calls.append(x) + raise ValueError("boom") + + with pytest.raises(ValueError): + fn(x=1) + with pytest.raises(ValueError): + fn(x=1) # must re-raise, not return a cached exception + + assert calls == [1, 1]