Skip to content

fix(hyperloom): classify engine capacity start failures - #1926

Open
kxyk99 wants to merge 1 commit into
AMD-AGI:mainfrom
kxyk99:fix/engine-capacity-class
Open

kxyk99 wants to merge 1 commit into
AMD-AGI:mainfrom
kxyk99:fix/engine-capacity-class

Conversation

@kxyk99

@kxyk99 kxyk99 commented Oct 16, 2026

Copy link
Copy Markdown
  • Description: vLLM logs EngineCore failed to start before its traceback, so the legacy server.log excerpt (two lines of context after a _SERVER_DEAD_MARKERS hit) ended at the first frame and dropped the ValueError that names the cause. The failure was recorded as server_init_dead, mapped to engine_core_init in the report, and left unknown by the log classifier. A baseline that dies on max_num_seqs (256) exceeds available Mamba cache blocks (237) is the example.
    • _subprocess_kill: a legacy marker now also keeps the exception lines in the 60 lines below it (nearest first, within max_chars); output is unchanged when none is present. New engine_capacity_cause() recognises the Mamba cache block, KV cache memory and empty KV cache errors and parses their numbers.
    • baseline and the grid runner assign engine_capacity ahead of server_init_dead (after aiter_jit_registry_mismatch and cuda_graph_capture_failed, so the eager-fallback retry is unchanged). The baseline record carries capacity: {kind, requested, available} and the ValueError line in error.
    • report: root_cause_type is engine_capacity and the headline is the capacity line. failure_signature: three patterns added to the existing RESOURCE_CONSTRAINT rule (no new kind, ladder.py already maps it), so the text is not a kernel or architecture gap.
    • Not changed: failure_evidence (stays unknown for the class, pinned by a test), recipe_journal, bypass_analysis, kernel/conc_sweep.
  • Linked issue(s): none filed.
  • Tests: 14 new tests: excerpt keeps the cause below the marker, parser (Mamba, KV memory, empty KV, 5 negatives), baseline with and without a benchmark_* workspace, grid runner watchdog path, report root_cause_type and headline, signature kind, attribution stays unknown. On main they fail (assertion failures, plus an import error for engine_capacity_cause). The six touched test files pass on current main with this change: 352 passed (python -m pytest on those six files).
  • Size/complexity triggers crossed: none assessed beyond the file count (11 files, tests included); the parts are one failure class threaded through one path.
  • Simplifies or refactors: no.
  • Observable effect: the baseline described above now reports error_class=engine_capacity with the cause line and the numbers, instead of server_init_dead with an excerpt ending at core.py ... run_engine_core. Other server_init_dead records gain the exception lines that followed their marker.
  • Breaking changes: no. server_init_dead consumers still receive it for every non-capacity failure. engine_capacity flows through the generic failure path (streak, launch log) like server_init_dead did.
  • PR addresses single concern: yes.
  • Root cause is upstream (Magpie/TraceLens/GEAK/IntelliKit/AgentKernelArena), ticket filed: no. vLLM's behaviour is by design (default max_num_seqs 256 below 70 GiB, check after KV cache sizing); the missing class is in Hyperloom.

vLLM logs "EngineCore failed to start" ahead of its traceback, so the
legacy server.log excerpt (two lines of context) ended at the first
frame and dropped the ValueError that names the cause. The failure was
recorded as server_init_dead, mapped to engine_core_init in the report
and left unclassified by the log classifier.

- Keep the exceptions named in the 60 lines below a legacy marker.
- Add engine_capacity_cause for the Mamba cache block, KV cache memory
  and empty KV cache errors; baseline and the grid runner assign
  engine_capacity ahead of server_init_dead and the baseline record
  carries the parsed numbers in "capacity".
- Report maps the class to root_cause_type engine_capacity and quotes
  the capacity line; the log classifier files the text under
  resource_constraint, not a kernel or architecture gap.
@kxyk99
kxyk99 requested a review from a team as a code owner October 16, 2026 06:30
@mehdi-saeedi
mehdi-saeedi requested a review from chaojhou October 16, 2026 12:06
@github-actions

Copy link
Copy Markdown

Gate job conclusion: failure (run) on f6698515c4447c49ac02415da465d2caa655799f, as reported by GitHub.

The report below was uploaded by that run; the conclusion above is the result.


Code metrics gate: FAILED

Judged: the 11 files this change touches. Files it does not touch never fail it; anything found there is listed under Outside this change for information.

Dimension Limit New Worse Baseline out of date Baseline entries vs base
Cyclomatic complexity fails > 20 0 1 0 72 +0
Cognitive complexity fails > 30 0 2 0 284 +0
Function length (lines) fails > 80 0 2 0 449 +0
Nested block depth fails > 5 0 0 0 27 +0
Module length (lines) warns > 800, fails > 1200 1 3 0 53 +0
Duplicated lines per file fails > 0 0 0 0 118 +0
Dead code (vulture) fails > 0 0 0 0 2 +0
Check Findings Effect
Comments 0
English only 0
Production code imports test code 0
Repeated literals 2 fails
A1 Private name of another package 0
A8 Flag argument 0
A9 Tuple return 0
A10 Raw vocabulary comparison 0
A11 Hidden global write 0
A12 Pure forwarder 0
A12 Single-implementation abstraction 0

New violations (not in the baseline): 1

Unit Dimension Value Limit
src/hyperloom/orchestrator/actions/executors/_subprocess_kill.py:1 Module length (lines) 1203 fails > 1200

Worse than the baseline: 8

