Skip to content

fix(kernel): follow KernelForge's CLI where it moved - #1228

Open
ZhengGong-amd wants to merge 3 commits into
mainfrom
feat/zgong/kernel-merge
Open

fix(kernel): follow KernelForge's CLI where it moved#1228
ZhengGong-amd wants to merge 3 commits into
mainfrom
feat/zgong/kernel-merge

Conversation

@ZhengGong-amd

@ZhengGong-amd ZhengGong-amd commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator
  • Description: what and why

KernelForge removed one CLI option and renamed another. This makes the places
that address its CLI match what it now declares, and — found while auditing
that surface — repairs a third producer/consumer disagreement that had been
silently discarding the published best result.

forge-fuse: --llm-model is now --model (forge_fusion.py:136).
This one is fatal today. forge-fuse is a plain click command, not one of the
tolerant ones, so an option it no longer declares raises UsageError and the
child exits 2 having authored nothing. The wrapper then finds no manifest and
reports no fusion_manifest.json at ... (forge-fusion rc=2) — an
infrastructure-shaped error for what is really a stale flag. Only the argv
string moves; llm_model stays as the key of the wrapper's own input JSON,
which is what request_handlers._run_forge_fusion writes. KernelForge renamed
--gpu-arch to --gpu-target in the same commit, but this repository never
passed it.

forge-loop / forge-rewrite-by-flydsl: --max-iters is gone. Both are
TolerantCommands, so sending it was never fatal — it was warned about, listed
in ignored_cli_options, and dropped. It is now gone from all three argv
builders in forge_submit.py, together with the parameters that carried it and
the FORGE_MAX_ITERS / FORGE_COMPILED_MAX_ITERS environment variables behind
them.

That last part deserves a sentence of its own: the compiled/ASM fellow cap
those variables fed could not have been working. KernelForge stopped acting
on --max-iters when the supervisor's intervention limit was removed, and its
own help had said "accepted but does not limit iterations or interventions"
ever since. So log.info("forge: capping compiled/ASM fellow %s iters %d -> %d")
announced a policy nothing enforced. Removing it changes no runtime behaviour;
it removes a false log line and two knobs that did nothing. Campaign length is
--max-hours plus the hard-kill timeout, which is what it already was. If the
intent — a smaller budget for structurally low-yield fellows — is still wanted,
the honest form is a reduced --max-hours for non-triton fellows, and that is a
policy change worth its own PR rather than a silent revival here.
forge_collective had already stopped sending the flag, calling it "a
documented no-op"; this follows that precedent.

