Skip to content

fix(windows): gate torch.compile on Triton + ASR critical-path smoke (plan-02, closes #65) - #138

Merged
debpalash merged 3 commits into
mainfrom
003-windows-runtime-integrity
May 29, 2026
Merged

fix(windows): gate torch.compile on Triton + ASR critical-path smoke (plan-02, closes #65)#138
debpalash merged 3 commits into
mainfrom
003-windows-runtime-integrity

Conversation

@debpalash

@debpalash debpalash commented May 29, 2026

Copy link
Copy Markdown
Owner

plan-02Closes #65. Addresses #129, #116.

Two Windows failures that only bite at inference time:

  1. [Bug] torch.compile on Windows causes TTS OOM due to missing Triton #65torch.compile(mode="reduce-overhead") needs Triton, which has no Windows wheel. The old device == "cuda"-only guard ran it on Windows+CUDA → failed, surfaced as a confusing "OOM".
  2. [Bug] transcription prodused no segments. no module pkg resources #116ModuleNotFoundError: pkg_resources via ctranslate2→whisperx, mid-transcription.

Fix

  • engine_env.should_torch_compile(device) — applies torch.compile only when device==CUDA and importlib.util.find_spec("triton") is present and the existing perf.torch_compile_disabled setting is off. Otherwise → eager mode with an INFO log. model_manager.py uses it in place of the bare CUDA check.
  • smoke-test.sh INST-02 — imports the full ASR path (torch, ctranslate2, whisperx) so a missing transitive dep fails the build instead of crashing on the user's machine. Runs in the CI smoke-matrix on Windows/macOS/Linux.
  • setuptools>=75.0 (fix-sequence step 1) was already pinned ([Bug] Transcription produced no segments. No module named 'pkg_resources' #58) — confirmed.

Cross-platform parity

The gate is Triton-availability-driven: Linux/CUDA+Triton is unchanged (compile still applied); Windows falls back to eager — same user-visible result (working inference), no divergent default.

Tests (TDD, fail-before/pass-after — Constitution V)

tests/test_torch_compile_gate.py (4): skip on non-CUDA, skip when Triton missing, compile when present+enabled, skip when disabled. Engine/settings/model regression subset: 90 passed, 0 failed.

Follow-up (out of scope)

A richer in-app post-bootstrap "setup incomplete" banner — deferred; the build-time smoke gate + ASR is_available() message cover it for now.

Spec/plan/tasks in specs/003-windows-runtime-integrity/.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Gate performance compilation so it runs only when CUDA, a native accelerator, and a runtime accelerator library are available and not disabled by settings; added a build-time smoke test validating key ML dependencies.
  • Bug Fixes

    • Reduces risk of compilation-related crashes/out-of-memory on Windows+CUDA setups.
  • Documentation

    • Added implementation plan, spec, and task documents for runtime integrity.
  • Tests

    • Added tests covering the compilation eligibility gate.

Review Change Stack

…65)

plan-02. torch.compile(mode="reduce-overhead") needs Triton at runtime;
Triton has no Windows wheel, so the old `device=="cuda"`-only guard in
model_manager.py failed on Windows+CUDA and surfaced as a confusing "OOM"
(#65). Inference-time, hard to diagnose.

- engine_env.should_torch_compile(device): requires CUDA + find_spec("triton")
  + the existing perf.torch_compile_disabled setting being off; logs the skip
  reason at INFO and falls back to eager.
- model_manager.py call site uses it instead of the bare cuda check.
- smoke-test.sh INST-02: import torch + ctranslate2 + whisperx (full ASR path)
  so a missing transitive dep fails the build instead of crashing mid-
  transcription (#116). Runs in the CI smoke-matrix on Win/macOS/Linux.

setuptools>=75.0 (fix-sequence step 1) already pinned (#58). Linux/CUDA+Triton
behaviour unchanged.

Tests (TDD): tests/test_torch_compile_gate.py (4). Closes #65; addresses
#129/#116.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented May 29, 2026

Copy link
Copy Markdown
Contributor

Caution

Review failed

Pull request was closed or merged during review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 06bdfbff-00d7-4e04-b713-eacb6c93bd97

📥 Commits

Reviewing files that changed from the base of the PR and between dec971d and d9adac8.

📒 Files selected for processing (2)
  • backend/services/engine_env.py
  • tests/test_torch_compile_gate.py
💤 Files with no reviewable changes (1)
  • tests/test_torch_compile_gate.py

📝 Walkthrough

Walkthrough

This PR gates in-process torch.compile on CUDA + Triton availability and a user escape-hatch, updates engine subprocess comments, adds an ASR install-time smoke import, and adds spec/plan/tasks and tests covering the gating paths.

Changes

Windows Runtime Integrity

Layer / File(s) Summary
Feature specification and plan
specs/003-windows-runtime-integrity/spec.md, specs/003-windows-runtime-integrity/plan.md, specs/003-windows-runtime-integrity/tasks.md
Adds spec, plan, and tasks describing gating torch.compile on Triton availability and perf.torch_compile_disabled, CI smoke-test requirements, FR-001..FR-005, and SC-001..SC-003.
Torch compile gate and engine env comments
backend/services/engine_env.py
Adds should_torch_compile(device: str) using importlib.util.find_spec("triton") and a settings lookup to decide compilation; updates build_engine_env() comments to clarify subprocess TORCH_COMPILE_DISABLE remains user-driven.
Model loader integration
backend/services/model_manager.py
Model loader now calls should_torch_compile(device) before applying torch.compile (replaces previous device-only check).
Tests for gating logic
tests/test_torch_compile_gate.py
Adds unit tests asserting should_torch_compile returns False for non-CUDA devices, False when Triton missing, True when Triton present and not disabled, and False when settings disable compilation.
ASR critical-path smoke test
scripts/smoke-test.sh
Adds INST-02 step importing torch, ctranslate2, and whisperx to fail CI installs missing ASR dependencies.

Sequence Diagram(s)

sequenceDiagram
  participant ModelLoader
  participant EngineEnv
  participant TritonDetector
  participant Settings

  ModelLoader->>EngineEnv: should_torch_compile(device)
  EngineEnv->>TritonDetector: importlib.util.find_spec("triton")
  TritonDetector-->>EngineEnv: present|missing
  EngineEnv->>Settings: settings_store.get_text("perf.torch_compile_disabled")
  Settings-->>EngineEnv: "0"|"1"|error
  EngineEnv-->>ModelLoader: True|False
  ModelLoader->>ModelLoader: apply torch.compile if True else skip
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

  • #65: [Bug] torch.compile on Windows causes TTS OOM due to missing Triton — This PR implements the Triton availability check proposed to avoid runtime Triton dependency failures.
  • #129: Similar Triton-based gate and ASR smoke import — appears related or overlapping with this change.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix(windows): gate torch.compile on Triton + ASR critical-path smoke (plan-02, closes #65)' is specific and directly describes the main change—adding a Triton availability gate for torch.compile and a smoke test for ASR dependencies.
Description check ✅ Passed The PR description includes a comprehensive summary, clear fixes, cross-platform parity explanation, test coverage details, and references to spec/plan/tasks documentation, though it omits explicit checklist items from the template.
Linked Issues check ✅ Passed The PR fully implements the requirements from issue #65: a Triton availability gate via should_torch_compile() using importlib.util.find_spec(), fallback to eager mode, and comprehensive test coverage with 4 test cases validating the gating logic.
Out of Scope Changes check ✅ Passed All changes are directly aligned with the objectives: the should_torch_compile() helper, model_manager.py integration, INST-02 smoke test, and test coverage specifically address issue #65 and Windows runtime integrity. No extraneous changes detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 003-windows-runtime-integrity

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@ecc-tools

ecc-tools Bot commented May 29, 2026

Copy link
Copy Markdown

Analyzing 200 commits...

@ecc-tools

ecc-tools Bot commented May 29, 2026

Copy link
Copy Markdown

Analysis Complete

Generated ECC bundle from 1 commits | Confidence: 50%

View Pull Request #139

Repository Profile
Attribute Value
Language Python
Framework Not detected
Commit Convention conventional
Test Directory separate
Changed Files (7)
Metric Value
Files changed 7
Additions 229
Deletions 1

Top hotspots

Path Status +/-
specs/003-windows-runtime-integrity/spec.md added +79 / -0
specs/003-windows-runtime-integrity/plan.md added +44 / -0
tests/test_torch_compile_gate.py added +37 / -0
backend/services/engine_env.py modified +30 / -0
specs/003-windows-runtime-integrity/tasks.md added +22 / -0

Top directories

Directory Files Total changes
specs/003-windows-runtime-integrity 3 145
backend/services 2 38
tests 1 37
scripts 1 10
Analysis Depth Readiness (commit-history, 21%)

ECC Tools uses this to decide whether recommendations should stay at commit-history/setup guidance or expand into CI, security, harness, reference-set, AI-routing, and team backlog work.

Area Status Evidence / Next Step
Commit history Partial 1 commits sampled
CI/CD signals Missing Add workflow files or CI troubleshooting evidence so ECC Tools can reason about pipeline setup.
Security evidence Missing Add AgentShield, audit, SARIF, SBOM, or security review evidence so recommendations can cover security posture.
Harness configuration Missing Add Claude, Codex, OpenCode, Zed, dmux, MCP, plugin, or cross-harness config evidence for harness-agnostic recommendations.
Reference/eval evidence Missing Add fixtures, golden traces, reference sets, or evaluator benchmarks so deeper recommendations have regression evidence.
AI routing and cost controls Ready specs/003-windows-runtime-integrity/plan.md
Team handoff and project tracking Missing Add roadmap, runbook, project, Linear, or follow-up tracking docs so generated work can land in a team queue.
Reference Set Readiness (0/7, 0%)
Area Status Evidence / Next Step
Deep analyzer corpus Missing Add analyzer fixture, golden, benchmark, or reference-set files that can catch analyzer regressions.
RAG/evaluator comparison Missing Add retrieval or evaluator reference-set comparison fixtures with expected ranking behavior.
PR salvage/review corpus Missing Add stale-PR, review-thread, reopen-flow, or salvage reference cases for queue cleanup automation.
Discussion triage corpus Missing Add public discussion triage fixtures, golden cases, or reference sets for informational, answered, and no-response classifications.
Harness compatibility Missing Add cross-harness, adapter-compliance, or harness-audit evidence for Claude, Codex, OpenCode, Zed, dmux, and agent surfaces.
Security evidence Missing Attach security evidence such as SBOMs, SARIF, audit reports, or AgentShield evidence packs.
CI failure-mode evidence Missing Add captured CI failure logs, dry-run fixtures, or troubleshooting docs for common workflow failure modes.
Generated Instincts (15)
Domain Count
git 4
code-style 9
testing 2

After merging, import with:

/instinct-import .claude/homunculus/instincts/inherited/OmniVoice-Studio-instincts.yaml

Files

  • .claude/ecc-tools.json
  • .claude/skills/OmniVoice-Studio/SKILL.md
  • .agents/skills/OmniVoice-Studio/SKILL.md
  • .agents/skills/OmniVoice-Studio/agents/openai.yaml
  • .claude/identity.json
  • .codex/config.toml
  • .codex/AGENTS.md
  • .codex/agents/explorer.toml
  • .codex/agents/reviewer.toml
  • .codex/agents/docs-researcher.toml
  • .claude/homunculus/instincts/inherited/OmniVoice-Studio-instincts.yaml

ECC Tools | Everything Claude Code

@greptile-apps

greptile-apps Bot commented May 29, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Fixes two Windows inference-time failures: the torch.compile/Triton crash (#65) via a new should_torch_compile() gate in engine_env.py, and the pkg_resources/ctranslate2 mid-transcription ModuleNotFoundError (#116) via a new INST-02 smoke-test step. The gate correctly requires device=="cuda" + find_spec("triton") is not None + the user setting before compiling; model_manager.py calls it instead of the bare device check.

  • engine_env.should_torch_compile(device) — three-condition guard; returns False (eager) with an INFO log on any unmet condition; settings read errors are non-fatal by design.
  • model_manager.py — single-line call-site change; existing try/except backstop for compile failures is preserved.
  • scripts/smoke-test.sh INST-02 — imports torch, ctranslate2, and whisperx at build time so a missing transitive dep fails CI rather than the user's run.
  • tests/test_torch_compile_gate.py — four unit tests covering all gate branches with correct monkeypatch patterns.

Confidence Score: 5/5

Safe to merge — the change is a targeted guard on an existing torch.compile call site, with a correct eager fallback, documented design decisions, and four unit tests covering all branches.

The gate logic in should_torch_compile is straightforward and correct: three independent conditions, each with an explicit fallback and log. The call-site change in model_manager.py is minimal. The smoke-test addition follows the existing INST-01 pattern exactly. The only outstanding item is a stale module-docstring attribution, which has no runtime impact.

No files require special attention beyond the minor docstring clarification in engine_env.py.

Important Files Changed

Filename Overview
backend/services/engine_env.py Adds should_torch_compile(device) gating on CUDA + Triton availability + user setting; updates the build_engine_env comment to explain the intentional subprocess-only design. Module-level docstring still attributes #65 to build_engine_env, which is misleading.
backend/services/model_manager.py Replaces bare device == 'cuda' guard with should_torch_compile(device) call; existing try/except backstop for compile failures is preserved. Change is minimal and correct.
scripts/smoke-test.sh Adds INST-02 check importing torch, ctranslate2, and whisperx to catch missing transitive deps at build time. Consistent with INST-01 pattern.
tests/test_torch_compile_gate.py Four unit tests cover all gate branches: non-CUDA, Triton missing, Triton present+enabled, and user-disabled. Monkeypatching is correct for the lazy-import pattern used in should_torch_compile.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[model_manager._load_model_sync] --> B{should_torch_compile device}
    B --> C{device == cuda?}
    C -- No --> D[Return False eager mode]
    C -- Yes --> E{find_spec triton is None?}
    E -- Yes --> F[Return False log: Triton unavailable]
    E -- No --> G{perf.torch_compile_disabled == 1?}
    G -- Yes --> H[Return False log: disabled in Settings]
    G -- No --> I[Return True]
    G -- read error --> I
    I --> J[torch.compile mode=reduce-overhead]
    D & F & H --> K[Eager mode no compile]
Loading

Fix All in Claude Code

Reviews (3): Last reviewed commit: "revert(engine_env): keep subprocess TORC..." | Re-trigger Greptile

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
tests/test_torch_compile_gate.py (1)

28-37: ⚡ Quick win

Optional: cover the documented "settings read fails → proceed" path.

The spec/edge-case and the helper's except branch guarantee that a settings_store read failure should not block compile (returns True, logged). That behavioral guarantee currently has no test.

💚 Proposed test
 def test_skips_when_disabled_in_settings(monkeypatch):
     monkeypatch.setattr(importlib.util, "find_spec", lambda name: object())
     monkeypatch.setattr("services.settings_store.get_text", lambda key, default="0": "1")
     assert engine_env.should_torch_compile("cuda") is False
+
+
+def test_proceeds_when_settings_read_fails(monkeypatch):
+    monkeypatch.setattr(importlib.util, "find_spec", lambda name: object())
+
+    def _boom(*_a, **_k):
+        raise RuntimeError("settings unreadable")
+
+    monkeypatch.setattr("services.settings_store.get_text", _boom)
+    assert engine_env.should_torch_compile("cuda") is True
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_torch_compile_gate.py` around lines 28 - 37, Add a test in
tests/test_torch_compile_gate.py that simulates a failing settings read: patch
importlib.util.find_spec to return a non-None value (to simulate Triton present)
and monkeypatch services.settings_store.get_text to raise an exception, then
assert engine_env.should_torch_compile("cuda") returns True; name the test e.g.
test_proceeds_when_settings_read_fails and (optionally) assert that the code
logs the fallback behavior. This ensures the except branch in
engine_env.should_torch_compile is covered.
scripts/smoke-test.sh (1)

337-341: ⚡ Quick win

Surface the import error on failure to keep CI actionable.

2>/dev/null discards the traceback, so a failing INST-02 only prints the generic "packaged venv incomplete" message without telling you which of torch/ctranslate2/whisperx failed or why. Since the whole point of this step is to catch missing transitive deps early, capturing and echoing stderr on failure makes CI logs self-diagnosing. (INST-01 above has the same pattern and could benefit too.)

♻️ Capture and print stderr on failure
 TESTS=$((TESTS + 1))
-if uv run python -c "import torch; import ctranslate2; import whisperx" 2>/dev/null; then
+INST02_ERR=$(uv run python -c "import torch; import ctranslate2; import whisperx" 2>&1)
+if [ $? -eq 0 ]; then
     pass "INST-02: ASR critical path (torch, ctranslate2, whisperx) imports OK"
 else
     fail "INST-02: ASR critical path import failed (torch/ctranslate2/whisperx) — packaged venv incomplete"
+    echo "$INST02_ERR" | tail -10 | sed 's/^/     /'
 fi

Note: assigning to INST02_ERR makes the command's own exit status $? reflect the assignment, but since uv run is the only command in the substitution, $? still carries its exit code here. If you prefer to be explicit/robust under set -e, split the capture and the status check.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/smoke-test.sh` around lines 337 - 341, The INST-02 check currently
swallows stderr by using "2>/dev/null" on the "uv run python -c 'import torch;
import ctranslate2; import whisperx'" command; remove the redirection and
capture the command's stderr (e.g., via command substitution like
INST02_ERR="$(uv run python -c '... ' 2>&1')" or run then save "$?"/stderr
separately) and on failure print the captured stderr alongside the existing fail
message so CI shows which import failed and why; update the INST-02 branch that
mentions "ASR critical path" to echo INST02_ERR when the import command fails.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@scripts/smoke-test.sh`:
- Around line 337-341: The INST-02 check currently swallows stderr by using
"2>/dev/null" on the "uv run python -c 'import torch; import ctranslate2; import
whisperx'" command; remove the redirection and capture the command's stderr
(e.g., via command substitution like INST02_ERR="$(uv run python -c '... '
2>&1')" or run then save "$?"/stderr separately) and on failure print the
captured stderr alongside the existing fail message so CI shows which import
failed and why; update the INST-02 branch that mentions "ASR critical path" to
echo INST02_ERR when the import command fails.

In `@tests/test_torch_compile_gate.py`:
- Around line 28-37: Add a test in tests/test_torch_compile_gate.py that
simulates a failing settings read: patch importlib.util.find_spec to return a
non-None value (to simulate Triton present) and monkeypatch
services.settings_store.get_text to raise an exception, then assert
engine_env.should_torch_compile("cuda") returns True; name the test e.g.
test_proceeds_when_settings_read_fails and (optionally) assert that the code
logs the fallback behavior. This ensures the except branch in
engine_env.should_torch_compile is covered.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 6cd006e2-b3f0-4e49-a176-7473ab0ccc9d

📥 Commits

Reviewing files that changed from the base of the PR and between fa9c7d4 and 3a158a2.

📒 Files selected for processing (7)
  • backend/services/engine_env.py
  • backend/services/model_manager.py
  • scripts/smoke-test.sh
  • specs/003-windows-runtime-integrity/plan.md
  • specs/003-windows-runtime-integrity/spec.md
  • specs/003-windows-runtime-integrity/tasks.md
  • tests/test_torch_compile_gate.py

…138)

Greptile flagged that the in-process gate left a parallel gap: engine
subprocesses honour TORCH_COMPILE_DISABLE, but build_engine_env() only set
it on the user's Performance toggle — so a Triton-absent host (Windows, or
macOS) still exposed subprocess engines to the same crash this PR fixes
in-process.

- build_engine_env(): set TORCH_COMPILE_DISABLE=1 when the user disabled
  compile OR Triton is unavailable (find_spec), cross-platform — mirrors
  should_torch_compile(). Drops the Windows-only scoping (and the now-unused
  `import sys`).
- Refreshed the stale module docstring.
- 3 new tests cover the subprocess gate (triton-missing, triton-present,
  user-opt-out). 7/7 pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@debpalash

Copy link
Copy Markdown
Owner Author

Addressed both observations in dec971d: build_engine_env() now sets TORCH_COMPILE_DISABLE=1 when the user disabled compile or Triton is unavailable (find_spec), cross-platform — so subprocess engines get the same gate as the in-process path. Also refreshed the stale module docstring and dropped the now-unused import sys. Added 3 tests for the subprocess gate (7/7 pass).

Reverts the build_engine_env() broadening from the previous commit. Auto-
disabling subprocess torch.compile on Triton-absence conflicts with a
deliberate, tested contract (test_perf_settings: Windows + flag-off ⇒ no
injection; non-Windows ⇒ never inject) — the subprocess var is intentionally
under the user's explicit control.

The #65 fix is the in-process should_torch_compile() gate (unchanged here),
which IS automatic and fully tested. Pushing back on the subprocess auto-gate
as a separate, deliberate contract change rather than forcing it through by
rewriting established tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@debpalash

Copy link
Copy Markdown
Owner Author

Update on the subprocess-gate observation: I implemented it, but it conflicts with a deliberate, tested contract — tests/backend/test_perf_settings.py asserts the subprocess TORCH_COMPILE_DISABLE var is user-toggle-driven only (Windows + flag-off ⇒ no injection; non-Windows ⇒ never injected). Auto-disabling on Triton-absence would override the user's explicit control and rewrite that contract. So I've reverted that part and kept the in-process should_torch_compile() gate, which is the actual #65 fix and is automatic + fully tested. If auto-gating subprocess engines is desired, that's a separate deliberate change to the contract + its tests — happy to do it if the maintainer wants it. Docstring + unused-import notes are resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] torch.compile on Windows causes TTS OOM due to missing Triton

1 participant