Skip to content

[fix] close the defects behind the MuseSpark run shortfall and delete state nothing reads - #2055

Merged
xiaofei-zheng merged 49 commits into
mainfrom
fix/zgong/bringup-read-whole-log
Oct 21, 2026
Merged

xiaofei-zheng merged 49 commits into
mainfrom
fix/zgong/bringup-read-whole-log

Conversation

@ZhengGong-amd

@ZhengGong-amd ZhengGong-amd commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator

Description

A 660-minute MuseSpark-1.2 run (816B MoE MXFP4, 8× MI355X, TP=8) finished at +5.99% against a 10% target. Tracing
that run back through the code found defects in five areas: what a KEEP is judged against, how a phase decides it is
done, what lease expiry claims to do, whether a dead lever can be seen as dead, and how the kernel arm is credited.
This PR fixes the defects that have a fix in the existing infrastructure, and deletes the mechanisms that were
verified to have no function (no reader, a constant value, or an unreachable branch). Each removal was checked for a
live path and a real effect; mechanisms with a live path that changes behaviour were kept and fixed instead.

GEAK and Forge are both kept as first-class kernel backends; nothing here weakens either route.

Every commit is one concern and its message states what an operator now sees. The branch is rebased onto
origin/main at b772e9434 (no merge commit).

Reconciliation with origin/main

The rebase was checked commit by commit against main for semantic overlap, not only textual conflicts:

Review follow-ups

  • failure_region could cut the failing line out (fixed, fix(bringup): start the failure region at the first line of the furthest milestone): milestone markers repeat per TP rank and while serving (GPU KV cache usage),
    so a later repeat could start the region after a rank's fatal line and lose its failure kind and env_fault. The
    region now starts at the first line of the furthest milestone reached; a test pins the reverse ordering.
  • Bring-up classification on the event loop (fixed, fix(bringup): classify a boot off the event loop): the
    baseline and integrate-bench observations now run in a worker thread. The previous edge-plus-milestone reader also
    streamed the whole log synchronously, so the loop placement predates this PR; the read stays whole because a root
    traceback can sit megabytes above the tail.
  • SWEEP doc still said the phase exits on sweep_done (fixed, docs(sweep): …).
  • output_throughput rename without a major bump: resolved by fix(breakdown): rename throughput_tok_s_per_gpu to output_throughput (schema 6.1) and record per-GPU output on baseline and validation rows #2023 (schema 6.1); this branch's copy is dropped.
  • Empty except flagged by code scanning (fixed, test(geak): …).

Bring-up classification

  • The server log is read whole for classification, so a milestone or a worker's root traceback megabytes into the log
    is no longer lost between fixed edge windows; the failure rules read only the region from the furthest milestone
    reached to the root traceback, so a rule match the process ran past (an autotuner's rejected config) does not name
    the failure. Classification runs off the event loop.

Measurement and KEEP

  • An agent's keep_threshold_pct can only raise the session's KEEP bar. A lower, negative or non-finite value is
    replaced by the session bar; before, 0 kept any non-negative gain and a negative value kept regressions.
  • assess_convergence is deleted: it always returned insufficient_rounds and nothing read it.
  • optimization_journal.json is read through the journal module only; failure attribution is carried from explore
    instead of being re-derived.

Phase state machine

  • When a further macro-cycle is refused, SWEEP closes on the real reason (global_converged for saturated
    directions, time_exhausted for too little time) instead of sweep_done.
  • Under --no-kernel, FRAMEWORK_AGENT's own exit reason is kept; the skip is marked kernel_skipped: true.
  • The unread predicate_inputs.phase_budget_pct and the 1000 macro-cycle ceiling are removed.

Leases and cancellation

  • prune_branch now expands a catalogue family (prep, shallow, …) into its member actions; before, pruning a
    family the prompt showed cancelled nothing. Proposing a member of a pruned family draws the pruned-action advisory.
  • After SIGKILL, draining a GEAK tree's pipes stops after 10 s instead of possibly blocking forever.
  • The unpublished lease_expired topic, gpu_pool.extend and the uncalled per-lease heartbeat are deleted; four
    docstrings that promised lease reclamation now say what the code does.

Lever liveness (FRAMEWORK_AGENT)

  • Empty and undispatchable authoring rounds now write an attempt row on the source lever, so a source arm that keeps
    coming back empty is seen as dry and the phase can leave on its plateau rule. In the audited run the arm was dead
    from the start and FRAMEWORK_AGENT could only leave on its budget.
  • The local-exploration arm stops dispatching once the source lever is dry.
  • A review that times out now settles the proposal in the session breakdown, matching the event log.
  • Preflight's agent-CLI warning tells the truth (no HTTP fallback exists): it resolves the CLI of the selected
    backend and warns no claude CLI / no codex CLI; specialists cannot start without it (assets/install.sh).
  • Claude specialists no longer load the operator's ~/.claude settings (--setting-sources=).
  • Deleted: three getattr switches that read attributes SharedState never had, the source_patch prune flag
    (a cached copy of a deterministic preflight), a broad except Exception: pass.

Kernel arm

  • A GEAK result whose config restates current_best and brings no loadable artifact settles as
    geak_no_material before any benchmark; in the audited run that no-op rebench cost 16.7 minutes.
  • The GEAK-harness replay is decided on Hyperloom's measurement, not on GEAK's self-reported throughput_speedup;
    GEAK's self-reported e2e_delta_pct no longer filters which accepted kernels go to the rebench.
  • The 5% hot-kernel gate counts a kernel as tried once either backend produced something for it. Before, "tried" was
    read from a ledger nothing wrote, so kernel_work_pending stayed true for any ≥5% kernel.
  • kernel_optimization_summary.json is built from the timeline's V6KernelAttempt records; GEAK success means
    "adopted by Hyperloom's rebench", and GEAK's own acceptances appear as claimed.
  • A roofline run whose trace was salvaged from a failed profile reports recovered, not succeeded.
  • The kernel backend is read once at bootstrap and recorded in the session.
  • Deleted: the never-written kernel_opt_task_attempts / last_kernel_opt ledger and its readers, the dead rocprof
    enrichment hook, roofline_measured and rocprof_roofline.

Linked issue(s)

None.

Tests

  • Tests were updated alongside each commit; replaced tests carry their contract assertions to the new path (named in
    each commit message). New contract tests cover the KEEP-bar floor, empty-round dryness, family pruning, the GEAK
    pre-measurement no-material settle, recovered profiles, the summary built from timeline records, and the bounded
    GEAK drain. Tests that only asserted a removed thing was absent, or duplicated another test's contract, were dropped.
  • Run locally before the rebase (no full-suite run; CI runs it): every changed test file plus every test file that
    imports a changed module (≈11.7k tests), every test file main had changed under src/hyperloom, and the
    GEAK/specialist suites touched by the reconciliation. The rebased tree was checked with ruff, lint-imports and
    scripts/code_metrics.py. The review follow-ups ran the bring-up suites and every test that observes a boot
    (315), the baseline and integrate executor suites (827), the GEAK drain test, and the attempt-ledger, preflight,
    specialist and reconcile suites touched by the module-length trims (428). The only failures are four tests that
    fail identically
    on the base commit in this environment (test_derive_runtime_paths ×2, test_cli_resume_launch_shape,
    test_tracelens_csv — shell ANTHROPIC_MODEL / ROCm-path dependent).
  • ruff check, ruff format --check on touched files; lint-imports: all contracts kept.

Size/complexity triggers crossed

None. scripts/code_metrics.py --base-ref b772e9434 passes: no new or worse unit, and every baseline entry the
branch touched is lowered. Three modules were already over their recorded length on origin/main; this branch
leaves each at or under its length there:

File Baseline origin/main This branch
orchestrator/phases/framework.py 3139 3148 3145
inference_optimizer/cli/preflight.py 2647 2674 2673
orchestrator/loop/coordinator.py 1423 1439 1439

Simplification

Mechanisms removed, with the contract preserved and where it is pinned:

  • Dead attempt ledger → "tried" now comes from integrate attempts, queued integrations, stack entries and controller
    results (test_untried_hot_dedup.py, test_kernel_idle_streak.py, test_kernel_idle_no_progress.py).
  • Two GEAK materiality checks (pre- and post-rebench) → one pre-measurement launch comparison
    (test_geak_revalidation_dispatch.py).
  • Three hand-rolled journal parsers → read_journal_entries (test_optimization_journal.py).
  • source_patch prune flag → the deterministic preflight it cached (test_custom_specialist.py,
    test_framework_*).
  • Claude/Codex CLI resolvers moved to hyperloom.common.agent_cli, one resolver for the CLI layer, the Claude role
    and the specialist launcher.

Observable effect

  • session_breakdown.json (stays at 6.1): per-kernel roofline rows drop roofline_measured and
    rocprof_roofline; the baseline action drops convergence. None of the three is documented in the reference, and
    each held a constant or unread value.
  • Workflow contract v3 (declares session breakdown 6.1): predicate_inputs.phase_budget_pct and
    sweep_reloop.max_cycles removed;
    no_kernel_skipped leaves stop_reasons (it was only ever a transition label).
  • kernel_optimization_summary.json schema_version 2 → 3: totals carries claimed / adopted / rejected / failed / needs_review / not_dispatched; rejection_breakdown is gone; by_kernel has one row per candidate.
  • Artifacts: kernel_metrics.csv drops roofline_measured; the bypass summary.json drops rocprof_enrich;
    the roofline action can report status: "recovered".
  • Env vars removed: HYPERLOOM_SPECIALIST_PERMISSION_MODE, INFERENCE_OPTIMIZER_KERNEL_OPT_MAX_FAILURES,
    HYPERLOOM_ROCPROF_ROOFLINE_ENRICH, HYPERLOOM_ROCPROF_ROOFLINE_TIMEOUT_SEC.
  • Docs: the 6.1 change list names rocprof_roofline (never populated) and roofline_measured / baseline-action
    convergence (removed in 6.1, constant).
  • Behaviour: a resumed session keeps the kernel backend it started with; specialists ignore
    ~/.claude/settings.json; remote-recipe kernel rewrites publish their real speedup (it was always 0.0);
    extend_lease observations no longer carry gpu_rows / gpu_refresh_error; a boot whose fatal line is followed
    by another rank's repeat of a milestone keeps its failure kind and env_fault; boot classification no longer
    stalls the coordinator loop; the preflight agent-CLI warning text names the backend.

Breaking changes

Yes — the removed fields, the workflow contract v3 and the env vars listed above. No documented
session-breakdown result field is renamed or removed, so the breakdown stays at 6.1.

PR addresses single concern

No. The commits share one root — the defects found tracing a single run — and each commit is one concern with its
own message, so they can be reviewed commit by commit. They are kept together because several touch the same
modules (writeback.py, kernel.py, shared_state.py) and were verified as a whole. Happy to split by area
(measurement, phases, leases, framework lever, kernel arm) if preferred.

Root cause is upstream

Partly. GEAK's run_e2e.py sets status = "ok" whenever speedup > 1.0, bypassing its own Director verdict, and
GEAK's journey file omits rejected candidates. Hyperloom no longer trusts either claim (its own rebench decides);
the upstream fixes are not part of this PR and no ticket is filed yet.

🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

Code metrics gate: PASSED

Judged: the 155 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 45 -3
Cognitive complexity fails > 30 0 0 0 170 -8
Function length (lines) fails > 80 0 0 0 315 -6
Nested block depth fails > 5 0 0 0 19 -1
Parameter count fails > 5 0 0 0 89 +0
Module length (lines) warns > 800, fails > 1200 0 0 0 47 -1
Duplicated lines per file fails > 0 0 0 0 96 +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): 8

