Skip to content

lfm2: keep a drafter's tapped rows on every forward - #1390

Merged
ashhart merged 3 commits into
ashhart:mainfrom
BlivionIaG:series/dspark-taps
Oct 30, 2026
Merged

ashhart merged 3 commits into
ashhart:mainfrom
BlivionIaG:series/dspark-taps

Conversation

@BlivionIaG

@BlivionIaG BlivionIaG commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Keeps a drafter’s tapped target rows across forward, prefill and retained-state paths. Without a drafter the tap path remains off.

Rebuilt on main d33dcfc767ee093393c6bfa00b3949bd7b4d8e88. The rejected #1379/#1382 guard commits are excluded. No M5 was accessed for this restack. Fresh CI is running; maintainer re-review remains required.

Scope and review fixes

Standalone tap changes only; independent of the pricing PR. Tap launch records and two planted controls are retained, along with current main’s unrelated contract registrations.

Validation

Head 4156e9e62. 57/57 build steps and 11/11 Metal draft-source host tests pass; the kernel-contract runner compiles. Lean: 425 on main and this branch, zero new. Device evidence in older comments remains scoped to its original head.

Part of #1374. The chain’s intermediate branches are now updated rather than leaving fixes only in the cumulative tip.

@ashhart ashhart left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Thanks @BlivionIaG. The tap operator has the same contract gap as #1377 (no planted controls or recorded launch limits), and this stacks on #1377.

@BlivionIaG

Copy link
Copy Markdown
Contributor Author

Thanks @ashhart. 3df2d0569 (main and #1377 merged in): the tap kernel has planted controls (rows packed at the hidden size, another tap's column overwritten) and recorded launch limits, as in #1377.

@BlivionIaG
BlivionIaG marked this pull request as ready for review October 26, 2026 21:37
@ashhart

ashhart commented Oct 27, 2026

Copy link
Copy Markdown
Owner

Thanks @BlivionIaG. The tap copy now has its launch record (M1 and M2 from --offline) and two planted controls that
go red, which closes the contract point from our last review. Without a drafter nothing is tapped and every forward runs
as before, stale taps are refused by generation, and a drafting stream only resumes a kept state that holds the
drafter's context.

It merges cleanly onto current main, and fmt, the lean check and zig build test pass on the merged stack. We will land
it after #1377 and our device check, preferably together with #1391 so it arrives with its first user. No changes
needed from you.

@BlivionIaG

Copy link
Copy Markdown
Contributor Author

@ashhart Rebased the tap-only branch on current main d33dcfc76, at 4156e9e62. The tap launch records and both planted controls are retained, and unrelated current-main contracts remain registered. No new functional feature was added. Local metadata checks pass 11/11 and the contract runner builds; zero new lean findings. Fresh CI is running.

BlivionIaG and others added 3 commits October 30, 2026 03:55
The lane core can put an external drafter in front of a target. The
drafter reads the target's hidden rows after some layers (its taps).
LFM2-MoE had no taps, so it could draft only with the core's own heads.

prepare_features names the layers. From then on, each forward copies
each row's output of those layers into the scratch (lfm2_tap, a plain
copy of bf16 values). features() gives a stream's rows of the latest
verify or one-token round. prefill_features hands each prompt chunk's
rows to the drafter before the chunk's end is kept for reuse. The
prompt's last row is kept beside the stream's caches for its first
draft.

A drafting stream resumes only a kept state that also holds its
drafter's context (Snap.draft). Without a drafter nothing changes: no
taps are kept and every forward runs as before.

lfm2_tap registers with the kernel contract (metal_lfm2_tap.zig): the
third of five taps' columns at 1, 10, 32 and 2,048 rows must hold the
layer's bits and the other columns what the call found. Gate 5 checks
its launch against every Apple chip we serve and this GPU.
test-lfm2-dspark checks the same copy through the family's own kernels.
…planted controls

lfm2_tap's launch is in lfm2_records.zig with the limits --offline
compiled, not this GPU's. Two controls edit the source: rows packed at the hidden size, and a column of another
tap overwritten. Each goes red at the shapes gate.
@ashhart
ashhart force-pushed the series/dspark-taps branch from 4156e9e to 5a10ade Compare October 30, 2026 03:55
@ashhart
ashhart merged commit 86e29f6 into ashhart:main Oct 30, 2026
9 checks passed
@ashhart

ashhart commented Oct 31, 2026

Copy link
Copy Markdown
Owner

Thank you @BlivionIaG. This is in TensorFold 1.2.0, released today: https://github.com/ashhart/TensorFold/releases/tag/v1.2.0

It landed with your commits under your own name, so you're listed as a TensorFold contributor, and it's credited to you in the release notes and the changelog.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants