fix(a2ui-bridge): fix critical bugs, add testing, integrate Tokenism simulator - #389
Conversation
Add errorIds.ts with stable error identifiers for aggregation in Sentry. Used by logError() calls in Tokenism UI components for: - Simulation failures - Geometry load errors - Health check failures - Network error classification Provides structured error tracking with consistent IDs across the Tokenism dashboard for monitoring and alerting. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
📝 WalkthroughWalkthroughAdds a centralized, type-safe ErrorIds set and threads those IDs into many UI logging sites; introduces timezone-aware UTC timestamps across numerous services; enhances the a2ui NATS bridge with managed lifespan, retries, and stronger error semantics; and expands the tokenism-simulator with background simulation execution, new endpoints, and public exports. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Client
participant FastAPI as A2UI App
participant Lifespan as App Lifespan
participant Bridge as publish_a2ui_event
participant NATS
rect rgba(200,230,255,0.4)
Note over Lifespan,Bridge: App startup (lifespan manager)
Lifespan -> NATS: connect with retries/backoff
NATS --> Lifespan: JetStream & subscriptions
end
Client -> FastAPI: HTTP/WebSocket A2UI event
alt valid event
FastAPI -> Bridge: validate & build A2UIEvent (timezone-aware ts)
Bridge -> NATS: publish to JetStream (raise on failure)
NATS --> Bridge: ack / error
Bridge --> FastAPI: success / raise -> FastAPI returns 503 or 200-with-warning
FastAPI --> Client: response (200 or 503 / structured error)
else invalid format / NATS down
FastAPI -> Client: structured error / 200 warning (userAction special-case)
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
pmoves/ui/lib/constants/errorIds.ts (1)
1-6: Consider documenting the immutability requirement.The JSDoc is clear and helpful. Consider adding a note that error ID values should never be changed once in use, as they serve as stable identifiers for historical error tracking and alerting in Sentry.
🔎 Suggested documentation enhancement
/** * Error ID constants for Sentry aggregation. * Each unique error type gets a stable ID for tracking and alerting. + * + * IMPORTANT: Once an error ID is in use, its value should never be changed + * to preserve historical tracking and alert continuity in Sentry. * * Usage: logError(message, error, 'error', { errorId: ErrorIds.TOKENISM_SIMULATION_FAILED, ... }) */
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
pmoves/ui/lib/constants/errorIds.ts
🧰 Additional context used
📓 Path-based instructions (1)
pmoves/ui/**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (pmoves/AGENTS.md)
UI updates: run
make -C pmoves notebook-workbench-smoke ARGS="--thread=<uuid>"to lint the Next.js bundle and validate Supabase connectivity; referencepmoves/docs/UI_NOTEBOOK_WORKBENCH.md
Files:
pmoves/ui/lib/constants/errorIds.ts
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-15T12:03:17.291Z
Learning: PRs should include clear description, linked issues, affected services, run/rollback notes, and screenshots for UI/flows; start from STARTER_PR_BODY.md and adjust sections as needed
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/AGENTS.md:0-0
Timestamp: 2025-12-07T11:03:53.415Z
Learning: PRs should include: clear description, linked issues, affected services, run/rollback notes, and screenshots for UI/flows
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Analyze (python)
🔇 Additional comments (2)
pmoves/ui/lib/constants/errorIds.ts (2)
8-28: LGTM! Well-structured error ID constants.The categorization is clear, naming conventions are consistent, and the
as constassertion properly enforces type safety. All error IDs are unique, and the structure aligns well with the Tokenism service integration described in the PR objectives.
30-30: Type derivation is correct and idiomatic.The exported
ErrorIdtype correctly derives a union of all error ID literal values from the constErrorIdsobject, enabling type-safe usage throughout the application. The pattern properly captures all 13 error IDs as a union type.
- Update JSDoc: "Sentry" → "Loki/Promtail" (actual observability stack) - Add explicit errorId?: ErrorId to ErrorContext interface - Import ErrorId type in errorUtils for type safety These changes address PR review feedback: - Documentation now accurately reflects the logging infrastructure - Explicit typing enables autocomplete and prevents typos 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
pmoves/ui/lib/errorUtils.ts (1)
11-12: LGTM! Type-safe addition for structured error tracking.The optional
errorIdfield enables stable error identifiers for log aggregation without breaking existing code. The JSDoc clearly documents its purpose.Optional refinement: Consider extracting
errorIdas a top-level field inStructuredLogEntry(similar tocomponentandactionat lines 32-33) for improved queryability in Loki:interface StructuredLogEntry { timestamp: string; level: ErrorSeverity; message: string; error?: { name: string; message: string; stack?: string; }; errorId?: ErrorId; // Top-level for easier filtering component?: string; action?: string; context?: Record<string, unknown>; }Then extract it in
logErrorat line 96:const entry: StructuredLogEntry = { timestamp: new Date().toISOString(), level: severity, message, error: { name: errorObj.name, message: errorObj.message, stack: errorObj.stack, }, + errorId: context?.errorId, component: context?.component, action: context?.action, context: context ? { ...context } : undefined, };Verification required: As per coding guidelines for UI files, run smoke tests to validate the changes:
#!/bin/bash # Lint Next.js bundle and validate connectivity make -C pmoves notebook-workbench-smoke ARGS="--thread=$(uuidgen)"Also verify that errorId is being used correctly across the codebase:
#!/bin/bash # Find usages of errorId in the UI codebase rg -nP --type=ts --type=tsx -C3 '\berrorId\s*[:?]' pmoves/ui/
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
pmoves/ui/lib/constants/errorIds.tspmoves/ui/lib/errorUtils.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- pmoves/ui/lib/constants/errorIds.ts
🧰 Additional context used
📓 Path-based instructions (1)
pmoves/ui/**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (pmoves/AGENTS.md)
UI updates: run
make -C pmoves notebook-workbench-smoke ARGS="--thread=<uuid>"to lint the Next.js bundle and validate Supabase connectivity; referencepmoves/docs/UI_NOTEBOOK_WORKBENCH.md
Files:
pmoves/ui/lib/errorUtils.ts
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-15T12:03:17.291Z
Learning: PRs should include clear description, linked issues, affected services, run/rollback notes, and screenshots for UI/flows; start from STARTER_PR_BODY.md and adjust sections as needed
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/AGENTS.md:0-0
Timestamp: 2025-12-07T11:03:53.415Z
Learning: PRs should include: clear description, linked issues, affected services, run/rollback notes, and screenshots for UI/flows
🧬 Code graph analysis (1)
pmoves/ui/lib/errorUtils.ts (1)
pmoves/ui/lib/constants/errorIds.ts (1)
ErrorId(30-30)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Analyze (python)
🔇 Additional comments (1)
pmoves/ui/lib/errorUtils.ts (1)
6-6: LGTM! Type-safe import for error identifiers.The type-only import correctly brings in the centralized ErrorId type, enabling autocomplete and type checking across error handling code.
Run the following script to verify the import path resolves correctly:
#!/bin/bash # Verify the errorIds.ts file exists and exports ErrorId type # Check if the errorIds.ts file exists fd -t f "errorIds.ts$" pmoves/ui/lib/constants/ # Verify ErrorId type is exported rg -nP "export type ErrorId" pmoves/ui/lib/constants/errorIds.ts
Add 22 new error IDs across 8 categories: - AUTH: JWT_PARSE_FAILED, JWT_MISSING_HEADER, JWT_INVALID_SIGNATURE, SUPABASE_AUTH_FAILED, SUPABASE_QUERY_FAILED - CHAT: CHAT_SEND_FAILED, CHAT_FETCH_FAILED - NOTEBOOK: NOTEBOOK_RUNTIME_FETCH_FAILED, NOTEBOOK_SOURCES_FETCH_FAILED, NOTEBOOK_SYNC_FAILED, NOTEBOOK_SYNC_TRIGGER_FAILED - JELLYFIN: JELLYFIN_SEARCH_FAILED, JELLYFIN_SYNC_STATUS_FAILED, JELLYFIN_LINK_FAILED, JELLYFIN_PLAYBACK_URL_FAILED, JELLYFIN_SYNC_TRIGGER_FAILED, JELLYFIN_BACKFILL_FAILED - RESEARCH: RESEARCH_INITIATE_FAILED, RESEARCH_TASK_FETCH_FAILED, RESEARCH_TASK_LIST_FAILED, RESEARCH_RESULTS_FETCH_FAILED, RESEARCH_CANCEL_FAILED, RESEARCH_HEALTH_CHECK_FAILED, RESEARCH_PUBLISH_FAILED - HIRAG: HIRAG_QUERY_FAILED, HIRAG_HEALTH_CHECK_FAILED, HIRAG_EXPORT_FAILED - ERROR_BOUNDARIES: ROOT_ERROR_BOUNDARY, DASHBOARD_ERROR_BOUNDARY - TENSORZERO: TENSORZERO_REQUEST_FAILED, TENSORZERO_TIMEOUT Add runtime validator: - isValidErrorId(value: string): value is ErrorId Update 25 logError() calls to include errorId: - pmoves/ui/lib/api/jellyfin.ts (6 errors) - pmoves/ui/lib/api/research.ts (7 errors) - pmoves/ui/lib/api/hirag.ts (3 errors) - pmoves/ui/lib/jwtUtils.ts (2 errors) - pmoves/ui/app/error.tsx (1 error) - pmoves/ui/app/dashboard/error.tsx (1 error) - pmoves/ui/app/api/chat/send/route.ts (1 error) - pmoves/ui/app/api/chat/messages/route.ts (1 error) - pmoves/ui/app/api/notebook/runtime/route.ts (1 error) - pmoves/ui/app/api/notebook/sources/route.ts (2 errors) - pmoves/ui/app/api/notebook/runtime/sync/route.ts (2 errors) Coverage: 28/30 logError() calls now use error IDs (93% ↑ from 10%) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fixes from PR review:
1. Fix hirag.ts success logging misuse
- Replace logError with logForDebugging for export success case
- Add logForDebugging import
2. Fix jellyfin.ts missing HTTP error logging
- Add logError to 4 HTTP non-ok response paths:
* getJellyfinPlaybackUrl (line 302)
* triggerJellyfinSync (line 344)
* triggerBackfill (line 391)
* getJellyfinSyncStatus (already had logging)
3. Fix JWT error semantics
- Rename JWT_MISSING_HEADER → JWT_INVALID_FORMAT
- More accurately reflects "JWT must have 3 parts" error
- Update jwtUtils.ts to use new error ID
4. Mark unused error IDs with @todo
- JWT_INVALID_SIGNATURE (not yet used)
- SUPABASE_AUTH_FAILED (not yet used)
- SUPABASE_QUERY_FAILED (not yet used)
- TENSORZERO_REQUEST_FAILED (not yet used)
- TENSORZERO_TIMEOUT (not yet used)
5. Fix documentation typos
- AUTHENTICATION/Authorization → AUTHENTICATION/AUTHORIZATION
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
pmoves/ui/lib/api/jellyfin.ts (1)
14-413: Run smoke test to validate the UI changes.This change systematically adds stable error identifiers to all Jellyfin API operations (search, sync status, link, playback URL, sync trigger, and backfill), improving observability and debugging capabilities without altering control flow or public APIs. All error IDs are properly defined in
errorIds.tsand consistently applied across the six functions.As per coding guidelines for UI updates, run the smoke test to validate the changes:
make -C pmoves notebook-workbench-smoke ARGS="--thread=<thread_uuid>"Replace
<thread_uuid>with an actual thread ID. The test lints the Next.js bundle and validates Supabase connectivity.
🧹 Nitpick comments (1)
pmoves/ui/lib/api/jellyfin.ts (1)
200-207: Error IDs added consistently; consider message helper for uniformity.The
errorIdfield is correctly threaded through both error paths. However, line 200 constructs the error message inline, whereas other functions in this file use thegetErrorMessage(response.status)helper. While functionally equivalent, using the helper would maintain consistency.🔎 Optional refactor for consistency
- const message = `HTTP ${response.status}: Failed to fetch sync status`; - logError('Jellyfin sync status HTTP error', new Error(message), 'warning', { + const message = getErrorMessage(response.status); + logError(`Jellyfin sync status failed: ${message}`, new Error(`HTTP ${response.status}`), 'warning', {Also applies to: 214-214
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
pmoves/ui/lib/api/hirag.tspmoves/ui/lib/api/jellyfin.tspmoves/ui/lib/constants/errorIds.tspmoves/ui/lib/jwtUtils.ts
🚧 Files skipped from review as they are similar to previous changes (2)
- pmoves/ui/lib/api/hirag.ts
- pmoves/ui/lib/constants/errorIds.ts
🧰 Additional context used
📓 Path-based instructions (1)
pmoves/ui/**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (pmoves/AGENTS.md)
UI updates: run
make -C pmoves notebook-workbench-smoke ARGS="--thread=<uuid>"to lint the Next.js bundle and validate Supabase connectivity; referencepmoves/docs/UI_NOTEBOOK_WORKBENCH.md
Files:
pmoves/ui/lib/jwtUtils.tspmoves/ui/lib/api/jellyfin.ts
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-15T12:03:17.291Z
Learning: PRs should include clear description, linked issues, affected services, run/rollback notes, and screenshots for UI/flows; start from STARTER_PR_BODY.md and adjust sections as needed
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/AGENTS.md:0-0
Timestamp: 2025-12-07T11:03:53.415Z
Learning: PRs should include: clear description, linked issues, affected services, run/rollback notes, and screenshots for UI/flows
📚 Learning: 2025-12-07T11:03:07.638Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-07T11:03:07.638Z
Learning: Applies to **/pmoves/**/*jellyfin*.py : Jellyfin Publisher must implement expanded error handling, reporting, and metadata propagation
Applied to files:
pmoves/ui/lib/api/jellyfin.ts
🧬 Code graph analysis (2)
pmoves/ui/lib/jwtUtils.ts (2)
pmoves/ui/lib/errorUtils.ts (1)
logError(79-102)pmoves/ui/lib/constants/errorIds.ts (1)
ErrorIds(8-75)
pmoves/ui/lib/api/jellyfin.ts (2)
pmoves/ui/lib/constants/errorIds.ts (1)
ErrorIds(8-75)pmoves/ui/lib/errorUtils.ts (1)
logError(79-102)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Analyze (python)
🔇 Additional comments (9)
pmoves/ui/lib/jwtUtils.ts (3)
3-3: LGTM: ErrorIds import supports enhanced observability.The import is correctly structured and necessary for the errorId enhancements below.
26-29: LGTM: Enhanced error logging improves observability.The addition of
errorId: ErrorIds.JWT_INVALID_FORMATand the more descriptive error message will significantly improve error tracking and debugging. The component context fallback is well-handled.
48-51: Smoke test execution required per coding guidelines before merge.The error logging enhancement is sound — adding
errorId: ErrorIds.JWT_PARSE_FAILEDaligns with the established pattern throughout the codebase and improves error traceability. However, as a UI TypeScript file update, per coding guidelines this must be validated with:make -C pmoves notebook-workbench-smoke ARGS="--thread=<uuid>"This will lint the Next.js bundle and validate Supabase connectivity. Please confirm execution and share results before approval.
pmoves/ui/lib/api/jellyfin.ts (6)
14-14: LGTM: ErrorIds import added correctly.The import is properly positioned and necessary for the error identification enhancements throughout this file.
159-164: LGTM: Error tracking enhanced for search operations.Both HTTP error and exception paths now include
ErrorIds.JELLYFIN_SEARCH_FAILEDfor consistent error identification. The addition ofsearchTermcontext on line 163 will aid in debugging search failures.Also applies to: 175-175
253-259: LGTM: Link operation errors now include rich context.The addition of
videoIdandjellyfinItemIdto the error context (lines 257-258) will facilitate debugging linking failures by providing the specific entities involved.Also applies to: 269-269
304-309: LGTM: Playback URL error tracking enhanced.Consistent error identification with
ErrorIds.JELLYFIN_PLAYBACK_URL_FAILEDacross both error paths.Also applies to: 319-319
346-351: LGTM: Sync trigger errors properly identified.The error identification is consistent across both HTTP and exception paths.
Also applies to: 360-360
393-398: LGTM: Backfill error tracking complete.All error paths now include proper error identification with
ErrorIds.JELLYFIN_BACKFILL_FAILED.Also applies to: 407-407
This commit addresses all Critical, Important, and selected Optional issues from comprehensive PR review of A2UI NATS Bridge and Tokenism Simulator. ## Sprint 1: Critical Fixes (6/6 complete) ### 1.1 Fix hardcoded absolute path - File: config/__init__.py - Changed from /home/pmoves/PMOVES.AI/pmoves/env.shared to relative path - Uses Path(__file__).resolve().parents[2] for portability ### 1.2 Fix weak default secret key - File: config/__init__.py - Replaced 'pmoves-tokenism-secret' with secrets.token_hex(32) - Logs warning when using auto-generated key ### 1.3 Convert publish_a2ui_event to raise exceptions - File: a2ui-nats-bridge/bridge.py - Changed from returning False to raising ConnectionError/RuntimeError - Updated all callers to handle exceptions with HTTP 503 ### 1.4 Convert NATSClient.connect to raise exceptions - File: config/nats.py - Added retry logic with exponential backoff (5 attempts, 1s→30s) - Raises ConnectionError after max attempts ### 1.5 Add TensorZero custom exceptions - File: config/tensorzero.py - Added TensorZeroError, TensorZeroHTTPError, TensorZeroTimeoutError - All with transient flag for smart retry logic ### 1.6 Fix misleading metric comment - File: a2ui-nats-bridge/bridge.py - Changed geometry_events_subscribed to a2ui_events_forwarded ## Sprint 2: Important Fixes (5/5 complete) ### 2.1 Replace datetime.utcnow() - Updated 12 occurrences across 6 files - Migrated to datetime.now(timezone.utc) for Python 3.12+ compatibility ### 2.2 Replace FastAPI on_event with lifespan - File: a2ui-nats-bridge/bridge.py - Added @asynccontextmanager lifespan function - Removed deprecated @app.on_event decorators - All 26 tests still pass ### 2.3 Add missing WeeklyMetrics fields - File: services/chit_encoder.py - Added new_participants=0 and staked_tokens=0 to fallback ### 2.4 Add WebSocket integration tests - File: tests/a2ui/test_bridge.py - Added TestA2UIEventTypes class with 4 new tests - Tests increased from 22 to 26 passing ### 2.5 Add CHIT encoding round-trip tests - New file: services/tokenism-simulator/tests/test_chit_encoder.py - 8 new tests for CGP packet encoding/decoding ## Sprint 3: Documentation (4/4 complete) ### 2.6 Document NATSClient methods - File: config/nats.py - Added comprehensive docstrings with Args/Returns/Raises ### 2.7 Document SimulationEngine methods - File: services/simulation_engine.py - Added docstrings for all 11 private methods ### 2.8 Document Bridge lifecycle functions - File: a2ui-nats-bridge/bridge.py - Enhanced connect_nats(), lifespan(), main() docstrings ### 2.9 Add module docstrings - Added docstrings to 4 __init__.py files with __all__ exports ## Sprint 4: Optional Enhancements (3/4 complete) ### 3.1 Restrict CORS origins - File: app.py - Changed from wildcard "*" to configurable ALLOWED_ORIGINS env var - Defaults to localhost:3000,8080,4000 ### 3.2 Complete async endpoint - File: api/simulation.py - Implemented background simulation using ThreadPoolExecutor - Added GET /api/v1/simulate/<id> status check endpoint ## Test Results - ✅ 26 A2UI bridge tests pass - ✅ 8 CHIT encoder tests pass - ✅ All Python files compile successfully 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…timezone.utc) Replaces all 41 occurrences of the deprecated datetime.utcnow() with the modern timezone-aware pattern datetime.now(timezone.utc) across the codebase. This ensures: - Timezone-aware datetime objects (UTC with explicit tzinfo) - Python 3.12+ compatibility (utcnow() was deprecated in 3.12) - Consistent ISO 8601 format serialization - Proper equality/comparison behavior between datetime objects Files modified (21 total): Services: - pmoves/services/agent_zero/controller.py (1) - pmoves/services/botz-gateway/main.py (7) - pmoves/services/comfy-watcher/watcher.py (1) - pmoves/services/common/cgp_mappers.py (1) - pmoves/services/common/events.py (1) - pmoves/services/consciousness-service/cgp_mapper.py (1) - pmoves/services/consciousness-service/persona_gate.py (1) - pmoves/services/pdf-ingest/app.py (1) - pmoves/services/pmoves-yt/yt.py (3) - pmoves/services/publisher/publisher.py (1) - pmoves/services/retrieval-eval/eval_utils.py (1) - pmoves/services/session-context-worker/main.py (3) - pmoves/services/session-context-worker/test_transform.py (3) - pmoves/services/tensorzero-config-api/logging.py (5) Tools: - pmoves/tools/consciousness_build.py (1) - pmoves/tools/consciousness_harvester.py (4) - pmoves/tools/mini_cli.py (1) Scripts: - pmoves/scripts/bootstrap_env.py (1) Submodules: - pmoves/integrations/archon (3 files committed separately) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 16
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (15)
pmoves/services/botz-gateway/main.py (1)
15-15: Critical:timezoneis not imported, causingNameErrorat runtime.The code uses
timezone.utcin 7 locations buttimezoneis missing from thedatetimeimport. This will crash every endpoint and the background cleanup task.Proposed fix
-from datetime import datetime, timedelta +from datetime import datetime, timedelta, timezonepmoves/services/pdf-ingest/app.py (1)
22-29:timezoneis not imported in the fallback block – will crash when executed.The fallback
envelopefunction referencestimezone.utcbut only importsdatetimeanduuid.Proposed fix
except Exception: # pragma: no cover - fallback for local runs without shared module import datetime import uuid + from datetime import timezone def envelope(topic: str, payload: dict, correlation_id: str | None = None, parent_id: str | None = None, source: str = "pdf-ingest") -> dict: env = { "id": str(uuid.uuid4()), "topic": topic, "ts": datetime.datetime.now(timezone.utc).isoformat() + "Z",pmoves/services/common/events.py (1)
1-1:timezoneis not imported – shared module will fail at runtime.This is a shared module used across multiple services. The
timezonereference on line 32 will cause aNameErrorfor all callers.Proposed fix (option 1: add import)
-import json, os, uuid, datetime +import json, os, uuid, datetime +from datetime import timezoneProposed fix (option 2: use qualified name)
- "ts": datetime.datetime.now(timezone.utc).isoformat() + "Z", + "ts": datetime.datetime.now(datetime.timezone.utc).isoformat() + "Z",Also applies to: 32-32
pmoves/services/publisher/publisher.py (1)
43-57:timezoneis not imported in the fallback block – will crash when executed.The fallback
envelopefunction referencestimezone.utcbut only importsdatetimeanduuid.Proposed fix
except Exception: # pragma: no cover - fallback used in tests without dependency import datetime import uuid + from datetime import timezone def envelope(pmoves/services/tensorzero-config-api/logging.py (1)
10-10:timezoneis not imported – all logging methods will fail at runtime.The
datetime.now(timezone.utc)calls on lines 289, 318, 345, 376, and 407 referencetimezonewhich is not imported.Proposed fix
-from datetime import datetime +from datetime import datetime, timezonepmoves/services/consciousness-service/cgp_mapper.py (1)
12-12:timezoneis not imported – CGP packet generation will fail.The
datetime.now(timezone.utc)call on line 81 referencestimezonewhich is not imported.Proposed fix
-from datetime import datetime +from datetime import datetime, timezonepmoves/tools/consciousness_build.py (1)
26-26:timezoneis not imported – JSONL writer will fail.The
datetime.now(timezone.utc)call on line 251 referencestimezonewhich is not imported.Proposed fix
-from datetime import datetime +from datetime import datetime, timezonepmoves/services/retrieval-eval/eval_utils.py (1)
6-15: Critical: Missingtimezoneimport causesNameErrorat runtime.The
timezonesymbol is used on line 15 but is not imported. This will raiseNameError: name 'timezone' is not definedwhenutc_now()is called.🔎 Proposed fix
-from datetime import datetime +from datetime import datetime, timezonepmoves/tools/mini_cli.py (1)
12-12: Critical: Missingtimezoneimport causesNameErrorat runtime.The
timezonesymbol is used on line 163 but is not imported (line 12 only importsdatetime). This will crash_write_provisioning_manifest()withNameError: name 'timezone' is not defined.🔎 Proposed fix
-from datetime import datetime +from datetime import datetime, timezoneAlso applies to: 161-168
pmoves/services/common/cgp_mappers.py (1)
3-8: Critical: Missingtimezonereference causesNameErrorat runtime.Line 8 uses
timezone.utcbuttimezoneis not imported. The module aliasesdatetimeas_dtbut the change doesn't use the alias consistently.🔎 Proposed fix (use the existing alias pattern)
def _now_iso() -> str: - return _dt.datetime.now(timezone.utc).isoformat() + "Z" + return _dt.datetime.now(_dt.timezone.utc).isoformat() + "Z"pmoves/services/consciousness-service/persona_gate.py (1)
11-12: Critical: Missingtimezoneimport causesNameErrorat runtime.The
timezonesymbol is used on line 162 but is not imported. Theevaluate()method will crash withNameError: name 'timezone' is not defined.🔎 Proposed fix
-from datetime import datetime +from datetime import datetime, timezoneAlso applies to: 160-163
pmoves/tools/consciousness_harvester.py (1)
42-42: Critical: Missingtimezoneimport causesNameErrorat runtime in 4 locations.The
timezonesymbol is used on lines 152, 230, 304, and 444 but is not imported. This will crash:
_handle_crawl_result()crawl_url_http()extract_theories()harvest_urls()🔎 Proposed fix
-from datetime import datetime +from datetime import datetime, timezonepmoves/services/session-context-worker/test_transform.py (1)
9-9: Critical: Missingtimezoneimport causesNameErrorat runtime in 3 locations.The
timezonesymbol is used on lines 114, 139, and 157 but is not imported. This test script will crash when executed.🔎 Proposed fix
-from datetime import datetime +from datetime import datetime, timezonepmoves/services/session-context-worker/main.py (1)
15-16: Critical: Missingtimezoneimport causesNameErrorat runtime in 3 locations.The
timezonesymbol is used on lines 162, 209, and 233 but is not imported. This production service will crash when processing session context messages via_build_metadata()and_transform_to_kb_upsert().🔎 Proposed fix
-from datetime import datetime +from datetime import datetime, timezonepmoves/services/a2ui-nats-bridge/bridge.py (1)
168-174: Replace string-based error matching with NATS error code check.The
nats-pylibrary provides error codes for JetStream exceptions. Use error code10058(JSStreamNameExistErr) instead of string matching:except APIError as e: if e.err_code == 10058: # stream name already in use logger.info("NATS stream 'A2UI' already exists") else: logger.error(f"Failed to create A2UI stream: {e}") raiseImport
APIErrorfromnats.js.errorsand catch that specifically instead of the genericJSError. This approach is used elsewhere in the codebase (seeagent_zero/controller.py:429) and is resilient to NATS server version changes.
🧹 Nitpick comments (11)
pmoves/services/session-context-worker/main.py (1)
417-427: Consider migrating from deprecatedon_eventtolifespancontext manager.The PR objectives mention "replace FastAPI on_event with lifespan" but this file still uses the deprecated
@app.on_event("startup")and@app.on_event("shutdown")decorators. FastAPI recommends thelifespancontext manager pattern for newer applications.🔎 Example lifespan pattern
from contextlib import asynccontextmanager @asynccontextmanager async def lifespan(app: FastAPI): # Startup global _nats_loop_task logger.info("Starting NATS resilience loop") _nats_loop_task = asyncio.create_task(_nats_resilience_loop()) yield # Shutdown global _nc if _nats_loop_task: _nats_loop_task.cancel() try: await _nats_loop_task except Exception: pass if _nc: try: await _nc.close() except Exception: pass app = FastAPI(title="Session Context Worker", version="0.1.0", lifespan=lifespan)pmoves/services/tokenism-simulator/config/nats.py (1)
55-57: Consider making retry parameters configurable.The retry parameters (
max_attempts=5,backoff=1.0,max_backoff=30.0) are hardcoded. For production flexibility, consider adding these toNATSConfigto allow environment-specific tuning.pmoves/tests/a2ui/test_bridge.py (1)
8-17: Consider using pytest'spythonpathconfiguration instead ofsys.pathmanipulation.The
sys.path.insertapproach works but is fragile. Modern pytest supports apythonpathoption inpyproject.tomlorpytest.inithat's cleaner and more maintainable.Example pytest.ini configuration
[pytest] pythonpath = pmoves/services/a2ui-nats-bridgepmoves/services/a2ui-nats-bridge/bridge.py (2)
332-343: Consider adding a metric for failed user action publishes.Returning 200 to avoid UI disruption is reasonable, but failed publishes are silent to monitoring. A counter like
a2ui_user_actions_failed_totalwould provide observability.
298-299: Minor inconsistency in timestamp format.The health check uses
+00:00suffix whileA2UIEventusesZsuffix (line 78). Both are valid ISO 8601, but consistency may simplify client parsing.Optional: Use consistent Z suffix
- "timestamp": datetime.now(timezone.utc).isoformat() + "timestamp": datetime.now(timezone.utc).isoformat().replace("+00:00", "Z")pmoves/services/tokenism-simulator/config/__init__.py (1)
88-90: Improved secret key generation, but dataclass pattern is unconventional.Good improvement: using
secrets.token_hex(32)instead of a hardcoded default. However, the_secret_key_envfield in a frozen dataclass is unconventional—it becomes a public field despite the underscore prefix.Consider moving the logic outside the dataclass:
🔎 Alternative pattern
def _get_secret_key() -> str: """Get secret key from environment or generate a secure one.""" env_key = os.getenv('SECRET_KEY', '') return env_key if env_key else secrets.token_hex(32) @dataclass(frozen=True) class ServiceConfig: # ... secret_key: str = field(default_factory=_get_secret_key)Note: This requires importing
fieldfromdataclasses.pmoves/services/tokenism-simulator/config/tensorzero.py (1)
165-180: Considerlogging.exceptionfor automatic traceback capture.Using
logging.exceptioninstead oflogging.errorautomatically includes the exception traceback, which aids debugging in production.🔎 Proposed improvement
except httpx.HTTPStatusError as e: - logger.error(f"HTTP error from TensorZero: {e.response.status_code} {e.response.text}") + logger.exception("HTTP error from TensorZero: %s %s", e.response.status_code, e.response.text) raise TensorZeroHTTPError(e.response.status_code, e.response.text) from e except httpx.TimeoutException as e: - logger.error(f"Timeout calling TensorZero after {self.timeout}s") + logger.exception("Timeout calling TensorZero after %ss", self.timeout) raise TensorZeroTimeoutError( f"TensorZero timeout after {self.timeout}s" ) from e except httpx.ConnectError as e: - logger.error(f"Connection error to TensorZero at {self.base_url}") + logger.exception("Connection error to TensorZero at %s", self.base_url) raise TensorZeroConnectionError( f"Cannot connect to TensorZero at {self.base_url}" ) from e except Exception as e: - logger.error(f"Unexpected error calling TensorZero: {e}") + logger.exception("Unexpected error calling TensorZero") raise TensorZeroError(f"TensorZero request failed: {e}") from epmoves/services/tokenism-simulator/services/chit_encoder.py (1)
129-138: Geometry generation is non-deterministic.The
np.random.lognormalandnp.random.uniformcalls use the global random state without a fixed seed. This means encoding the sameSimulationResulttwice may produce different geometry points, which could complicate reproducibility and testing.Consider whether deterministic output is desired (e.g., seed based on
simulation_id).🔎 Optional: Deterministic geometry
def _create_wealth_geometry( self, result: SimulationResult, metrics: WeeklyMetrics, ) -> dict[str, Any]: + # Seed based on simulation_id for reproducible geometry + rng = np.random.default_rng(hash(result.simulation_id) % (2**32)) + # Generate synthetic wealth distribution based on metrics n_participants = metrics.active_participants avg_wealth = metrics.avg_wealth gini = metrics.gini_coefficient sigma = -np.log(1 - gini) * 0.5 mu = np.log(avg_wealth) - sigma**2 / 2 - wealth_points = np.random.lognormal(mu, sigma, n_participants) + wealth_points = rng.lognormal(mu, sigma, n_participants) # ... update other np.random calls to use rngpmoves/services/tokenism-simulator/tests/test_chit_encoder.py (1)
8-13: Avoidsys.pathmanipulation; use pytest configuration instead.Direct
sys.path.insertis brittle and can cause issues with IDE tooling and test isolation. Configure the Python path inpytest.iniorpyproject.toml, or use relative imports with a proper package structure.🔎 Recommended: pytest configuration
In
pyproject.tomlorpytest.ini:[tool:pytest] pythonpath = pmoves/services/tokenism-simulatorThen remove the sys.path manipulation:
-import sys import pytest from decimal import Decimal - -# Add service to path -sys.path.insert(0, "pmoves/services/tokenism-simulator") from models.simulation import (pmoves/services/tokenism-simulator/services/simulation_engine.py (2)
228-298:_simulate_weekis async but performs no async operations.The method is declared
asyncand awaited at line 111, but its body contains noawaitexpressions. While this works, it adds unnecessary overhead.Consider making it synchronous unless you plan to add async operations (e.g., external data fetches) in the future.
🔎 Make method synchronous
- async def _simulate_week( + def _simulate_week( self, params: SimulationParameters, state: dict[str, Any], week_num: int, ) -> WeeklyMetrics:And update the call site:
- metrics = await self._simulate_week(params, current_state, week) + metrics = self._simulate_week(params, current_state, week)
213-214: Global random seed affects all NumPy random operations.Using
np.random.seed(42)modifies global state, which could cause issues with concurrent simulations or other code using NumPy's random functions.Consider using a local
np.random.Generatorinstance for isolation:🔎 Use local random generator
def _initialize_state(self, params: SimulationParameters) -> dict[str, Any]: # Generate initial wealth distribution - np.random.seed(42) + rng = np.random.default_rng(42) sigma = -np.log(1 - params.initial_gini) * 0.5 mu = np.log(1000) - sigma**2 / 2 - initial_wealth = np.random.lognormal(mu, sigma, params.initial_participants) + initial_wealth = rng.lognormal(mu, sigma, params.initial_participants) return { "wealth": list(initial_wealth), + "rng": rng, # Pass to _simulate_week and _apply_contract_logic # ... }Then update
_simulate_weekand_apply_contract_logicto usestate["rng"]instead ofnp.random.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (33)
pmoves/integrations/archonpmoves/scripts/bootstrap_env.pypmoves/services/a2ui-nats-bridge/bridge.pypmoves/services/agent_zero/controller.pypmoves/services/botz-gateway/main.pypmoves/services/comfy-watcher/watcher.pypmoves/services/common/cgp_mappers.pypmoves/services/common/events.pypmoves/services/consciousness-service/cgp_mapper.pypmoves/services/consciousness-service/persona_gate.pypmoves/services/pdf-ingest/app.pypmoves/services/pmoves-yt/yt.pypmoves/services/publisher/publisher.pypmoves/services/retrieval-eval/eval_utils.pypmoves/services/session-context-worker/main.pypmoves/services/session-context-worker/test_transform.pypmoves/services/tensorzero-config-api/logging.pypmoves/services/tokenism-simulator/api/__init__.pypmoves/services/tokenism-simulator/api/simulation.pypmoves/services/tokenism-simulator/app.pypmoves/services/tokenism-simulator/config/__init__.pypmoves/services/tokenism-simulator/config/nats.pypmoves/services/tokenism-simulator/config/tensorzero.pypmoves/services/tokenism-simulator/models/__init__.pypmoves/services/tokenism-simulator/services/__init__.pypmoves/services/tokenism-simulator/services/chit_encoder.pypmoves/services/tokenism-simulator/services/simulation_engine.pypmoves/services/tokenism-simulator/tests/__init__.pypmoves/services/tokenism-simulator/tests/test_chit_encoder.pypmoves/tests/a2ui/test_bridge.pypmoves/tools/consciousness_build.pypmoves/tools/consciousness_harvester.pypmoves/tools/mini_cli.py
✅ Files skipped from review due to trivial changes (2)
- pmoves/integrations/archon
- pmoves/services/tokenism-simulator/tests/init.py
🧰 Additional context used
📓 Path-based instructions (6)
**/pmoves/**/*{eval,retrieval,test,harness}*.py
📄 CodeRabbit inference engine (GEMINI.md)
Wire the retrieval-eval harness as a persona publish gate and exercise creator pipeline end-to-end
Files:
pmoves/services/session-context-worker/test_transform.pypmoves/services/retrieval-eval/eval_utils.pypmoves/services/tokenism-simulator/tests/test_chit_encoder.pypmoves/tests/a2ui/test_bridge.py
pmoves/services/**/*.py
📄 CodeRabbit inference engine (pmoves/AGENTS.md)
pmoves/services/**/*.py: Keep modules small and single-purpose; share helpers inservices/common/
FastAPI routes: snake_case function names; path names kebab-case only in URLs
Validate payloads against schemas before publishing events usingservices/common/events.py
Files:
pmoves/services/session-context-worker/test_transform.pypmoves/services/retrieval-eval/eval_utils.pypmoves/services/tokenism-simulator/services/__init__.pypmoves/services/common/cgp_mappers.pypmoves/services/agent_zero/controller.pypmoves/services/tokenism-simulator/tests/test_chit_encoder.pypmoves/services/session-context-worker/main.pypmoves/services/tokenism-simulator/api/__init__.pypmoves/services/tensorzero-config-api/logging.pypmoves/services/tokenism-simulator/models/__init__.pypmoves/services/consciousness-service/persona_gate.pypmoves/services/tokenism-simulator/services/simulation_engine.pypmoves/services/consciousness-service/cgp_mapper.pypmoves/services/tokenism-simulator/config/nats.pypmoves/services/tokenism-simulator/services/chit_encoder.pypmoves/services/tokenism-simulator/config/tensorzero.pypmoves/services/common/events.pypmoves/services/comfy-watcher/watcher.pypmoves/services/tokenism-simulator/config/__init__.pypmoves/services/tokenism-simulator/api/simulation.pypmoves/services/publisher/publisher.pypmoves/services/a2ui-nats-bridge/bridge.pypmoves/services/botz-gateway/main.pypmoves/services/pdf-ingest/app.pypmoves/services/pmoves-yt/yt.pypmoves/services/tokenism-simulator/app.py
pmoves/**/*.py
📄 CodeRabbit inference engine (pmoves/AGENTS.md)
Python 3.11+, 4-space indentation, prefer type hints
Files:
pmoves/services/session-context-worker/test_transform.pypmoves/services/retrieval-eval/eval_utils.pypmoves/services/tokenism-simulator/services/__init__.pypmoves/services/common/cgp_mappers.pypmoves/services/agent_zero/controller.pypmoves/tools/consciousness_harvester.pypmoves/services/tokenism-simulator/tests/test_chit_encoder.pypmoves/tools/mini_cli.pypmoves/scripts/bootstrap_env.pypmoves/tests/a2ui/test_bridge.pypmoves/services/session-context-worker/main.pypmoves/tools/consciousness_build.pypmoves/services/tokenism-simulator/api/__init__.pypmoves/services/tensorzero-config-api/logging.pypmoves/services/tokenism-simulator/models/__init__.pypmoves/services/consciousness-service/persona_gate.pypmoves/services/tokenism-simulator/services/simulation_engine.pypmoves/services/consciousness-service/cgp_mapper.pypmoves/services/tokenism-simulator/config/nats.pypmoves/services/tokenism-simulator/services/chit_encoder.pypmoves/services/tokenism-simulator/config/tensorzero.pypmoves/services/common/events.pypmoves/services/comfy-watcher/watcher.pypmoves/services/tokenism-simulator/config/__init__.pypmoves/services/tokenism-simulator/api/simulation.pypmoves/services/publisher/publisher.pypmoves/services/a2ui-nats-bridge/bridge.pypmoves/services/botz-gateway/main.pypmoves/services/pdf-ingest/app.pypmoves/services/pmoves-yt/yt.pypmoves/services/tokenism-simulator/app.py
**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Use Python 3.11+ with 4-space indentation and prefer type hints in all Python code
Files:
pmoves/services/session-context-worker/test_transform.pypmoves/services/retrieval-eval/eval_utils.pypmoves/services/tokenism-simulator/services/__init__.pypmoves/services/common/cgp_mappers.pypmoves/services/agent_zero/controller.pypmoves/tools/consciousness_harvester.pypmoves/services/tokenism-simulator/tests/test_chit_encoder.pypmoves/tools/mini_cli.pypmoves/scripts/bootstrap_env.pypmoves/tests/a2ui/test_bridge.pypmoves/services/session-context-worker/main.pypmoves/tools/consciousness_build.pypmoves/services/tokenism-simulator/api/__init__.pypmoves/services/tensorzero-config-api/logging.pypmoves/services/tokenism-simulator/models/__init__.pypmoves/services/consciousness-service/persona_gate.pypmoves/services/tokenism-simulator/services/simulation_engine.pypmoves/services/consciousness-service/cgp_mapper.pypmoves/services/tokenism-simulator/config/nats.pypmoves/services/tokenism-simulator/services/chit_encoder.pypmoves/services/tokenism-simulator/config/tensorzero.pypmoves/services/common/events.pypmoves/services/comfy-watcher/watcher.pypmoves/services/tokenism-simulator/config/__init__.pypmoves/services/tokenism-simulator/api/simulation.pypmoves/services/publisher/publisher.pypmoves/services/a2ui-nats-bridge/bridge.pypmoves/services/botz-gateway/main.pypmoves/services/pdf-ingest/app.pypmoves/services/pmoves-yt/yt.pypmoves/services/tokenism-simulator/app.py
pmoves/services/*/tests/test_*.py
📄 CodeRabbit inference engine (pmoves/AGENTS.md)
pmoves/services/*/tests/test_*.py: Usepytestwithtests/per service (e.g.,services/<name>/tests/test_*.py) for testing
Mock external systems (NATS, MinIO, Neo4j) and validate envelope/schema with sample payloads in tests
Files:
pmoves/services/tokenism-simulator/tests/test_chit_encoder.py
**/{.github,ci,lint,scripts}/**/*.{py,js,yaml,yml}
📄 CodeRabbit inference engine (GEMINI.md)
Draft a CI-oriented pack manifest linter for validation
Files:
pmoves/scripts/bootstrap_env.py
🧠 Learnings (4)
📓 Common learnings
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-07T11:02:53.362Z
Learning: When requested to summarize a pull request, provide a short (3–5 bullet) recap highlighting risky areas, test coverage, and any follow-up work; point the author back to the PR template checkboxes if key validations are missing
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-15T12:03:17.291Z
Learning: PRs should include clear description, linked issues, affected services, run/rollback notes, and screenshots for UI/flows; start from STARTER_PR_BODY.md and adjust sections as needed
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/AGENTS.md:0-0
Timestamp: 2025-12-07T11:03:53.415Z
Learning: PRs should include: clear description, linked issues, affected services, run/rollback notes, and screenshots for UI/flows
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-15T12:03:17.291Z
Learning: Mandatory context before changes: read pmoves/docs/PMOVES.AI PLANS/ROADMAP.md and pmoves/docs/NEXT_STEPS.md to align with current sprint focus
📚 Learning: 2025-12-07T11:03:53.415Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/AGENTS.md:0-0
Timestamp: 2025-12-07T11:03:53.415Z
Learning: Applies to pmoves/services/*/tests/test_*.py : Mock external systems (NATS, MinIO, Neo4j) and validate envelope/schema with sample payloads in tests
Applied to files:
pmoves/services/tokenism-simulator/tests/test_chit_encoder.py
📚 Learning: 2025-12-15T12:03:17.291Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-15T12:03:17.291Z
Learning: Applies to pmoves/env.shared.example : Copy env.shared.example → env.shared and fill in secrets; never commit real secrets in env.shared
Applied to files:
pmoves/services/tokenism-simulator/config/__init__.py
📚 Learning: 2025-12-07T11:03:53.415Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/AGENTS.md:0-0
Timestamp: 2025-12-07T11:03:53.415Z
Learning: Keep shared defaults in `env.shared` and machine-specific overrides in `.env.local`. Copy `env.shared.example` → `env.shared`; never commit secrets
Applied to files:
pmoves/services/tokenism-simulator/config/__init__.py
🧬 Code graph analysis (8)
pmoves/services/tokenism-simulator/services/__init__.py (2)
pmoves/services/tokenism-simulator/services/simulation_engine.py (2)
SimulationEngine(36-431)get_simulation_engine(438-458)pmoves/services/tokenism-simulator/services/chit_encoder.py (1)
CHITEncoder(29-282)
pmoves/services/tokenism-simulator/tests/test_chit_encoder.py (2)
pmoves/services/tokenism-simulator/models/simulation.py (1)
SimulationScenario(27-33)pmoves/services/tokenism-simulator/services/chit_encoder.py (4)
CHITEncoder(29-282)to_json(275-277)from_json(279-282)encode_simulation_result(42-96)
pmoves/tests/a2ui/test_bridge.py (1)
pmoves/services/a2ui-nats-bridge/bridge.py (2)
A2UIEvent(67-119)from_a2ui_dict(87-119)
pmoves/services/tokenism-simulator/models/__init__.py (1)
pmoves/services/tokenism-simulator/models/simulation.py (7)
SimulationParameters(36-75)SimulationResult(111-148)WeeklyMetrics(78-108)SimulationScenario(27-33)ContractType(18-24)CGPPacket(185-221)CalibrationData(151-182)
pmoves/services/tokenism-simulator/services/simulation_engine.py (1)
pmoves/services/tokenism-simulator/models/simulation.py (1)
WeeklyMetrics(78-108)
pmoves/services/tokenism-simulator/config/nats.py (1)
pmoves/services/tokenism-simulator/config/__init__.py (1)
NATSConfig(32-46)
pmoves/services/tokenism-simulator/api/simulation.py (2)
pmoves/services/tokenism-simulator/models/simulation.py (2)
SimulationParameters(36-75)SimulationScenario(27-33)pmoves/services/tokenism-simulator/services/simulation_engine.py (3)
get_simulation_engine(438-458)run_simulation(85-158)close(424-431)
pmoves/services/pdf-ingest/app.py (1)
pmoves/services/hi-rag-gateway-v2/web/script.js (1)
now(263-263)
🪛 Ruff (0.14.10)
pmoves/services/session-context-worker/test_transform.py
114-114: Undefined name timezone
(F821)
139-139: Undefined name timezone
(F821)
157-157: Undefined name timezone
(F821)
pmoves/services/retrieval-eval/eval_utils.py
15-15: Undefined name timezone
(F821)
pmoves/services/tokenism-simulator/services/__init__.py
11-16: __all__ is not sorted
Apply an isort-style sorting to __all__
(RUF022)
pmoves/services/common/cgp_mappers.py
8-8: Undefined name timezone
(F821)
pmoves/services/agent_zero/controller.py
86-86: Undefined name timezone
(F821)
pmoves/tools/consciousness_harvester.py
152-152: Undefined name timezone
(F821)
230-230: Undefined name timezone
(F821)
304-304: Undefined name timezone
(F821)
444-444: Undefined name timezone
(F821)
pmoves/tools/mini_cli.py
163-163: Undefined name timezone
(F821)
pmoves/scripts/bootstrap_env.py
184-184: Undefined name timezone
(F821)
pmoves/services/session-context-worker/main.py
162-162: Undefined name timezone
(F821)
209-209: Undefined name timezone
(F821)
233-233: Undefined name timezone
(F821)
pmoves/tools/consciousness_build.py
251-251: Undefined name timezone
(F821)
pmoves/services/tensorzero-config-api/logging.py
289-289: Undefined name timezone
(F821)
318-318: Undefined name timezone
(F821)
345-345: Undefined name timezone
(F821)
376-376: Undefined name timezone
(F821)
407-407: Undefined name timezone
(F821)
pmoves/services/tokenism-simulator/models/__init__.py
22-30: __all__ is not sorted
Apply an isort-style sorting to __all__
(RUF022)
pmoves/services/consciousness-service/persona_gate.py
162-162: Undefined name timezone
(F821)
pmoves/services/consciousness-service/cgp_mapper.py
81-81: Undefined name timezone
(F821)
pmoves/services/tokenism-simulator/config/nats.py
77-77: Do not catch blind exception: Exception
(BLE001)
81-81: Consider moving this statement to an else block
(TRY300)
83-83: Do not catch blind exception: Exception
(BLE001)
92-94: Avoid specifying long messages outside the exception class
(TRY003)
244-244: Local variable e is assigned to but never used
Remove assignment to unused variable e
(F841)
pmoves/services/tokenism-simulator/config/tensorzero.py
169-169: Use logging.exception instead of logging.error
Replace with exception
(TRY400)
170-172: Avoid specifying long messages outside the exception class
(TRY003)
174-174: Use logging.exception instead of logging.error
Replace with exception
(TRY400)
175-177: Avoid specifying long messages outside the exception class
(TRY003)
179-179: Use logging.exception instead of logging.error
Replace with exception
(TRY400)
180-180: Avoid specifying long messages outside the exception class
(TRY003)
pmoves/services/common/events.py
32-32: Undefined name timezone
(F821)
pmoves/services/comfy-watcher/watcher.py
80-80: Undefined name timezone
(F821)
pmoves/services/tokenism-simulator/api/simulation.py
101-101: Do not catch blind exception: Exception
(BLE001)
108-108: Use logging.exception instead of logging.error
Replace with exception
(TRY400)
257-257: Do not catch blind exception: Exception
(BLE001)
258-258: Use logging.exception instead of logging.error
Replace with exception
(TRY400)
pmoves/services/publisher/publisher.py
57-57: Undefined name timezone
(F821)
pmoves/services/a2ui-nats-bridge/bridge.py
201-201: Unused function argument: app
(ARG001)
246-246: Avoid specifying long messages outside the exception class
(TRY003)
258-258: Avoid specifying long messages outside the exception class
(TRY003)
323-323: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
382-382: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
441-441: Use logging.exception instead of logging.error
Replace with exception
(TRY400)
pmoves/services/botz-gateway/main.py
157-157: Undefined name timezone
(F821)
189-189: Undefined name timezone
(F821)
217-217: Undefined name timezone
(F821)
249-249: Undefined name timezone
(F821)
331-331: Undefined name timezone
(F821)
425-425: Undefined name timezone
(F821)
463-463: Undefined name timezone
(F821)
pmoves/services/pdf-ingest/app.py
29-29: Undefined name timezone
(F821)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Analyze (python)
🔇 Additional comments (32)
pmoves/services/botz-gateway/main.py (1)
157-157: Timezone-aware UTC timestamps are the correct approach.Once the missing
timezoneimport is added, these changes correctly replace the deprecateddatetime.utcnow()withdatetime.now(timezone.utc), which is the recommended pattern for Python 3.11+ and avoids deprecation warnings in Python 3.12+.Also applies to: 189-189, 217-217, 249-249, 331-331, 425-425, 463-463
pmoves/services/pmoves-yt/yt.py (1)
21-37: Fallback envelope implementation looks correct.The
timezonereference on line 30 correctly uses the module-level import from line 3, whiledatetime.datetimeuses the module imported in the except block. The scoping is valid.pmoves/services/tokenism-simulator/config/nats.py (5)
14-14: LGTM: Timezone-aware import.The addition of
timezoneenables the shift to timezone-aware UTC timestamps at line 114, which is a best practice for avoiding ambiguity in distributed systems.
74-78: JetStream exception handling is appropriate.The bare
Exceptioncatch here is acceptable because JetStream is optional functionality. Failure to enable JetStream should not prevent the NATS connection from succeeding, and the warning is logged appropriately.
114-114: Excellent: Timezone-aware UTC timestamps.The change from
datetime.utcnow()todatetime.now(timezone.utc)correctly produces timezone-aware timestamps, eliminating ambiguity in message envelopes.
34-42: LGTM: Comprehensive docstring enhancements.The expanded docstrings across
__init__, publish helpers,close,is_connected, andget_nats_clientimprove maintainability and follow Python conventions.Also applies to: 132-161, 207-212, 219-223, 232-236
49-94: All callers properly handle theConnectionErrorexception through exception propagation.The
NATSClient.connect()method is called only inSimulationEngine.initialize(), which documents that it raisesConnectionError. The entry pointget_simulation_engine()is called from Flask routes that wrap the call in try-except blocks (lines 76–111 and 176–194 inapi/simulation.py). Additionally, other callers likeconsciousness_harvester.py(line 524) andconsciousness-service/main.py(line 77) also wrap their respectiveconnect()calls in exception handlers.pmoves/tests/a2ui/test_bridge.py (2)
152-154: LGTM!Metric name correctly updated to match the renamed
a2ui_events_forwarded_totalcounter in bridge.py.
219-271: Good test coverage for A2UI event types.The test class comprehensively covers the standard A2UI event types. The parameterized approach in
test_all_event_types_validatedis efficient.Consider adding edge case tests for robustness, such as events with extra unexpected fields or deeply nested payloads, but this is optional for initial coverage.
pmoves/services/a2ui-nats-bridge/bridge.py (9)
22-24: LGTM!Correct imports for the lifespan context manager pattern and timezone-aware timestamps.
51-53: LGTM!Metric name
a2ui_events_forwarded_totalis more descriptive and accurately reflects the counter's purpose.
76-80: LGTM!Timezone-aware UTC timestamps ensure consistent event ordering across distributed systems. The
Zsuffix is the canonical ISO 8601 format for UTC.
200-226: LGTM!The lifespan pattern correctly manages NATS connection lifecycle. The
appparameter is required by FastAPI's lifespan signature even when unused—the static analysis warning (ARG001) is a false positive.
238-258: LGTM!Exception-based error handling with proper chaining (
from e) at line 258 is correct. The documented exceptions (ConnectionError, RuntimeError) align with the implementation.
261-280: LGTM!Clean delegation to
publish_a2ui_eventwith properly documented exception propagation.
437-442: Good granular error handling for WebSocket events.The differentiated error handling for validation errors vs. NATS errors provides clear client feedback. For line 441,
logging.exceptionwould include the traceback automatically, which may help debugging NATS issues—but this is optional.
477-479: LGTM!Correctly increments the renamed
a2ui_events_forwardedmetric.
502-512: LGTM!Clear docstring documenting environment variables and proper type hint.
pmoves/services/tokenism-simulator/models/__init__.py (1)
1-30: LGTM!The module correctly exports all public models including the new
CalibrationData. The docstring accurately describes the module's purpose.The Ruff hint about
__all__sorting (RUF022) is a style preference—the current ordering logically groups related types, which is a reasonable alternative to alphabetical sorting.pmoves/services/tokenism-simulator/config/tensorzero.py (1)
23-72: Well-designed exception hierarchy with retry semantics.The
transientattribute enables intelligent retry logic upstream. The classification of 5xx as transient and 4xx as non-transient is correct. Timeout and connection errors being transient is also appropriate.pmoves/services/tokenism-simulator/api/__init__.py (1)
1-11: LGTM!Clean module initialization with appropriate docstring and focused export surface.
pmoves/services/tokenism-simulator/services/__init__.py (1)
1-16: LGTM!The module correctly exports the core services with their factory functions. The
__all__ordering groups related items (engine, encoder) which is a reasonable organizational choice.pmoves/services/tokenism-simulator/services/chit_encoder.py (2)
63-77: Good addition of default values for new fields.The default
WeeklyMetricsnow correctly includesnew_participants=0andstaked_tokens=0, aligning with the model definition.
94-94: Timezone-aware timestamp usage is correct.Consistent use of
datetime.now(timezone.utc)across all encoding methods aligns with the project-wide shift to timezone-aware timestamps.pmoves/services/tokenism-simulator/tests/test_chit_encoder.py (2)
25-83: Good round-trip test coverage.The tests verify JSON encode/decode preserves key fields (
simulation_id,geometry,metadata) and handle both minimal and complex geometry structures.
232-337: Comprehensive weekly metrics geometry tests.Good coverage of geometry structure validation and week selection from multi-week results. The assertions verify the expected hyperbolic geometry format.
pmoves/services/tokenism-simulator/services/simulation_engine.py (3)
62-83: Well-documented initialization with proper exception specification.The docstring clearly specifies the connections established and the
ConnectionErrorthat may be raised. Good practice for async initialization patterns.
100-100: Correct timezone-aware timestamp for simulation ID.Using
datetime.now(timezone.utc)ensures consistent, timezone-aware simulation IDs across all deployments.
358-374: Good explicit return type annotation.Adding
-> Noneto_update_stateclarifies that the method modifies state in-place and returns nothing.pmoves/services/tokenism-simulator/api/simulation.py (3)
13-16: LGTM!The added imports are appropriate for implementing background simulation execution with thread-based concurrency and timezone-aware timestamps.
120-120: LGTM!Timezone-aware UTC timestamp improves consistency and eliminates timezone ambiguity.
173-194: Verify synchronous endpoint behavior under load.This endpoint creates a new event loop and blocks the Flask worker thread for the entire simulation duration. If simulations are long-running (as suggested by the async endpoint), this could:
- Exhaust Flask worker threads under moderate load
- Cause client timeouts
- Reduce throughput significantly
The async endpoint (lines 207-259) is the recommended pattern. Consider whether this synchronous endpoint should remain or be deprecated in favor of the async flow.
Do you want to keep both endpoints? If so, document the use case for the synchronous endpoint and consider adding timeout warnings to the API documentation.
| lines: List[str] = [] | ||
| lines.append("# Managed by pmoves/scripts/bootstrap_env.py") | ||
| lines.append(f"# Generated at {_dt.datetime.utcnow().isoformat()}Z") | ||
| lines.append(f"# Generated at {_dt.datetime.now(timezone.utc).isoformat()}Z") |
There was a problem hiding this comment.
timezone is not defined – script will crash at runtime.
The timezone name is not imported. Since datetime is aliased as _dt on line 11, use _dt.timezone.utc or add the import.
Proposed fix
- lines.append(f"# Generated at {_dt.datetime.now(timezone.utc).isoformat()}Z")
+ lines.append(f"# Generated at {_dt.datetime.now(_dt.timezone.utc).isoformat()}Z")📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| lines.append(f"# Generated at {_dt.datetime.now(timezone.utc).isoformat()}Z") | |
| lines.append(f"# Generated at {_dt.datetime.now(_dt.timezone.utc).isoformat()}Z") |
🧰 Tools
🪛 Ruff (0.14.10)
184-184: Undefined name timezone
(F821)
🤖 Prompt for AI Agents
In pmoves/scripts/bootstrap_env.py around line 184, the code uses timezone.utc
but timezone is not imported; update the line to use the already-aliased
datetime module by replacing timezone.utc with _dt.timezone.utc, or
alternatively add an import for timezone (e.g., from datetime import timezone)
at the top so timezone.utc is defined; ensure the chosen fix is consistent with
the existing aliasing of datetime as _dt.
| try: | ||
| await publish_a2ui_event(event) | ||
| except (ConnectionError, RuntimeError) as e: | ||
| raise HTTPException(status_code=503, detail=str(e)) |
There was a problem hiding this comment.
Preserve exception chain with from e.
The static analysis hint (B904) is valid. Using from e preserves the original traceback for debugging.
Proposed fix
try:
await publish_a2ui_event(event)
except (ConnectionError, RuntimeError) as e:
- raise HTTPException(status_code=503, detail=str(e))
+ raise HTTPException(status_code=503, detail=str(e)) from e🧰 Tools
🪛 Ruff (0.14.10)
323-323: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
🤖 Prompt for AI Agents
In pmoves/services/a2ui-nats-bridge/bridge.py around lines 320 to 323, the
except block re-raises an HTTPException but drops the original exception
context; update the raise to preserve the exception chain by using "raise
HTTPException(status_code=503, detail=str(e)) from e" so the original traceback
is retained for debugging and diagnostics.
| try: | ||
| await publish_a2ui_event(mock_event) | ||
| except (ConnectionError, RuntimeError) as e: | ||
| raise HTTPException(status_code=503, detail=str(e)) |
There was a problem hiding this comment.
Preserve exception chain with from e.
Same issue as line 323—use from e for better debugging.
Proposed fix
try:
await publish_a2ui_event(mock_event)
except (ConnectionError, RuntimeError) as e:
- raise HTTPException(status_code=503, detail=str(e))
+ raise HTTPException(status_code=503, detail=str(e)) from e📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| try: | |
| await publish_a2ui_event(mock_event) | |
| except (ConnectionError, RuntimeError) as e: | |
| raise HTTPException(status_code=503, detail=str(e)) | |
| try: | |
| await publish_a2ui_event(mock_event) | |
| except (ConnectionError, RuntimeError) as e: | |
| raise HTTPException(status_code=503, detail=str(e)) from e |
🧰 Tools
🪛 Ruff (0.14.10)
382-382: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
🤖 Prompt for AI Agents
In pmoves/services/a2ui-nats-bridge/bridge.py around lines 379 to 382, the
except block re-raises an HTTPException without preserving the original
exception chain; update the re-raise to include "from e" so the original
ConnectionError/RuntimeError is chained (i.e., raise
HTTPException(status_code=503, detail=str(e)) from e), mirroring the fix applied
at line 323 to improve traceback and debugging.
| "id": str(uuid.uuid4()), | ||
| "topic": topic, | ||
| "ts": datetime.datetime.utcnow().isoformat() + "Z", | ||
| "ts": datetime.datetime.now(timezone.utc).isoformat() + "Z", |
There was a problem hiding this comment.
Critical: timezone is not imported.
Line 86 references timezone.utc, but timezone is not in scope. This will raise a NameError at runtime when the fallback envelope function is invoked.
🔎 Proposed fix
Add the missing import after line 72:
import datetime
+ from datetime import timezone
import uuidCommittable suggestion skipped: line range outside the PR's diff.
🧰 Tools
🪛 Ruff (0.14.10)
86-86: Undefined name timezone
(F821)
🤖 Prompt for AI Agents
In pmoves/services/agent_zero/controller.py around line 86, the code uses
timezone.utc but timezone is not imported; add the missing import (e.g., insert
"from datetime import timezone" after line 72) so timezone is in scope and
datetime.datetime.now(timezone.utc) will not raise a NameError.
| continue | ||
|
|
||
| key = datetime.datetime.utcnow().strftime("comfyui/%Y/%m/%d/") + fn | ||
| key = datetime.datetime.now(timezone.utc).strftime("comfyui/%Y/%m/%d/") + fn |
There was a problem hiding this comment.
Critical: timezone is not imported.
The code references timezone.utc but timezone is undefined. This will raise a NameError at runtime when this line executes.
🔎 Proposed fixes
Option 1 (recommended): Add the missing import
import asyncio
import datetime
+from datetime import timezone
import hashlib
import jsonOption 2: Use the fully qualified name
- key = datetime.datetime.now(timezone.utc).strftime("comfyui/%Y/%m/%d/") + fn
+ key = datetime.datetime.now(datetime.timezone.utc).strftime("comfyui/%Y/%m/%d/") + fn📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| key = datetime.datetime.now(timezone.utc).strftime("comfyui/%Y/%m/%d/") + fn | |
| key = datetime.datetime.now(datetime.timezone.utc).strftime("comfyui/%Y/%m/%d/") + fn |
🧰 Tools
🪛 Ruff (0.14.10)
80-80: Undefined name timezone
(F821)
🤖 Prompt for AI Agents
In pmoves/services/comfy-watcher/watcher.py around line 80, the code uses
timezone.utc but timezone is not imported; add the missing import by adding
"from datetime import timezone" at the top of the file (or alternatively replace
timezone.utc with datetime.timezone.utc) so timezone is defined and the
expression datetime.datetime.now(timezone.utc) does not raise a NameError.
| # Resolve env.shared path relative to this config file | ||
| # Config file is at: .../tokenism-simulator/config/__init__.py | ||
| # Repo root is 3 levels up, then pmoves/env.shared | ||
| _env_path = Path(__file__).resolve().parents[2] / "pmoves" / "env.shared" | ||
| if _env_path.exists(): | ||
| load_dotenv(_env_path) | ||
| else: | ||
| logger.warning(f"Environment file not found: {_env_path}, using system environment") |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Find env.shared file location
echo "=== Searching for env.shared file ==="
fd -t f "env.shared" 2>/dev/null || echo "No env.shared found"
echo ""
echo "=== Checking config file location ==="
fd -t f "__init__.py" pmoves/services/tokenism-simulator/config 2>/dev/null
echo ""
echo "=== Reading config/__init__.py content (first 50 lines) ==="
if [ -f "pmoves/services/tokenism-simulator/config/__init__.py" ]; then
head -50 pmoves/services/tokenism-simulator/config/__init__.py
else
echo "File not found"
fi
echo ""
echo "=== Checking for env.shared in pmoves directory ==="
ls -la pmoves/ | grep -E "^-|env" || echo "No files matching pattern"Repository: POWERFULMOVES/PMOVES.AI
Length of output: 7418
🏁 Script executed:
#!/bin/bash
# Verify the exact path that the current code produces
python3 << 'EOF'
from pathlib import Path
# Simulate the config file location
config_file = Path("pmoves/services/tokenism-simulator/config/__init__.py")
# Current code in review
current_path = config_file.parents[2] / "pmoves" / "env.shared"
print(f"Current code produces: {current_path}")
# Expected location based on env.shared.example
expected_path = Path("pmoves/env.shared")
print(f"Expected location: {expected_path}")
# Calculate correct parents index
correct_path_v1 = config_file.parents[3] / "env.shared"
print(f"Correct fix (v1): {correct_path_v1}")
correct_path_v2 = config_file.parents[4] / "pmoves" / "env.shared"
print(f"Correct fix (v2): {correct_path_v2}")
print(f"\nDo they match? v1={correct_path_v1 == expected_path}, v2={correct_path_v2 == expected_path}")
EOFRepository: POWERFULMOVES/PMOVES.AI
Length of output: 153
Incorrect path calculation for env.shared file.
The path resolution is wrong. From the config file location at pmoves/services/tokenism-simulator/config/__init__.py:
parents[2]resolves to.../pmoves/services(not repo root)- Appending
"pmoves" / "env.shared"yields.../pmoves/services/pmoves/env.shared
The env file is located at pmoves/env.shared in the repository root.
Fix
# Resolve env.shared path relative to this config file
# Config file is at: .../tokenism-simulator/config/__init__.py
-# Repo root is 3 levels up, then pmoves/env.shared
-_env_path = Path(__file__).resolve().parents[2] / "pmoves" / "env.shared"
+# tokenism-simulator is at: pmoves/services/tokenism-simulator
+# env.shared is at: pmoves/env.shared (2 levels up from tokenism-simulator)
+_env_path = Path(__file__).resolve().parents[2] / "env.shared"Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In pmoves/services/tokenism-simulator/config/__init__.py around lines 21-28, the
code uses parents[2] and then appends "pmoves"/"env.shared", which yields
.../pmoves/services/pmoves/env.shared; instead compute the env.shared path
directly from the pmoves package root by using parents[3] and joining
"env.shared" (i.e. Path(__file__).resolve().parents[3] / "env.shared"), then
load_dotenv that path and keep the existing exists() check and warning behavior.
| except Exception as e: | ||
| logger.warning( | ||
| f"NATS connection attempt {attempt+1}/{max_attempts} failed: {e}" | ||
| ) | ||
| if attempt < max_attempts - 1: | ||
| logger.info(f"Retrying in {backoff:.1f}s...") | ||
| await asyncio.sleep(backoff) | ||
| backoff = min(backoff * 2, max_backoff) | ||
|
|
There was a problem hiding this comment.
Critical: Narrow exception handling to avoid catching system exceptions.
Catching bare Exception at line 83 will intercept system exceptions like KeyboardInterrupt, SystemExit, and asyncio.CancelledError, preventing graceful shutdown and complicating debugging. Catch specific NATS-related exceptions instead.
🔎 Proposed fix
- except Exception as e:
+ except (OSError, asyncio.TimeoutError, nats.errors.Error) as e:
logger.warning(
f"NATS connection attempt {attempt+1}/{max_attempts} failed: {e}"
)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| except Exception as e: | |
| logger.warning( | |
| f"NATS connection attempt {attempt+1}/{max_attempts} failed: {e}" | |
| ) | |
| if attempt < max_attempts - 1: | |
| logger.info(f"Retrying in {backoff:.1f}s...") | |
| await asyncio.sleep(backoff) | |
| backoff = min(backoff * 2, max_backoff) | |
| except (OSError, asyncio.TimeoutError, nats.errors.Error) as e: | |
| logger.warning( | |
| f"NATS connection attempt {attempt+1}/{max_attempts} failed: {e}" | |
| ) | |
| if attempt < max_attempts - 1: | |
| logger.info(f"Retrying in {backoff:.1f}s...") | |
| await asyncio.sleep(backoff) | |
| backoff = min(backoff * 2, max_backoff) |
🧰 Tools
🪛 Ruff (0.14.10)
83-83: Do not catch blind exception: Exception
(BLE001)
| try: | ||
| await _nats_client.connect() | ||
| except Exception as e: | ||
| # Reset client on connection failure so it can be retried | ||
| _nats_client = None | ||
| raise |
There was a problem hiding this comment.
Minor: Remove unused exception variable.
The exception variable e at line 244 is assigned but never used. Either remove it from the except clause or use it in the re-raise/logging.
🔎 Proposed fix
try:
await _nats_client.connect()
- except Exception as e:
+ except Exception:
# Reset client on connection failure so it can be retried
_nats_client = None
raise🧰 Tools
🪛 Ruff (0.14.10)
244-244: Local variable e is assigned to but never used
Remove assignment to unused variable e
(F841)
🤖 Prompt for AI Agents
In pmoves/services/tokenism-simulator/config/nats.py around lines 242 to 247,
the except block declares an unused variable `e`; remove the unused variable by
changing `except Exception as e:` to `except Exception:` (or alternatively log
the exception before re-raising if you want the details), keeping the client
reset (`_nats_client = None`) and the bare `raise` to re-raise the original
exception.
| response = await self.chat_completion(messages, temperature=0.3) | ||
| return response.raw_response if response else None | ||
| return response.raw_response |
There was a problem hiding this comment.
Return value may not match expected calibration format.
The method returns response.raw_response, which is the full API response envelope (containing choices, usage, etc.). However, the prompt asks the LLM to return a JSON object with suggestions and confidence keys, which would be in response.content.
If the intent is to return the parsed calibration suggestions, you should parse response.content as JSON.
🔎 Proposed fix
+import json
+
+# In suggest_calibration method:
response = await self.chat_completion(messages, temperature=0.3)
- return response.raw_response
+ try:
+ return json.loads(response.content)
+ except json.JSONDecodeError as e:
+ logger.warning("Failed to parse calibration response as JSON: %s", e)
+ return {"suggestions": [], "confidence": 0.0, "raw_content": response.content}🤖 Prompt for AI Agents
In pmoves/services/tokenism-simulator/config/tensorzero.py around lines 318 to
319, the method currently returns response.raw_response (the full API envelope)
but the prompt expects a JSON object with suggestions and confidence; change the
return to parse response.content (or response.content.text depending on the
response shape) into JSON and return the parsed object containing the
suggestions and confidence keys, and add a small guard to handle JSON parse
errors (raise or return a clear error/empty structure) so the caller always
receives the expected calibration dict.
| final_gini=Decimal('0.3'), | ||
| final_poverty_rate=Decimal('0.1'), | ||
| total_transactions=1000, | ||
| total_volume=Decimal('50000.00'), | ||
| weekly_metrics=[ | ||
| WeeklyMetrics( | ||
| week_number=0, | ||
| avg_wealth=Decimal('1000'), | ||
| median_wealth=Decimal('950'), | ||
| gini_coefficient=Decimal('0.3'), | ||
| poverty_rate=Decimal('0.1'), | ||
| total_transactions=100, | ||
| total_volume=Decimal('10000'), | ||
| active_participants=50, | ||
| new_participants=5, | ||
| staked_tokens=Decimal('500'), | ||
| circulating_supply=Decimal('1000') |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
find pmoves/services/tokenism-simulator -name "*.py" -type f | head -20Repository: POWERFULMOVES/PMOVES.AI
Length of output: 778
🏁 Script executed:
rg "class WeeklyMetrics" pmoves/services/tokenism-simulator/ -A 30Repository: POWERFULMOVES/PMOVES.AI
Length of output: 3394
Use float literals instead of Decimal for WeeklyMetrics fields.
The WeeklyMetrics model defines avg_wealth, gini_coefficient, poverty_rate, total_volume, staked_tokens, and circulating_supply as float fields. Replace the Decimal literals with float literals to match the model's type annotations and avoid unnecessary coercion.
🤖 Prompt for AI Agents
In pmoves/services/tokenism-simulator/tests/test_chit_encoder.py around lines
107 to 123, the WeeklyMetrics instance uses Decimal(...) literals for fields
that are typed as float; replace those Decimal(...) values with plain float
literals (e.g., 1000.0, 0.3, 0.1, 10000.0, 500.0, 1000.0) so the test constructs
match the WeeklyMetrics float annotations and avoid unnecessary coercion.
Summary
This PR addresses Critical and Important issues from PR review of A2UI NATS Bridge integration, plus adds the Tokenism Simulator service with E2B agent sandbox components.
Critical Fixes (A2UI Bridge)
.gitmoduleslines 104, 113 (e2b-desktop, e2b-spells)nc.is_connected()bugnc.is_connected→nc.is_connected()Important Improvements (A2UI Bridge)
condition: service_healthyto NATS dependency"degraded"when NATS disconnectedNew Features
Tokenism Simulator Service - Token economy simulation with:
Observability:
/d/tokenismTesting
Unit Tests (22 tests - all passing)
Integration Tests (6 tests)
Smoke Test Script
Validates:
.gitmodulesURLs (no typos)bridge.pyfixes (is_connected, validation, exceptions)Tokenism Simulator Tests
Files Changed
Core Fixes:
.gitmodules- Fixed submodule URL typospmoves/services/a2ui-nats-bridge/bridge.py- Health check, validation, exceptionspmoves/docker-compose.yml- Healthcheck dependencypmoves/supabase/migrations/20251230000000_tokenism_simulator.sql- RLS policiesNew Service:
pmoves/services/tokenism-simulator/- Full Tokenism simulator implementationpmoves/vendor/e2b-*- 5 E2B submodules addedTests:
pmoves/tests/a2ui/test_bridge.py- 22 unit testspmoves/tests/functional/test_a2ui_bridge_integration.py- Integration testspmoves/tests/functional/test_a2ui_smoke.sh- Smoke test scriptpmoves/tests/functional/test_tokenism_simulator.py- Tokenism testsDocs:
.claude/context/nats-subjects.md- Updated subject catalog.claude/context/services-catalog.md- New service docs.claude/context/submodules.md- E2B submodule docsObservability:
pmoves/monitoring/grafana/dashboards/tokenism.json- New dashboardpmoves/monitoring/prometheus/prometheus.yml- Tokenism scrape configsUI:
pmoves/ui/components/tokenism/- Updated GeometricView, ResultsPanelpmoves/ui/lib/tokenismClient.ts- REST client integrationTest Results
Checklist
🤖 Generated with Claude Code
Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com
Summary by CodeRabbit
New Features
Chores
✏️ Tip: You can customize this high-level summary in your review settings.