Repository navigation
refactor(fusion): delete the dead and repeated code in thirteen over-gate functions - #2067
Conversation
…one change scan _AuthorWorkspaceGuard.__init__ validated author targets and nominated module directories with two copies of the same lexical, resolved and symlink checks; both loops now call _contained_path. enforce() found the changed paths and later proved restoration with two hand-written scans of the index entries, index flags, Git status and snapshotted worktree states; both now call _changed_paths. Deleted, and why it is safe: - The "if not value: continue" guards in both loops and the "or []" default of new_module_dirs: the only production caller, _run_registered_author_once, already drops empty strings and always passes the list, as do the two tests that build the guard directly. - baseline_status_paths: it was exactly the key set of baseline_states. - The __init__ assignment of preserved_relpaths: its only reader, _ensure_safe_parent, runs only inside enforce() after enforce() sets it. - The loop that deduplicated new_module_dirs: the list is now derived from the new_module_baselines keys, which deduplicate by the same resolved path. Verification scans a superset of the paths it scanned before (it also recaptures preserved paths, then subtracts them), so a restoration it accepted before it still accepts, and a failed one still fails. One message changes outside the callers' contract: a module directory that is lexically outside the worktree but resolves inside it is reported as "outside the Git worktree" instead of as a symlink escape. Both are the same non-transient safety rejection, and the only production source of module directories (command.py, _author_module_dirs) passes parents of files that are also targets, which are checked first. Co-authored-by: Cursor <cursoragent@cursor.com>
…hor_once _run_registered_author_once ran to 134 lines: it built the backend run spec, pinned HIP_VISIBLE_DEVICES around the session, enforced the workspace and turned every outcome into an exit code. The session now lives in _run_author_session (spec, GPU pin and outer watchdog), and the verdict for a session that returned sits in _author_result_verdict beside the existing _author_run_error_verdict for one that raised. Deleted, and why it is safe: - The nested _run coroutine: asyncio.run now awaits asyncio.wait_for directly. Every backend's run is a coroutine function (the AgentBackend protocol, the Claude and Codex backends, every test double), so creating the coroutine before the loop starts runs nothing early. - Four copies of str(getattr(result, "text", "") or ""): result is final once the session ends, so the text is read once. - The record-log, log-error, no-retry sequence repeated by the restoration failure and the violation branches: both call one local _rejected, which writes the same log text and returns the same codes. - The targets, final_text, end_reason, backend, timeout_s, workdir and log_path aliases. Outside the callers' contract: the spec is now built, and HIP_VISIBLE_DEVICES set, inside the catch that keeps restoration running, so an exception from either would be recorded as the session's failure after the workspace is enforced instead of escaping run_author. Neither can raise for the values the callers pass (the GPU id is a click string option, the paths are the guard's own resolved paths). Co-authored-by: Cursor <cursoragent@cursor.com>
_prepare_author_harness and _finish_author_harness carried a second mode, selected by inherited=True, that copied an existing harness into staging and afterwards checked the author had not changed it. Every caller passes inherited=False (command.py _run_author_only, harness_authoring.py _author_baseline_harness), so the mode, its flag, its copy and comparison branches and the stat import they needed are deleted. harness_path was read only by the inherited copy, so _prepare_author_harness no longer takes it. Tests: the staging tests call the two functions without the removed arguments, and test_inherited_harness_staging_detects_author_mutation, which exercised only the deleted mode, is removed with it. Co-authored-by: Cursor <cursoragent@cursor.com>
run carried every stage path inline and threaded seven parallel locals (validation, artifacts, loop_manifest, compile_pass_outcome, loop_result, patches_out, nomination_summary) through a four-way branch into one final RunOutcome. Each path now returns its RunOutcome directly: _run_fusion_stages opens the fusion run and reports the multi-patch nomination, _run_single_patch claims a compile pass or authors and settles one patch, and _discover picks the discovery mode. The locals, the split.* aliases, the target_speedup and run_arch aliases and the final twelve-line RunOutcome construction are deleted. Deleted because no path can reach them any more: - _settle_single_patch_workspace's outcome parameter and its early return for multi-patch and compile-pass outcomes; only the single-patch authored paths call it now, and they never had artifacts, patches or a claim. - exported_ok on the multi-patch and compile-pass paths, read only by that early-returning settle call. - _split_nomination's top_recipe parameter, always recipes[0] or None. _exit_code_for_run reads kept and termination_reason from the loop dict the manifest records, which is set exactly when the LoopResult was, so the exit code is unchanged. The repo-scope refusal for patterns discovery moved into the patterns branch of _discover; nothing with a side effect runs between its old and new position. A stubbed differential run of every stage path (combine kept/exhausted/infrastructure failure, author-only rc 0 and 1, no stage, multi-patch, dry run) gives identical manifests, worker calls, log lines and exit codes on base and branch. Co-authored-by: Cursor <cursoragent@cursor.com>
run_fusion_loop drops from cognitive 32 / 111 lines to 25 / 73. Deleted: - the global_best_speedup running maximum. The "best so far" prompt context is now the max measured speedup in history, which yields the same value at every iteration (first maximum wins, NaN included). - the hand-written failed ValidationResult for a crashed campaign. It duplicated campaign._failed_campaign field for field, note included. - the getattr default on Recipe.already_satisfied, a declared dataclass field with a default. - the separate keeper and near-miss best updates and the continue that split them. One condition states the rule: a keeper may replace the best, a near-miss only while nothing has been kept. The campaign call and its crash handling move into _campaign_verdict: a crashed campaign still costs one recipe, FusionAbort still aborts the run, and the error log line is unchanged. A stubbed base/branch differential over 11 scripted runs (keepers, demotions, crashes, abort, NaN and signed-zero speedups, budget cuts, already-satisfied recipes, an empty run) produced identical results, history, ledgers, hook calls and log lines. Co-authored-by: Cursor <cursoragent@cursor.com>
The six reworked fusion functions are now within every code-metrics threshold, so their cognitive-complexity and function-lines entries go, and author.py's module-lines entry drops from 1322 to its new 1263. Only this change's entries move. --update-baseline also lowered the module-lines entry of orchestrator/phases/machine_state.py, a file this change does not touch; that line is left at its base value. Co-authored-by: Cursor <cursoragent@cursor.com>
load_op_busy_from_kineto_trace and load_op_bytes_from_kineto_trace each
carried their own copy of the same trace read: open the file (gzipped or
not), parse the JSON, take traceEvents, and bail out on anything that is
not a list. Both copies now go through one _load_trace_events, which
returns the dict events of a readable trace and an empty list otherwise.
Safe because both loaders already returned their empty result for an
empty event list (total stays 0), so an unreadable or malformed trace
still yields ({}, None, 0.0) and {} respectively, and the non-dict events
the loops used to skip are dropped by the helper instead. The deleted
`name.endswith(".json.gz")` clause was implied by `suffix == ".gz"`.
discover.py keeps its own _load_trace_events: #1867 replaces it with
kernelforge.trace_events.load_trace_events, which this helper can then
be swapped for.
load_op_bytes_from_kineto_trace goes from cognitive 33 to 26 (ruff C901
13 -> 10, 43 -> 30 lines).
Co-authored-by: Cursor <cursoragent@cursor.com>
_extract_json_array ran two copies of the same string-aware brace scanner over the same model text back to back: _salvage_objects for the complete top-level objects, then _repair_truncated_object for the one a cut left open. Their in-string, escape, depth and start transitions were identical; the repair copy only added the depth-1 commas. _salvage_objects now records those commas during its own pass and hands the open tail (its text, open depth, whether a string is open, and the comma offsets) to _repair_truncated_object, which keeps only the close-and-parse attempts. The repaired object is appended under the same "not already recovered" rule, so _extract_json_array lost its second call. Deleted guards, all unreachable: `start >= 0` on a close (a close to depth 0 always follows the opening brace that set start), the reset of start and the comma list on a close (both are reset by the next opening brace and read only while an object is open), `depth <= 0 or start < 0` (start is set whenever depth is positive), and `or not obj` (an empty dict already fails the name check). A differential run of base against this commit over 28,848 truncated and random texts (1,961 of them repaired on base) gave identical _extract_json_array and salvage results. _repair_truncated_object goes from cognitive 39 to 11 (ruff C901 19 -> 5, 48 -> 18 lines). Co-authored-by: Cursor <cursoragent@cursor.com>
existing_operator_hints_from_knowledge recomputed the paragraph-length penalty and the declared-operator bonus inside the loop over boundaries, although neither depends on the boundary. Take the best overlap over the boundaries first and apply both once; rounding is monotone, so every score is bit-identical. Also delete the checks that could not change the result: the empty evidence-source return (the empty boundary-term check below covers it), the filter that dropped empty term sets (an empty set only contributes a zero overlap to the max), and the ValueError fallback around relative_to (every path comes from rglob under the same root). Co-authored-by: Cursor <cursoragent@cursor.com>
build_recipes built every claimed compile pass from a _PatternEvidence bag that existed only to carry the authoring recipe's evidence fields to _compile_pass_recipe, and computed the sorted matched categories twice. The function now builds the authoring Recipe once and, when the pass is claimable, _compile_pass_recipe derives the claim from it; the bag is deleted. The claim's description template takes the noun and subject so discovery can share it. Also deleted: the `if compile_pass` guard (vllm_compile_pass_state returns None for an empty pass name before it probes anything), the have_source alias of bool(source_text), and the second assignment of `already`. The two drop branches are one condition: `confirmed is False` already implies the source was read. Differential run against the base module: 2,100 random scenarios (vLLM and SGLang, every probe state, include_unconfirmed on and off, with and without byte shares), recipes and log records identical. Co-authored-by: Cursor <cursoragent@cursor.com>
…pass claim parse_discovered_recipes resolved a proposal's files through two branches (single-file discovery reused a run-wide source text and file list, repo scope built its own) and rendered the file list twice for two log lines. _proposal_edit_files now returns the files a proposal edits, call site first, for both scopes, and the scope gate reads exactly those files (_scope_gate_drops). In single-file discovery that is still the one source file the prompt embedded, now read per proposal instead of once per run. A claimed compile pass is built by locate._compile_pass_recipe from the authored recipe instead of a second hand-written Recipe. Also deleted: the `if pass_name` guard (vllm_compile_pass_state returns None for an empty name before it probes), the second candidate_kind normalisation (one condition now), the unpacking of target fields into locals, and the priority try/except (hyperloom.common.coerce.to_float). The measured categories are computed once per run instead of per proposal, and source_anchors goes through _as_sequence. Out of contract only (the prompt asks for a 0.0-1.0 priority and a list of anchor strings): a boolean, NaN or infinite priority now falls back to the listing-order default (was 1.0/0.0, NaN or inf); a truthy source_anchors that is neither a list nor a string becomes one stringified anchor (a number raised TypeError, a dict gave its keys); a non-numeric category share raises before the first proposal instead of when a proposal matches it. No in-repo producer emits any of these. Differential run against the base module: 3,000 random payloads (both scopes, every probe state, explicit and implicit targets, with and without category shares), recipes and log records identical; 800 more with out-of-contract priorities differ only in trigger_share and the order it sets. Co-authored-by: Cursor <cursoragent@cursor.com>
validate_recipe ran all four gates in one 158-line body and wrote out the same never-measured ValidationResult twice, for a compile failure and for a runner that returned no parity samples. Both now come from _unmeasured_rejection. The worst error and the minimum SNR are max() and min() (default None) over the values the samples report instead of a hand-rolled fold; the builtins make the same comparisons in the same order, NaN included. Gates (c) and (d) depend only on the microbench outcome, the parity error, rtol and the target speedup, so they move whole into _microbench_verdict. validate_recipe keeps the compile and parity gates and hands the parity winner over. Out of contract only: when two samples carry non-numeric parity values (the harness contract says float or null), the TypeError for max_abs_err is raised before the one for snr_db, where the fold raised whichever came first by sample order. Differential run against the base module: 50,000 random runner outcomes (every gate verdict, NaN and infinite parity values, skipped and missing timings, known and unknown launch counts), results and the order of runner calls identical. Co-authored-by: Cursor <cursoragent@cursor.com>
Removes the cognitive-complexity, function-lines and nested-blocks entries of the functions now within the limits (load_op_bytes_from_kineto_trace, _repair_truncated_object, existing_operator_hints_from_knowledge, parse_discovered_recipes, build_recipes, validate_recipe, _salvage_objects) and lowers module-lines for discover.py (1539 -> 1447) and validate.py (1517 -> 1513). No other entry changes. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Code metrics gate: PASSEDJudged: the 10 files this change touches. Files it does not touch never fail it; anything found there is listed under Outside this change for information.
Already over at the base (backlog, not this change's): 3
87 findings in files this change does not touchOutside this change (informational): 87
...and 62 more; the job log lists every row.
Thresholds and sources: |
| run_error: BaseException | None = None | ||
| try: | ||
| result = _run_author_session(prompt, workspace.workdir, agent, guard, progress) | ||
| except BaseException as exc: # noqa: BLE001 - safety restoration must always run |
| run_error: BaseException | None = None | ||
| try: | ||
| result = _run_author_session(prompt, workspace.workdir, agent, guard, progress) | ||
| except BaseException as exc: # noqa: BLE001 - safety restoration must always run |
ZhengGong-amd
left a comment
There was a problem hiding this comment.
Please reconsider one point before merge.
src/kernelforge/fusion/diagnose.py:91-103adds_load_trace_events, butsrc/kernelforge/fusion/discover.py:186-197already has an identical_load_trace_events, anddiscover.py:138-147(hot_kernels_from_trace) has a third inline copy.discoveralready imports from.diagnose(discover.py:25). AGENTS.md Clean design: extend the existing behaviour instead of adding a copy.
Action: keep one reader (e.g. publicdiagnose.load_trace_events), havediscoverimport it, deletediscover.py:186-197and the inline read atdiscover.py:138-147.
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
|
Addressed the review. Kept |
xiaofei-zheng
left a comment
There was a problem hiding this comment.
What this PR does
Thirteen functions under src/kernelforge/fusion/ were over the code-metrics cyclomatic, cognitive, length or nesting gate because the same work was written twice or was never reached. Each is brought under its limits by deleting the duplicate rather than splitting it: one containment check and one change scan in the author workspace guard, one kineto trace reader shared by both diagnose loaders and by discover, one string-aware brace scan that now also feeds the truncated-proposal repair, one per-paragraph knowledge score, one _compile_pass_recipe owner for both the pattern and the LLM path, one proposal file resolution, one never-measured validation rejection, and the inherited-harness staging mode every production caller switched off. run() and validate_recipe are split along their stage boundaries. Net −296 production lines; the baseline loses 20 entries.
Blocking issues
1. The description's numbers and one of its claims are from an earlier head.
- "Production code: +539 / −809 (net −270)" — at head
3c3a1c4the eight production files are +542 / −838 (net −296). discover.py1,539 → 1,447 appears three times (body lines 62, 185 and the Gate section), but the file is 1,421 lines at head, which is also what this PR's own baseline hunk writes (scripts/code_metrics_baseline.txt:741).- Known merge interactions, #1867: "Until then, discover keeps its own identical reader." At head
discover.py:24imports_load_trace_eventsfrom.diagnoseand the local copy is gone. - The commit table lists 13 commits; head has 14 non-merge commits.
refactor(fusion): reuse trace event loadinglanded after the body was written, and only the appended Review response paragraph mentions it.
The release cut aggregates these descriptions, and a reviewer checking the refactor against the stated line counts and module lengths is checking it against a tree that no longer exists. Please refresh the three numbers and the #1867 bullet against head.
No other blocking issue. Everything else I checked held.
Checked: author.py, command.py, diagnose.py, discover.py, harness_authoring.py, locate.py, loop.py, validate.py at head against bb2da63, field by field for every moved block — models.py:60-106 for every Recipe default the new constructors stop passing (rocm_native True, already_satisfied False, predicted_gain/mem_share 0.0, all matching the deleted explicit values); campaign.py:71-85 for _failed_campaign's note being byte-identical to the inlined ValidationResult and for the absence of an import cycle; locate.py:418-453 for vllm_compile_pass_state("") returning None above the probe; loop.py:267-281 for to_dict() carrying kept/termination_reason now that _exit_code_for_run reads a dict; command.py:1346-1361 to confirm multi_patch and fuse_all_confirmed are never both true, so nomination["resolved"] is unchanged; command.py:517,1041-1082 to confirm _settle_single_patch_workspace is now called on exactly the two paths that previously executed its body; author.py:587-660,830-880 for preserved_relpaths being assigned before _ensure_safe_parent can read it, and for _changed_paths reproducing both the enforce-time scan and the post-restore verification scan (baseline_states.keys() == baseline_status_paths by construction).
Ran: a differential harness over 636 truncated-JSON inputs — every prefix of a three-object array with nested braces, braces inside strings and escaped quotes, plus 400 randomized truncations with trailing junk — comparing base _salvage_objects + _repair_truncated_object against head _salvage_objects: 0 differences. A second differential pass drove the raw run(request) callback on both trees across 1,280 stage/flag/recipe-set configurations with only the leaf stage functions stubbed, comparing call order, exit code and the full manifest: identical, including 96 EXIT_INFRASTRUCTURE_FAILURE exits through the new dict-valued loop parameter. Same approach for _discover (48 combos), parse_discovered_recipes (384 combos across both scopes and all four PassState shapes), build_recipes (120 combos), run_fusion_loop (18 runs, comparing to_dict(), patches, best_recipe, on_keep order and the rendered experience ledger), _AuthorWorkspaceGuard (13 enforce scenarios and 8 constructor cases against real git repos) and both diagnose loaders across nine trace shapes: identical in every case.
pytest: test_loop, test_discover, test_discovery_recovery, test_fusion_scope_gate, test_repo_scope — 79 passed. test_author_extra, test_resolve_and_cli, test_locate_extra, test_compile_pass_enable, test_diagnose — 177 passed / 14 failed at head, 178 passed / 14 failed at base: the same 14 pre-existing Windows symlink and subprocess failures, and the one-test delta is the deleted test_inherited_harness_staging_detects_author_mutation. Linux CI is green at head.
Base bb2da63332dcbc46bdf10702c516ef43eb80a016 · head 3c3a1c4843a21020da0896de17f0e92b97b2cd1d.
Verified at 3c3a1c4: the duplicate kineto trace readers are gone (one _load_trace_events in fusion/diagnose.py:91; discover imports it and both discover copies are deleted, 9439c55). CI green, merges cleanly with main. Note for the author: the description's line totals, discover.py length (1,421 now), commit table and the #1867 bullet still describe the pre-fix head.
chaojhou
left a comment
There was a problem hiding this comment.
Verified at 3c3a1c4: the duplicate kineto trace readers are gone (one _load_trace_events in fusion/diagnose.py, imported by discover). Every review item on the code is fixed, CI is green and the branch merges cleanly with main.
Before or right after merge, please refresh the PR description against this head (line and module counts, commit table, and the statements xiaofei-zheng / ZhengGong-amd listed): the release notes are built from it.
LGTM
What this does
Thirteen functions in
src/kernelforge/fusion/were over the code-metrics gate. Most of what put them over was code written twice or code no caller reaches. This PR deletes it and splits what remains along the steps each function already had, so each one is now under every limit it broke.Production code: +542 / -838 lines (net -296) in 8 files. Tests: +9 / -78 in 1 file. Code-metrics baseline: 20 entries retired, 3 lowered, none added.
What changes in each module
author.py: the workspace guard has one containment check,_AuthorWorkspaceGuard._contained_path, and one change scan,_AuthorWorkspaceGuard._changed_paths, in place of a second hand-written copy of each. The agent session moves into_run_author_session, replacing the nested_runcoroutine;_author_result_verdictturns a returned run into an exit code and a retry decision, and the rejection ending that_run_registered_author_oncerepeated is one_rejected.harness_authoring.py: the inherited-harness staging mode, which every production caller turned off, is deleted with theinheritedflag of_prepare_author_harnessand_finish_author_harnessand theharness_pathparameter of_prepare_author_harness.command.py:runno longer threads parallel locals into itsRunOutcome;_discover,_run_fusion_stagesand_run_single_patchare its paths.diagnose.pyanddiscover.py:_load_trace_eventsindiagnose.pyis the one kineto trace reader, used by both kineto loaders and bydiscover; the readerdiscoverkept and the inline copy inhot_kernels_from_traceare deleted.discover.py:_salvage_objectsis the one string-aware brace scan, and_repair_truncated_objectnow uses it;existing_operator_hints_from_knowledgescores each knowledge paragraph once;parse_discovered_recipesresolves a proposal's edit files once, in_proposal_edit_files, and asks_scope_gate_dropswhether the scope gate drops it.locate.py: the compile-pass claim is derived from the authoredRecipe, forbuild_recipesand for discovery alike;_PatternEvidenceand the compile-passRecipediscovery built by hand are deleted.loop.py:_campaign_verdictis one recipe's campaign verdict; the runningglobal_best_speedupand a hand-built failedValidationResultare deleted.validate.py:_unmeasured_rejectionwrites a rejection decided before anything was measured, in place of its repeated copies, andvalidate_recipehands the microbench gate to_microbench_verdict.Functions brought under the gate
Baseline entries this PR retires, with their values at base:
author.py:_AuthorWorkspaceGuard.__init__(cognitive 37, lines 118);_AuthorWorkspaceGuard.enforce(cognitive 39, lines 92);_run_registered_author_once(lines 134)command.py:run(cognitive 38, lines 222)diagnose.py:load_op_bytes_from_kineto_trace(cognitive 33)discover.py:_repair_truncated_object(cognitive 39);existing_operator_hints_from_knowledge(cognitive 34);parse_discovered_recipes(cognitive 89, lines 199);_salvage_objects(nesting 6)harness_authoring.py:_finish_author_harness(cognitive 32)locate.py:build_recipes(cognitive 32, lines 101)loop.py:run_fusion_loop(cognitive 32, lines 111)validate.py:validate_recipe(cognitive 33, lines 158)Baseline entries this PR lowers:
author.pymodule lines: 1,322 → 1,263discover.pymodule lines: 1,539 → 1,421validate.pymodule lines: 1,517 → 1,513Observable effect
None for any input the repo's own callers produce: manifests, exit codes, experience ledgers, patches, restored workspaces, diagnosis shares, discovered and located recipes and their ranking, validation verdicts and notes, and log lines are the same.
Inputs that no in-repo caller produces now behave differently:
new_module_dirs=NoneraisesTypeError, and an empty path is no longer skipped. On Windows only, two module-directory errors name the directory as resolved rather than as spelled. A preserved path that becomes unreadable during restoration is reported as a capture error instead of being skipped.HIP_VISIBLE_DEVICESis recorded as the session's failure after the workspace is enforced, instead of escapingrun_author.forge-fuse. A discovery mode other than patterns, llm or anchored, combined with--repo-scope, gets the repo-scope usage error.run_fusion_loop. A recipe object withoutalready_satisfiedraisesAttributeErrorinstead of counting as unsatisfied.priorityfalls back to the listing-order default; a truthysource_anchorsthat is neither a list nor a string becomes one stringified anchor; a non-numeric category share raises before the first proposal is parsed.TypeErrorformax_abs_erris raised before the one forsnr_db.build_recipes. An invalid regex in the static fused-marker table would raise after the compile-pass probe instead of before it.Single-file discovery now reads the target's source file once per proposal that reaches the scope gate instead of once per run; the result is the same.
Checklist
test_resolve_and_cli.py, five staging tests drop theinheritedandharness_patharguments with their assertions unchanged, andtest_inherited_harness_staging_detects_author_mutationis deleted: it pinned only the deletedinherited=Truemode, which no production path reaches. No other test changed. Linux CI is green at head3c3a1c484.size-exception: the thirteen functions share modules, the baseline file and one review context, and splitting them would put the same files in several PRs. No function this PR adds or changes crosses a gate limit. Over a review trigger and within the gate, each one ordered sequence of steps:_run_registered_author_once(79 lines, cyclomatic 13),parse_discovered_recipes(79 lines),build_recipes(80),runincommand.py(75),run_fusion_loop(73),validate_recipe(71),_run_fusion_stages(68),_microbench_verdict(66) and_AuthorWorkspaceGuard.__init__(63)._salvage_objects(cyclomatic 14, up from 13 now that it also serves the repair) and_extract_json_array(12, down from 13) are character scanners whose branches are the scanner's states._author_baseline_harnesskeeps its 87-line baseline entry; this PR only drops the staging arguments it passes.author.py,command.py,discover.pyandvalidate.pystay over the 1,200-line module limit they were already over, each shorter than at base.Commits
Squash-merged as
b07c1414bfrom head3c3a1c484.27b3fb0b2refactor(fusion): give the author workspace guard one path check and one change scan62ad293earefactor(fusion): split the author session out of _run_registered_author_once102965b59refactor(fusion): delete the inherited-harness staging modea64d83450refactor(fusion): give forge-fuse's stage paths their own functions93b6bfc9crefactor(fusion): bring run_fusion_loop under the size gate37eceb678refactor(fusion): drop the baseline entries the reworked functions left1ac86f149refactor(fusion): one trace reader for both kineto loaders in diagnose5d2e172d3refactor(fusion): salvage and repair truncated proposals in one scan59541e78drefactor(fusion): score each knowledge paragraph once in operator hints11c5b4262refactor(fusion): derive the compile-pass claim from the authored recipeb79db5863refactor(fusion): resolve each proposal's edit files once, share the pass claime3f17a0b7refactor(fusion): split validate_recipe at the microbench gate8ff5b16bdchore(code-metrics): retire the fusion baseline entries this unit fixed9439c5507refactor(fusion): reuse trace event loadingorigin/main