fix: Phase 2 hardening, persistence, and Python 3.11+ fixes - #345
Conversation
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
WalkthroughThis PR introduces a complete UI service infrastructure with Docker deployment, a Flute Gateway client library for TTS streaming audio synthesis, health monitoring endpoints, and supporting documentation. Changes span Docker Compose configuration, multi-stage Dockerfiles, Next.js routing and configuration, client-side audio integration libraries, and dashboard monitoring enhancements. Changes
Sequence Diagram(s)sequenceDiagram
actor User as User/<br/>Browser
participant UI as pmoves-ui
participant FLUTE_HTTP as Flute HTTP<br/>Gateway (8055)
participant WEB_AUDIO as Web Audio API
User->>UI: Request audio synthesis
UI->>FLUTE_HTTP: POST /synthesize<br/>(text, options)
FLUTE_HTTP-->>FLUTE_HTTP: Synthesize audio
FLUTE_HTTP-->>UI: ArrayBuffer
UI->>WEB_AUDIO: playAudio(buffer)
WEB_AUDIO-->>User: Play audio
rect rgb(220, 245, 250)
Note over UI,WEB_AUDIO: Health Check (Docker healthcheck)
end
UI->>FLUTE_HTTP: GET /health
FLUTE_HTTP-->>UI: 200 OK
sequenceDiagram
actor User as User/<br/>Browser
participant UI as pmoves-ui
participant FLUTE_WS as Flute WS<br/>Gateway (8056)
participant WEB_AUDIO as Web Audio API
User->>UI: Start streaming synthesis
UI->>FLUTE_HTTP: POST /session
Note over FLUTE_HTTP: (not shown:<br/>assumed HTTP)
FLUTE_HTTP-->>UI: FluteSession<br/>(sessionId, wsUrl)
UI->>FLUTE_WS: WebSocket connect<br/>(sessionId)
FLUTE_WS-->>UI: Connected
loop User sends text chunks
User->>UI: sendText(chunk)
UI->>FLUTE_WS: Text message
FLUTE_WS-->>FLUTE_WS: Synthesize chunk
FLUTE_WS-->>UI: Audio ArrayBuffer
UI->>WEB_AUDIO: playAudio(buffer)
WEB_AUDIO-->>User: Play audio
end
rect rgb(245, 220, 220)
Note over UI,FLUTE_WS: Auto-Reconnect on<br/>Disconnect (max retries)
end
User->>UI: disconnect()
UI->>FLUTE_WS: Close WebSocket
FLUTE_WS-->>UI: Closed
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes The PR spans heterogeneous subsystems including Docker orchestration, multi-stage containerization, WebSocket-based streaming client with reconnection logic, health monitoring integration, environment variable handling for client-side networking, and presign authentication refactoring. The FluteClient class introduces non-trivial state management, auto-reconnect mechanisms, and session-based workflows requiring careful validation. Multiple interrelated changes across infrastructure, client libraries, and UI components demand systematic review of each cohort's correctness and integration points. Possibly related PRs
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
pmoves/services/notebook-sync/Dockerfile (1)
9-18: Entrypoint requires root privileges - cannot run as non-root user.The Dockerfile sets
USER pmovesbefore the entrypoint executes, but/entrypoint.shcontains operations requiring root:
chown -R pmoves:pmoves "$db_dir"requires root privileges (errors suppressed with|| true)su -s /bin/sh pmovesrequires root to switch usersThis will fail at runtime. Either:
- Do NOT set
USER pmovesin the Dockerfile; instead have the entrypoint drop privileges to pmoves after setup, OR- Move all directory creation and ownership setup to the Dockerfile before the
USER pmovesdirective
🧹 Nitpick comments (3)
pmoves/services/media-audio/Dockerfile (1)
5-13: Consider consolidating jsonschema in requirements.lock.The build restructuring correctly separates dependencies from application code for better caching. However, installing
jsonschema>=4.0.0separately to avoid hash conflicts (line 12) bypasses the lock file's version pinning, potentially introducing version drift.Consider addressing the root cause of the hash conflict by:
- Regenerating
requirements.lockwithjsonschema>=4.0.0explicitly included- Using a consistent hash algorithm across all dependencies
- If external index conflicts are unavoidable, document the specific conflict in a comment
This ensures reproducible builds and prevents future dependency resolution issues.
pmoves/services/flute-gateway/prosodic/types.py (1)
62-67: Optional: Consider extracting validation messages to class-level constants.The inline error messages in
__post_init__work correctly but could be extracted to class-level constants for consistency with Ruff's TRY003 guideline. This is purely a style preference and not functionally necessary.Example refactor (optional)
@dataclass(frozen=True) class PauseConfig: """Configuration for prosodic pause behavior. Attributes: pause_ms: Duration of pause in milliseconds. can_breath: Whether breath sounds are allowed at this boundary. breath_probability: Probability [0,1] of inserting breath sound. """ + _ERR_NEGATIVE_PAUSE = "PauseConfig.pause_ms must be non-negative, got {}" + _ERR_INVALID_PROBABILITY = "PauseConfig.breath_probability must be in [0.0, 1.0], got {}" pause_ms: float can_breath: bool breath_probability: float def __post_init__(self) -> None: """Validate invariants after initialization.""" if self.pause_ms < 0: - raise ValueError(f"PauseConfig.pause_ms must be non-negative, got {self.pause_ms}") + raise ValueError(self._ERR_NEGATIVE_PAUSE.format(self.pause_ms)) if not 0.0 <= self.breath_probability <= 1.0: - raise ValueError( - f"PauseConfig.breath_probability must be in [0.0, 1.0], got {self.breath_probability}" - ) + raise ValueError(self._ERR_INVALID_PROBABILITY.format(self.breath_probability))Based on learnings, Ruff hint noted but inline messages are acceptable for validation.
pmoves/services/media-video/Dockerfile (1)
5-25: Consider maintaining a lock file for reproducible builds.The build restructuring correctly separates dependencies from code and skips PyTorch packages that the base image provides. However, replacing the lock file with explicit version pins (lines 11-24) makes dependency management more fragile:
- No hash verification for supply-chain security
- Manual version list is harder to maintain and audit
- Inconsistent with media-audio's approach (which uses requirements.lock)
If external index conflicts prevent using
requirements.lock, consider:
- Using
pip-compilewith--generate-hashesto create a lock file that handles multiple indexes- Documenting the specific PyTorch/PyPI index conflict
- Standardizing the approach across media-audio and media-video for maintainability
# Example: Use pip-tools with extra index # requirements.in: --extra-index-url https://download.pytorch.org/whl/cu121 fastapi==0.114.2 ...This maintains reproducibility while handling external indexes.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
pmoves/.gitignorepmoves/docker-compose.ymlpmoves/services/deepresearch/worker.pypmoves/services/flute-gateway/prosodic/types.pypmoves/services/flute-gateway/requirements.txtpmoves/services/media-audio/Dockerfilepmoves/services/media-video/Dockerfilepmoves/services/notebook-sync/Dockerfilepmoves/services/vibevoice-realtime/Dockerfile
🧰 Additional context used
📓 Path-based instructions (5)
**/.gitignore
📄 CodeRabbit inference engine (CLAUDE.md)
When a launcher involves cloning 3rd party repositories, downloading files dynamically, or files generated during installation/running, include these file paths in .gitignore file (e.g., Sqlite Databases, environment variables, user-specific files)
Files:
pmoves/.gitignore
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/deepresearch/worker.pypmoves/services/flute-gateway/prosodic/types.py
pmoves/**/*.py
📄 CodeRabbit inference engine (pmoves/AGENTS.md)
Python 3.11+, 4-space indentation, prefer type hints
Files:
pmoves/services/deepresearch/worker.pypmoves/services/flute-gateway/prosodic/types.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/deepresearch/worker.pypmoves/services/flute-gateway/prosodic/types.py
pmoves/**/docker-compose.yml
📄 CodeRabbit inference engine (pmoves/AGENTS.md)
Use Compose profiles (
data,workers) to scope what runs locally in docker-compose.yml
Files:
pmoves/docker-compose.yml
🧠 Learnings (28)
📓 Common learnings
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/{agent-zero,archon}/**/*.py : For Agents/Archon full-stack validation, follow the 'All Services Up, Then Tests' section in `pmoves/docs/SMOKETESTS.md` and use `make -C pmoves agents-headless-smoke`, `make -C pmoves smoke-gpu`, and `make -C pmoves verify-all`
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-15T12:03:17.291Z
Learning: Applies to services/**/README.md : Update services/*/README.md and pmoves/docs/PMOVES.AI PLANS/ runbooks when touching service operational code
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/**/environment.yml : Preferred Python: Conda 3.11+ (env name: `PMOVES.AI` or `pmoves-ai`); use `environment.yml` at repo root for setup
Applied to files:
pmoves/services/media-audio/Dockerfilepmoves/services/media-video/Dockerfile
📚 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: Agents images: default uses published images set in `pmoves/env.shared`. For custom code, build a thin overlay FROM the published image and tag it
Applied to files:
pmoves/services/media-audio/Dockerfilepmoves/services/notebook-sync/Dockerfilepmoves/services/media-video/Dockerfile
📚 Learning: 2025-12-15T12:01:31.388Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/realtime/CLAUDE.md:0-0
Timestamp: 2025-12-15T12:01:31.388Z
Learning: Applies to pmoves/docs/ARTSTUFF/realtime/**/*.{js,json} : In shell.run API requests for Python apps, always use virtual environments via the venv attribute, which automatically creates or reuses existing virtual environments
Applied to files:
pmoves/services/media-audio/Dockerfile
📚 Learning: 2025-12-15T12:02:18.878Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/realtime/GEMINI.md:0-0
Timestamp: 2025-12-15T12:02:18.878Z
Learning: Applies to pmoves/docs/ARTSTUFF/realtime/**/*{install,start}.{js,json} : Always use virtual environments for Python apps via shell.run venv attribute in Pinokio launcher scripts
Applied to files:
pmoves/services/media-audio/Dockerfile
📚 Learning: 2025-12-15T12:04:26.230Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/realtime/AGENTS.md:0-0
Timestamp: 2025-12-15T12:04:26.230Z
Learning: Applies to pmoves/docs/ARTSTUFF/realtime/**/*.js : For Python apps, always use virtual environments via the venv attribute in shell.run. This attribute automatically creates a venv or uses if it already exists
Applied to files:
pmoves/services/media-audio/Dockerfile
📚 Learning: 2025-12-15T12:02:50.226Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/realtime/.windsurfrules:0-0
Timestamp: 2025-12-15T12:02:50.226Z
Learning: Applies to pmoves/docs/ARTSTUFF/realtime/**/.gitignore : Project `.gitignore` must include entries for dynamically generated files, cloned repositories, downloaded files, virtual environments, and user-specific configurations
Applied to files:
pmoves/.gitignore
📚 Learning: 2025-12-15T12:01:03.100Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/realtime/.cursorrules:0-0
Timestamp: 2025-12-15T12:01:03.100Z
Learning: Applies to pmoves/docs/ARTSTUFF/realtime/**/.gitignore : Include paths for cloned git repositories, downloaded files, and dynamically generated files (Sqlite Databases, environment variables, user-specific files) in .gitignore to prevent them from being committed
Applied to files:
pmoves/.gitignore
📚 Learning: 2025-12-15T12:03:41.584Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/Ultimate-TTS-Studio.git/AGENTS.md:0-0
Timestamp: 2025-12-15T12:03:41.584Z
Learning: Applies to pmoves/docs/ARTSTUFF/Ultimate-TTS-Studio.git/**/.gitignore : Include all generated files, downloaded repositories, and dynamic artifacts in .gitignore file to maintain clean repository state
Applied to files:
pmoves/.gitignore
📚 Learning: 2025-12-15T12:02:18.878Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/realtime/GEMINI.md:0-0
Timestamp: 2025-12-15T12:02:18.878Z
Learning: Applies to pmoves/docs/ARTSTUFF/realtime/**/.gitignore : Include dynamically created or cloned files in .gitignore file such as repositories, downloaded files, databases, and user-specific files
Applied to files:
pmoves/.gitignore
📚 Learning: 2025-12-15T12:01:31.388Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/realtime/CLAUDE.md:0-0
Timestamp: 2025-12-15T12:01:31.388Z
Learning: Applies to pmoves/docs/ARTSTUFF/realtime/**/.gitignore : When a launcher involves cloning 3rd party repositories, downloading files, or generating files dynamically, include these file paths in .gitignore (e.g., cloned repos, downloaded files, generated databases, user-specific environment variables)
Applied to files:
pmoves/.gitignore
📚 Learning: 2025-12-15T12:04:26.230Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/realtime/AGENTS.md:0-0
Timestamp: 2025-12-15T12:04:26.230Z
Learning: Applies to pmoves/docs/ARTSTUFF/realtime/**/.gitignore : When a launcher involves cloning 3rd party repositories, downloading files dynamically, or generating files during installation, include these paths in .gitignore
Applied to files:
pmoves/.gitignore
📚 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: Mandatory context before changes: read pmoves/docs/PMOVES.AI PLANS/ROADMAP.md and pmoves/docs/NEXT_STEPS.md to align with current sprint focus
Applied to files:
pmoves/.gitignore
📚 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: Read `pmoves/docs/PMOVES.AI PLANS/ROADMAP.md` and `pmoves/docs/NEXT_STEPS.md` before making changes to align with current sprint focus
Applied to files:
pmoves/.gitignore
📚 Learning: 2025-12-15T12:01:31.388Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/realtime/CLAUDE.md:0-0
Timestamp: 2025-12-15T12:01:31.388Z
Learning: Applies to pmoves/docs/ARTSTUFF/realtime/**/*.json : When writing launcher projects for existing git repositories, do not modify the project app folder even if installations fail - instead create additional files in the launcher folder to work around issues, unless the user explicitly requests app modifications
Applied to files:
pmoves/.gitignore
📚 Learning: 2025-12-22T07:49:51.075Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-22T07:49:51.075Z
Learning: Applies to **/.gitignore : When a launcher involves cloning 3rd party repositories, downloading files dynamically, or files generated during installation/running, include these file paths in .gitignore file (e.g., Sqlite Databases, environment variables, user-specific files)
Applied to files:
pmoves/.gitignore
📚 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: Pin agent images by setting `AGENT_ZERO_IMAGE`, `ARCHON_IMAGE`, `ARCHON_UI_IMAGE`, and `PMOVES_YT_IMAGE` in `pmoves/env.shared`
Applied to files:
pmoves/.gitignore
📚 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: Core application code is located in the `pmoves/` directory; general documentation is located in `docs/` directory
Applied to files:
pmoves/.gitignore
📚 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/**/docker-compose.yml : Use Compose profiles (`data`, `workers`) to scope what runs locally in docker-compose.yml
Applied to files:
pmoves/services/notebook-sync/Dockerfilepmoves/docker-compose.yml
📚 Learning: 2025-12-15T12:04:26.230Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/realtime/AGENTS.md:0-0
Timestamp: 2025-12-15T12:04:26.230Z
Learning: Applies to pmoves/docs/ARTSTUFF/realtime/**/*.js : Try to find development options to launch apps without Docker. Use automatic installation and launch for the user's platform via scripts instead of Docker
Applied to files:
pmoves/services/notebook-sync/Dockerfilepmoves/services/vibevoice-realtime/Dockerfile
📚 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 requirements.{txt,lock} : Use uv pip compile --generate-hashes for Python dependency locks on Python 3.11 to ensure reproducible builds
Applied to files:
pmoves/services/flute-gateway/requirements.txt
📚 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 services/**/README.md : Update services/*/README.md and pmoves/docs/PMOVES.AI PLANS/ runbooks when touching service operational code
Applied to files:
pmoves/docker-compose.yml
📚 Learning: 2025-12-15T12:02:18.878Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/realtime/GEMINI.md:0-0
Timestamp: 2025-12-15T12:02:18.878Z
Learning: Applies to pmoves/docs/ARTSTUFF/realtime/**/start.js : Use shell.run API with daemon: true, venv, env, path, message, and on event monitoring for launching servers in start.js
Applied to files:
pmoves/services/vibevoice-realtime/Dockerfile
📚 Learning: 2025-12-15T12:02:18.878Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/realtime/GEMINI.md:0-0
Timestamp: 2025-12-15T12:02:18.878Z
Learning: Applies to pmoves/docs/ARTSTUFF/realtime/**/*{install,start,update,reset}.{js,json} : Use Pinokio shell.run API features like env, venv, input, path, sudo, on to reduce script code instead of raw shell commands
Applied to files:
pmoves/services/vibevoice-realtime/Dockerfile
📚 Learning: 2025-12-15T12:03:41.584Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/Ultimate-TTS-Studio.git/AGENTS.md:0-0
Timestamp: 2025-12-15T12:03:41.584Z
Learning: Applies to pmoves/docs/ARTSTUFF/Ultimate-TTS-Studio.git/**/start.js : Set `daemon: true` at the root level of launcher scripts when launching long-running server processes to prevent process termination after script completion
Applied to files:
pmoves/services/vibevoice-realtime/Dockerfile
📚 Learning: 2025-12-15T12:03:41.584Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/Ultimate-TTS-Studio.git/AGENTS.md:0-0
Timestamp: 2025-12-15T12:03:41.584Z
Learning: Applies to pmoves/docs/ARTSTUFF/Ultimate-TTS-Studio.git/**/{install,start,update,reset,*.js} : Use `shell.run` API with relative paths (no absolute paths) for the `path` attribute to ensure cross-platform compatibility and correct working directory context
Applied to files:
pmoves/services/vibevoice-realtime/Dockerfile
📚 Learning: 2025-12-15T12:03:41.584Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/Ultimate-TTS-Studio.git/AGENTS.md:0-0
Timestamp: 2025-12-15T12:03:41.584Z
Learning: Applies to pmoves/docs/ARTSTUFF/Ultimate-TTS-Studio.git/**/{install,start,update,reset}.js : In shell.run API calls, minimize launch flags and parameters, preferring app defaults over explicit configuration unless necessary
Applied to files:
pmoves/services/vibevoice-realtime/Dockerfile
📚 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/**/{media,analysis,pipeline}*.py : Implement `media-video` and `media-audio` analysis pipelines with GPU auto-detect for faster-whisper
Applied to files:
pmoves/services/media-video/Dockerfile
🪛 Ruff (0.14.8)
pmoves/services/flute-gateway/prosodic/types.py
63-63: Avoid specifying long messages outside the exception class
(TRY003)
⏰ 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: tests (3.11)
🔇 Additional comments (12)
pmoves/services/flute-gateway/requirements.txt (2)
3-4: The requirements split is properly implemented.The setup is correct and complete:
- Hash verification works with pip's secure installs and supports multiple hash algorithms including sha256
requirements-pipecat.txtcontains the removed dependencies:pipecat-ai[silero]==0.0.98,aiortc==1.12.0,av==14.4.0requirements.lock(93508 bytes) provides hashed dependency pins for the main requirements- The Dockerfile correctly installs both files in sequence: first
requirements.txt(with hash verification viarequirements.lock), thenrequirements-pipecat.txt(without hashes to avoid conflicts)- Python 3.11 container is used as expected
- The separation is intentionally documented to avoid hash verification conflicts between the locked and external packages
1-1: Lock files are properly configured with hash verification.The requirements.lock file is correctly generated using
uv pip compile --generate-hashesand properly referenced by requirements.txt. The split is intentional: main dependencies are locked with hashes for reproducibility, while optional pipecat dependencies in requirements-pipecat.txt remain unlocked to avoid hash verification conflicts—which is documented in the code comments.pmoves/services/deepresearch/worker.py (2)
274-274: LGTM: Import required for registry lookup.The REGISTRY import is necessary to support the new helper function that prevents duplicate metric registration.
319-329: Counter initialization correctly uses the helper function.The updated counter creation prevents duplicate registration errors when the module is imported multiple times (e.g., via
python -m). Both counters are initialized with appropriate names, descriptions, and labelnames.Note: Robustness depends on the helper function validation improvements suggested above.
pmoves/.gitignore (1)
55-55: LGTM! Runtime data exclusion is appropriate.The addition of
pmoves/data/agent-zero/correctly excludes Agent Zero's runtime settings from version control, aligning with the new volume mount in docker-compose.yml and the coding guideline to ignore dynamically generated files.pmoves/services/media-audio/Dockerfile (1)
3-3: LGTM! PYTHONPATH addition enables shared module imports.Adding
PYTHONPATH=/appallows media-audio to import fromservices.common, resolving the ModuleNotFoundError mentioned in the PR objectives.pmoves/services/flute-gateway/prosodic/types.py (1)
46-67: LGTM! Python 3.11+ compatibility correctly implemented.The migration from NamedTuple to frozen dataclass with
__post_init__validation resolves Python 3.11+ compatibility issues while maintaining immutability and the same validation logic. The public API remains unchanged.pmoves/services/media-video/Dockerfile (1)
3-3: LGTM! PYTHONPATH enables shared module imports.Adding
PYTHONPATH=/appallows media-video to import fromservices.common, consistent with the media-audio Dockerfile changes.pmoves/docker-compose.yml (4)
341-341: LGTM! Hostname normalized to lowercase.Standardizing
SUPABASE_URLto lowercasepmoves.aifollows DNS conventions and aligns with the PR objective to normalize Archon SUPABASE_URL.
402-402: LGTM! Consistent hostname normalization.The
SUPABASE_URLhostname is correctly normalized to lowercasepmoves.ai, consistent with the chat-relay change.
448-450: LGTM! Build context correctly set for shared module access.The explicit build context at pmoves root (
.) and dockerfile paths enable these services to copyservices/commonduring build, aligning with the Dockerfile restructuring changes.Also applies to: 473-475
764-765: LGTM! Settings persistence correctly implemented.The new volume mount for
/a0/tmpensures Agent Zero'ssettings.jsonpersists between container restarts, addressing the PR objective for Agent Zero persistence.
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
pmoves/docker-compose.yml (1)
341-341: Hostname casing still inconsistent across services.This line uses lowercase
pmoves.ai, but lines 622, 727, 816-817 still use uppercasePMOVES.AI. This inconsistency should be resolved project-wide.Applies to: 402, 858
🧹 Nitpick comments (5)
pmoves/ui/lib/fluteClient.ts (3)
131-141: Potential stale closure in auto-reconnect.When
setTimeouttriggers reconnection, it captures the originalonMessage,onError, andonClosecallbacks. If the caller has updated these handlers between disconnection and reconnection, the old handlers will still be used.Consider storing callbacks as instance properties to allow updates, or document this behavior.
🔎 Alternative: Store callbacks as instance properties
export class FluteClient { private ws: WebSocket | null = null; private readonly httpUrl: string; private readonly wsUrl: string; private reconnectAttempts = 0; private maxReconnectAttempts = 3; + private onMessageHandler?: (data: ArrayBuffer) => void; + private onErrorHandler?: (error: Event) => void; + private onCloseHandler?: (event: CloseEvent) => void; // In connect(): + this.onMessageHandler = onMessage; + this.onErrorHandler = onError; + this.onCloseHandler = onClose; // In onclose handler: - setTimeout(() => this.connect(onMessage, onError, onClose), 1000 * this.reconnectAttempts); + setTimeout(() => this.connect(this.onMessageHandler!, this.onErrorHandler, this.onCloseHandler), 1000 * this.reconnectAttempts);
177-191: AudioContext resource leak on repeated calls.Each
playAudiocall creates a newAudioContext. While it's closed after playback, browsers limit concurrent AudioContexts (typically 6). Rapid successive calls before playback completes could exhaust this limit.Consider reusing a single AudioContext or adding a queue mechanism for production use.
🔎 Proposed fix: Reuse AudioContext
+let sharedAudioContext: AudioContext | null = null; + +function getAudioContext(): AudioContext { + if (!sharedAudioContext || sharedAudioContext.state === 'closed') { + sharedAudioContext = new AudioContext(); + } + return sharedAudioContext; +} + export async function playAudio(audioData: ArrayBuffer): Promise<void> { - const audioContext = new AudioContext(); + const audioContext = getAudioContext(); const audioBuffer = await audioContext.decodeAudioData(audioData); const source = audioContext.createBufferSource(); source.buffer = audioBuffer; source.connect(audioContext.destination); source.start(0); return new Promise((resolve) => { source.onended = () => { - audioContext.close(); resolve(); }; }); }
193-201: Singleton lacks reset capability for testing.The singleton pattern is convenient but makes testing difficult. Consider adding a
resetFluteClient()function or using dependency injection patterns for testability.pmoves/ui/Dockerfile (2)
8-9: Curl is unnecessary in the builder stage.The builder stage only performs the build and doesn't need curl. Installing it adds ~15MB and extends build time. Remove it from the builder stage.
🔎 Proposed fix
WORKDIR /app -# Install curl for health checks -RUN apt-get update && apt-get install -y --no-install-recommends curl && rm -rf /var/lib/apt/lists/* - # Install dependencies COPY package*.json ./
12-13: Usenpm ciinstead ofnpm installfor reproducible builds.
npm ciis preferred in CI/Docker builds as it:
- Installs exact versions from
package-lock.json- Removes existing
node_modulesfirst- Fails if
package-lock.jsonis out of sync🔎 Proposed fix
# Install dependencies COPY package*.json ./ -RUN npm install +RUN npm ci
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
pmoves/docker-compose.ymlpmoves/ui/Dockerfilepmoves/ui/app/api/health/route.tspmoves/ui/lib/fluteClient.tspmoves/ui/next.config.mjs
🧰 Additional context used
📓 Path-based instructions (2)
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/app/api/health/route.tspmoves/ui/lib/fluteClient.ts
pmoves/**/docker-compose.yml
📄 CodeRabbit inference engine (pmoves/AGENTS.md)
Use Compose profiles (
data,workers) to scope what runs locally in docker-compose.yml
Files:
pmoves/docker-compose.yml
🧠 Learnings (11)
📓 Common learnings
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/{agent-zero,archon}/**/*.py : For Agents/Archon full-stack validation, follow the 'All Services Up, Then Tests' section in `pmoves/docs/SMOKETESTS.md` and use `make -C pmoves agents-headless-smoke`, `make -C pmoves smoke-gpu`, and `make -C pmoves verify-all`
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
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-15T12:03:17.291Z
Learning: Agents/Archon: for full-stack validation, follow the 'All Services Up, Then Tests' section in pmoves/docs/SMOKETESTS.md and the Archon service guide
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-15T12:03:17.291Z
Learning: UI updates: run make -C pmoves notebook-workbench-smoke ARGS='--thread=<uuid>' to lint the Next.js bundle and validate Supabase connectivity; reference pmoves/docs/UI_NOTEBOOK_WORKBENCH.md
📚 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/ui/**/*.{js,jsx,ts,tsx} : UI updates: run `make -C pmoves notebook-workbench-smoke ARGS="--thread=<uuid>"` to lint the Next.js bundle and validate Supabase connectivity; reference `pmoves/docs/UI_NOTEBOOK_WORKBENCH.md`
Applied to files:
pmoves/ui/next.config.mjspmoves/ui/Dockerfilepmoves/docker-compose.yml
📚 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: UI updates: run make -C pmoves notebook-workbench-smoke ARGS='--thread=<uuid>' to lint the Next.js bundle and validate Supabase connectivity; reference pmoves/docs/UI_NOTEBOOK_WORKBENCH.md
Applied to files:
pmoves/ui/Dockerfilepmoves/docker-compose.yml
📚 Learning: 2025-12-15T12:04:26.230Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/realtime/AGENTS.md:0-0
Timestamp: 2025-12-15T12:04:26.230Z
Learning: Applies to pmoves/docs/ARTSTUFF/realtime/**/*.js : Try to find development options to launch apps without Docker. Use automatic installation and launch for the user's platform via scripts instead of Docker
Applied to files:
pmoves/ui/Dockerfile
📚 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: Agents images: default uses published images set in `pmoves/env.shared`. For custom code, build a thin overlay FROM the published image and tag it
Applied to files:
pmoves/ui/Dockerfile
📚 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/**/docker-compose.yml : Use Compose profiles (`data`, `workers`) to scope what runs locally in docker-compose.yml
Applied to files:
pmoves/docker-compose.yml
📚 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 services/**/README.md : Update services/*/README.md and pmoves/docs/PMOVES.AI PLANS/ runbooks when touching service operational code
Applied to files:
pmoves/docker-compose.yml
📚 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: Mandatory context before changes: read pmoves/docs/PMOVES.AI PLANS/ROADMAP.md and pmoves/docs/NEXT_STEPS.md to align with current sprint focus
Applied to files:
pmoves/docker-compose.yml
📚 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/{agent-zero,archon}/**/*.py : For Agents/Archon full-stack validation, follow the 'All Services Up, Then Tests' section in `pmoves/docs/SMOKETESTS.md` and use `make -C pmoves agents-headless-smoke`, `make -C pmoves smoke-gpu`, and `make -C pmoves verify-all`
Applied to files:
pmoves/docker-compose.yml
📚 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: Agents/Archon: for full-stack validation, follow the 'All Services Up, Then Tests' section in pmoves/docs/SMOKETESTS.md and the Archon service guide
Applied to files:
pmoves/docker-compose.yml
📚 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 {Dockerfile,docker-compose.yml,docker-compose.*.yml,pmoves/docker-compose.*.override.yml} : Dockerfile and docker-compose.yml must follow multi-arch build practices (amd64+arm64) with Trivy scanning for HIGH/CRITICAL vulnerabilities
Applied to files:
pmoves/docker-compose.yml
⏰ 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: tests (3.11)
🔇 Additional comments (10)
pmoves/ui/lib/fluteClient.ts (2)
45-53: LGTM on constructor with environment fallbacks.The constructor properly chains optional parameters → environment variables → localhost defaults, which is appropriate for local development and containerized deployment.
83-93: Verify browser support requirements before usingAbortSignal.timeout().
AbortSignal.timeout()works across the latest devices and browser versions since April 2024, but may not work in older devices or browsers. If support for older browsers is needed, implement a fallback usingAbortControllerwith manual timeout handling.pmoves/ui/next.config.mjs (1)
8-8: LGTM - Standalone output aligns with Dockerfile.The
output: 'standalone'configuration correctly supports the containerized deployment approach in the Dockerfile, which runsnode server.jsfrom the standalone build output.pmoves/ui/Dockerfile (2)
26-38: LGTM - Good security hardening with non-root user.The non-root user configuration with explicit UID/GID 65532 follows security best practices and aligns with other PMOVES services as mentioned in the comments.
46-47: LGTM - Healthcheck properly configured.The healthcheck configuration (30s interval, 10s timeout, 60s start period, 3 retries) is appropriate for a Next.js application and matches the docker-compose configuration.
pmoves/docker-compose.yml (4)
421-447: LGTM - Well-structured pmoves-ui service definition.The new UI service is properly configured with:
- Appropriate profile (
ui) per coding guidelines- Correct network memberships (
app_tier,api_tier,supabase_net)- Health check matching the Dockerfile and route implementation
- Environment variables for service discovery
792-793: LGTM - Agent-zero settings persistence added.The new volume mapping for
/a0/tmpenables persistence ofsettings.jsonbetween container restarts, addressing the PR objective.
862-863: LGTM - PYTHONPATH addition for archon vendor sources.Adding
/app/vendor/archon/pythonto PYTHONPATH allows proper module resolution for the archon service.
476-478: LGTM - Explicit build context for media services.The explicit
context: .anddockerfile: services/media-video/Dockerfilepattern properly enables the services to access the sharedservices/modules via PYTHONPATH as mentioned in the PR objectives.Applies to: 501-503
pmoves/ui/app/api/health/route.ts (1)
7-14: Ensure npm_package_version is explicitly injected at build time for the health endpoint.The
process.env.npm_package_versionvariable is only available within npm scripts context and won't be present in standalone production builds unless explicitly set. The fallback to'0.1.0'prevents crashes but means the endpoint will always return a default version rather than the actual application version. Set this environment variable during the build step (in your build script or Dockerfile) or read the version frompackage.jsonat build time.
Critical fixes: - Add error logging to isHealthy() catch block (was silent failure) - Fix WebSocket message type: 'synthesize' → 'text' - Add error handling to playAudio() with proper cleanup Improvements: - Add onReconnectExhausted callback for connection failure notification - Implement session management using FluteSession interface - Add createSession() and connectWithSession() methods - Add @throws JSDoc annotations and browser-only warnings Session API reference: POST /v1/sessions returns session_id, websocket_url 🤖 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 (2)
pmoves/ui/lib/fluteClient.ts (2)
193-244: Guard against concurrent connection attempts.The check at line 200 only prevents reconnection if the WebSocket is already
OPEN. IfreadyStateisCONNECTING(0),CLOSING(2), orCLOSED(3), the guard passes and a new WebSocket is created, potentially leaking the previous instance.🔎 Suggested enhancement
- if (this.ws?.readyState === WebSocket.OPEN) { + if (this.ws && (this.ws.readyState === WebSocket.OPEN || this.ws.readyState === WebSocket.CONNECTING)) { console.warn('FluteClient: Already connected'); return; } + + // Clean up any existing WebSocket in other states + if (this.ws) { + this.ws.close(); + this.ws = null; + }This prevents creating a new connection while one is in progress and cleans up stale connections.
288-309: Add runtime guard for SSR compatibility.The function instantiates
AudioContextdirectly, which will throw in server-side rendering contexts. While the@warningannotation documents this limitation, a runtime check would prevent unexpected errors if the function is inadvertently called server-side.🔎 Suggested enhancement
export async function playAudio(audioData: ArrayBuffer): Promise<void> { + if (typeof window === 'undefined' || typeof AudioContext === 'undefined') { + throw new Error('playAudio() is only available in browser environments'); + } + const audioContext = new AudioContext();This provides a clearer error message and prevents unexpected SSR failures.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
pmoves/ui/lib/fluteClient.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/fluteClient.ts
🧠 Learnings (1)
📓 Common learnings
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/{agent-zero,archon}/**/*.py : For Agents/Archon full-stack validation, follow the 'All Services Up, Then Tests' section in `pmoves/docs/SMOKETESTS.md` and use `make -C pmoves agents-headless-smoke`, `make -C pmoves smoke-gpu`, and `make -C pmoves verify-all`
⏰ 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). (2)
- GitHub Check: tests (3.11)
- GitHub Check: Analyze (python)
🔇 Additional comments (10)
pmoves/ui/lib/fluteClient.ts (10)
1-44: Well-structured interfaces and documentation.The file header, JSDoc examples, and type definitions are clear and comprehensive. The interface design properly separates concerns between synthesis options and session management.
66-74: Clean constructor with environment-aware defaults.The use of
NEXT_PUBLIC_*environment variables is appropriate for Next.js, and the localhost fallbacks are sensible for development.
85-104: Solid HTTP synthesis implementation.Error handling includes status codes and response text, which aids debugging. The ArrayBuffer return type aligns with the Web Audio API requirements.
114-131: Proper session creation with field mapping.The snake_case to camelCase transformation and Date parsing align with TypeScript conventions. Error handling is consistent with other methods.
138-149: Robust health check with timeout.The use of
AbortSignal.timeout(5000)prevents hanging requests, and graceful error handling returns a boolean status without throwing.
254-259: Clear connection state validation.The method correctly checks the WebSocket state before sending and provides a helpful error message directing users to call
connect()orconnectWithSession()first.
264-270: Proper cleanup on disconnect.The method uses the standard close code 1000 for normal closure and cleans up both the WebSocket reference and stored callbacks.
275-277: Simple and correct connection state getter.
311-325: Convenient singleton pattern for simple use cases.The lazy initialization is straightforward and provides a shared instance for applications that don't need multiple client instances or custom URLs.
1-325: Verify UI integration with smoke tests.As per the coding guidelines, UI updates should be validated with the notebook workbench smoke tests to ensure Next.js bundle integrity and Supabase connectivity.
#!/bin/bash # Run the UI notebook workbench smoke tests with a test thread UUID # This validates the Next.js build and integration points make -C pmoves notebook-workbench-smoke ARGS="--thread=$(uuidgen)"Reference
pmoves/docs/UI_NOTEBOOK_WORKBENCH.mdfor additional context on the test suite.
Critical: - archon-agent-work-orders healthcheck: /health → /healthz (service exposes /healthz per main.py:248) Major: - pmoves-ui NEXT_PUBLIC env vars: use localhost fallback (NEXT_PUBLIC vars are build-time embedded for browser use) - deepresearch Prometheus: add try/except with type validation (safer than direct private _names_to_collectors access) Minor: - Normalize supabase_kong hostname to lowercase (4 occurrences) (Docker DNS is case-sensitive on some configurations) - vibevoice-realtime: create /models directory with ownership (entrypoint.sh writes to /models via snapshot_download) 🤖 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: 1
🧹 Nitpick comments (1)
pmoves/services/deepresearch/worker.py (1)
302-320: Consider validating labelnames to prevent subtle mismatches.The function validates metric type but not labelnames. If an existing Counter was registered with different labelnames,
.labels()calls will fail at runtime with confusing errors.🔎 Proposed enhancement to validate labelnames
def _get_or_create_counter(name: str, description: str, labelnames: tuple) -> Counter: """Get existing counter or create new one (safe for module reimport via -m flag). The python -m flag can cause module double-import, which would register Prometheus metrics twice. This function uses try/except to handle duplicate registration and validates the existing metric type. """ try: return Counter(name, description, labelnames=labelnames) except ValueError as e: if "Duplicated timeseries" in str(e): # Metric already exists; retrieve and validate type existing = REGISTRY._names_to_collectors.get(name) if existing is not None and isinstance(existing, Counter): + # Validate labelnames match to prevent runtime errors + if hasattr(existing, '_labelnames') and existing._labelnames != labelnames: + raise ValueError( + f"Metric '{name}' exists with labelnames {existing._labelnames}, " + f"but requested {labelnames}" + ) from e return existing raise TypeError( f"Metric '{name}' exists but is {type(existing).__name__}, not Counter" ) from e raise
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
pmoves/docker-compose.ymlpmoves/services/deepresearch/worker.pypmoves/services/vibevoice-realtime/Dockerfile
🧰 Additional context used
📓 Path-based instructions (4)
pmoves/**/docker-compose.yml
📄 CodeRabbit inference engine (pmoves/AGENTS.md)
Use Compose profiles (
data,workers) to scope what runs locally in docker-compose.yml
Files:
pmoves/docker-compose.yml
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/deepresearch/worker.py
pmoves/**/*.py
📄 CodeRabbit inference engine (pmoves/AGENTS.md)
Python 3.11+, 4-space indentation, prefer type hints
Files:
pmoves/services/deepresearch/worker.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/deepresearch/worker.py
🧠 Learnings (20)
📓 Common learnings
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/{agent-zero,archon}/**/*.py : For Agents/Archon full-stack validation, follow the 'All Services Up, Then Tests' section in `pmoves/docs/SMOKETESTS.md` and use `make -C pmoves agents-headless-smoke`, `make -C pmoves smoke-gpu`, and `make -C pmoves verify-all`
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-15T12:04:26.230Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/realtime/AGENTS.md:0-0
Timestamp: 2025-12-15T12:04:26.230Z
Learning: Applies to pmoves/docs/ARTSTUFF/realtime/**/*.js : Try to find development options to launch apps without Docker. Use automatic installation and launch for the user's platform via scripts instead of Docker
Applied to files:
pmoves/services/vibevoice-realtime/Dockerfile
📚 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 {Dockerfile,docker-compose.yml,docker-compose.*.yml,pmoves/docker-compose.*.override.yml} : Dockerfile and docker-compose.yml must follow multi-arch build practices (amd64+arm64) with Trivy scanning for HIGH/CRITICAL vulnerabilities
Applied to files:
pmoves/services/vibevoice-realtime/Dockerfile
📚 Learning: 2025-12-15T12:02:18.878Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/realtime/GEMINI.md:0-0
Timestamp: 2025-12-15T12:02:18.878Z
Learning: Applies to pmoves/docs/ARTSTUFF/realtime/**/*{install,start}.{js,json} : Always use virtual environments for Python apps via shell.run venv attribute in Pinokio launcher scripts
Applied to files:
pmoves/services/vibevoice-realtime/Dockerfile
📚 Learning: 2025-12-15T12:01:31.388Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/realtime/CLAUDE.md:0-0
Timestamp: 2025-12-15T12:01:31.388Z
Learning: Applies to pmoves/docs/ARTSTUFF/realtime/**/{install,start,update,reset}.js : Scripts must be able to replicate install and launch steps 100% - include all 3rd party package installations and repository downloads in scripts, do not assume end user's system state, and make everything self-contained
Applied to files:
pmoves/services/vibevoice-realtime/Dockerfile
📚 Learning: 2025-12-15T12:02:18.878Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/realtime/GEMINI.md:0-0
Timestamp: 2025-12-15T12:02:18.878Z
Learning: Applies to pmoves/docs/ARTSTUFF/realtime/**/*{install,start,update,reset}.{js,json} : Scripts must be able to replicate install and launch steps 100% for end users, do not assume system state and make everything self-contained
Applied to files:
pmoves/services/vibevoice-realtime/Dockerfile
📚 Learning: 2025-12-15T12:03:41.584Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/Ultimate-TTS-Studio.git/AGENTS.md:0-0
Timestamp: 2025-12-15T12:03:41.584Z
Learning: Applies to pmoves/docs/ARTSTUFF/Ultimate-TTS-Studio.git/**/{install,start,update,reset}.js : Always use the `venv` attribute in shell.run API calls for Python projects instead of manually managing virtual environments
Applied to files:
pmoves/services/vibevoice-realtime/Dockerfile
📚 Learning: 2025-12-15T12:04:26.230Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/realtime/AGENTS.md:0-0
Timestamp: 2025-12-15T12:04:26.230Z
Learning: Applies to pmoves/docs/ARTSTUFF/realtime/**/install.js : Install scripts should work for each specific operating system. Ignore Docker related instructions and use platform-specific install/launch instructions instead
Applied to files:
pmoves/services/vibevoice-realtime/Dockerfile
📚 Learning: 2025-12-15T12:02:18.878Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/realtime/GEMINI.md:0-0
Timestamp: 2025-12-15T12:02:18.878Z
Learning: Applies to pmoves/docs/ARTSTUFF/realtime/**/*{install,start,update,reset}.{js,json} : Use Pinokio shell.run API features like env, venv, input, path, sudo, on to reduce script code instead of raw shell commands
Applied to files:
pmoves/services/vibevoice-realtime/Dockerfile
📚 Learning: 2025-12-15T12:03:41.584Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/Ultimate-TTS-Studio.git/AGENTS.md:0-0
Timestamp: 2025-12-15T12:03:41.584Z
Learning: Applies to pmoves/docs/ARTSTUFF/Ultimate-TTS-Studio.git/**/start.js : Set `daemon: true` at the root level of launcher scripts when launching long-running server processes to prevent process termination after script completion
Applied to files:
pmoves/services/vibevoice-realtime/Dockerfile
📚 Learning: 2025-12-15T12:02:50.226Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/realtime/.windsurfrules:0-0
Timestamp: 2025-12-15T12:02:50.226Z
Learning: Applies to pmoves/docs/ARTSTUFF/realtime/**/install.js : Install scripts should avoid modifying the cloned project folder (app directory) and instead create additional files in launcher folder to work around installation issues without touching app logic
Applied to files:
pmoves/services/vibevoice-realtime/Dockerfile
📚 Learning: 2025-12-15T12:02:18.878Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/realtime/GEMINI.md:0-0
Timestamp: 2025-12-15T12:02:18.878Z
Learning: Applies to pmoves/docs/ARTSTUFF/realtime/**/start.js : Use shell.run API with daemon: true, venv, env, path, message, and on event monitoring for launching servers in start.js
Applied to files:
pmoves/services/vibevoice-realtime/Dockerfile
📚 Learning: 2025-12-15T12:04:26.230Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/realtime/AGENTS.md:0-0
Timestamp: 2025-12-15T12:04:26.230Z
Learning: Applies to pmoves/docs/ARTSTUFF/realtime/**/*.js : When running shell commands, take full advantage of the Pinokio shell.run API features like env, venv, input, path, sudo, and on to reduce script code
Applied to files:
pmoves/services/vibevoice-realtime/Dockerfile
📚 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/**/docker-compose.yml : Use Compose profiles (`data`, `workers`) to scope what runs locally in docker-compose.yml
Applied to files:
pmoves/docker-compose.yml
📚 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 services/**/README.md : Update services/*/README.md and pmoves/docs/PMOVES.AI PLANS/ runbooks when touching service operational code
Applied to files:
pmoves/docker-compose.yml
📚 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: UI updates: run make -C pmoves notebook-workbench-smoke ARGS='--thread=<uuid>' to lint the Next.js bundle and validate Supabase connectivity; reference pmoves/docs/UI_NOTEBOOK_WORKBENCH.md
Applied to files:
pmoves/docker-compose.yml
📚 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/{agent-zero,archon}/**/*.py : For Agents/Archon full-stack validation, follow the 'All Services Up, Then Tests' section in `pmoves/docs/SMOKETESTS.md` and use `make -C pmoves agents-headless-smoke`, `make -C pmoves smoke-gpu`, and `make -C pmoves verify-all`
Applied to files:
pmoves/docker-compose.yml
📚 Learning: 2025-12-15T12:02:50.226Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/realtime/.windsurfrules:0-0
Timestamp: 2025-12-15T12:02:50.226Z
Learning: Applies to pmoves/docs/ARTSTUFF/realtime/**/start.js : Server launchers should configure apps to run at localhost (127.0.0.1) instead of 0.0.0.0 by using environment variables or startup flags
Applied to files:
pmoves/docker-compose.yml
📚 Learning: 2025-12-15T12:03:41.584Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/Ultimate-TTS-Studio.git/AGENTS.md:0-0
Timestamp: 2025-12-15T12:03:41.584Z
Learning: Applies to pmoves/docs/ARTSTUFF/Ultimate-TTS-Studio.git/**/start.js : Always attempt to configure servers to launch at 127.0.0.1 or localhost rather than 0.0.0.0 using launch flags or environment variables
Applied to files:
pmoves/docker-compose.yml
📚 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: Agents/Archon: for full-stack validation, follow the 'All Services Up, Then Tests' section in pmoves/docs/SMOKETESTS.md and the Archon service guide
Applied to files:
pmoves/docker-compose.yml
🪛 Ruff (0.14.10)
pmoves/services/deepresearch/worker.py
317-319: Avoid specifying long messages outside the exception class
(TRY003)
⏰ 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). (2)
- GitHub Check: tests (3.11)
- GitHub Check: Analyze (python)
🔇 Additional comments (7)
pmoves/services/vibevoice-realtime/Dockerfile (1)
37-44: Excellent security hardening implementation; previous concern addressed.The non-root user setup follows security best practices:
- High-numbered UID/GID (65532) is appropriate for container service accounts
/sbin/nologinshell prevents interactive access- Comprehensive ownership changes cover all runtime directories (
/app,/app/vibevoice,/models)- Correct ordering with
chownbeforeUSERdirectiveThe
/modelsdirectory creation and ownership that was flagged in the previous review has been properly implemented (line 40-41), ensuring the entrypoint can write model downloads without permission errors.pmoves/services/deepresearch/worker.py (1)
327-337: LGTM!The Prometheus counter creation now safely handles module reimport via the try/except wrapper. The labelnames are appropriate for tracking fallback reasons and request status.
pmoves/docker-compose.yml (5)
432-433: LGTM!The Flute Gateway URLs now use localhost fallbacks that are accessible from the browser. Ports 8055 and 8056 are exposed on the host (line 415), so client-side connections will work correctly.
792-793: LGTM!The new tmp directory mount provides persistence for Agent Zero's
settings.json, allowing runtime configuration to survive container restarts. The host path is configurable viaAGENT_ZERO_TMP_DIRfor flexibility.
476-478: LGTM!The explicit build context at repository root (
.) allows media service Dockerfiles to accessservices/common/for shared imports, aligning with the PR objective to fix import resolution.Also applies to: 501-503
862-863: LGTM!The
PYTHONPATHaddition allowsarchon-agent-work-ordersto import vendored Archon Python modules, ensuring dependency resolution works correctly.
341-341: LGTM!All
SUPABASE_URLandSUPABASE_REALTIME_URLreferences now consistently use the lowercasesupabase_kong_pmoves.aihostname for container-to-container communication. This normalization addresses Docker DNS case-sensitivity concerns.Also applies to: 402-402, 622-622, 727-727, 816-817, 858-858
- NEXT_PUBLIC_SUPABASE_URL: Use localhost:8000 fallback for browser-side Supabase access (internal Docker hostnames don't resolve in browser) - archon-agent-work-orders: Fix healthcheck endpoint /healthz → /health (service exposes /health, not /healthz) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Phase 1 - Environment Variables: - Add 20+ missing NEXT_PUBLIC_* environment variables - Configure all agent service URLs (Agent Zero, Archon, Hi-RAG) - Add TensorZero, Open Notebook, monitoring stack URLs - Add server-side POSTGREST_URL, PRESIGN_SHARED_SECRET - Fix variable naming: NEXT_PUBLIC_OPEN_NOTEBOOK_API_URL Phase 2 - Hardcoded URL Fixes: - monitor/page.tsx: Use NEXT_PUBLIC_GRAFANA/PROMETHEUS/LOKI_URL - presign.ts: Remove insecure 'change_me' fallback (security fix) Now throws actionable error when PRESIGN_SHARED_SECRET missing Documentation: - Add learnings for Docker DNS casing, NEXT_PUBLIC patterns - Add learnings for Dockerfile permissions, Prometheus registry Fixes: PMOVES UI not connected to backend services Refs: PR #345 🤖 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 (2)
pmoves/ui/app/dashboard/monitor/page.tsx (1)
143-143: Consider defensive URL parsing for misconfigured env vars.If
NEXT_PUBLIC_GRAFANA_URL(or the other URL vars) is set to an invalid URL,new URL(...)will throw at render time. While the fallbacks protect against unset vars, a malformed override would crash the component.This is a minor edge case—misconfiguration would surface immediately—but if you want defensive handling:
🔎 Optional: safe port extraction helper
// At module level function getPort(url: string): string { try { return new URL(url).port || '80'; } catch { return '80'; } }Then use
{getPort(GRAFANA_URL)}in JSX.pmoves/ui/lib/presign.ts (1)
70-76: Error message should clarify optional authentication requirements.The error message at lines 73-74 suggests
PRESIGN_SHARED_SECRETis always required, but the code at lines 46-49 correctly allows requests without it. The service'scheck_auth()function (api.py:32-34) skips authentication ifPRESIGN_SHARED_SECRETis not configured on the server, meaning the secret is optional for both client and server. When authentication fails with 401/403, the error message should clarify that the secret is only required if the server has it configured, or that client and server secrets must match if both are present. Consider updating the error message to be more accurate about the optional nature of this credential.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
.claude/learnings/docker-dns-casing-2025.md.claude/learnings/dockerfile-permissions-2025.md.claude/learnings/nextjs-env-vars-2025.md.claude/learnings/prometheus-registry-2025.mdpmoves/docker-compose.ymlpmoves/ui/app/dashboard/monitor/page.tsxpmoves/ui/lib/presign.ts
✅ Files skipped from review due to trivial changes (2)
- .claude/learnings/docker-dns-casing-2025.md
- .claude/learnings/dockerfile-permissions-2025.md
🧰 Additional context used
📓 Path-based instructions (3)
.claude/**/*.md
📄 CodeRabbit inference engine (AGENTS.md)
Mirror service/endpoint changes in .claude/context/services-catalog.md and add command stubs in .claude/commands/ when relevant
Files:
.claude/learnings/prometheus-registry-2025.md.claude/learnings/nextjs-env-vars-2025.md
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/app/dashboard/monitor/page.tsxpmoves/ui/lib/presign.ts
pmoves/**/docker-compose.yml
📄 CodeRabbit inference engine (pmoves/AGENTS.md)
Use Compose profiles (
data,workers) to scope what runs locally in docker-compose.yml
Files:
pmoves/docker-compose.yml
🧠 Learnings (9)
📓 Common learnings
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-15T12:03:17.291Z
Learning: UI updates: run make -C pmoves notebook-workbench-smoke ARGS='--thread=<uuid>' to lint the Next.js bundle and validate Supabase connectivity; reference pmoves/docs/UI_NOTEBOOK_WORKBENCH.md
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/{agent-zero,archon}/**/*.py : For Agents/Archon full-stack validation, follow the 'All Services Up, Then Tests' section in `pmoves/docs/SMOKETESTS.md` and use `make -C pmoves agents-headless-smoke`, `make -C pmoves smoke-gpu`, and `make -C pmoves verify-all`
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/ui/**/*.{js,jsx,ts,tsx} : UI updates: run `make -C pmoves notebook-workbench-smoke ARGS="--thread=<uuid>"` to lint the Next.js bundle and validate Supabase connectivity; reference `pmoves/docs/UI_NOTEBOOK_WORKBENCH.md`
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/ui/**/*.{js,jsx,ts,tsx} : UI updates: run `make -C pmoves notebook-workbench-smoke ARGS="--thread=<uuid>"` to lint the Next.js bundle and validate Supabase connectivity; reference `pmoves/docs/UI_NOTEBOOK_WORKBENCH.md`
Applied to files:
pmoves/ui/app/dashboard/monitor/page.tsxpmoves/docker-compose.yml
📚 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: UI updates: run make -C pmoves notebook-workbench-smoke ARGS='--thread=<uuid>' to lint the Next.js bundle and validate Supabase connectivity; reference pmoves/docs/UI_NOTEBOOK_WORKBENCH.md
Applied to files:
pmoves/ui/app/dashboard/monitor/page.tsxpmoves/docker-compose.yml
📚 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 services/**/README.md : Update services/*/README.md and pmoves/docs/PMOVES.AI PLANS/ runbooks when touching service operational code
Applied to files:
pmoves/docker-compose.yml
📚 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/**/docker-compose.yml : Use Compose profiles (`data`, `workers`) to scope what runs locally in docker-compose.yml
Applied to files:
pmoves/docker-compose.yml
📚 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/{agent-zero,archon}/**/*.py : For Agents/Archon full-stack validation, follow the 'All Services Up, Then Tests' section in `pmoves/docs/SMOKETESTS.md` and use `make -C pmoves agents-headless-smoke`, `make -C pmoves smoke-gpu`, and `make -C pmoves verify-all`
Applied to files:
pmoves/docker-compose.yml
📚 Learning: 2025-12-15T12:02:50.226Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/realtime/.windsurfrules:0-0
Timestamp: 2025-12-15T12:02:50.226Z
Learning: Applies to pmoves/docs/ARTSTUFF/realtime/**/start.js : Server launchers should configure apps to run at localhost (127.0.0.1) instead of 0.0.0.0 by using environment variables or startup flags
Applied to files:
pmoves/docker-compose.yml
📚 Learning: 2025-12-15T12:03:41.584Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/Ultimate-TTS-Studio.git/AGENTS.md:0-0
Timestamp: 2025-12-15T12:03:41.584Z
Learning: Applies to pmoves/docs/ARTSTUFF/Ultimate-TTS-Studio.git/**/start.js : Always attempt to configure servers to launch at 127.0.0.1 or localhost rather than 0.0.0.0 using launch flags or environment variables
Applied to files:
pmoves/docker-compose.yml
📚 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: Agents/Archon: for full-stack validation, follow the 'All Services Up, Then Tests' section in pmoves/docs/SMOKETESTS.md and the Archon service guide
Applied to files:
pmoves/docker-compose.yml
⏰ 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: tests (3.11)
🔇 Additional comments (11)
.claude/learnings/prometheus-registry-2025.md (1)
1-52: Well-documented pattern for safe Prometheus metric registration.The learning document clearly articulates the problem with direct private API access and provides a sound solution using try/except with type validation. The pattern correctly handles the "Duplicated timeseries" error case and validates both existence and type using
isinstance(), preventing silent failures when metric types conflict. The anti-pattern comparison effectively illustrates the risks of the naive approach.Please verify that the pattern documented here matches the implementation now in use at
pmoves/services/deepresearch/worker.py(referenced in the AI summary as introducing_get_or_create_counter()). If the implementation deviates (e.g., in handling labelnames validation or error messages), this documentation should be updated to reflect the actual code..claude/learnings/nextjs-env-vars-2025.md (1)
1-46: Well-documented learning on Next.js environment variable pitfalls.This document clearly explains the build-time embedding behavior of
NEXT_PUBLIC_*variables and provides an actionable pattern with localhost fallbacks. The detection script is a helpful addition for catching misconfigurations.pmoves/ui/app/dashboard/monitor/page.tsx (2)
6-9: Good use of environment variables with localhost fallbacks.This pattern correctly handles the client-side URL resolution issue documented in
.claude/learnings/nextjs-env-vars-2025.md. The fallback defaults are appropriate for local development.
17-42: Clean polling implementation with proper cleanup.The
activeflag pattern correctly prevents state updates after unmount, and the error handling is well-structured. The 5-second polling interval is reasonable for monitoring data.As per coding guidelines, ensure you've validated the UI changes:
make -C pmoves notebook-workbench-smoke ARGS="--thread=<uuid>"pmoves/ui/lib/presign.ts (1)
62-66: LGTM: Simplified fetch call improves maintainability.Removing the retry logic and making a direct fetch call reduces complexity while maintaining the same functionality.
pmoves/docker-compose.yml (6)
341-341: LGTM: Hostname normalization to lowercase is correct.All
SUPABASE_URLreferences now consistently use lowercasepmoves.aihostname, which aligns with DNS standards and resolves previous inconsistencies.Based on learnings, DNS hostnames should use consistent casing.
Also applies to: 402-402, 644-644, 749-749, 838-839, 880-880
814-815: LGTM: Agent Zero settings persistence is correctly configured.The new volume mount for
/a0/tmpenables persistence ofsettings.jsonacross container restarts, following the same pattern as other Agent Zero mounts. The PR objectives indicate that.gitignorehas been updated to excludepmoves/data/agent-zero/from version control.
906-906: No action required. The healthcheck endpoint is correctly configured to probe/healthfor the archon-agent-work-orders service, which is different from the main archon service's/healthzendpoint. These services have separate health check implementations appropriate to their configurations.
498-500: Build context change correctly enables shared module access with proper Dockerfile configuration.The build context path is resolved relative to the docker-compose.yml file location, and dockerfile paths are resolved relative to the build context. The implementation is correct:
Both
media-videoandmedia-audioservices setcontext: .and use COPY instructions that properly account for the repository-level context (e.g.,COPY services/common /app/services/common). PYTHONPATH environment variables are set in both Dockerfiles to specify directories Python should search for modules, enabling the services to access shared modules as intended.The services are correctly assigned to
["workers", "orchestration"]profiles, complying with the guideline to use Compose profiles for scoping local execution.
421-470: LGTM: pmoves-ui service configuration is correct.The new UI service properly separates client-side (
NEXT_PUBLIC_*) and server-side environment variables:
- Client-side vars correctly use
localhostURLs (accessible from browser)- Server-side vars correctly use Docker hostnames (container-to-container)
Port mapping
4482:3000exposes the UI on the host, and the healthcheck endpoint is appropriate.As per coding guidelines, UI updates should be validated with smoke tests:
#!/bin/bash # Verify UI service health endpoint and configuration # Reference: pmoves/docs/UI_NOTEBOOK_WORKBENCH.md # Check if UI service health endpoint is defined echo "=== Checking UI health endpoint ===" fd -t f "route.ts" pmoves/ui/app/api/health/ --exec cat {} # Check UI Dockerfile for standalone output echo -e "\n=== Verifying UI Dockerfile configuration ===" rg -n "standalone|OUTPUT" pmoves/ui/Dockerfile -A 2 -B 2 # Check Next.js config for standalone output echo -e "\n=== Verifying Next.js config ===" rg -n "output.*standalone" pmoves/ui/next.config.mjs -A 2 -B 2Additionally, run
make -C pmoves notebook-workbench-smoke ARGS="--thread=<uuid>"to validate the Next.js bundle and connectivity.
884-885: PYTHONPATH configuration for archon-work-orders is correctly set.The
PYTHONPATH=/app/vendor/archon/pythonenvironment variable is properly placed in the archon-work-orders service. The Dockerfile confirms the vendor sources are cloned/copied to/app/vendor/archon/python, matching the path in the environment variable. The main archon service omits this setting because it starts via-m services.archon.main(which may handle sys.path internally), while archon-work-orders starts directly withpython -m uvicorn, requiring explicit PYTHONPATH for module resolution.
- Normalize Supabase Kong hostnames to lowercase (DNS convention) - Remove duplicate ARCHON_SUPABASE_BASE_URL env var definition - Fix notebook-sync Dockerfile: remove USER directive so entrypoint can run chown/su as root before dropping privileges - Improve deepresearch _get_or_create_counter: use module-level cache to avoid private prometheus_client API dependency 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add Docker deployment for the PMOVES.AI Unified Portal (pmoves/ui): - **Dockerfile**: Multi-stage build with Node 20, standalone output, non-root user (pmoves:65532), and health check - **docker-compose.yml**: Add pmoves-ui service on port 4482 with Flute-Gateway, Agent Zero, Archon, and Hi-RAG environment variables - **next.config.mjs**: Enable standalone output for minimal production image - **Health API**: Add /api/health endpoint for container orchestration - **Flute Client**: Add WebSocket/HTTP client for voice integration Port allocation: - 4482: Production pmoves-ui - 3001: Local dev only (not Docker) Start with: docker compose --profile ui up -d pmoves-ui Access at: http://localhost:4482 Resolves: PMOVES.AI Unified Portal deployment gap Related: docs/Unified and Modular PMOVES UI Design.md 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Critical fixes: - Add error logging to isHealthy() catch block (was silent failure) - Fix WebSocket message type: 'synthesize' → 'text' - Add error handling to playAudio() with proper cleanup Improvements: - Add onReconnectExhausted callback for connection failure notification - Implement session management using FluteSession interface - Add createSession() and connectWithSession() methods - Add @throws JSDoc annotations and browser-only warnings Session API reference: POST /v1/sessions returns session_id, websocket_url 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Critical: - archon-agent-work-orders healthcheck: /health → /healthz (service exposes /healthz per main.py:248) Major: - pmoves-ui NEXT_PUBLIC env vars: use localhost fallback (NEXT_PUBLIC vars are build-time embedded for browser use) - deepresearch Prometheus: add try/except with type validation (safer than direct private _names_to_collectors access) Minor: - Normalize supabase_kong hostname to lowercase (4 occurrences) (Docker DNS is case-sensitive on some configurations) - vibevoice-realtime: create /models directory with ownership (entrypoint.sh writes to /models via snapshot_download) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- NEXT_PUBLIC_SUPABASE_URL: Use localhost:8000 fallback for browser-side Supabase access (internal Docker hostnames don't resolve in browser) - archon-agent-work-orders: Fix healthcheck endpoint /healthz → /health (service exposes /health, not /healthz) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Phase 1 - Environment Variables: - Add 20+ missing NEXT_PUBLIC_* environment variables - Configure all agent service URLs (Agent Zero, Archon, Hi-RAG) - Add TensorZero, Open Notebook, monitoring stack URLs - Add server-side POSTGREST_URL, PRESIGN_SHARED_SECRET - Fix variable naming: NEXT_PUBLIC_OPEN_NOTEBOOK_API_URL Phase 2 - Hardcoded URL Fixes: - monitor/page.tsx: Use NEXT_PUBLIC_GRAFANA/PROMETHEUS/LOKI_URL - presign.ts: Remove insecure 'change_me' fallback (security fix) Now throws actionable error when PRESIGN_SHARED_SECRET missing Documentation: - Add learnings for Docker DNS casing, NEXT_PUBLIC patterns - Add learnings for Dockerfile permissions, Prometheus registry Fixes: PMOVES UI not connected to backend services Refs: PR #345 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
16ece27 to
9fd7a53
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
pmoves/services/vibevoice-realtime/Dockerfile (1)
1-1: Update PyTorch base image to 2.6.0 or later due to critical RCE vulnerability.PyTorch version 2.5.1 contains a critical Remote Command Execution (RCE) vulnerability (CVE-2025-32434) affecting the torch.load() function when used with weights_only=True. This flaw has been assigned a critical CVSS v4 score of 9.3 and has been patched in PyTorch version 2.6.0. Multiple newer versions are available: 2.9.1 (Nov 2025), 2.9.0 (Oct 2025), 2.8.0 (Aug 2025), 2.7.1 (Jun 2025), and 2.7.0 (Apr 2025).
Additionally, huggingface_hub 0.27.1 (Dec 16, 2024) is outdated; the latest version is 1.2.3 (released Dec 12, 2025).
🧹 Nitpick comments (7)
.claude/learnings/prometheus-registry-2025.md (2)
23-23: Document the rationale for still using the private API in the exception path.While the documentation criticizes direct
REGISTRY._names_to_collectorsaccess, the recommended pattern still uses it on line 27 within the exception handler:existing = REGISTRY._names_to_collectors.get(name). This appears contradictory. Consider either:
- Explicitly documenting that the private API is acceptable in the error path with type validation as a safeguard, or
- Exploring if prometheus_client provides a public API for metric lookup by name (e.g.,
REGISTRY._get_names_to_collectors()or similar).Also applies to: 27-28
50-52: Add specific code references and link to PR changes.The "Related" section is vague. Consider adding:
- Direct links to the prometheus_client documentation sections on REGISTRY and Counter.
- Specific file and line references to where this pattern is applied (e.g., deepresearch module mentioned in PR #345).
- Link to python
python -mdocumentation explaining double-import behavior.pmoves/services/vibevoice-realtime/Dockerfile (1)
21-23: Consider pinning to a specific commit SHA for reproducible builds.Currently cloning from the
mainbranch allows upstream changes to affect builds unpredictably. For better supply chain security and build reproducibility, consider pinningVIBEVOICE_GIT_REFto a specific commit SHA rather than a branch name.🔎 Example approach
ARG VIBEVOICE_GIT_REMOTE=https://github.com/microsoft/VibeVoice.git -ARG VIBEVOICE_GIT_REF=main +ARG VIBEVOICE_GIT_REF=<commit-sha> RUN git clone --depth 1 --single-branch --branch "${VIBEVOICE_GIT_REF}" "${VIBEVOICE_GIT_REMOTE}" /app/vibevoicepmoves/ui/Dockerfile (2)
8-9: Unnecessary curl installation in builder stage.The
curlpackage is installed in the builder stage but is only used for health checks in the runner stage. This adds unnecessary bloat to the builder layer.🔎 Proposed fix
-# Install curl for health checks -RUN apt-get update && apt-get install -y --no-install-recommends curl && rm -rf /var/lib/apt/lists/* - # Install dependencies COPY package*.json ./
11-13: Prefernpm ciovernpm installfor reproducible builds.Using
npm ciensures deterministic installs frompackage-lock.json, which is critical for CI/CD reproducibility and security (prevents unexpected dependency updates).🔎 Proposed fix
# Install dependencies COPY package*.json ./ -RUN npm install +RUN npm cipmoves/ui/lib/fluteClient.ts (2)
288-309: AudioContext resource leak risk on rapid calls.Each
playAudio()call creates a newAudioContext. Browsers limit concurrentAudioContextinstances (typically 4-6). Rapid successive calls could exhaust this limit before previous contexts close.🔎 Proposed fix using shared AudioContext
+// Shared AudioContext for playback (browsers limit concurrent instances) +let sharedAudioContext: AudioContext | null = null; + +function getAudioContext(): AudioContext { + if (!sharedAudioContext || sharedAudioContext.state === 'closed') { + sharedAudioContext = new AudioContext(); + } + return sharedAudioContext; +} + export async function playAudio(audioData: ArrayBuffer): Promise<void> { - const audioContext = new AudioContext(); + const audioContext = getAudioContext(); + + // Resume if suspended (autoplay policy) + if (audioContext.state === 'suspended') { + await audioContext.resume(); + } + try { const audioBuffer = await audioContext.decodeAudioData(audioData); const source = audioContext.createBufferSource(); source.buffer = audioBuffer; source.connect(audioContext.destination); source.start(0); return new Promise((resolve, reject) => { source.onended = () => { - audioContext.close(); resolve(); }; }); } catch (error) { - await audioContext.close(); throw error; } }
297-304: Promise in playAudio never rejects after decoding succeeds.The
Promisecreated for playback completion only resolves viaonended—if playback fails after starting (e.g., context closed externally), the Promise hangs indefinitely. Consider adding a timeout or relying on the outer catch.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (12)
.claude/learnings/docker-dns-casing-2025.md.claude/learnings/dockerfile-permissions-2025.md.claude/learnings/nextjs-env-vars-2025.md.claude/learnings/prometheus-registry-2025.mdpmoves/docker-compose.ymlpmoves/services/vibevoice-realtime/Dockerfilepmoves/ui/Dockerfilepmoves/ui/app/api/health/route.tspmoves/ui/app/dashboard/monitor/page.tsxpmoves/ui/lib/fluteClient.tspmoves/ui/lib/presign.tspmoves/ui/next.config.mjs
✅ Files skipped from review due to trivial changes (1)
- .claude/learnings/dockerfile-permissions-2025.md
🚧 Files skipped from review as they are similar to previous changes (3)
- .claude/learnings/docker-dns-casing-2025.md
- pmoves/ui/next.config.mjs
- pmoves/docker-compose.yml
🧰 Additional context used
📓 Path-based instructions (2)
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/app/dashboard/monitor/page.tsxpmoves/ui/app/api/health/route.tspmoves/ui/lib/fluteClient.tspmoves/ui/lib/presign.ts
.claude/**/*.md
📄 CodeRabbit inference engine (AGENTS.md)
Mirror service/endpoint changes in .claude/context/services-catalog.md and add command stubs in .claude/commands/ when relevant
Files:
.claude/learnings/nextjs-env-vars-2025.md.claude/learnings/prometheus-registry-2025.md
🧠 Learnings (16)
📓 Common learnings
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/{agent-zero,archon}/**/*.py : For Agents/Archon full-stack validation, follow the 'All Services Up, Then Tests' section in `pmoves/docs/SMOKETESTS.md` and use `make -C pmoves agents-headless-smoke`, `make -C pmoves smoke-gpu`, and `make -C pmoves verify-all`
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-15T12:03:17.291Z
Learning: UI updates: run make -C pmoves notebook-workbench-smoke ARGS='--thread=<uuid>' to lint the Next.js bundle and validate Supabase connectivity; reference pmoves/docs/UI_NOTEBOOK_WORKBENCH.md
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/ui/**/*.{js,jsx,ts,tsx} : UI updates: run `make -C pmoves notebook-workbench-smoke ARGS="--thread=<uuid>"` to lint the Next.js bundle and validate Supabase connectivity; reference `pmoves/docs/UI_NOTEBOOK_WORKBENCH.md`
Applied to files:
pmoves/ui/Dockerfilepmoves/ui/app/dashboard/monitor/page.tsx
📚 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: UI updates: run make -C pmoves notebook-workbench-smoke ARGS='--thread=<uuid>' to lint the Next.js bundle and validate Supabase connectivity; reference pmoves/docs/UI_NOTEBOOK_WORKBENCH.md
Applied to files:
pmoves/ui/Dockerfilepmoves/ui/app/dashboard/monitor/page.tsx
📚 Learning: 2025-12-15T12:04:26.230Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/realtime/AGENTS.md:0-0
Timestamp: 2025-12-15T12:04:26.230Z
Learning: Applies to pmoves/docs/ARTSTUFF/realtime/**/*.js : Try to find development options to launch apps without Docker. Use automatic installation and launch for the user's platform via scripts instead of Docker
Applied to files:
pmoves/ui/Dockerfilepmoves/services/vibevoice-realtime/Dockerfile
📚 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: Agents images: default uses published images set in `pmoves/env.shared`. For custom code, build a thin overlay FROM the published image and tag it
Applied to files:
pmoves/ui/Dockerfile
📚 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 {Dockerfile,docker-compose.yml,docker-compose.*.yml,pmoves/docker-compose.*.override.yml} : Dockerfile and docker-compose.yml must follow multi-arch build practices (amd64+arm64) with Trivy scanning for HIGH/CRITICAL vulnerabilities
Applied to files:
pmoves/services/vibevoice-realtime/Dockerfile
📚 Learning: 2025-12-15T12:02:18.878Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/realtime/GEMINI.md:0-0
Timestamp: 2025-12-15T12:02:18.878Z
Learning: Applies to pmoves/docs/ARTSTUFF/realtime/**/*{install,start}.{js,json} : Always use virtual environments for Python apps via shell.run venv attribute in Pinokio launcher scripts
Applied to files:
pmoves/services/vibevoice-realtime/Dockerfile
📚 Learning: 2025-12-15T12:01:31.388Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/realtime/CLAUDE.md:0-0
Timestamp: 2025-12-15T12:01:31.388Z
Learning: Applies to pmoves/docs/ARTSTUFF/realtime/**/{install,start,update,reset}.js : Scripts must be able to replicate install and launch steps 100% - include all 3rd party package installations and repository downloads in scripts, do not assume end user's system state, and make everything self-contained
Applied to files:
pmoves/services/vibevoice-realtime/Dockerfile
📚 Learning: 2025-12-15T12:02:18.878Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/realtime/GEMINI.md:0-0
Timestamp: 2025-12-15T12:02:18.878Z
Learning: Applies to pmoves/docs/ARTSTUFF/realtime/**/*{install,start,update,reset}.{js,json} : Scripts must be able to replicate install and launch steps 100% for end users, do not assume system state and make everything self-contained
Applied to files:
pmoves/services/vibevoice-realtime/Dockerfile
📚 Learning: 2025-12-15T12:03:41.584Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/Ultimate-TTS-Studio.git/AGENTS.md:0-0
Timestamp: 2025-12-15T12:03:41.584Z
Learning: Applies to pmoves/docs/ARTSTUFF/Ultimate-TTS-Studio.git/**/{install,start,update,reset}.js : Always use the `venv` attribute in shell.run API calls for Python projects instead of manually managing virtual environments
Applied to files:
pmoves/services/vibevoice-realtime/Dockerfile
📚 Learning: 2025-12-15T12:04:26.230Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/realtime/AGENTS.md:0-0
Timestamp: 2025-12-15T12:04:26.230Z
Learning: Applies to pmoves/docs/ARTSTUFF/realtime/**/install.js : Install scripts should work for each specific operating system. Ignore Docker related instructions and use platform-specific install/launch instructions instead
Applied to files:
pmoves/services/vibevoice-realtime/Dockerfile
📚 Learning: 2025-12-15T12:02:18.878Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/realtime/GEMINI.md:0-0
Timestamp: 2025-12-15T12:02:18.878Z
Learning: Applies to pmoves/docs/ARTSTUFF/realtime/**/*{install,start,update,reset}.{js,json} : Use Pinokio shell.run API features like env, venv, input, path, sudo, on to reduce script code instead of raw shell commands
Applied to files:
pmoves/services/vibevoice-realtime/Dockerfile
📚 Learning: 2025-12-15T12:03:41.584Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/Ultimate-TTS-Studio.git/AGENTS.md:0-0
Timestamp: 2025-12-15T12:03:41.584Z
Learning: Applies to pmoves/docs/ARTSTUFF/Ultimate-TTS-Studio.git/**/start.js : Set `daemon: true` at the root level of launcher scripts when launching long-running server processes to prevent process termination after script completion
Applied to files:
pmoves/services/vibevoice-realtime/Dockerfile
📚 Learning: 2025-12-15T12:02:50.226Z
Learnt from: CR
Repo: POWERFULMOVES/PMOVES.AI PR: 0
File: pmoves/docs/ARTSTUFF/realtime/.windsurfrules:0-0
Timestamp: 2025-12-15T12:02:50.226Z
Learning: Applies to pmoves/docs/ARTSTUFF/realtime/**/install.js : Install scripts should avoid modifying the cloned project folder (app directory) and instead create additional files in launcher folder to work around installation issues without touching app logic
Applied to files:
pmoves/services/vibevoice-realtime/Dockerfile
📚 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/**/docker-compose.yml : Use Compose profiles (`data`, `workers`) to scope what runs locally in docker-compose.yml
Applied to files:
pmoves/services/vibevoice-realtime/Dockerfile
📚 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 .claude/**/*.md : Mirror service/endpoint changes in .claude/context/services-catalog.md and add command stubs in .claude/commands/ when relevant
Applied to files:
.claude/learnings/nextjs-env-vars-2025.md
⏰ 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 (12)
.claude/learnings/prometheus-registry-2025.md (2)
1-52: Verify alignment with .claude/ guidelines.Per the coding guidelines,
.claude/**/*.mdfiles should mirror service/endpoint changes in.claude/context/services-catalog.mdand add command stubs in.claude/commands/when relevant. This file documents a Prometheus registration pattern related to the deepresearch service mentioned in PR #345. Confirm whether:
.claude/context/services-catalog.mdwas updated to reflect deepresearch changes.- Command stubs were added to
.claude/commands/for testing or validating the Prometheus pattern (e.g., a smoke test for metric registration).
24-33: The pattern correctly identifies duplicate metrics by checking the actual error message from prometheus_client. This approach is reliable and not brittle—the error message has remained stable across versions and is integral to the library's public behavior.pmoves/services/vibevoice-realtime/Dockerfile (1)
40-41: LGTM! The/modelsdirectory setup correctly addresses the previous review.The addition of
mkdir -p /modelsand including/modelsin the ownership change ensures the entrypoint script can write model downloads without permission errors, all while maintaining non-root execution.pmoves/ui/Dockerfile (1)
26-50: LGTM! Solid security hardening.Good practices observed:
- Non-root user with explicit UID/GID (65532)
- Ownership properly transferred before
USERdirective- Health check with reasonable intervals and start period for Next.js cold start
- Standalone server deployment pattern is correct
pmoves/ui/app/api/health/route.ts (1)
7-14: LGTM! Clean health endpoint implementation.The endpoint correctly returns all necessary fields for container orchestration. Minor note:
process.env.npm_package_versionis only set when running vianpm runscripts and won't be available in the standalone server context—the'0.1.0'fallback appropriately handles this.Based on learnings, consider running
make -C pmoves notebook-workbench-smoke ARGS='--thread=<uuid>'to lint the Next.js bundle and validate connectivity.pmoves/ui/lib/presign.ts (1)
62-77: LGTM! Good security hardening.The removal of the insecure
'change_me'fallback and addition of actionable error messaging for auth failures is a solid security improvement. The explicit 401/403 handling with configuration guidance will help developers diagnose misconfiguration quickly.pmoves/ui/app/dashboard/monitor/page.tsx (2)
17-42: LGTM! Proper cleanup pattern for polling.The
activeflag prevents state updates after unmount, andclearIntervalproperly cleans up the timer. The 5-second polling interval is reasonable for a monitoring dashboard.
133-176: Code already uses host-accessible monitoring URLs.The monitoring service URLs are correctly configured with
localhostand published ports (Grafana: 3002, Prometheus: 9090, Loki: 3100), not internal Docker hostnames. Although NEXT_PUBLIC_* variables are inlined at build time and do not respond to changes after build, the current configuration is already appropriate for browser access. No changes needed.Likely an incorrect or invalid review comment.
pmoves/ui/lib/fluteClient.ts (3)
66-74: LGTM! Clean constructor with environment fallbacks.Good pattern using optional constructor parameters with env var fallbacks for flexibility between configured deployments and local development.
138-149: LGTM! Health check with proper timeout.Using
AbortSignal.timeout(5000)ensures the health check doesn't hang indefinitely—good defensive coding for service availability checks.
227-244: LGTM! Solid reconnection logic with backoff.The auto-reconnect implementation correctly:
- Uses linear backoff (1s × attempt count)
- Limits retries via
maxReconnectAttempts- Resets counter on successful connection
- Notifies via
onReconnectExhaustedcallback.claude/learnings/nextjs-env-vars-2025.md (1)
1-46: LGTM! Valuable documentation for common Next.js Docker pitfall.This learning captures a real issue with clear explanation and actionable pattern. The detection command is useful for CI/CD validation.
As per coding guidelines, consider mirroring any new service/endpoint changes in
.claude/context/services-catalog.mdif the Flute Gateway or other services documented here aren't already catalogued.
| def _get_or_create_counter(name: str, description: str, labelnames: tuple) -> Counter: | ||
| """Get existing counter or create new one (safe for module reimport via -m flag).""" | ||
| try: | ||
| return Counter(name, description, labelnames=labelnames) | ||
| except ValueError as e: | ||
| if "Duplicated timeseries" in str(e): | ||
| # Metric already exists; retrieve and validate type | ||
| existing = REGISTRY._names_to_collectors.get(name) | ||
| if existing is not None and isinstance(existing, Counter): | ||
| return existing | ||
| raise TypeError( | ||
| f"Metric '{name}' exists but is {type(existing).__name__}, not Counter" | ||
| ) from e | ||
| raise |
There was a problem hiding this comment.
Address labelnames mismatch scenarios.
The function accepts a labelnames tuple but does not validate that an existing metric's labelnames match. If a metric with the same name but different labelnames exists, isinstance(existing, Counter) will pass, but the returned metric may have incompatible labelnames. Consider documenting:
- Whether prometheus_client raises an error for labelnames mismatches, or
- Adding explicit labelnames validation when retrieving an existing metric.
🤖 Prompt for AI Agents
In .claude/learnings/prometheus-registry-2025.md around lines 20 to 33, the
helper returns an existing Counter without verifying its labelnames, which can
silently return a metric with incompatible labels; when retrieving the existing
collector, compare the provided labelnames tuple to the collector's labelnames
(e.g., existing._labelnames or existing._labelnames property) and if they differ
raise a clear TypeError indicating the name exists with different labelnames, or
alternatively log the mismatch and re-raise ValueError; also add a short comment
documenting the chosen behavior and why labelname validation is required.
| // Monitoring service URLs (configured via NEXT_PUBLIC_* env vars for client-side access) | ||
| const GRAFANA_URL = process.env.NEXT_PUBLIC_GRAFANA_URL || 'http://localhost:3002'; | ||
| const PROMETHEUS_URL = process.env.NEXT_PUBLIC_PROMETHEUS_URL || 'http://localhost:9090'; | ||
| const LOKI_URL = process.env.NEXT_PUBLIC_LOKI_URL || 'http://localhost:3100'; |
There was a problem hiding this comment.
Add defensive URL parsing to prevent runtime crashes.
new URL() throws on invalid input. If an environment variable contains a malformed URL or is set to an internal Docker hostname that the browser can't parse, the component will crash during render.
🔎 Proposed fix with safe URL helpers
+// Safe URL helpers to prevent runtime crashes from invalid env vars
+function safeGetPort(urlString: string, fallbackPort = '80'): string {
+ try {
+ return new URL(urlString).port || fallbackPort;
+ } catch {
+ return fallbackPort;
+ }
+}
+
// Monitoring service URLs (configured via NEXT_PUBLIC_* env vars for client-side access)
const GRAFANA_URL = process.env.NEXT_PUBLIC_GRAFANA_URL || 'http://localhost:3002';
const PROMETHEUS_URL = process.env.NEXT_PUBLIC_PROMETHEUS_URL || 'http://localhost:9090';
const LOKI_URL = process.env.NEXT_PUBLIC_LOKI_URL || 'http://localhost:3100';Then replace inline new URL(...).port || '80' calls with safeGetPort(GRAFANA_URL), etc.
📝 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.
| // Monitoring service URLs (configured via NEXT_PUBLIC_* env vars for client-side access) | |
| const GRAFANA_URL = process.env.NEXT_PUBLIC_GRAFANA_URL || 'http://localhost:3002'; | |
| const PROMETHEUS_URL = process.env.NEXT_PUBLIC_PROMETHEUS_URL || 'http://localhost:9090'; | |
| const LOKI_URL = process.env.NEXT_PUBLIC_LOKI_URL || 'http://localhost:3100'; | |
| // Safe URL helpers to prevent runtime crashes from invalid env vars | |
| function safeGetPort(urlString: string, fallbackPort = '80'): string { | |
| try { | |
| return new URL(urlString).port || fallbackPort; | |
| } catch { | |
| return fallbackPort; | |
| } | |
| } | |
| // Monitoring service URLs (configured via NEXT_PUBLIC_* env vars for client-side access) | |
| const GRAFANA_URL = process.env.NEXT_PUBLIC_GRAFANA_URL || 'http://localhost:3002'; | |
| const PROMETHEUS_URL = process.env.NEXT_PUBLIC_PROMETHEUS_URL || 'http://localhost:9090'; | |
| const LOKI_URL = process.env.NEXT_PUBLIC_LOKI_URL || 'http://localhost:3100'; |
🤖 Prompt for AI Agents
In pmoves/ui/app/dashboard/monitor/page.tsx around lines 6 to 9, the code uses
process.env NEXT_PUBLIC_* URLs directly and callers use new URL(...) which can
throw for malformed or unresolvable values; add a small defensive helper (e.g.,
safeParseUrl(url?: string): URL | null and safeGetPort(url?: string,
defaultPort='80'): string) that catches errors from new URL and returns null or
a default, validate/normalize the env values using that helper at module init,
and replace all inline new URL(...).port or similar calls with
safeGetPort(GRAFANA_URL) / safeGetPort(PROMETHEUS_URL) / safeGetPort(LOKI_URL)
so rendering won’t throw on bad env vars.
Phase 2 hardening: Docker security, Prometheus patterns, DNS fixes
- Normalize Supabase Kong hostnames to lowercase (DNS convention) - Remove duplicate ARCHON_SUPABASE_BASE_URL env var definition - Fix notebook-sync Dockerfile: remove USER directive so entrypoint can run chown/su as root before dropping privileges - Improve deepresearch _get_or_create_counter: use module-level cache to avoid private prometheus_client API dependency 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Normalize Supabase Kong hostnames to lowercase (DNS convention) - Remove duplicate ARCHON_SUPABASE_BASE_URL env var definition - Fix notebook-sync Dockerfile: remove USER directive so entrypoint can run chown/su as root before dropping privileges - Improve deepresearch _get_or_create_counter: use module-level cache to avoid private prometheus_client API dependency 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…tion (#443) * refactor(env): Phase 2 - Migrate API tier to env-tier-api anchor (#350) Phase 2 of env consolidation: API tier migration Changes: - Fix tier anchor syntax (block-style env_file with required: false) - Migrate postgrest, presign, retrieval-eval to <<: *env-tier-api - Create env.tier-api.example with secure defaults API tier services receive data tier URLs and internal credentials only, no external API keys (OPENAI_API_KEY, etc.) Services migrated: - postgrest: PostgREST database gateway - presign: MinIO URL presigner - retrieval-eval: Hi-RAG evaluation service 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Codex Agent <codex-agent@example.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> * refactor(env): Phase 3 - Migrate LLM tier to env-tier-llm anchor (#351) Phase 3 of env consolidation: LLM tier migration Changes: - Fix tier anchor syntax (block-style env_file with required: false) - Migrate tensorzero-ui to <<: *env-tier-llm - Create env.tier-llm.example with all LLM provider API keys CRITICAL: LLM tier is the ONLY tier with access to external API keys. All other services call TensorZero internally, not providers directly. Services in LLM tier: - tensorzero-gateway: Already using <<: *env-tier-llm - tensorzero-ui: Migrated from legacy env_file - tensorzero-clickhouse: Uses inline env (no API keys needed) - pmoves-ollama: Uses inline env (no API keys needed) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Codex Agent <codex-agent@example.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> * refactor(env): Phase 6 - Migrate agent tier + API additions (#354) Completes the 6-tier environment consolidation by migrating: **Agent Tier (10 services):** - mesh-agent, deepresearch, supaserch, consciousness-service - archon-agent-work-orders, botz-gateway, publisher-discord - messaging-gateway, jellyfin-bridge, chat-relay **API Tier Additions (4 services):** - postgrest-cli, hi-rag-gateway, hi-rag-gateway-gpu, hi-rag-gateway-v2-gpu **Worker Tier (6 services) - included in this commit:** - render-webhook, comfy-watcher, pdf-ingest, langextract - notebook-sync, session-context-worker **Media Tier (10 services) - included in this commit:** - ultimate-tts-studio, flute-gateway, ffmpeg-whisper - media-video, media-audio, channel-monitor - invidious, invidious-companion, grayjay-plugin-host, grayjay-server Security improvement: 30 services now use tier-based env_file anchors instead of legacy x-env-legacy pattern. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Codex Agent <codex-agent@example.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> * fix(security): GPU access + production hardening (health checks, image pins, required password) (#355) * docs: address PR review comments for env tier consolidation - Add GPU Orchestrator and E2B Runner to services-catalog.md - Add gpu-orchestrator to env.tier-api.example service list - Create learnings file documenting 6-tier env architecture - Add env.tier-*.example files for worker, media, agent tiers Addresses nitpick comments from PRs #349-354. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(gpu): ensure GPU access for all CUDA-enabled services - gpu-orchestrator: Add GPU deploy section + NVIDIA_VISIBLE_DEVICES - ultimate-tts-studio: Add NVIDIA_VISIBLE_DEVICES env var - hi-rag-gateway-gpu: Add NVIDIA_VISIBLE_DEVICES env var - hi-rag-gateway-v2-gpu: Add NVIDIA_VISIBLE_DEVICES env var - media-audio: Change base image to nvidia/cuda:12.4.1-runtime-ubuntu22.04 (was python:3.11-slim which caused silent CPU fallback) This fixes silent CPU fallbacks where PyTorch CUDA packages were installed but the CUDA runtime was not available in the container. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(security): production hardening - health checks and image pinning Critical security and reliability fixes: 1. **POSTGRES_PASSWORD now required** - Changed from insecure default `:-pmoves` to required syntax `${VAR:?error}`. Compose will fail if POSTGRES_PASSWORD is not set (lines 59, 78, 937). 2. **Pinned 8 :latest images to specific versions:** - postgrest/postgrest:latest → v12.2.3 - minio/minio:latest → RELEASE.2024-12-18T13-15-44Z - ollama/ollama:latest → 0.5.4 - tensorzero/gateway:latest → 2024.12.18 - tensorzero/ui:latest → 2024.12.18 - invidious:latest → 2024.12.09 - invidious-companion:latest → 2024.12.20 - grayjay:latest → 2024.11.01 3. **Added health checks to 37 services** (52 total, up from 15): - Data tier: qdrant, meilisearch, minio - API tier: hi-rag-*, retrieval-eval, presign, render-webhook - Worker tier: extract-worker, pdf-ingest, langextract, notebook-sync, ffmpeg-whisper, media-video, media-audio, pmoves-yt, channel-monitor - Agent tier: agent-zero, mesh-agent, deepresearch, supaserch - TensorZero: gateway, ui, ollama - Others: publisher-discord, messaging-gateway, jellyfin-bridge 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(health): address PR review critical issues Fixes critical issues identified by PR review: MinIO: - Change health check from `mc ready local` to curl-based (minio/minio image doesn't include mc binary) NATS: - Add `-m 8222` flag to enable HTTP monitoring port (health check was targeting port that wasn't enabled) Health checks: - comfy-watcher: verify module imports instead of just `import sys` - mesh-agent: verify main module and NATS client availability Missing start_period: - postgres: add 15s start_period - chat-relay: add 30s start_period - n8n-agent: add 30s start_period - invidious-postgres: add 15s start_period All 52 health checks now have start_period defined. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Codex Agent <codex-agent@example.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> * security(dockerfile): Harden notebook-sync and vibevoice-realtime Increase Dockerfile hardening from 33/36 (91.7%) to 35/36 (97.2%): - notebook-sync: Add USER pmoves (user creation already existed) - vibevoice-realtime: Add full hardening with UID/GID 65532 Accepted exception: agent-zero uses root for initialization then drops to pmoves via 'su' for the service process. This pattern is required by upstream Agent Zero's prepare.py and /ins/copy_A0.sh. Pattern reference: flute-gateway/Dockerfile 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(infra): Address PR #345 CodeRabbit review comments - Normalize Supabase Kong hostnames to lowercase (DNS convention) - Remove duplicate ARCHON_SUPABASE_BASE_URL env var definition - Fix notebook-sync Dockerfile: remove USER directive so entrypoint can run chown/su as root before dropping privileges - Improve deepresearch _get_or_create_counter: use module-level cache to avoid private prometheus_client API dependency 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(infra): Archon Supabase connectivity and UI dashboard fixes Changes: - Archon health check: Add Kong gateway hostname support for internal Docker networking (supabase_kong_pmoves.ai:8000) - UI dashboard: Add /dashboard redirect page to /dashboard/services - Grafana: Fix env var placeholders and job name mismatches in queries - Docs: Add placeholder for Jellyfin service documentation The Archon health check now properly handles both: - Supabase CLI endpoint (host.docker.internal:65421) - Internal Kong gateway (supabase_kong_pmoves.ai:8000) This resolves the 404 errors in Archon health checks when using internal Docker DNS names instead of host.docker.internal. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * chore(gitignore): Exclude agent-zero runtime data directory Add pmoves/data/agent-zero/ to gitignore. This directory contains runtime settings (settings.json) that persist via Docker volume mount. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(deepresearch): Prometheus counter double-registration Use registry lookup pattern instead of try/except for counter registration. Prevents 'Duplicated timeseries' error when container restarts with existing registry state. Before: try/except around Counter() creation After: REGISTRY._names_to_collectors.get() for existing lookup 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(flute-gateway): add logging to silent exception handlers (#323) - Add warning log to Supabase health check exception handler - Improve persona fetch error logging with status code and truncated body - Add metrics tracking for non-200 persona fetch responses Closes #322 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Codex Agent <codex-agent@example.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> * docs: add comprehensive service documentation (#338) Merged after rebase to resolve Jellyfin README conflict * fix(compose): Agent Zero settings persistence and Archon hostname - Add volume mount ./data/agent-zero/tmp:/a0/tmp for settings.json Root cause: PMOVES-Agent-Zero/python/helpers/settings.py:162 stores settings at /a0/tmp/settings.json but path was not mounted - Normalize Archon SUPABASE_URL to lowercase supabase_kong_pmoves.ai Root cause: Docker DNS is case-sensitive on some configurations - Fix archon-agent-work-orders health check: /healthz → /health Root cause: Service exposes /health, not /healthz 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Codex Agent <codex-agent@example.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
…tion (#443) * refactor(env): Phase 2 - Migrate API tier to env-tier-api anchor (#350) Phase 2 of env consolidation: API tier migration Changes: - Fix tier anchor syntax (block-style env_file with required: false) - Migrate postgrest, presign, retrieval-eval to <<: *env-tier-api - Create env.tier-api.example with secure defaults API tier services receive data tier URLs and internal credentials only, no external API keys (OPENAI_API_KEY, etc.) Services migrated: - postgrest: PostgREST database gateway - presign: MinIO URL presigner - retrieval-eval: Hi-RAG evaluation service 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Codex Agent <codex-agent@example.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> * refactor(env): Phase 3 - Migrate LLM tier to env-tier-llm anchor (#351) Phase 3 of env consolidation: LLM tier migration Changes: - Fix tier anchor syntax (block-style env_file with required: false) - Migrate tensorzero-ui to <<: *env-tier-llm - Create env.tier-llm.example with all LLM provider API keys CRITICAL: LLM tier is the ONLY tier with access to external API keys. All other services call TensorZero internally, not providers directly. Services in LLM tier: - tensorzero-gateway: Already using <<: *env-tier-llm - tensorzero-ui: Migrated from legacy env_file - tensorzero-clickhouse: Uses inline env (no API keys needed) - pmoves-ollama: Uses inline env (no API keys needed) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Codex Agent <codex-agent@example.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> * refactor(env): Phase 6 - Migrate agent tier + API additions (#354) Completes the 6-tier environment consolidation by migrating: **Agent Tier (10 services):** - mesh-agent, deepresearch, supaserch, consciousness-service - archon-agent-work-orders, botz-gateway, publisher-discord - messaging-gateway, jellyfin-bridge, chat-relay **API Tier Additions (4 services):** - postgrest-cli, hi-rag-gateway, hi-rag-gateway-gpu, hi-rag-gateway-v2-gpu **Worker Tier (6 services) - included in this commit:** - render-webhook, comfy-watcher, pdf-ingest, langextract - notebook-sync, session-context-worker **Media Tier (10 services) - included in this commit:** - ultimate-tts-studio, flute-gateway, ffmpeg-whisper - media-video, media-audio, channel-monitor - invidious, invidious-companion, grayjay-plugin-host, grayjay-server Security improvement: 30 services now use tier-based env_file anchors instead of legacy x-env-legacy pattern. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Codex Agent <codex-agent@example.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> * fix(security): GPU access + production hardening (health checks, image pins, required password) (#355) * docs: address PR review comments for env tier consolidation - Add GPU Orchestrator and E2B Runner to services-catalog.md - Add gpu-orchestrator to env.tier-api.example service list - Create learnings file documenting 6-tier env architecture - Add env.tier-*.example files for worker, media, agent tiers Addresses nitpick comments from PRs #349-354. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(gpu): ensure GPU access for all CUDA-enabled services - gpu-orchestrator: Add GPU deploy section + NVIDIA_VISIBLE_DEVICES - ultimate-tts-studio: Add NVIDIA_VISIBLE_DEVICES env var - hi-rag-gateway-gpu: Add NVIDIA_VISIBLE_DEVICES env var - hi-rag-gateway-v2-gpu: Add NVIDIA_VISIBLE_DEVICES env var - media-audio: Change base image to nvidia/cuda:12.4.1-runtime-ubuntu22.04 (was python:3.11-slim which caused silent CPU fallback) This fixes silent CPU fallbacks where PyTorch CUDA packages were installed but the CUDA runtime was not available in the container. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(security): production hardening - health checks and image pinning Critical security and reliability fixes: 1. **POSTGRES_PASSWORD now required** - Changed from insecure default `:-pmoves` to required syntax `${VAR:?error}`. Compose will fail if POSTGRES_PASSWORD is not set (lines 59, 78, 937). 2. **Pinned 8 :latest images to specific versions:** - postgrest/postgrest:latest → v12.2.3 - minio/minio:latest → RELEASE.2024-12-18T13-15-44Z - ollama/ollama:latest → 0.5.4 - tensorzero/gateway:latest → 2024.12.18 - tensorzero/ui:latest → 2024.12.18 - invidious:latest → 2024.12.09 - invidious-companion:latest → 2024.12.20 - grayjay:latest → 2024.11.01 3. **Added health checks to 37 services** (52 total, up from 15): - Data tier: qdrant, meilisearch, minio - API tier: hi-rag-*, retrieval-eval, presign, render-webhook - Worker tier: extract-worker, pdf-ingest, langextract, notebook-sync, ffmpeg-whisper, media-video, media-audio, pmoves-yt, channel-monitor - Agent tier: agent-zero, mesh-agent, deepresearch, supaserch - TensorZero: gateway, ui, ollama - Others: publisher-discord, messaging-gateway, jellyfin-bridge 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(health): address PR review critical issues Fixes critical issues identified by PR review: MinIO: - Change health check from `mc ready local` to curl-based (minio/minio image doesn't include mc binary) NATS: - Add `-m 8222` flag to enable HTTP monitoring port (health check was targeting port that wasn't enabled) Health checks: - comfy-watcher: verify module imports instead of just `import sys` - mesh-agent: verify main module and NATS client availability Missing start_period: - postgres: add 15s start_period - chat-relay: add 30s start_period - n8n-agent: add 30s start_period - invidious-postgres: add 15s start_period All 52 health checks now have start_period defined. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Codex Agent <codex-agent@example.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> * security(dockerfile): Harden notebook-sync and vibevoice-realtime Increase Dockerfile hardening from 33/36 (91.7%) to 35/36 (97.2%): - notebook-sync: Add USER pmoves (user creation already existed) - vibevoice-realtime: Add full hardening with UID/GID 65532 Accepted exception: agent-zero uses root for initialization then drops to pmoves via 'su' for the service process. This pattern is required by upstream Agent Zero's prepare.py and /ins/copy_A0.sh. Pattern reference: flute-gateway/Dockerfile 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(infra): Address PR #345 CodeRabbit review comments - Normalize Supabase Kong hostnames to lowercase (DNS convention) - Remove duplicate ARCHON_SUPABASE_BASE_URL env var definition - Fix notebook-sync Dockerfile: remove USER directive so entrypoint can run chown/su as root before dropping privileges - Improve deepresearch _get_or_create_counter: use module-level cache to avoid private prometheus_client API dependency 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(infra): Archon Supabase connectivity and UI dashboard fixes Changes: - Archon health check: Add Kong gateway hostname support for internal Docker networking (supabase_kong_pmoves.ai:8000) - UI dashboard: Add /dashboard redirect page to /dashboard/services - Grafana: Fix env var placeholders and job name mismatches in queries - Docs: Add placeholder for Jellyfin service documentation The Archon health check now properly handles both: - Supabase CLI endpoint (host.docker.internal:65421) - Internal Kong gateway (supabase_kong_pmoves.ai:8000) This resolves the 404 errors in Archon health checks when using internal Docker DNS names instead of host.docker.internal. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * chore(gitignore): Exclude agent-zero runtime data directory Add pmoves/data/agent-zero/ to gitignore. This directory contains runtime settings (settings.json) that persist via Docker volume mount. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(deepresearch): Prometheus counter double-registration Use registry lookup pattern instead of try/except for counter registration. Prevents 'Duplicated timeseries' error when container restarts with existing registry state. Before: try/except around Counter() creation After: REGISTRY._names_to_collectors.get() for existing lookup 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(flute-gateway): add logging to silent exception handlers (#323) - Add warning log to Supabase health check exception handler - Improve persona fetch error logging with status code and truncated body - Add metrics tracking for non-200 persona fetch responses Closes #322 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Codex Agent <codex-agent@example.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> * docs: add comprehensive service documentation (#338) Merged after rebase to resolve Jellyfin README conflict * fix(compose): Agent Zero settings persistence and Archon hostname - Add volume mount ./data/agent-zero/tmp:/a0/tmp for settings.json Root cause: PMOVES-Agent-Zero/python/helpers/settings.py:162 stores settings at /a0/tmp/settings.json but path was not mounted - Normalize Archon SUPABASE_URL to lowercase supabase_kong_pmoves.ai Root cause: Docker DNS is case-sensitive on some configurations - Fix archon-agent-work-orders health check: /healthz → /health Root cause: Service exposes /health, not /healthz 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Codex Agent <codex-agent@example.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
- Normalize Supabase Kong hostnames to lowercase (DNS convention) - Remove duplicate ARCHON_SUPABASE_BASE_URL env var definition - Fix notebook-sync Dockerfile: remove USER directive so entrypoint can run chown/su as root before dropping privileges - Improve deepresearch _get_or_create_counter: use module-level cache to avoid private prometheus_client API dependency 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Phase 2 hardening: Docker security, Prometheus patterns, DNS fixes
Phase 2 hardening: Docker security, Prometheus patterns, DNS fixes
- Normalize Supabase Kong hostnames to lowercase (DNS convention) - Remove duplicate ARCHON_SUPABASE_BASE_URL env var definition - Fix notebook-sync Dockerfile: remove USER directive so entrypoint can run chown/su as root before dropping privileges - Improve deepresearch _get_or_create_counter: use module-level cache to avoid private prometheus_client API dependency 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Summary
PMOVES.AI Unified Portal Deployment
NEW: The main PMOVES.AI dashboard is now deployable as a Docker service:
Files Added
pmoves/ui/Dockerfile- Multi-stage build, Node 20, non-root userpmoves/ui/app/api/health/route.ts- Health check endpointpmoves/ui/lib/fluteClient.ts- Flute-Gateway voice integration clientFiles Modified
pmoves/docker-compose.yml- Added pmoves-ui servicepmoves/ui/next.config.mjs- Enabled standalone outputTest plan
make smokepassespytest -qpasses (14/14)/api/healthreturns healthy statusDockerfile Hardening Status
🤖 Generated with Claude Code
Summary by CodeRabbit
Release Notes
New Features
Bug Fixes
✏️ Tip: You can customize this high-level summary in your review settings.