debug info, inspect --graph, and honest failure preservation
September 2026 snapshot: the compiler can finally tell a debugger where your code lives, the inspector can walk the semantic graph, and failure artifacts stay where you can find them.
Opt-in DWARF debug info
Section titled “Opt-in DWARF debug info”janus build --emit-debug-info now carries real debug metadata end-to-end:
DW_TAG_compile_unit(producerJanus compiler) andDW_TAG_subprogramentries with reallow_pc/high_pcranges.- Per-instruction
DILocationlines resolved from ASTDB source coordinates —addr2linemaps call sites back to the correct.janline. - DWARF4 line tables for binutils 2.47 compatibility (Gap 174), including per-thunk subprograms for compiler-generated thunks (Gap 175).
The flag stays off by default: a janus build without it is unchanged, byte
for byte. Debug-info carriers are strictly for debuggers — SPEC-259 forbids
using !dbg for Traceline carriers, which ride as opaque values instead.
janus inspect --graph and --traceline
Section titled “janus inspect --graph and --traceline”janus inspect app.jan --graph=42 # JSONL dump rooted at ASTDB node 42janus inspect app.jan --traceline=<uuid> # placeholder: exits non-zero until SPEC-259 P1--graph=<node_id> (SPEC-259 §7.2) emits a JSONL dump of the semantic graph
rooted at the given ASTDB node id — the first P0 piece of the Traceline
story. --traceline=<uuid> (§7.3) is accepted but honestly pending: it exits
non-zero so CI scripts can detect the unfinished state instead of silently
returning nothing.
Failure artifacts you can actually find
Section titled “Failure artifacts you can actually find”janus build --keep-temps-on-failure now does what it always claimed (Gap
166): a failed compile preserves the scratch directory and prints its path to
stderr, while successful builds clean up as before. Companion tooling: setting
TRACE_NODE=<qtjir_node_id> prefixes lowering-pass trace lines with
[TRACE_NODE=<id>] so a single node’s lifecycle can be grepped across all
emission sites (Gap 169).
Compiler fixes
Section titled “Compiler fixes”- Gap 149 — checked integer-cast sentinels convert into error unions.
- Gap 160 —
Shron an unsigned left operand lowers toLShr, notASHR. - Gap 162 — imported structs with slice fields and inline methods keep their layout across module boundaries.
- Gap 165 — interpreter bitwise/shift ops, EU passthrough, and signed truncate brought in line with the AOT path.
- Gap 163 (S4) — canonical-prefix mangling for cross-importer alias bridges.
Stdlib
Section titled “Stdlib”std.encoding.msgpack— error paths migrated tofail/error-union contract wording.
Build tooling
Section titled “Build tooling”scripts/zb (the OOM-protected build wrapper) now throttles the full test
suite to -j6 under a hard CPUQuota=480% systemd ceiling — faster suites on
big machines without starving the desktop. Tune with ZB_MAX_TEST_JOBS and
ZB_TEST_CPU_QUOTA.
Verification at the cut
Section titled “Verification at the cut”Full ./scripts/zb test on this tree: 160 compile steps green, 5 known-red
steps in 3 classes, all reproduced identically on the pre-v2026.9.1-alpha
binary (pre-existing baseline reds, not regressions): the
std/io/adapters_smoke cross-module impl-method symbol (Gap 148 family
reopen), the xmod_func_alias_reexport tombstone (Gap 163 reopen), the
std/code_graph SliceLen ICE (Gap 176), and the fnptr-capture link failure
(Gap 177). Gaps filed in the compiler gap tracker with repros.