Module Lines Limit
src/hyperloom/inference_optimizer/breakdown/recorder/baseline_event.py 915 warns > 800
src/hyperloom/inference_optimizer/breakdown/recorder/roofline_event.py 979 warns > 800
src/hyperloom/inference_optimizer/cli/bootstrap.py 930 warns > 800
src/hyperloom/orchestrator/knowledge/remote_recipe/values.py 1196 warns > 800
src/hyperloom/orchestrator/roles/claude.py 1159 warns > 800
src/hyperloom/orchestrator/specialists/dispatch.py 1012 warns > 800
src/hyperloom/orchestrator/trace_analysis/_bypass_report.py 1097 warns > 800
src/hyperloom/orchestrator/trace_analysis/bypass_trace_analysis.py 890 warns > 800

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

Unit Dimension Base Now
src/hyperloom/orchestrator/state/shared_state.py:97 resolve_graded_comparison Cognitive complexity 34 34
src/hyperloom/inference_optimizer/cli/__init__.py:1782 _reexport_session_environment Function length (lines) 111 107
src/hyperloom/inference_optimizer/cli/__init__.py:2308 _resolve_agent_lineup Function length (lines) 89 89
src/hyperloom/inference_optimizer/cli/__init__.py:2203 _resolve_run_topology Function length (lines) 92 92
src/hyperloom/orchestrator/kernel/request_handlers.py:2784 _run_forge_gemm_tuning Cognitive complexity 125 125
src/hyperloom/orchestrator/phases/kernel.py:1226 KernelPhase._run_geak_kernel_phase Cognitive complexity 130 130
src/hyperloom/orchestrator/kernel/request_handlers.py:2784 _run_forge_gemm_tuning Cyclomatic complexity 57 57
src/hyperloom/orchestrator/phases/kernel.py:1226 KernelPhase._run_geak_kernel_phase Cyclomatic complexity 52 52
src/hyperloom/inference_optimizer/cli/__init__.py:2415 _run_optimize Function length (lines) 279 279
src/hyperloom/inference_optimizer/cli/preflight.py:2376 _preflight Function length (lines) 209 208
src/hyperloom/orchestrator/knowledge/recipe_journal.py:740 RecipeJournalCollaborator._record_fact_per_variant Function length (lines) 116 116
src/hyperloom/orchestrator/loop/writeback.py:3420 WritebackCollaborator.build_env_spec Function length (lines) 111 111
src/hyperloom/orchestrator/phases/framework.py:1246 FrameworkPhase._maybe_rearm_authored_lane Function length (lines) 104 104
src/hyperloom/orchestrator/phases/framework.py:1941 FrameworkPhase._submit_framework_agent_candidate_for_review Function length (lines) 98 98
src/hyperloom/orchestrator/phases/framework.py:2185 FrameworkPhase.maybe_reauthor_from_critic_feedback Function length (lines) 133 133
src/hyperloom/orchestrator/phases/framework.py:514 _record_source_attempt Function length (lines) 151 151
src/hyperloom/orchestrator/phases/kernel.py:1226 KernelPhase._run_geak_kernel_phase Function length (lines) 483 482
src/hyperloom/orchestrator/phases/kernel.py:2124 KernelPhase.promote_geak_from_candidate Function length (lines) 167 167
src/hyperloom/orchestrator/prompts/prompt_builder.py:616 _section_decision_framework Function length (lines) 104 104
src/hyperloom/orchestrator/specialists/subprocess_.py:797 SpecialistSubprocessDispatcher.run Function length (lines) 350 350
src/hyperloom/orchestrator/trace_analysis/tracelens_analysis.py:4347 main Function length (lines) 898 898
src/hyperloom/orchestrator/trace_analysis/tracelens_analysis.py:3847 write_reports Function length (lines) 204 204
src/hyperloom/inference_optimizer/breakdown/schema.py:1 Module length (lines) 2690 2687
src/hyperloom/inference_optimizer/cli/__init__.py:1 Module length (lines) 2752 2748
src/hyperloom/inference_optimizer/cli/preflight.py:1 Module length (lines) 2674 2673

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

