TypeAudio

Compiler asks

This document is the ledger of what TypeAudio rests on in the compiler and what it asks of it. The compiler is typeshade/typeshade. Its proposals live in its changes/ directory, and changes/README.md there is the process. compiler-changes.md at the root of this repository is the other record: it lists the proposals this repository has handled, when the compiler pin moves.

The loop is docs/vision.md, section 10. A row moves through these states:

State Meaning
candidate The pressure is named. Nothing is measured.
measured A workaround exists here. A record names the device, the date, the commit and the numbers.
issue #N The general part is raised on typeshade/typeshade.
proposal NNNN (draft, accepted, implemented) The lifecycle state of the compiler proposal, as its status line says.
retired The pin moved past the implementation, compiler-changes.md records the id, the workaround is gone.

The letters and the ids are stable. A new ask takes the next free letter. After Z, an ask takes two letters, in order: AA, AB, AC. A row never changes its letter.

1. The proposals this engine rests on

Five proposals were drafted and accepted on 2026-11-02, in the session that wrote the design. Four shape the host face a unit shows the developer (docs/vision.md, section 8, "The host face"), and one the fuse report that explain reads. The last two rows, 0119 and 0120, are proposals of the compiler that name typeaudio in their downstream entries. No ask of this ledger leads to either.

Id Proposal What it gives TypeAudio Status on 2026-11-02
0108 changes/0108-host-view-jsdoc.md The host view carries the author's JSDoc verbatim, so a unit's documentation reaches the editor through the host face. Implemented: items 1 to 3 by #887 (77ced44, 2026-11-02), the inherited-field deviation closed by its record; Amendment 1 accepted (#915, bb82036b) and item 4, the members of an exported class carry their comments (decision D4), implemented by #937 (f4f4b7d2, 2026-11-02). Amendment 2 (#978, a80551b4, 2026-11-02) drops the static field from item 4's list, since the view declares none.
0109 changes/0109-host-classes.md An exported class is a value of the host face: new and the methods run on the CPU tier, an instance is the struct's host value, a struct result is an instance. The engine's new OnePole(0.1) on the host rests on it. Implemented (#890, squash commit 9dbc298, 2026-11-02). Two deviations open in the proposal's record: the view's flat declaration where TypeScript refuses an override; a mixin's members untested. Amendment 1 (#960, 376f8927, 2026-11-02, decision D5): item 6, a Resident made from instances keeps their classes and read() returns instances (ask N). Implemented by #993 (87af4eb0, 2026-11-02), which the pin 87af4eb0 holds; pull request #15 of this repository retires the workaround.
0110 changes/0110-class-consistency.md Rule 8.29: a class is its struct and its functions in every place a struct or a function can be. The class arm of the differential gate holds a method to one result in a compute entry, a kernel loop, the host class and the oracle. Implemented (#883, bef6574, 2026-11-02), with the host leg of the class arm on the host class of 0109; the deferral deviation is closed by its record.
0116 changes/0116-host-type-family.md typeshade/runtime exports a family of host types spelled as the shader spells them (f32, vec3, array<f32>), so the host view reads as the .shade.ts file does. Renumbered from 0111 (#884, c33f743). Implemented (#918, 9822490f, 2026-11-02) with Amendment 1 (#925, 334b9fc4), which declared the twenty exports of the common modules and §74 and decided D7 to D10: a struct is spelled by its name and an exported class as the class, a struct binding by its name beside its packed forms, a matrix carries its name, and item 4 names its exceptions.
0118 changes/0118-fuse-group-tier.md Each group of a FuseReport carries the tier it ran on, and a group below its plan's tier says why in its why, so explain reads where each node ran instead of inferring it (ask P). Implemented (#990, 480b6a64, 2026-11-02), which the pin 87af4eb0 holds. Accepted (#959, 6c1799ec) with D1 to D3 as drafted: tier on every group; the reason in why; the call layer's own text. One deviation open in the proposal's record (D-1): the reason a tier gives for a call it has no program for repeats "runs on the CPU" (peak runs on the CPU, it runs on the CPU, loop 1 reduces, ...). Pull request #15 of this repository retires the workaround.
0119 changes/0119-subgroup-reduction-variant.md A kernel function's reduction whose operator gives one value in every order folds inside a subgroup first on a WebGPU device that has subgroups, as a second WGSL variant that the runtime selects by feature and probe: an integer +, a bitwise operator, min or max, and min or max on a float; and a scatter a[k] op= e into an integer array. No source changes, and the bits are the tree's. peak (src/kernels/meter.shade.ts, shape R) reduces with max on f32, which the variant covers. An f32 sum keeps the tree, as sumFrame of experiment 4 does. The proposal's entry for typeaudio says "No known integer reduction in a kernel function. The record notes the id at the pin." Accepted (#977, merge 64caf3ea, 2026-11-02), amended twice by #1024 (d7f035ea, 2026-11-03), and implemented on the compiler's main (ad0a3865, read 2026-11-03) after the pin, in three stages: #1020 (8d693f34, the second WGSL text), #1026 (043f8cad, the runtime selects it by feature and a known-answer probe) and #1027 (ad0a3865, Rules 8.22, 10.2 and 11.23, surface §38, §65 and §69). The proposal reads implemented, with deviations D-1 to D-7 in its record. D-2 (a fused plan keeps one text) and D-3 (reflect().variants is not delivered) are open. The pin 87af4eb0 holds none of it. It names typeaudio under downstream, so scripts/downstream-impact.ts lists it once a pin passes its implementation, and compiler-changes.md then records its id. At the next pin move this repository gets: the variant for a call of peak that is not fused (D-2), on a device that has subgroups and passes the probe, with the same bits and no source change; DeviceInfo.subgroups, the observation of the probe or null; DeviceStatistics.variants, the text ('subgroup' or 'tree') that the last call of each kernel function dispatched; and createDevice({ subgroups: 'off' }), which skips the probe. Nothing here is retired. Inference: while D-2 is open, the engine's block keeps the tree for peak, which is the last call of a fused group on WebGPU (bun run test:gpu prints "mixdown+drive+gain+peak (fused)"); and explain could name the variant that Device.statistics gives.
0120 changes/0120-device-rhi.md createDevice() becomes the one public entry point. A Device keeps every member it has, and gains the operations of the program runtime (load, frame, sampler, submit, native, canvas and draw), over a render hardware interface that the compiler owns, with a CPU backend for the program runtime. createRuntime(), runtime(), Runtime and RuntimeOptions stay for one release with a warning, and the release after it removes them, with configure({ runtime }). The proposal says that a host of createDevice() and of entry and kernel calls sees no change, except one WebGL2 context (its open point O5). Accepted (#1030, 66bdb832, 2026-11-03). Not implemented at the pin 87af4eb0 or on the compiler's main (read 2026-11-03). It names typeaudio under downstream: "The same search and migration as typenn", that is, a host or test that calls createRuntime, runtime() or configure({ runtime }) moves to createDevice() before the release that removes them. So scripts/downstream-impact.ts lists it once a pin passes its implementation, and compiler-changes.md then records its id. One file here would change: experiments/07-sound-match/browser.ts calls createRuntime, rt.load, rt.frame, rt.device, rt.tier and rt.destroy, and would move to createDevice(), device.load, device.frame, device.native, device.tier and device.dispose (the proposal's migration table). No call of runtime() and no configure({ runtime }) was found here (searched on 2026-11-03). The rest of this repository imports createDevice, configure({ prefer }), resident, Device, DeviceInfo, DeviceStatistics, FuseReport, mergeReports and Resident from typeshade/runtime. Of them the proposal lists createDevice, configure, Device and DeviceOptions among its reshaped exports. A proposal to watch at the next pin move.

At the first compiler pin, 145666068ca5d6ecfba32aa0ea4289cf0fc3b762 (pull request #5), the proposals' status lines read: 0108 accepted, 0109 implemented, 0110 implemented, 0116 accepted. The implementation of 0116 (#918, 9822490f) came after the pin. So did 0108's item 4 (#937, f4f4b7d2), the fixes #953, #962 and #964, and the acceptance of 0118 (#959) and of 0109's Amendment 1 (#960).

At the second compiler pin, 87af4eb0d9d15f02b66b8341b72cab0944290472 (pull request #15), the status lines of 0108, 0109, 0110, 0116 and 0118 read implemented. The move passed the implementations of 0116 (#918), of 0108's item 4 (#937), of 0118 (#990, 480b6a64) and of 0109's Amendment 1 (#993, 87af4eb0), and the fix #962. compiler-changes.md records 0109 and 0118. The status line of 0119 reads accepted at that pin, and the pin holds no implementation of it. The script lists 0119 once a pin passes its implementation.

2. The asks

Each row names the pressure, the compiler's place, the workaround this repository writes first, and the experiment that measures it (docs/experiments.md). Every row is a candidate on 2026-11-02 unless its status says otherwise. docs/vision.md, section 9, cites D, E and F.

A. A lane writes its own block of frames

B. A metadata channel from a class to the host

C. The precision of the transcendentals

D. f64 transcendentals on the device

E. Subnormals

F. A worklet build of the CPU tier

G. An FFT as a common module

H. GPU time

I. The cost of many dispatches

J. A length read inside a loop body or an index on WebGL2

K. The WebAssembly tier

L. Reverse-mode grad

M. A static builder on an abstract base

N. A Resident of class instances reads back as objects of their fields

O. A composed unit keeps its class on the host only in its own file

P. The tier of each group in a fuse report

Q. A pin that Node loads

R. A method's comment in the host view

S. The cost of the CPU tier's generated code

T. A sum over the lanes of each frame on the GPU

U. The dispatches and the arrays of each group of a fuse report

V. The CPU tier's cost of entering a call with a long array

W. A loop that pushes over a range the device holds

X. A write at an offset the host passes, out[at + n]

Y. The dispatches of each group in a fuse report

Z. A plan's GPU time without a read of each plan

AA. WebGL2 loops for a kernel that writes a vec2 element, writes off its counter, or writes two arrays

3. Issues raised on the compiler

The issues found while the proposals were implemented, on 2026-11-02, the issues the first code raised (pull request #5, asks M, N, P and Q), the issues experiments 2 and 3 raised (asks S, C and E, and the FFT's findings under G), the issues experiments 4 to 7 raised (#983 to #986, #991, #992, #997, #998, #1017 and #1018), and the earlier issues the asks cite.

The states are those of 2026-11-03, at the pin 87af4eb0.

Issue Title, shortened Bears on Status
#900 The WebGL2 pass program drops _phx_len_table for a length read inside an index J Fixed by #939 (b3bf0af8), in the pin 87af4eb0
#901 The commit-msg hook reads a merge against its first parent The implementing pull requests, not the engine Closed: fixed by #932 and #956
#908 TS8070 names a static function by its emitted name The refusal's wording for a unit's static helper Fixed on main by #953 (a659ae36)
#689 A kernel loop that reads another array's .length has no WebGL2 tier J Open
#459 A WebAssembly tier between WebGL2 and the CPU K, F Open; change 0042 draft
#535 Reverse-mode grad before 1.0 L Open; change 0056 accepted
#539 A stable sort of u32 keys with values on every tier Experiment 6: one cloud's grains need no sort Open
#542 GPU time through typeshade/runtime H Open
#543 The cost of many dispatches I Open
#944 new this() in a static builder of an abstract class is refused (TS8035) M Closed: fixed by #962 (20759ec9), in the pin 87af4eb0; ask M retired
#945 read() of a Resident of class instances returns plain objects N Open; answered by 0109 Amendment 1 (#960), implemented by #993 (87af4eb0), in the pin; ask N retired
#946 The fuse report names the plan's best tier but not the tier of each group P Open; answered by change 0118 (#959), implemented by #990 (480b6a64), in the pin; ask P retired
#947 A source tarball pin has no dist/: tshc and the Vite plugin fail under Node Q Open
#961 The CPU tier allocates an array for the inout values of every method call S Open
#966 WebGL2 does not bind the _fp64 guard of an f64 entry; the call never returns G (variant C), D Closed: fixed on main by #1003 (92c3d2ff), after the pin; the workaround stays until the pin moves past it
#967 An f64 module constant is refused, with a misleading TS8022 after it G (variant C), D Open
#968 The determinism report has no row for subnormal flushing E Open
#969 A device's sin/cos may use all of the 2^-11 bound; a bounded-error form C Open
#970 WebGL2 refuses an f64 local kept across a barrier G (variant C), D Closed: fixed on main by #1014 (130c4bf9), after the pin; the workaround stays until the pin moves past it
#983 The kernel-loop proof refuses a write at tape[at + n] (TS8070) where tape[n * 1 + at] lowers X (experiments 5 and 6) Closed: fixed by #994 (3b7019da), in the pin 87af4eb0; the workarounds stay in the code
#984 A loop that pushes over a range the device holds runs the whole function on the CPU tier W Open
#985 FuseReport.dispatches counts 10 for a plan whose groups' workgroupShapes show 3 U and Y (the count of dispatches) Open
#986 A plan on a device with timestamp-query maps its timestamps back before it resolves Z Open
#991 A per-frame sum over lanes in the tree order has no GPU form T Open
#992 A scratch array of a fuse scope is destroyed after every plan, so a stream re-creates it each block U (the arrays of a group) Open
#997 The call's read check refuses a guarded read that stays inside the array (a TypeError; tshc check says nothing) Experiment 5 (record 05, candidate issue 1): the guarded pad Open; pull request #1029 open
#998 A queued call runs on the output of a call that failed Experiment 5 (record 05, candidate issue 2): a block that queues its calls Open; a decision on the queue after a failed call (propagate the error: a proposal; or document it)
#1017 compileModuleJs runs a reverse-mode derivative with a loop in the interpreter L Fixed on main by #1019 (e30bbe57), after the pin; the probe form of experiment 7 retires when the pin moves past it
#1018 The pipeline of a reverse-mode derivative with a frame loop grows past usable with the parameter count (SwiftShader) L Open

4. How a row moves

  1. Write the workaround in this repository, in the unit it belongs to or under experiments/.
  2. Run the experiment on a device.
  3. Write the record: the command, the date, the commit, the pin, the device and the numbers.
  4. Set the row's status to measured, with the record's id.
  5. Raise the general part as an issue on typeshade/typeshade. Set the status to issue #N.
  6. Open a proposal in the compiler's changes/, status: draft, with downstream: typeaudio.
  7. When the proposal is implemented, move the pin and record the id in compiler-changes.md.
  8. Retire the workaround. Set the status to retired.