Unit Dimension Baseline Now
src/hyperloom/orchestrator/actions/executors/_grid_runner.py:873 run_grid Cognitive complexity 196 199
src/hyperloom/orchestrator/actions/executors/baseline.py:3371 BenchmarkRunExecutor._run_single_benchmark Cognitive complexity 120 126
src/hyperloom/orchestrator/actions/executors/baseline.py:3371 BenchmarkRunExecutor._run_single_benchmark Cyclomatic complexity 39 41
src/hyperloom/orchestrator/actions/executors/_grid_runner.py:873 run_grid Function length (lines) 1040 1041
src/hyperloom/orchestrator/actions/executors/baseline.py:3371 BenchmarkRunExecutor._run_single_benchmark Function length (lines) 578 596
src/hyperloom/orchestrator/actions/executors/_grid_runner.py:1 Module length (lines) 2247 2250
src/hyperloom/orchestrator/actions/executors/baseline.py:1 Module length (lines) 4253 4308
src/hyperloom/orchestrator/actions/executors/report.py:1 Module length (lines) 1391 1397

Repeated literals: 2

Where Problem
src/hyperloom/orchestrator/actions/executors/baseline.py:3787 'engine_capacity' is written 3 times (was 0); name it as a module-level constant
src/hyperloom/orchestrator/actions/executors/report.py:97 'engine_capacity' is written 3 times (was 0); name it as a module-level constant

How to fix

  • New or worse: split the unit (extract a function, a class, a module) until it is back under the limit, or no worse than its recorded value. The baseline cannot absorb a new violation: CI refuses any baseline entry added or raised relative to the base branch.
  • Baseline out of date: something improved. Run python scripts/code_metrics.py --update-baseline and commit scripts/code_metrics_baseline.txt; the command only lowers or removes entries.
  • Repeated literals: name the value once as a module-level constant and use the name.
  • Override: the baseline-raise PR label waives new, worse and baseline-growth findings and the failing design checks (they stay listed here). Use it only with the reason in the PR description; it waives nothing else.
  • Tools for a local run: pip install ruff==0.16.2 complexipy==8.0.1 vulture==2.16 and npm install -g jscpd@5.4.1 (or point CODE_METRICS_JSCPD at another jscpd command, such as npx --yes jscpd@<version>).

Already over at the base (backlog, not this change's): 1

Unit Dimension Base Now
src/hyperloom/orchestrator/actions/executors/baseline.py:2309 BenchmarkRunExecutor._run_once Function length (lines) 683 683
93 findings in files this change does not touch

Outside this change (informational): 93

Unit Dimension Baseline Now
src/hyperloom/orchestrator/enablement/recipe/projections.py project_launch_evidence Cognitive complexity absent 36
src/hyperloom/orchestrator/state/shared_state.py resolve_graded_comparison Cognitive complexity absent 34
src/hyperloom_kb/collect/mapping.py _experience Cognitive complexity absent 31
src/hyperloom_kb/schema.py FieldDeclaration.__post_init__ Cognitive complexity absent 32
src/kernelforge/cli/forge_loop_command.py _prepare_measurement_driver Cognitive complexity absent 36
src/kernelforge/cli/forge_loop_command.py _read_kb_warm_start Cognitive complexity absent 40
src/kernelforge/loop/runner.py IterationLoop._collect_session_candidate Cognitive complexity absent 44
src/kernelforge/loop/runner.py IterationLoop._rule_on_attempt Cognitive complexity absent 38
src/hyperloom_kb/tests/test_cli.py Duplicated lines per file absent 18
src/hyperloom_kb/tests/test_global_identity_and_pull.py Duplicated lines per file absent 13
src/hyperloom_kb/tests/test_local_state.py Duplicated lines per file absent 18
src/hyperloom/inference_optimizer/cli/__init__.py _reexport_session_environment Function length (lines) absent 112
src/hyperloom/inference_optimizer/cli/__init__.py _resolve_agent_lineup Function length (lines) absent 89
src/hyperloom/inference_optimizer/cli/__init__.py _resolve_run_topology Function length (lines) absent 92
src/hyperloom/inference_optimizer/cli/__init__.py _resume_session Function length (lines) absent 171
src/hyperloom/inference_optimizer/cli/__init__.py _seed_fresh_session Function length (lines) absent 183
src/hyperloom/inference_optimizer/multi_node/cli.py _restart_multinode Function length (lines) absent 107
src/hyperloom/inference_optimizer/multi_node/scripts/launch_multinode.py _build_parser Function length (lines) absent 84
src/hyperloom/inference_optimizer/multi_node/scripts/launch_multinode.py _spawn_rank_actors Function length (lines) absent 90
src/hyperloom_kb/http_service.py RequestHandler._dispatch Function length (lines) absent 91
src/hyperloom_kb/sync.py GlobalSync.pull Function length (lines) absent 86
src/kernelforge/cli/forge_loop_command.py _RunReporter.build_result Function length (lines) absent 91
src/kernelforge/cli/forge_loop_command.py _prepare_measurement_driver Function length (lines) absent 140
src/kernelforge/cli/forge_loop_command.py _read_kb_warm_start Function length (lines) absent 154
src/kernelforge/loop/knowledge_integration.py _measure_warmstart_field Function length (lines) absent 83

...and 68 more; the job log lists every row.

Verdict computed by the gate scripts in /home/runner/work/_temp/code-metrics-gate, not by this tree's copy.

Thresholds and sources: [tool.hyperloom.code_metrics] in pyproject.toml. Tools: complexipy 8.0.1, jscpd 5.4.1, ruff 0.16.2, vulture 2.16.

This branch has not been deployed

No deployments
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.

1 participant