58 findings in files this change does not touch

Outside this change (informational): 58

Unit Dimension Baseline Now
src/hyperloom_kb/collect/mapping.py _experience Cognitive complexity absent 31
src/kernelforge/cli/forge_loop_command.py forge_loop Cognitive complexity absent 31
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/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 84
src/hyperloom_kb/sync.py GlobalSync.pull Function length (lines) absent 84
src/kernelforge/loop/runner.py IterationLoop._close_iteration Function length (lines) absent 117
src/kernelforge/loop/runner.py IterationLoop._collect_session_candidate Function length (lines) absent 185
src/kernelforge/loop/runner.py IterationLoop._implementer_history Function length (lines) absent 112
src/kernelforge/loop/runner.py IterationLoop._rule_on_attempt Function length (lines) absent 102
src/kernelforge/loop/runner.py IterationLoop._source_attempt Function length (lines) absent 175
src/hyperloom_kb/http_service.py Module length (lines) absent 1525
src/kernelforge/cli/forge_loop_command.py Module length (lines) absent 2003
src/hyperloom/orchestrator/actions/executors/_geak_sweep.py sweep_via_geak Cognitive complexity 67 70
src/hyperloom/orchestrator/actions/executors/_grid_runner.py run_grid Cognitive complexity 177 180
src/hyperloom/orchestrator/actions/executors/explore.py ExploreExecutor.__call__ Cognitive complexity 369 383
src/hyperloom/orchestrator/phases/prelude.py PreludePhase.maybe_enqueue_warm_replay Cognitive complexity 190 191
src/hyperloom/orchestrator/actions/executors/_grid_runner.py run_grid Cyclomatic complexity 55 56
src/hyperloom/orchestrator/actions/executors/explore.py ExploreExecutor.__call__ Cyclomatic complexity 76 83
src/hyperloom/orchestrator/phases/prelude.py PreludePhase.maybe_enqueue_warm_replay Cyclomatic complexity 48 49
src/hyperloom/agents/quantization/driver/retry.py quantize_via_prompt Function length (lines) 102 103
src/hyperloom/inference_optimizer/breakdown/exporter.py build Function length (lines) 132 136
src/hyperloom/inference_optimizer/cli/kb.py _bootstrap_recipe_kb Function length (lines) 91 92
src/hyperloom/inference_optimizer/multi_node/scripts/apply_tracelens_patch_multinode.py _apply_on_pod Function length (lines) 101 102

...and 33 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.

@ZhengGong-amd ZhengGong-amd changed the title fix: close the defects behind the MuseSpark run shortfall and delete state nothing reads [fix] close the defects behind the MuseSpark run shortfall and delete state nothing reads Oct 20, 2026
@ZhengGong-amd

Copy link
Copy Markdown
Collaborator Author

size-exception

@xiaofei-zheng

Copy link
Copy Markdown
Collaborator

Review of #2055

What it does: traces a 660-minute MuseSpark-1.2 run that finished at +5.99% against a 10% target back to five areas of the code — what a KEEP is judged against, how a phase decides it is done, what lease expiry claims to do, whether a dead lever can be seen as dead, how the kernel arm is credited — fixes the defects that have a fix in the existing infrastructure, and deletes the mechanisms verified to have no reader, no effect, or no reachable branch. Net −3.5k lines across 160 files, 42 commits plus one origin/main merge.

Blocking issues: 3

1. failure_region can cut the failing line out of the region the bring-up rules read — src/hyperloom/orchestrator/bringup/ladder.py:193-211, consumed at ladder.py:257 and bringup/observe.py:80

_region_start anchors the region at the last _PROGRESS_MARKERS hit before the root traceback, or anywhere in the stream when there is no traceback (end = len(text)). The markers are case-insensitive substrings, and some of them recur long after the milestone they name:

  • "kv cache" (ladder.py:49) matches vLLM's periodic serving line ... Running: N reqs, ... GPU KV cache usage: 0.3% ..., and matches each TP rank's own KV-cache allocation line during startup.
  • "loading weights" and "capture cuda graph" likewise repeat per rank.

So any stream shaped <fatal line> -> <a line containing a marker> -> [optional traceback] starts its region after the fatal line, and rules.classify_failure matches nothing on it. Two consequences, both from classify() at ladder.py:345-352:

  • No Python traceback (HIP [FATAL ERROR], NCCL abort — the process aborts without raising): signature.is_actionable is False and frame is None, so has_failure is False and the observation carries stage_failed=None, env_fault=None. On the post-bench path (integrate_patch.py:4706 _record_bench_bringup, which classifies a whole benchmark log) stage_reached still reaches HTTP_READY from _progress_across, so BootObservation.booted (common/bringup.py:280) is True — a server that died mid-benchmark reads as a clean boot with no failure.
  • With a traceback, matched_marker / env_fault drop from the real cause to the tail consequence (EngineDeadError), the inverse of what the commit message argues for.

Trigger in a real config: TP=8 vLLM where one rank hits resource_constraint while the other ranks print their own KV-cache or graph-capture lines afterwards; or any server that crashes after serving began. Cost: env_fault is what enablement/lane.py:220 _check_environment_terminal reads to set stop_reason=environment_fault and stop the run rather than author a framework patch for a host fault — losing it sends the run on to blame the patch.

At the merge base (73b01c0) _classified_streams passed the whole text to classify_failure, so this is introduced here. The new test test_a_rule_match_the_process_ran_past_does_not_name_the_failure covers only the milestone-before-failure ordering, not the reverse. Anchoring the region on a milestone's first occurrence, or on markers that cannot recur after boot, closes it.

2. Documented result fields renamed without the major schema_version bump the contract requires — src/hyperloom/inference_optimizer/session/sbd_v6.py:22, written at breakdown/collectors/v6.py:367,689 and recorder/baseline_event.py:224

outcome.baseline.throughput_tok_s_per_gpu and outcome.final.throughput_tok_s_per_gpu become output_throughput while schema_version stays hyperloom.session_breakdown.v6.0. docs/reference/session-breakdown.md:598-603, which this PR edits, states the opposite rule: "Never removing or renaming a documented field of a result section within a major schema_version. Such changes require a major bump ... and every removed or renamed field is given a disposition in the section it left." The same doc tells consumers to gate on the major component only, and to index on (session_id, final.throughput_tok_s_per_gpu, …). An external consumer following the published rules therefore accepts a v6 document and reads a missing headline number, with no version signal that anything changed. No disposition entry is added either — the field row at :273 is replaced outright. AGENTS.md § Finish the replacement puts persisted data inside the compatibility boundary.