Checked and deliberately not changed:

  • The fusion manifest reader keys off fusion_loop.kept
    (forge_fusion.py:255), which is precisely the field KernelForge tightened to
    require the loop's best_commit before it reports a keep. It inherits the
    stricter verdict with no edit, and never infers a keep from a non-null
    speedup. Manifest keys, values and schema_version are unchanged upstream.
  • Nothing here imports kernel_agents or forge_llm at the Python level (only
    install.sh's import probe, whose targets still exist), so KernelForge
    lifting the workspace guard out of its Codex backend and deleting
    CodexSafetyError reaches nothing in this repository. The codex_session.py
    docstring that mentions the guard says only why CodexBackend cannot be
    reused, which is still true.
  • Every other option in all five argv builders here — _run_loop_via_cli,
    _run_rewrite_via_cli, _run_vendor_playbook_loop_via_cli,
    forge_collective._build_cmd, forge_fusion._build_cmd — was cross-checked
    against KernelForge's current cli.py and fusion/command.py. All still
    declared, with unchanged types and defaults.

best_result.json was being thrown away, and now is not.
forge_submit.py:2298 gated the published best on schema_version != 1, but
KernelForge has stamped 2 there since 2026-08-13
(MANIFEST_SCHEMA_VERSION, loop/reporting.py:24) — before this series, so
this is a pre-existing drift rather than fallout from it.
_validated_forge_best_result therefore rejected every published best and the
kernel backend fell through to the caller checkpoint or the stdout sentinel,
losing the one record that survives a hard kill, which is the case that file
exists for.

The gate now names the producer's constant rather than a bare literal, and a
test pins the two together (pytest.importorskip on
kernel_agents.loop.reporting, so it runs wherever KernelForge is resolvable
from $FORGE_PATH and skips elsewhere) so the next bump cannot drift
unnoticed. The checkpoint gate beside it stays at 1 — the checkpoint really
does carry that version.

What makes this low-risk rather than a leap: eight tests already covered this
salvage path end to end — timeout salvage, recovery-channel disagreement,
in-place restore failure, same-iteration conflict — and they were passing only
because their own fixtures repeated the wrong version. Pointing the fixtures at
what the producer publishes was the only other change needed. The behaviour was
specified and tested all along; it was simply unreachable in production.

  • Linked issue(s): none. Pairs with the KernelForge branch
    refactor/zgong/shared-substrate, whose CHANGELOG [Unreleased] records the
    removed option and the two renamed ones.

  • Tests: added/updated? commands run?

Updated. The argv tests now assert the absence of both flags rather than
their values, so neither can come back unnoticed:
test_forge_long_horizon_cli.py adds --max-iters to the existing
"options forge-loop does not declare" loop and asserts it out of the rewrite
argv; test_forge_fusion.py asserts --model is present and --llm-model is
not. The max_iters= keyword arguments in four test modules went with the
parameters they fed.

One test added: the schema pin described above. Four fixture files now carry
the schema_version the producer writes.

pytest src/hyperloom/agents/kernel/tests/ -q
    3 failed, 1895 passed, 27 skipped
    (the 3 failures reproduce on a clean origin/main checkout: two
     credential-precedence tests and one hermetic-env test that read the
     ambient environment)
pytest src/hyperloom/inference_optimizer/tests/test_kernel_request_handlers_units.py -q
    331 passed
ruff check <changed files>
    All checks passed
  • Breaking changes: yes — for operators only, and only nominally.
    FORGE_MAX_ITERS and FORGE_COMPILED_MAX_ITERS no longer exist. Anything
    setting them was setting a value that reached a flag KernelForge discarded, so
    no run changes shape; the variables just stop being read. Recorded under
    ### Removed in the changelog.

🤖 Generated with Claude Code

Two options this repository sends to KernelForge no longer exist there.

`forge-fuse` renamed `--llm-model` to `--model`, and unlike `forge-loop` it is
not a tolerant command: an unknown option is a click UsageError, so the child
exited 2 before authoring anything and the wrapper reported the outcome as a
missing `fusion_manifest.json` — an infrastructure-shaped error for what was
really a stale flag. Only the argv string moves; the `llm_model` key in the
wrapper's own input JSON is what the orchestrator writes and stays as it is.
`--gpu-arch` was renamed alongside it, but this repository never passed it.

`--max-iters` was deleted from `forge-loop` and `forge-rewrite-by-flydsl`.
Those two are tolerant, so sending it was never fatal — it was reported as an
ignored option and dropped. It is gone from all three argv builders here,
along with the parameters that carried it and the `FORGE_MAX_ITERS` /
`FORGE_COMPILED_MAX_ITERS` environment variables behind them. The compiled/ASM
fellow cap those fed could not have worked: KernelForge stopped acting on the
value when the supervisor's intervention limit was removed, so the block
logged a cap it never applied. Campaign length is `--max-hours` and the hard
kill, which is what it already was. `forge_collective` had already stopped
sending the flag for the same reason.

The argv tests now assert the absence of both flags rather than their values,
so neither can return unnoticed.

Not changed, having been checked: the fusion manifest reader keys off
`fusion_loop.kept`, which is exactly the field KernelForge tightened to require
a commit, so it inherits the stricter verdict with no edit; nothing here
imports from `kernel_agents` or `forge_llm`, so the workspace guard moving out
of the Codex backend and the deletion of `CodexSafetyError` reach nothing; and
every other option in all five argv builders is still declared upstream.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ZhengGong-amd
ZhengGong-amd requested a review from a team as a code owner August 19, 2026 02:43
_validated_forge_best_result gated on schema_version == 1. KernelForge has
stamped 2 into best_result.json since 2026-08-13, so the gate rejected every
published best and the kernel backend fell through to the caller checkpoint or
the stdout sentinel — losing the one record that survives a hard kill, which is
the case that file exists for.

The gate now names the producer's constant instead of a bare literal, and a
test pins the two together so the next bump cannot drift unnoticed. The
checkpoint gate beside it stays at 1: the checkpoint really does carry that
version.

Eight tests already covered this salvage path in full; they were passing only
because their own fixtures repeated the wrong version. They now publish what
the producer publishes, which is why fixing the gate needed no other change:
the behaviour was specified and tested all along, just never reachable.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Aug 19, 2026

Copy link
Copy Markdown

CI E2E report — ❌ Failed

item value
result ❌ Failed
model Qwen/Qwen3-0.6B (dense)
resources 1× GPU, TP=1
PR branch feat/zgong/kernel-merge
commit 921f0beb6ddee9cafabbfd6d89f848723b5d5b33
session_id ffd82ddc-7b81-46a5-9e2f-ddc172828517
queue → dispatch 386m 2s
run time 4m 22s
total 390m 24s

details

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant