Skip to content

refactor: one table owns every value warmed into a specialist - #1887

Merged
chaojhou merged 1 commit into
mainfrom
fix/chenyi/specialist-export-one-table
Oct 17, 2026
Merged

chaojhou merged 1 commit into
mainfrom
fix/chenyi/specialist-export-one-table

Conversation

@chennyiiis

Copy link
Copy Markdown
Contributor
  • Description: what and why

Follow-up to review feedback on #1881 (finding 2, export-rule). The per-field export rule in warm_specialist_params was still spelled three ways: _STATE_PARAMS for values exported when truthy, _POSITIVE_NUMBER_PARAMS for numbers exported when above zero, and a branch of its own for the framework name because that one is stripped first. The reviewer is right that this is one rule written three times.

Converting before the test collapses them: an empty string, an empty container and a zero all read as nothing to export. The second table and the framework branch go, and framework becomes an ordinary row with str.strip as its conversion.

The getattr(state, attr, None) / or 0 defaults go with them. Every field in the table is declared on SharedState, so a missing attribute is a programming error worth raising rather than a silent skip (AGENTS.md Trust the caller).

  • Linked issue(s): close/fix refs

Review feedback on #1881.

  • Tests: added/updated? commands run?

test_warm_specialist_params_fills_defaults is deleted as superseded, per review finding 3. Its three assertions are carried across rather than dropped: tp is covered by the table test, and gpu_type and kb_subgraph move into test_warm_specialist_params_always_writes_the_unconditional_keys together with keep_threshold_pct, which the reviewer asked be taken out of the "omits an empty field" test. Those two keys and kb_subgraph are written whatever the session holds, so a specialist reads them without a presence test; that is a contract, not an implementation detail, and it now has a test that says so instead of two asserts lodged in a test about something else.

The one suggestion not taken: driving the table tests from the production _STATE_PARAMS. A test that reads the table it is checking cannot catch a wrong row, so the test keeps its own literal table.

Run locally: pytest over test_coordinator_async_methods_coverage_unit.py, test_coordinator_async_batch2_unit.py, test_specialist_integration.py, test_specialist_lessons_section.py, test_custom_specialist.py, test_experience_kb_integration.py, test_specialist_roofline_evidence.py, test_specialist_runtime_findings.py, test_gaps_field.py, test_bringup_round_scenario.py - 376 passed.

  • Size/complexity triggers crossed: split, or why the shape is right:
unit cyclomatic cognitive function-lines
warm_specialist_params 45 to 41 109 to 102 188 to 180

Already over, lowered again, no new unit. Measured with the pinned ruff 0.16.2, complexipy 8.0.1 and the gate own collectors.

  • If this simplifies or refactors: which mechanism was removed, which contract was preserved, and the tests that show it:

Removed: a second export rule and a third spelling of it, plus the getattr defaults that could never fire. Preserved: every value a specialist is warmed with, bar the one effect below, pinned by the table test that already existed.

  • Observable effect:

A negative tp, conc, isl, osl, max_model_len or baseline_tput is now exported to the specialist rather than dropped. None of those fields has a negative sentinel - a negative value there is already a broken session, and an operator debugging one now sees it in the specialist's params instead of seeing a field that looks unset.

  • Breaking changes: no

  • PR addresses single concern: yes

  • Root cause is upstream: no

…alist

The per-field export rule was spelled three ways: a table for values exported
when truthy, a second for numbers exported when above zero, and a branch of its
own for the framework name because that one is stripped first. Converting
before the test makes them one rule and one table -- an empty string, an empty
container and a zero all read as nothing to export -- so the second table and
the framework branch go.

The `getattr` defaults go with them: every field in the table is declared on
SharedState, so a missing attribute is a programming error worth raising rather
than a silent skip.

Cyclomatic complexity of warm_specialist_params drops from 45 to 41, cognitive
from 109 to 102, and its length from 188 lines to 180.

Observable effect: a negative `tp`, `conc`, `isl`, `osl`, `max_model_len` or
`baseline_tput` is now exported rather than dropped. None of those fields has a
negative sentinel -- a negative value there is already a broken session, and it
is now visible to the specialist instead of looking like an unset field.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Code metrics gate: PASSED

Judged: the 3 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 0 0 73 +0
Cognitive complexity fails > 30 0 0 0 289 +0
Function length (lines) fails > 80 0 0 0 453 +0
Nested block depth fails > 5 0 0 0 27 +0
Module length (lines) warns > 800, fails > 1200 0 0 0 53 +0
Duplicated lines per file fails > 0 0 0 0 120 +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 0
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

Module length warning: over 800 lines, within the 1200-line failure limit (not failing): 1

Module Lines Limit
src/hyperloom/orchestrator/specialists/dispatch.py 1054 warns > 800
88 findings in files this change does not touch

Outside this change (informational): 88

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 63 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.

@chaojhou chaojhou left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

PR #1887 -- refactor: one table owns every value warmed into a specialist

What it does: warm_specialist_params spelled one export rule ("hand a SharedState value to a specialist only when the session has one") three ways: a truthy table, a separate above-zero table for numbers, and an inline strip branch for framework. The PR converts each value before the truthiness test, so framework, tp, conc, isl, osl, max_model_len and baseline_tput become ordinary rows of _STATE_PARAMS. The second table, the framework branch and the unreachable getattr/or 0 defaults are deleted. The one observable change is stated in the description: a negative workload number is now exported instead of dropped.

Blocking issues: none

Checked: src/hyperloom/orchestrator/specialists/dispatch.py (_STATE_PARAMS, warm_specialist_params at head), src/hyperloom/orchestrator/state/shared_state.py (field declarations 345-804, from_dict), every in-tree writer of the 16 exported fields (cli/bootstrap.py, loop/writeback.py, knowledge/recipe_kb_t0.py), the 12 callers of warm_specialist_params, test_coordinator_async_methods_coverage_unit.py (_STATE_EXPORTS and the warm_specialist_params tests), scripts/code_metrics_baseline.txt, overlapping #1883 | Ran: import of head _STATE_PARAMS + SharedState from a git archive of the head (default state exports nothing; tp=-1 is exported), git grep / git log -S for None writers and Optional annotations; scoped pytest SKIPPED (pytest not installed locally; CI test shards green at head); ruff C901 SKIPPED locally (ruff not installed; code-metrics gate passed at head with 45 -> 41) | SKIPPED: V4 -- files past the first 100 of #1869/#1675/#1276/#1154/#1032 not compared | Base: 190604f | Head: 8cccef8

LGTM

@chaojhou
chaojhou merged commit 7707930 into main Oct 17, 2026
40 checks passed
@chaojhou
chaojhou deleted the fix/chenyi/specialist-export-one-table branch October 17, 2026 04:48
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.

2 participants