In-tree consumers were all migrated and src/hyperloom_kb/mappings/hyperloom-sbd-v6.yaml does not read the field, so the breakage is confined to out-of-tree consumers — exactly the population the guarantee covers. The PR body raises this as an open question; answering it: the rename needs the v7 cutover, or the old key has to stay alongside the new one until one lands.

3. docs/conceptual/optimization-loop.md:487 still states a SWEEP exit this PR makes unreachable

The line reads "The phase exits on sweep_done (or sweep_failed)." With FRAMEWORK_AGENT enabled (the default), _reloop_decision (phases/machine_state.py:1408-1435) returns False only together with a reloop_blocked value, and _RELOOP_BLOCK_TERMINALS (:907-913) now maps all four of them — this PR added all_directions_saturated -> global_converged and insufficient_remaining -> time_exhausted. terminal_reason is therefore never None, and the fall-through at :1705 that emits sweep_done is reachable only under --no-framework-agent. At 73b01c0 the map held three entries, so the sentence was true then. The PR adds a correct paragraph at :494 describing the new reasons but leaves the contradicting sentence seven lines above it, unqualified, in the same section.


Checked: bring-up ladder (ladder.py, observe.py, reconcile.py) against the base classifier; KEEP-bar floor (proposals.floor_keep_threshold, to_float non-finite rejection, every inject_explore_runtime_params / default_integrate_params / handle_delegate call site); prune_branch family expansion including the scope='queued' + baseline path and cancel_family([]); review-timeout settle wiring (coordinator.py:589 -> Reconciler._author_timeout_deny -> settle_dropped_proposal); the GEAK no-material pre-measurement settle and the GPU-drain move; untried_hot_reusable_kernels "tried" sources against the base, where nothing wrote kernel_opt_task_attempts / last_kernel_opt; attempt_summary.py v2->v3 and every reader of kernel_optimization_summary.json; status: "recovered" against every roofline/profile status accept-set (writeback.py:2400, shared_state.profile_trace_usable, request_handlers.py:2704, is_promotable_result); the agent_cli.py extraction against the base function bodies, all three migrated call sites and the dropped .importlinter ignore; --setting-sources= against the credential paths this repo actually uses; a whole-tree sweep for surviving readers of assess_convergence, kernel_opt_task_attempts, last_kernel_opt, roofline_measured, rocprof_roofline, rocprof_enrich, lease_expired, rejection_breakdown, no_kernel_skipped, max_cycles, profile_recovered, throughput_tok_s_per_gpu and the four removed env vars (none found, docs included); the workflow contract v3 digest, recomputed and matching; code_metrics_baseline.txt, every touched entry lowered or removed; prompt and doc sync for pending_keep_kernels, integration_id, the SWEEP goal text and specialist_rescue.md.

Ran: static verification and targeted greps in a worktree at 8fdb867. The inference_optimizer suites do not collect on this host (ModuleNotFoundError: fcntl), so finding 1 is argued from the code path rather than from a local run; CI covers the suites.

CI at this head: test shard 3/6 failed on both 3.10 and 3.11 with exit 143 and "the runner has received a shutdown signal" — a runner flake rather than a test failure, and it is what makes both coverage jobs report a missing shard. Worth a rerun. code-metrics fails on the three module-length findings the description already accounts for; it needs the baseline-raise label the description asks for, which is not on the PR yet.

Base: 73b01c07123bceccd3f24e3da8760f3b0070115c | Head: 8fdb867494f2b7b9832858f44e5e619159d21c4f

@xiaofei-zheng xiaofei-zheng 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.

Review of #2055

What it does. A 660-minute MuseSpark run finished at +5.99% against a 10% target; tracing it back through the code found defects in five areas (what a KEEP is judged against, how a phase decides it is done, what lease expiry claims to do, whether a dead lever can be seen as dead, how the kernel arm is credited). The PR fixes those in place — the KEEP bar becomes a floor an agent may only raise, SWEEP closes on the rule that actually refused the next macro-cycle, prune_branch expands a catalogue family into its member actions, an empty or undispatchable authoring round now charges an attempt row to its lever, a GEAK config that restates current_best settles before it is benchmarked, and the hot-kernel "tried" test reads from queued integrations, integrate verdicts, the optimization stack and the rewrite controller instead of a ledger nothing wrote — and deletes the mechanisms verified to have no function (the per-kernel attempt ledger, assess_convergence, the lease_expired topic, gpu_pool.extend, the per-lease heartbeat, the rocprof enrichment hook, the 1000 macro-cycle ceiling, four env vars). kernel_optimization_summary.json goes to schema_version 3, rebuilt from the timeline's V6KernelAttempt records.

Blocking issues: 2

1. A documented result field of session_breakdown.json is renamed without the major schema_version bump the contract requires.

outcome.baseline.throughput_tok_s_per_gpu and outcome.final.throughput_tok_s_per_gpu become output_throughput (breakdown/recorder/baseline_event.py:224, breakdown/collectors/v6.py:367,667,689, both renderers), while inference_optimizer/session/sbd_v6.py:22 stays hyperloom.session_breakdown.v6.0 and exporter_version is untouched.

docs/reference/session-breakdown.md states the rule twice, and this PR edits those lines without changing it: compatibility rules — "Renamed, removed, or semantically changed fields of a result section require a major bump"; stability guarantee #1 — "Never removing or renaming a documented field of a result section within a major schema_version ... every removed or renamed field is given a disposition in the section it left" (only enablement is carved out). outcome is a result section, the field was documented, and the same page named it the recommended index key ((session.session_id, final.throughput_tok_s_per_gpu, ...)) — that line is rewritten, the old key is deleted, and no disposition entry replaces it.

A consumer pinned on major version 6, as the page instructs, therefore reads null for the headline number with no version change to detect the cutover by. There is no alias: at head throughput_tok_s_per_gpu appears nowhere outside the unrelated conc-sweep input_throughput_tok_s_per_gpu. The in-repo skew case is real as well — a baseline timeline event written by a pre-rename build and exported by this build yields outcome.baseline.output_throughput = null.

On the open question the description raises: src/hyperloom_kb/mappings/hyperloom-sbd-v6.yaml reads $attempt.measurement.after_tput and $doc.metadata.grading.objective, neither of which this rename touches, so a v7 cutover costs the mapping's file name, not its body. Either cut over to v7 with the disposition entry, or keep emitting the old key for the remainder of v6.

2. Bring-up classification lost its read bound and runs on the event loop.

read_bringup_log (orchestrator/actions/executors/baseline.py:273) now does path.read_bytes() on the whole server.log. At 931af8ab the same function took 64 KiB from each edge and streamed the middle for milestone lines only, so at most ~128 KiB plus the milestones ever reached the classifier. Nothing between the read and the classifier caps it.

The text is then walked repeatedly. server_child_elapsed_sec (baseline.py:304) constructs a datetime per timestamped line over the whole file, and _LOG_LINE.finditer runs over the whole file three times — failure_region → _root_traceback (bringup/ladder.py:140) inside classify, again at ladder.py:349, and a third time in observe_bringup's closing classify_failure(failure_region(evidence)) (bringup/observe.py:80). Each failure_region also materialises a full lowered copy of the text (ladder.py:197) and scans it once per progress marker. There is no early exit.

The caller is a synchronous closure: record_bringup is defined inside async def _run_single_benchmark (baseline.py:3387) and called directly at baseline.py:3497 and :3513, while the benchmark subprocess itself is correctly offloaded with asyncio.to_thread (baseline.py:3473). integrate_patch.py:4725 pays the same cost once per bench variant. So the coordinator loop — heartbeat, lease renewal, every other in-flight lane — blocks for a pass linear in log size, once per baseline round and once per bench variant, where it was constant before.

The repo states the size this has to survive: baseline.py:149 — "Bounded per-file read so log scanning never slurps a multi-GB server.log", _LOG_SCAN_MAX_BYTES = 262_144, applied to server.log among others (baseline.py:1576); enablement/artifacts.py:38 — "Server logs routinely exceed _FILE_SIZE_LIMIT" (2 MiB) — and caps its copy at a 1 MiB tail. I could not run a production-sized log in this environment, so no measured number is quoted; the unbounded read, the three full passes and the loop placement are read off the code. What the commit wanted — a milestone or a root traceback that can lie anywhere — needs a deeper read, not an unbounded one on the event loop.


Checked: orchestrator/kernel/{attempt_summary,_kernel_decisions,geak_config,geak_runner,request_handlers}.py; phases/{framework,machine,machine_state,kernel,kernel_stack,geak_adoption}.py; state/{shared_state,_shared_state/*,failure_evidence}.py; loop/{coordinator,writeback,intent_router,proposals,dispatcher}.py; bus/*; specialists/*; common/agent_cli.py; breakdown/**; actions/executors/{baseline,report,roofline}.py; trace_analysis/**; bringup/**; cli/preflight.py; knowledge/**; docs, prompts, SKILL.md.

Verified by whole-tree grep that every removed name is swept (kernel_opt_task_attempts, last_kernel_opt, roofline_measured, rocprof_roofline, rocprof_enrich, no_kernel_skipped, predicate_inputs.phase_budget_pct, sweep_reloop.max_cycles, assess_convergence, and the four env vars) with zero surviving references in code, docs, prompts or examples; that global_converged / time_exhausted are in STOP_REASON_VOCAB, the v3 contract, the schema enum and the renderer map, and in SUCCESS_STOP_REASONS so the exit code is unchanged; that recovered is accepted by profile_trace_usable() and _promote_roofline with no surviving == "succeeded" reader; that floor_keep_threshold cannot emit NaN or inf because to_float rejects them; that common/agent_cli.py is equivalent to the two resolvers it replaces and that .importlinter removes an ignore rather than adding one; that the deleted lease machinery had no publisher or reader at the merge base; and that the v3 workflow_contract digest recomputes to the const it pins.

Also checked and clean: the "tried" reclassification cannot retire a sibling kernel (record_matches_task requires task-group or kernel-id agreement before it looks at source_file) and both rejection writers leave a record the new definition sees; the removed macro-cycle ceiling leaves SWEEP bounded by the no-gain streak, the session deadline and max_ticks; the new attempt row is written only on a newly stamped terminal row, so it cannot double-count against the plateau rule.

Considered and not reported: a family-scope prune_branch cancels a queued enablement-revalidation baseline without the exclusion drain_queued_baselines applies — pre-existing at 931af8ab via prune_branch{family: "baseline"}, which cancel_family matched by task kind there too, so this diff does not introduce it.

Ran: no test execution — this box is Windows and the suite's conftest is POSIX-only (fcntl); CI is green at head on all 12 test shards, coverage, CodeQL, ruff, pylint, mypy, import-linter and bandit. code-metrics is red at head on exactly the three module-length entries the description tables (framework 3173, preflight 2678, coordinator 1440); the baseline-raise label it asks for is not applied, so that check stays red until it is.

Base: 931af8abed2807d204c2e6db04ce0d416febe5c6 — Head: 9bea6d1e5c96fdfd0b74f41aaf48e6d6fef03970

@xiaofei-zheng xiaofei-zheng 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.

Re-review at f2744e38

Both findings from the previous round are resolved.

1. The session_breakdown rename is no longer this PR's. #2023 landed the
throughput_tok_s_per_gpu → output_throughput rename on main with its own version decision
(hyperloom.session_breakdown.v6.1); this branch drops its copy, no longer touches sbd_v6.py,
and the description now says so and declares 6.1 in the workflow contract. I checked the body's
replacement claim: roofline_measured, rocprof_roofline and convergence appear nowhere under
docs/ at the merge base, so "none of the three is documented in the reference" holds, and the
contract digest is pinned by test_workflow_evaluation_contract.py:122, which is green at head.

2. The bring-up classification no longer runs on the event loop.
fix(bringup): classify a boot off the event loop wraps both record_bringup call sites
(baseline.py:3498, :3514) and _record_bench_bringup (integrate_patch.py:4631) in
asyncio.to_thread, so the pass sits beside the benchmark subprocess it follows rather than in
front of the heartbeat and the lease renewals. read_bringup_log's docstring now states the
linearity and the obligation.

Blocking issues: 1

  1. The bring-up failure-classification change is an operator-visible effect the description does
    not state.
    failure_region / _region_start (bringup/ladder.py:194-213) do not exist at the
    merge base: this PR introduces scoping of the failure rules to a region, and
    fix(bringup): start the failure region at the first line of the furthest milestone then changes
    where that region begins. The outcome an operator reads changes with it — matched_marker,
    env_fault, failure_text and therefore whether a failed boot stops the run as an environment
    fault. The PR's own tests show the discrimination: on
    test_a_rule_match_the_process_ran_past_does_not_name_the_failure, an autotuner's "out of
    resource: shared memory" line that precedes a later milestone no longer names the failure, where
    on main it is what the rules match first; on
    test_a_milestone_another_rank_repeats_after_the_failing_line_keeps_it_in_the_region, a rank
    repeating a milestone after another rank's fatal line no longer costs the observation its
    env_fault.
    The description's ## Observable effect section is otherwise exhaustive — every removed field,
    artifact column and env var is there — but carries nothing about bring-up, and the only mention
    of this work is the line in ## Description naming the commit
    (fix(bringup): read the server log whole …) without saying what changes for someone who will
    never read the diff. AGENTS.md Every change states its observable effect in its own PR
    description
    makes that statement the PR's job, because the release cut aggregates these
    descriptions and cannot reconstruct them from commit subjects.
    Action: add a bullet under ## Observable effect for what a failed boot now reports, and for the
    classification moving to a worker thread.

Checked this round: git log and full diff from the new merge base e25cb2db2 — the five commits
added since 9bea6d1e5 (fix(bringup): start the failure region …,
fix(bringup): classify a boot off the event loop, docs(sweep), test(geak), chore(metrics))
plus the rebase onto the new main. LadderStage is an ordered enum, so the new
max(stage) / min(at) selection in _region_start picks the furthest stage and its first line as
the docstring says. The test(geak) and docs(sweep) commits are test- and docs-only; the
chore(metrics) commit only lowers baseline entries. Re-verified the reconciliation section against
main: #2023, #2024/#2052/#2056/#2057, #2040, #2041, #2049 and #2050 are each named with what was
kept from which side.

CI at head: everything green except code-metrics, which fails on the same three module-length
entries the description tables (preflight.py 2678, coordinator.py 1440, framework.py 3173).
The baseline-raise label the description asks for is still not applied, so that check stays red
until it is.

Base: e25cb2db2a572f3af70103f2b91aa3a0fa683d4c — Head: f2744e38105789e8704a45ec96b35cff08955cc5

@xiaofei-zheng

Copy link
Copy Markdown
Collaborator

Re-check at 54952207

The finding from the last round is resolved: ## Observable effect now carries the bring-up
behaviour — a boot whose fatal line is followed by another rank's repeat of a milestone keeps its
failure kind and env_fault, boot classification no longer stalls the coordinator loop, and the
preflight agent-CLI warning names the backend.

The three commits added since f2744e38 check out:

  • refactor(framework): build an undelivered round's attempt row in the ledger — AttemptRow's
    field order is lever_kind, outcome, adopted, gain_pct, before_tput, after_tput, and
    AttemptRow.undelivered_round passes exactly (lever_kind, outcome, False, None, None, None)
    positionally with task_id and specialist_task_id both bound to the specialist task, so the
    recorded row is identical to the constructor call it replaces.
  • refactor(preflight): resolve the selected agent CLI through one branch — the consolidated
    warning points both backends at assets/install.sh, which is truthful for codex as well: it
    installs the [llm] extra, whose openai-codex is the runtime resolve_codex_executable() falls
    back to when nothing is on PATH. The parametrised test moves with the wording.
  • refactor(coordinator): explain both deferred reconciler links in one comment — comment only.

Blocking issues: 1

  1. The branch no longer merges. mergeable: CONFLICTING / mergeStateStatus: DIRTY at
    54952207. origin/main is 26 commits ahead of the merge base e25cb2db2, and a trial merge
    conflicts in three files: scripts/code_metrics_baseline.txt,
    src/hyperloom/orchestrator/actions/executors/integrate_patch.py (main's refactor(integrate-patch): resolve, apply and grade one patch through named stages #1998, which splits
    resolve/apply/grade into named stages) and src/hyperloom/orchestrator/kernel/geak_config.py
    (main's refactor(kernel): reuse geak_spec_name in _geak_accepted_kernel_specs #2046, which reuses geak_spec_name in _geak_accepted_kernel_specs — the same function
    this branch changes). Both overlaps are semantic, not just textual, so they want the same
    commit-by-commit reconciliation the description already does for fix(breakdown): rename throughput_tok_s_per_gpu to output_throughput (schema 6.1) and record per-GPU output on baseline and validation rows #2023, fix(geak): hold back the rebench's own round and let GEAK's GPUs drain before it #2040, fix(specialist): a catalogue domain holds at most one queued or running scope=domain specialist #2041, fix: narrow, remove or log the remaining broad handlers outside the files under restructuring #2049 and
    [fix]Enablement: run later phases on the promoted runtime checkout; add a ROCm install path for SGLang checkouts #2050.

Not yet checkable at this head: only Analyze (python), Gitleaks and the Read the Docs build have
reported. code-metrics — which the three new commits exist to turn green, and which was failing on
preflight.py, coordinator.py and framework.py — has not run, so whether those three modules are
back under their baseline is unverified. I will re-check once the branch merges cleanly and the
matrix reports.

ZhengGong-amd and others added 2 commits October 21, 2026 10:04
…o the failure

read_bringup_log kept 64 KiB from each end of server.log and carried at most
200 milestone lines out of the middle. On real logs that lost both halves of
what the ladder needs:

- A shard progress bar repeats "Loading safetensors checkpoint" hundreds of
  times, so the 200-line cap filled before "Application startup complete" and
  served GLM-5.2 boots were classified as never reaching HTTP_READY.
- A worker's root traceback megabytes above the tail never reached the ladder,
  so the failure was keyed on the engine's EngineDeadError re-raise instead.

The log is now read whole; the edge window, the middle milestone scan, the
edge_bytes parameter and PROGRESS_MARKER_SUBSTRINGS are gone.

Reading everything exposed the failure rule table, which takes the
highest-precedence match anywhere in the text, to lines the process ran past
(Triton autotune rejecting a config read as kernel_resource_limit). The rules
now read failure_region(): from the last milestone line before the root
traceback to the end. A later milestone proves the process got past a line;
the lines between that milestone and the traceback are kept because native
code prints the cause there (RCCL "HIP failure: 'out of memory'"). The
observation and the verdict's signature use the same region.

Co-authored-by: Cursor <cursoragent@cursor.com>
The baseline action in the session breakdown no longer carries a
`convergence` block. It was built from the warm-up and the measured round
alone, and with one round discarded as warm-up the verdict was always
`insufficient_rounds`, so the block never said anything a reader could act
on and no decision branched on it. Building it ran inside a catch-all that
would also have swallowed a failure of the cold-start check sharing that
block.

The `baseline_cold_start_delta_high` warning and its log line are
unchanged: a measured round more than 25% above its warm-up still flags
the anchor as possibly low.

Co-Authored-By: Claude <noreply@anthropic.com>
ZhengGong-amd and others added 19 commits October 21, 2026 10:04
…constants

The stalled-domain force dispatch read an enable switch and two thresholds off
SharedState attributes that do not exist, so the feature was always on and the
thresholds were always the module constants (8 specialist rounds, 12 rounds
without a KEEP). The reads are gone and the constants are used directly; the
docstring now says which counter a forced dispatch resets (the dispatch
counter, not the keep counter). No behaviour change; the dispatch log line no
longer repeats the fixed thresholds.

Co-Authored-By: Claude <noreply@anthropic.com>
…ng source_patch

A patch specialist with no git source tree to write into was refused by a
deterministic preflight, and the first refusal also wrote "source_patch" into
pruned_families. That entry was only a cached copy of the preflight: every
reader recomputed it anyway, except that once written it stayed for the rest
of the session, so a source tree that became available later never unblocked
patch specialists.

Both the Orchestration delegate path and the stalled-domain force dispatch
now ask one SpecialistDispatchCollaborator method, which runs the preflight
and records the first refusal in last_action_failures as before. The custom
specialist falls back to research mode on the preflight error itself.

Observable effect: "source_patch" no longer appears in pruned_families, so
the state render shown to Orchestration, the final report's pruned_families
line and the console session summary no longer list it; the refusal reason
(no_git_framework_source_root) stays in last_action_failures, and the custom
specialist's research-only observation now names that reason instead of
"source_patch_pruned".

Co-Authored-By: Claude <noreply@anthropic.com>
When no Critic verdict arrived within the review TTL, the reconciler wrote a
reject verdict and dropped the in-memory pending proposal, but never passed
through the verdict handler. The event log said rejected while the session
breakdown left the proposal unsettled, so a timed-out proposal read as still
pending in the framework timeline.

The timeout deny now settles the proposal as dropped (reason review_timeout)
through the same router method a Critic reject uses. The reconcile report's
denied_reviews list, which fed only its own summary log line, is removed; each
timeout deny still logs its own warning.

Co-Authored-By: Claude <noreply@anthropic.com>
Preflight warned whenever node, claude or codex was missing from PATH and
said the Claude/Codex backends "may fall back to direct HTTP" and that
install.sh would bring all three in. No such fallback exists: specialists
fail to start without their CLI. Nothing runs node, a codex runtime bundled
with the Codex SDK satisfied the backend while still drawing the warning,
and install.sh installs only the claude CLI.

Preflight now resolves the CLI of the agent backend this deployment selects,
the same way the specialist launcher does, and warns only when it is missing,
naming where it looked and how to install it. It remains a warning.

The Claude and Codex CLI resolvers move to hyperloom.common.agent_cli so the
CLI layer, the Claude role and the specialist launcher share one resolver
without the CLI importing the orchestrator.

Co-Authored-By: Claude <noreply@anthropic.com>
HYPERLOOM_SPECIALIST_PERMISSION_MODE let an operator change the
--permission-mode passed to Claude specialist subprocesses. Nothing sets it,
and under --print any value but bypassPermissions stops the specialist from
writing its Bash heartbeat, so it is reaped as stale and retried until the
attempt budget is spent -- the variable could only break specialists.

The variable is removed along with its documentation, and the specialist
subprocess config no longer carries a permission mode: Claude specialists
always run with --permission-mode bypassPermissions, which is what every run
already used. Setting the variable now has no effect.

Co-Authored-By: Claude <noreply@anthropic.com>
…ings

Claude specialist subprocesses were started without --setting-sources while
inheriting HOME and CLAUDE_CONFIG_DIR, so the CLI loaded the operator's
~/.claude/settings.json (and any .claude/ settings in the checkout it ran in):
their hooks, permission rules, env overrides and model choices silently
changed how an unattended specialist behaved from one host to the next.

Specialists now run with --setting-sources= (no user, project or local
settings), the same isolation the one-shot Claude calls already use.
Credentials still reach them through the forwarded environment and the CLI's
own config; an operator who relied on settings.json to configure specialists
will find those settings no longer apply.

Co-Authored-By: Claude <noreply@anthropic.com>
…launch

_geak_result_has_material still took a prior best (flags, envs, controls)
to compare GEAK's accepted config against, but no production caller passes
one any more: whether a config changes current_best is decided before the
rebench by comparing the launch it produces. The parameters and their
fingerprint comparison are gone; the helper now answers only whether a
result carries an artifact or a non-empty launch config.

The comparisons those parameters pinned are now tested against the launch
comparison itself: untrusted environment keys on either side, complete
(replace) configs, delta configs over a complete current_best, unset
environment names, and removal lists. Removal lists now count toward that
launch identity, so a GEAK config whose only change is a removal the
composed flags cannot show (an inherited recipe flag, or clearing an
inherited removal with an explicit empty list) is benchmarked instead of
being settled as no_material.

Co-Authored-By: Claude <noreply@anthropic.com>
KERNEL waited for the GPUs GEAK handed back before every call into the
rebench, including the ones that end without a measurement: a GEAK config
that restates current_best settles as geak_no_material, and an invalid
config or an invalid native source is recorded and dropped. Each of those
still reaped this session's leftover servers and waited up to the GPU-free
timeout for nothing.

The rebench now takes the handed-off cards and drains them only once it
knows a measurement follows (the explore rebench, the GEAK-harness replay
or the native-source revalidation). A rebench recovered from a result.json
on resume now drains the same cards as a fresh one; it did not wait at all
before.

Co-Authored-By: Claude <noreply@anthropic.com>
The stalled-domain dispatch no longer prunes source_patch or saves state
when the patch preflight refuses a specialist; it records the refusal once
in last_action_failures, which test_specialist_lifecycle already pins. The
force_prune save site therefore exercised a save that no longer happens.

Co-Authored-By: Claude <noreply@anthropic.com>
…est milestone

The failure rules read a stream from its last milestone line before the root
traceback. Milestone markers are substrings that repeat: every TP rank prints
its own KV-cache and weight-loading lines, and a serving vLLM prints
"GPU KV cache usage" every few seconds. When one rank's fatal line (a HIP
out-of-memory abort, an NCCL error) was followed by another rank's repeat of
the same milestone, the region started after the fatal line, no rule matched,
and the observation lost its failure kind and env_fault, so a host fault no
longer stopped the run as environment_fault.

The region now starts at the first line of the furthest milestone the stream
reached before the root traceback. Repeats of a stage already reached no longer
move it, and a rule match before a later milestone (an autotuner's rejected
config before startup completes) still stays out of it.

Co-Authored-By: Claude <noreply@anthropic.com>
Reading a server log whole and classifying it is linear in the log's size,
and it ran on the coordinator's event loop after every baseline benchmark and
every integrate_patch bench, stalling heartbeats, lease renewals and every
other lane for as long as the pass took on a large log. The baseline
benchmark's boot observation and the integrate bench's now run in a worker
thread, as the benchmark subprocess around them already does.

Co-Authored-By: Claude <noreply@anthropic.com>
…ng rule

The SWEEP section still said the phase exits on sweep_done. With
FRAMEWORK_AGENT enabled, a finished ladder now either loops back or closes on
the rule that refused the next macro-cycle, as the paragraph below it states;
only a failed ladder closes as sweep_failed. Documentation only.

Co-Authored-By: Claude <noreply@anthropic.com>
The drain test's cleanup killed the escaped descendant inside a
try/except ProcessLookupError: pass, which code scanning flags as an empty
except. contextlib.suppress states the same thing: the child may already be
gone. Test-only change.

Co-Authored-By: Claude <noreply@anthropic.com>
…up units

Co-Authored-By: Claude <noreply@anthropic.com>
…ledger

An authoring round that delivered nothing wrote its attempt row through a
twenty-line constructor call spelling out "not adopted, no gain, no
throughput". AttemptRow.undelivered_round now names that row next to the row
shape, so the FRAMEWORK writer is one line, and the dispatch-failure recorder's
signature fits on one line. framework.py is back under its length on main.
No change in what is recorded.

Co-Authored-By: Claude <noreply@anthropic.com>
…comment

The reconciler's proposal links are callables because the resume replay
rebuilds the pending proposals after the reconciler is built; one comment now
covers both, keeping coordinator.py at its length on main. Comment only.

Co-Authored-By: Claude <noreply@anthropic.com>
The agent-CLI check picked the resolver by backend and then spelled out a
backend-specific message. It now selects the resolver once and prints one
warning naming the backend: "no claude CLI" or "no codex CLI", that
specialists cannot start without it, and that assets/install.sh installs it.
preflight.py is back under its length on main.

Co-Authored-By: Claude <noreply@anthropic.com>
…nstant

6.1 states every key it removes with its disposition. The roofline per-kernel
rows' rocprof_roofline was never populated and joins that list; the rows'
roofline_measured (always false) and the baseline action's convergence
(always insufficient_rounds) are listed with the disposition "removed in 6.1,
constant". The session-breakdown reference, the upgrade notes and the
breakdown skill now name them. Documentation only.

Co-Authored-By: Claude <noreply@anthropic.com>
…nch shrank

Co-Authored-By: Claude <noreply@anthropic.com>
@ZhengGong-amd
ZhengGong-amd force-pushed the fix/zgong/bringup-read-whole-log branch from 5495220 to de191c3 Compare October 21, 2026 10:11
@xiaofei-zheng

Copy link
Copy Markdown
Collaborator

Re-review at de191c32 — no blocking issues

Every point raised in the earlier rounds is closed, and the branch merges again.

1. The output_throughput rename and its dispositions. The rename moved to main as #2023's
schema 6.1, which the reference declares as an explicit exception to the major-bump rule and
backs with a disposition list. docs(breakdown): list the 6.1 removals of keys that only carried a constant adds this branch's three removals to it — roofline event
ext.actions[].kernel_roofline.kernels[].rocprof_roofline under never populated, and
roofline_measured and baseline event ext.actions[].convergence under the new
removed in 6.1, constant disposition — in docs/reference/session-breakdown.md,
docs/reference/upgrade.md and the breakdown skill. That satisfies the stability guarantee's
second half for this PR's removals.

2. Boot classification off the event loop. baseline.py:3498 and :3515 and the renamed
_observe_bench_boot at integrate_patch.py:4612 all run under asyncio.to_thread, beside the
benchmark subprocess they follow.

3. The bring-up effect is stated. ## Observable effect and the new ### Bring-up classification section say what a failed boot now reports: a rule match the process ran past no
longer names the failure, a milestone another rank repeats after the fatal line no longer costs the
observation its failure kind and env_fault, and the classification runs off the loop.

4. mergeable: CONFLICTING is resolved. Rebased onto b772e9434. I checked both conflict
resolutions rather than the merge status alone:

5. code-metrics is green. The three modules that were over their baseline are now at or under
their length on main, and the description's table matches the tree exactly: framework.py 3145 vs
main 3148, preflight.py 2673 vs 2674, coordinator.py 1439 vs 1439. The baseline-raise request
is withdrawn from the description. All 33 reporting checks pass; the 7 skips are the usual e2e,
pages-deploy and duration-update jobs.

Also checked this round: AttemptRow.undelivered_round passes
(lever_kind, outcome, False, None, None, None) positionally against a field order of
lever_kind, outcome, adopted, gain_pct, before_tput, after_tput, with task_id and
specialist_task_id both bound to the specialist task, so the recorded row is byte-identical to the
constructor call it replaces; the consolidated preflight warning points both backends at
assets/install.sh, which is truthful for codex because it installs the [llm] extra whose
openai-codex is the runtime resolve_codex_executable() falls back to; the coordinator.py
change is comment-only; and the reconciliation section now names #2046, #1998, #2047, #2048 and the
later over-gate cleanups with what was kept from which side.

LGTM.

@xiaofei-zheng xiaofei-zheng 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.

Re-reviewed at de191c3 — no blocking issues; see the detailed comment above. Every point from the earlier rounds is closed: the output_throughput rename moved to main's declared schema 6.1 exception and this branch's three removals now carry dispositions in the reference, the upgrade notes and the breakdown skill; boot classification runs off the event loop at all three call sites; the description states the bring-up effect; the rebase onto b772e94 keeps #2046's geak_spec_name and #1998's named stages with this branch's changes re-applied inside them; and code-metrics is green with the three module lengths matching the description exactly. All 33 reporting checks pass.

Approving so the earlier change requests no longer block. A code-owner review is still required by the release ruleset.

@xiaofei-zheng
xiaofei-zheng merged commit fbcd0c3 into main Oct 21, 2026
40 of 42 checks passed
@xiaofei-zheng
xiaofei-zheng deleted the fix/zgong/bringup-read-whole-log branch October 21, 2026 10:39
chennyiiis pushed a commit that referenced this pull request Oct 21, 2026
…kernel-3

Resolve the kernel attempt-summary conflict toward main: #2055 rewrote
build_kernel_optimization_summary as a projection of the KERNEL timeline
events and deleted the per-kernel attempt ledger this branch's restructuring
had reorganised, so the branch's helpers for that ledger have nothing left to
restructure. The file is main's.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
chennyiiis pushed a commit that referenced this pull request Oct 21, 2026
…kernel-2

#2055 deleted the per-kernel attempt ledger (kernel_opt_task_attempts,
last_kernel_opt) and rewrote untried_hot_reusable_kernels, _queue_kernel_keep
and the identity resolvers around it, so the branch's decomposition of those
reads has nothing left to decompose. Main's behaviour is taken whole there, and
the branch's structure is re-applied by hand on what survives:

- enqueue_nominated_patch keeps its single fusion lane (no `lane` parameter, no
  forge_rewrite branch) over main's two-lane body.
- _existing_integration_id, _pending_record_settled, _bind_result_to_pending,
  _attempt_totals, _record_integration_keep and _reject_integration are carried
  across, each minus the ledger reads #2055 removed.
- untried_hot_reusable_kernels and its helpers are main's, unchanged.

HL_VERIFIED_MICRO_PROMOTE_THRESHOLD and HL_PROMOTE_VERIFIED_MICRO_NEEDS_REVIEW
are gone with _queue_kernel_keep; nothing reads them on main.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
chennyiiis pushed a commit that referenced this pull request Oct 21, 2026
…knowledge

#2055 deletes state nothing reads, and this branch had relocated one of the
readers: _build_kernel_optimizations_from_state became the module-level
kept_kernel_optimizations with _index_integrate_attempts,
_kernel_optimization_row and _last_rebenched_throughput beside it. A textual
merge would have resurrected the whole join over the deleted
kernel_opt_task_attempts ledger. Main's deletion wins and is re-applied to the
branch's shape: those four units, the kernel_optimizations attrs key and the
extras merge that carried it into the KB row are gone, and the config arm's
attempt now copies the attribution explore stored instead of re-deriving it
(_attempt_failure no longer takes the outcome).

The two conflicted tests take main's side: it replaced the recipe-attrs
kernel_optimizations assertions with one that pins an earlier session's rows
being carried forward, and deleted the e2e_decision tests of the retired join.
The branch's move from _build_recipe_attrs_from_state to
recipe_attrs_from_state is carried across in the surviving cases.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
chennyiiis pushed a commit that referenced this pull request Oct 21, 2026
…loop

#2055's only change inside the conflicted region is comment text, and the
comment sits in code this branch had moved: the GPU-lease TTL note now lives in
_admit_gpu_specialist, not in the dispatch loop main edited. The branch's
extraction is kept and main's wording is re-applied there, so the retired
"iron law" phrasing does not survive the move. gpu_lease_ttl_sec's rewritten
docstring, the unwind-window note and the conc_sweep skip comment merged into
place unchanged.

scripts/code_metrics_baseline.txt is resolved by the ratchet and dispatcher.py's
module-lines entry lowered to the merged file's 1454.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
chennyiiis pushed a commit that referenced this pull request Oct 21, 2026
…state

Two of main's changes landed in code this branch had moved, so the merge is
resolved by hand on the branch's shape:

- #2060 replaced profile_workload_context's shlex round-trip with
  normalize_server_args, but the branch had lifted that computation above the
  context literal. The import merged and the call did not; the branch's
  joined_args now goes through normalize_server_args, so a JSON server-arg
  value survives the profile context, and `import shlex` is gone.
- #2055 deleted the rocprof roofline enrichment, whose merge the branch had
  moved into the module-level _hot_kernel_row. _hot_kernel_row loses its
  rocprof_by_kernel_id argument and its rocprof_roofline field,
  _ROOFLINE_SIGNAL_KEYS loses that key, and _build_hot_kernel_summaries takes
  only the result, as on main.

last_kernel_opt, kernel_opt_task_attempts, the kernel_opt_attempts accessors,
kernel_opt_attempts_count, the _resolve_kernel_patch_identity shim and
resolve_kernel_opt_max_failures stay deleted; none is read anywhere in the tree.
SharedState.record_trace_analyze is untouched.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size-exception Waives the PR diff budget; added by a maintainer with a reason in the PR description

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants