You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The schematic canvas already paints a wire's live 1-bit-style logic state through color and stroke (issues #76/#77): a WireNet with no value draws dashed and in the "off" color, an all-zero net draws thin and in the "zero" color, and a net carrying any non-zero bit draws thick and in the "non-zero" color. What the canvas does not do is show a numeric value for a multi-bit net — every non-zero multi-bit bus paints identically regardless of whether it carries 1 or 0xFFFF, and there is no way to see a bus's actual value without opening ElementValueDisplays' modal report or the trace window. This task closes that specific gap: an on-canvas numeric value label for multi-bit WireNets, plus a UI toggle for on-canvas value rendering (color/stroke and the new label together), reusing the paint-time read the coloring already performs — no new sampling tap, no new serialized state.
Intended Audience & Impact
Students drawing and simulating circuits in the editor. Today, reading a multi-bit bus's value mid-simulation means stopping to click the wire and read a modal dialog (ElementValueDisplays.show, src/jls/edit/ElementValueDisplays.java), or opening the trace window — both break the student's focus on the live schematic. A numeric label drawn where the wire already is removes that detour for the common case of "what value is this bus carrying right now."
Instructors authoring or grading in batch (-b) mode. No effect: batch mode never constructs the CircuitPanel/CircuitRenderer paint path this task touches (see § Observations, O5), so nothing changes for headless runs regardless of the toggle's default.
tier: taskevidence_commit: c5cee1baff3451a85787b4a09bd0b2b05af7dfddpart_of_feature: 533# FEAT-C23-4; this task was filed as TASK-C533-3 under itblocked_by: []blocks:
- 693# sibling task under #533; directive states this task lands before it
- 695# sibling task under #533; its in-flight-event overlay draws on top of# this task's on-canvas value state, so it must land firstrelated:
- 504# CAP-23; its §1 step 3 wavefront animation is described as depending# on this task's rendering path, but 961 is a task and 504 is a# capstone — per scientific-task v6 rule 8 a task may not carry a# blocks/blocked_by edge to a capstone, so this is recorded# reference-only here (the capstone-side edge, if any, lives on #504)
- 76# prior art: the 1-bit color channel this task's label sits beside
- 77# prior art: ElementRenderer/CircuitRenderer split this task reuses
- 527# named by the old filing as the owner of recording/history and a# future SampleSink stream; neither WaveModel nor SampleSink exist# in the tree at evidence_commit (git grep, § Observations O6), so# this task reads WireNet.value directly, not through #527's stream
The #693/#695/#504/#527 relationships above are carried forward from the original filing's prose (maintainer directive, 2026-08-16); this migration did not and could not re-verify their current state on GitHub (out of scope for this pass — see § Open Questions & Decisions Needed).
1. Background & Prior Work
Wire and wire-end rendering moved off the model classes and into the jls.edit renderer registry in issue #77: ElementRenderers.draw (src/jls/edit/ElementRenderers.java:47-56 (quotes: * element's own {@code draw} if none is registered.; } else {)) dispatches to a registered ElementRenderer — WireRenderer for Wire and WireEndRenderer for WireEnd — registered in BuiltinElementRenderers.install() (src/jls/edit/BuiltinElementRenderers.java:100-101). Issue #76 added the "second channel" principle this task extends: value state must be readable without color vision, so Wire/WireEnd already carry both a color and a stroke/glyph encoding, pinned by test/jls/elem/WireValueChannelTest.java.
jls.sim.TraceGeometry (src/jls/sim/TraceGeometry.java:1-9) is the precedent this task's Outcome text points at for a "headless model, thin Swing consumer" split: pure display-geometry computation, deliberately free of AWT, unit-tested independently of the Swing trace viewer it feeds. ARCHITECTURE.md:224-226 (quotes: Layer 1 (present) is headless model assertions; layers 2 (Swing) names this the project's "Layer 1" (headless model assertions) versus "Layer 2/3" (Swing harness, render-to-image) split.
Issue #527 is named by the original filing as the eventual owner of value recording (a SampleSink stream); no WaveModel or SampleSink type exists anywhere in the tree at evidence_commit (git grep -rln "WaveModel\|SampleSink" -- '*.java' returns no results), so this task cannot attach to that stream and instead reads WireNet.getValue() directly at paint time, the same way the existing color/stroke encoding already does.
2. Observations
O1 — the color/stroke value channel for 1-bit-shaped state already exists and is a live paint consumer, not a test fixture.WireRenderer.draw (src/jls/edit/WireRenderer.java:58-91) reads the net's value every paint:
BitSetvalue = w.hasNet() ? w.getValue() : null;
(src/jls/edit/WireRenderer.java:62), then selects a Palette color per state:
(src/jls/edit/WireRenderer.java:69-76), and a matching stroke via strokeFor (src/jls/edit/WireRenderer.java:43-56): dashed for null/HiZ, a thick round stroke for any non-empty value, a plain 1px stroke for an all-zero value. This is called from the real interactive paint path, not only from a test: CircuitRenderer.draw calls ElementRenderers.draw(g, el) for every visible wire (src/jls/edit/CircuitRenderer.java:144), and CircuitRenderer.draw is itself called from SimpleEditor's paintComponent override:
CircuitRenderer.of(circuit).draw(g,selected,me);
(src/jls/edit/SimpleEditor.java:2488, inside paintComponent opening at src/jls/edit/SimpleEditor.java:2448). This refutes the original filing's Outcome claim that "Wire has no draw path that consults WireNet.value" — it does, and has since issues #76/#77.
O2 — no numeric value label is drawn on the canvas for any wire, 1-bit or multi-bit.BitSetUtils.toDisplay is the codebase's one value-to-string formatter (src/jls/BitSetUtils.java:237-244 (quotes: return str;)). git grep -n "BitSetUtils.toDisplay" -- '*.java' returns 14 call sites, all inside src/jls/elem/ (Display.java:295, InputPin.java:128, JumpEnd.java:314, JumpStart.java:313, Memory.java:950-951, OutputPin.java:114,224, Pin.java:289,293, Register.java:467,681,684, Wire.java:342) — every one feeds a tooltip/infoText/TellUser dialog or a System.out trace line, none a Graphics draw call. git grep -n "drawString" -- 'src/jls/edit/WireRenderer.java' 'src/jls/edit/WireEndRenderer.java' matches only the existing probe-name label (src/jls/edit/WireRenderer.java:106,112,123,128); there is no second drawString for a value.
O3 — Wire.infoText already formats a value string on click/hover, but only for that modal path, and toDisplay has no radix parameter.Wire.infoText builds ", value = " + BitSetUtils.toDisplay(getValue(),net.getBits()) (src/jls/elem/Wire.java:342). BitSetUtils.toDisplay's signature is toDisplay(@Nullable BitSet value, int bits) (src/jls/BitSetUtils.java:237) — it takes no radix argument and always returns the fixed composite string "0x" + hex + " (" + decimal + " unsigned, " + signed + " signed)", or "HiZ" for null (src/jls/BitSetUtils.java:239-243). There is no per-WireNet or global "active radix" setting anywhere this formatter consults; radix is instead a private, per-element display preference on individual elements — e.g. Constant's own default radix field (src/jls/edit/ConstantDialog.java:41) and Display's own radix radio buttons (src/jls/edit/DisplayDialog.java:79-120 (quotes: /** Radio button selecting binary display radix. */; radix.add(b16);)) are each configured independently per element instance, not from any shared or wire-scoped setting.
O4 — no on-canvas value-rendering toggle exists.git grep -n "showValue\|ShowValue\|valueRendering\|ValueRendering\|WireValueStyle" -- '*.java' returns no results. The color/stroke encoding of O1 is unconditional today: it runs on every paint of every wire with no way to turn it off from the UI.
O5 — batch/headless runs never reach the paint path this task touches, independent of any toggle. Batch mode is documented as one of JLS's "headless one-shot modes" (src/jls/ToolkitPolicy.java:24) and is offered as the -b flag "run in batch (headless) mode" (src/jls/JLSStart.java:763 (quotes: "run in batch (headless) mode"),)). WireRenderer, WireEndRenderer, CircuitRenderer, and SimpleEditor all live in src/jls/edit/, a package excluded from the headless core by design (ARCHITECTURE.md's headless-core packages, enforced by HeadlessCoreRatchetTest, test/jls/HeadlessCoreRatchetTest.java:53), and no batch code path constructs a SimpleEditor/CircuitPanel to invoke paintComponent. HeadlessCoreRatchetTest's FORBIDDEN_IMPORT pattern (test/jls/HeadlessCoreRatchetTest.java:56-58 (quotes: + "(?:java\.awt\.|javax\.swing\.|jls\.edit\.)");)) forbids java.awt.*/javax.swing.*/jls.edit.* imports inside CORE_PACKAGE_PREFIXES, which includes src/jls/sim/ and src/jls/elem/ (test/jls/HeadlessCoreRatchetTest.java:74-76) — i.e. the ratchet this task's AC2 cites is already the mechanism keeping value rendering out of headless code, and this task adds nothing to jls.sim or jls.elem that would trip it.
O6 — no SampleSink/WaveModel recording layer exists yet.git grep -rln "WaveModel\|SampleSink" -- '*.java' returns no results at evidence_commit. The original filing's "or #527's SampleSink stream where one is already attached" alternative is therefore not available today; this task can only read WireNet.getValue() directly, the same access WireRenderer already uses (O1).
O7 — no Wire-adjacent state is persisted today beyond connectivity and tri-state.Wire.save is a documented no-op: "Wires don't get saved." / public void save(PrintWriter output) { // do nothing } (src/jls/elem/Wire.java:120-125). WireEnd.save (src/jls/elem/WireEnd.java:586-593 (quotes: if (isAttached()) {)) writes only a tristate flag and, if attached, the connected put's name — no value, radix, or rendering-mode field of any kind.
3. Research Question
Can a multi-bit WireNet's current numeric value be shown on the schematic canvas, and on-canvas wire-value rendering as a whole be made user-toggleable, without adding a second sampling mechanism, without changing the .jls file format, and without adding an AWT/Swing import to jls.sim?
4. Hypothesis (falsifiable)
H1. A multi-bit numeric value label can be added to WireRenderer.draw's existing per-wire paint call, reusing the already-fetched BitSet value (src/jls/edit/WireRenderer.java:62) and the existing text-layout pattern the probe-name label already uses (src/jls/edit/WireRenderer.java:97-131 (quotes: } // end of draw method)), without any new field on Wire or WireNet and without a new Graphics acquisition path.
H2. A UI toggle for on-canvas value rendering (color/stroke plus the new label) can be added as pure state read at paint time — no persisted field, no .jls schema change — because no such state exists on Wire/WireEnd/WireNet today (O7) and save() for both element types already ignores rendering concerns entirely.
H3. Because WireRenderer/WireEndRenderer/CircuitRenderer already sit entirely inside src/jls/edit/, outside every package HeadlessCoreRatchetTest polices (O5), this task can satisfy "no AWT/Swing import added to jls.sim" (the surviving, narrower form of the old AC2) without any special-casing — the ratchet already forbids it structurally.
5. Predictions
P1. At evidence_commit, git grep -n "BitSetUtils.toDisplay\|drawString" -- 'src/jls/edit/WireRenderer.java' shows zero value-label draw calls (confirmed, O2). After the fix, it shows at least one, gated on the net being multi-bit (net.getBits() > 1) and on the new toggle being enabled.
P2. At evidence_commit, git grep -n "showValue\|ShowValue\|valueRendering\|ValueRendering" -- '*.java' returns no results (confirmed, O4). After the fix, it resolves to a discoverable toggle (menu item and/or preference field) with its own unit test asserting the paint path is unchanged when the toggle is off.
P3.test/jls/elem/WireValueChannelTest.java's existing assertions (O1's color/stroke encoding) continue to pass unmodified — this task does not touch the 1-bit color/stroke channel, only adds the multi-bit label and the toggle around the whole value-rendering feature.
P4. Saving a circuit with the new toggle on and again with it off produces byte-identical .jls output, because neither state lives on Wire, WireEnd, or WireNet (H2, O7) — no new save()/load() branch is added.
P5.test/jls/HeadlessCoreRatchetTest.java's BASELINE gains no new entries: the new label/toggle code lives in src/jls/edit/, never in src/jls/sim/ or src/jls/elem/ (H3).
6. Materials & Apparatus
Existing headless-render test harness pattern from test/jls/elem/WireValueChannelTest.java's render(Consumer<Graphics2D>) helper (renders to an off-screen BufferedImage, counts non-background pixels) — reusable for a new label-presence assertion without a display.
mvn verify (tests + SpotBugs, warnings-as-errors) as the standing gate; not run as part of this filing pass per the enhancement evidence standard (no build executed — see § Open Questions & Decisions Needed).
No new test rig needs to be built first: WireValueChannelTest's fixture-construction pattern (Circuit → WireEnds → Wire → WireNet → net.setValue(...)) already exercises exactly the object graph a multi-bit label test needs, just with a wider BitSet/bits value.
7. Interface & Data Contract
7.1 External interfaces modified
GUI surface only: the schematic canvas (SimpleEditor's circuit panel) gains (a) a numeric value label drawn beside/along multi-bit wires and (b) a new toggle (menu item and/or preference) controlling whether on-canvas value rendering (existing color/stroke plus the new label) is active. No CLI/batch (-b) flag changes — batch mode never constructs the panel this touches (O5). No .jls file format change (docs/file-format.md) — Wire.save/WireEnd.save are unaffected (O7, P4). No HDL export change (jls.hdl is untouched by this task's scope).
7.2 External interfaces consumed
java.awt.Graphics/Graphics2D, FontMetrics for text measurement and drawString for the label — the same JDK surfaces WireRenderer.draw already consumes for the probe-name label (src/jls/edit/WireRenderer.java:97-131 (quotes: } // end of draw method)). No new JDK API, environment variable, font, or OS service.
7.3 Data consumed (structure)
The task reads WireNet.getValue() (a @Nullable BitSet, src/jls/elem/WireNet.java:428) and WireNet.getBits() (int), both already public accessors on the in-memory circuit model — trusted, process-local state, not hostile input (the .jls file itself is untouched, see 7.1). No external schema.
7.4 Internal interfaces provided — public
A value→style mapping in the spirit of TraceGeometry (src/jls/sim/TraceGeometry.java:1-9): given a BitSet/null value and a bit width, return the label text (reusing BitSetUtils.toDisplay, src/jls/BitSetUtils.java:237, or a narrower radix-free formatter — see Open Question on "active radix") and/or which of the existing three visual states (off/zero/non-zero) applies. Whether this becomes a standalone class (e.g. WireValueLabel alongside WireRenderer's existing strokeFor, src/jls/edit/WireRenderer.java:43) or stays a static method on WireRenderer is a Method-time (§8) decision; either way it must be a pure function over (BitSet, int) -> String/state, callable and testable without a Graphics context — the same shape strokeFor already has. Precondition: none (accepts null). Postcondition: total function, never throws for any BitSet/bits combination.
7.5 Internal interfaces provided — private
The toggle's read accessor inside the paint path (e.g. a static or instance boolean WireRenderer/SimpleEditor consults before drawing the label and/or the color/stroke) — implementation-private, enforced by keeping it package- or class-private the way WireRenderer's existing fields already are; not part of any public API surface.
7.6 Data provided (structure)
A drawn string on the Graphics canvas — visual output only, no new in-memory or on-disk structure. If §7.4's mapping is extracted as a standalone class, its return type (label text, and/or a value-state enum) is defined there, following strokeFor's existing BasicStroke return as precedent (src/jls/edit/WireRenderer.java:43-56).
7.7 Data durably tracked
N/A — no new durable state. The toggle, if it is to persist across sessions (a preference), would be the one durable addition; whether it does is an Open Question below. Wire/WireEnd/WireNet gain no new persisted field (O7, P4).
7.8 Data ephemerally used
The toggle's in-memory state (if not persisted) lives for the session only, the same lifetime as other SimpleEditor view preferences. Nothing is lost mid-operation if it resets — it only affects what the next paint draws, exactly as the existing color/stroke encoding already behaves with no persistence today (O4).
7.9 Concurrency model
Synchronous, EDT-only, matching the existing pattern: WireRenderer.draw already reads live WireNet value state from inside paintComponent (src/jls/edit/SimpleEditor.java:2448-2488), which Swing invokes on the Event Dispatch Thread. This task adds no new thread, lock, or SwingWorker — the label read is the same unsynchronized read of shared mutable simulator state the color/stroke encoding already performs every repaint; this task introduces no new concurrency exposure beyond what O1's already-shipped code has.
7.10 Data transformations
Let $w$ be a Wire, $n = w.\mathrm{net}$ its WireNet, $v = n.\mathrm{getValue}() \in \mathrm{BitSet} \cup {\bot}$ ($\bot$ = HiZ/no value), and $b = n.\mathrm{getBits}()$.
Existing (O1, unchanged by this task):
$$f_{\mathrm{style}}(v) = \begin{cases} \text{dashed, off-color} & v = \bot \ \text{thin solid, zero-color} & v \neq \bot \wedge v = \emptyset \ \text{thick solid, nonzero-color} & v \neq \bot \wedge v \neq \emptyset \end{cases}$$
New (this task):
$$f_{\mathrm{label}}(v, b) = \begin{cases} \varnothing & b \le 1 \ \mathrm{toDisplay}(v, b) & b > 1 \end{cases}$$
where $\mathrm{toDisplay}$ is the existing total function at src/jls/BitSetUtils.java:237-244 (quotes: return str;) (or a replacement formatter, per the Open Question on "active radix" below), and $\varnothing$ means "draw nothing" — 1-bit nets keep only $f_{\mathrm{style}}$, matching O1/O2 exactly.
$$f_{\mathrm{toggle}}(t, v, b) = \begin{cases} f_{\mathrm{style}}(v) \cup f_{\mathrm{label}}(v,b) & t = \mathrm{on} \ \text{today's unconditional } f_{\mathrm{style}}(v),\ \varnothing\text{ label} & t = \mathrm{off} \end{cases}$$
Every stage is total (no partiality) — $\bot$ and $b \le 1$ are both explicit cases, not omissions, so § 7.11 (Failure modes) has no undefined input to own for this pipeline specifically.
7.11 Failure modes & error handling
No I/O, no file parsing, no network — the only inputs are already-validated in-memory model state (BitSet/int). toDisplay already handles null (returns "HiZ", src/jls/BitSetUtils.java:239-240) and is total over all (BitSet, int) pairs, so there is no malformed-input case to guard against for the label itself. If §8 extracts a new pure model class, its constructor/static methods must not throw for any reachable (BitSet, int) combination (mirrors strokeFor's current total behavior, src/jls/edit/WireRenderer.java:43-56). An interrupted paint (e.g. window closed mid-repaint) is already handled by the existing try { CircuitRenderer.of(circuit).draw(...) } catch (Exception e) { ... } wrapper (src/jls/edit/SimpleEditor.java:2486-2491 (quotes: // draw all elements, selected ones last; e.printStackTrace();)); this task adds no new exception path outside that existing envelope.
7.12 Compatibility, versioning & migration
Old .jls files load unchanged — no field added to Wire/WireEnd/WireNet's save/load contract (O7). Save output is byte-identical with the toggle on or off (P4) because no rendering-mode bit is written to the file. All existing callers of WireRenderer/ElementRenderers/CircuitRenderer keep compiling — this task adds to WireRenderer.draw's body and possibly one new pure-function class, no signature of an existing public method changes. test/jls/elem/WireValueChannelTest.java's existing assertions hold unmodified (P3) — the 1-bit color/stroke round-trip is untouched.
8. Method / Experimental Design
Confirm at pickup that O1–O7 still hold (rule 6): re-run the six git grep commands in § Observations and re-open the cited files at the current HEAD; if any citation has drifted, re-derive the line numbers before proceeding.
Resolve the Open Question on "active radix" (below) — pick the label format before writing code, since it determines f_label's definition in §7.10.
Add a new regression test (e.g. WireValueLabelTest alongside WireValueChannelTest) asserting: (a) a 1-bit net's rendered ink is unchanged from WireValueChannelTest's existing baseline with the label feature present but inapplicable (b <= 1); (b) a multi-bit net with a distinguishing non-zero value renders additional ink versus the same net with the label suppressed; (c) the test fails at the pre-change commit (no label exists, O2) and passes post-change.
Implement f_label (§7.10) as a pure function, either a static method on WireRenderer beside strokeFor or a new small class — decide per the §7.4 note — and wire it into WireRenderer.draw gated on net.getBits() > 1 and the new toggle.
Add the toggle: a boolean read at the top of WireRenderer.draw (and, if the color/stroke channel is also meant to be gated per AC2's "with it off, the paint path is unchanged from today," the existing O1 branch too), plus its UI control (menu item and/or preference) and one test asserting the paint path is byte-for-byt identical to pre-change when the toggle is off.
Add a save/load round-trip test asserting .jls output is byte-identical with the toggle on vs. off (P4), pinning §7.12's compatibility claim.
Run mvn verify locally; confirm HeadlessCoreRatchetTest's BASELINE needs no new entries (P5) and WireValueChannelTest passes unmodified (P3).
9. Data Collection & Analysis
Each new/changed behavior is asserted by a named JUnit test: the multi-bit label by the new WireValueLabelTest (§8), the toggle's off-path no-op by a paint-path-unchanged test, and the save/load byte-identity by a round-trip test. mvn verify's SpotBugs pass and warnings-as-errors gate are the standing static-analysis check; their pass/fail is recorded in the PR, not re-derived here (no build was run during this filing pass — see § Open Questions & Decisions Needed).
10. Falsification Criteria
H1 is refuted if the multi-bit label cannot be added without a new field on Wire/WireNet or a new Graphics acquisition path distinct from WireRenderer.draw's existing one — investigate why the existing per-paint value read (O1) is insufficient before assuming a new sampling tap is needed.
H2 is refuted if the toggle turns out to need persistence that cannot be added without a .jls schema change — if so, P4 fails and the toggle must be re-scoped to a session-only (non-persisted) preference, or a follow-up issue must own the format change explicitly (rule 4, atomic scope).
H3 is refuted if any new code this task adds lands inside src/jls/sim/, src/jls/elem/, src/jls/hdl/, src/jls/module/, or src/jls/core/ and imports java.awt.*/javax.swing.* — HeadlessCoreRatchetTest fails immediately (test/jls/HeadlessCoreRatchetTest.java:74-76), and the label/toggle logic must move into src/jls/edit/ instead.
11. Threats to Validity
This filing pass ran no build or GUI render (enhancement evidence standard — no mvn verify, no on-screen manual check); every O1–O7 observation above is git grep/file-read evidence at evidence_commit, not an executed test run. An executor must re-verify at pickup per rule 6.
Headless-vs-GUI divergence: WireValueChannelTest's off-screen BufferedImage rendering (no real display) is a good proxy for pixel-level assertions but does not exercise the real SimpleEditor/EDT paint cycle end-to-end; a manual GUI check (with platform) belongs in the PR per § Data Collection & Analysis.
Line numbers throughout are pinned to c5cee1baff3451a85787b4a09bd0b2b05af7dfdd and will drift with any edit to the cited files; re-derive before trusting (rule 1, rule 6).
The #693/#695/#504/#527/#533 cross-references in § Status & Dependencies are carried forward from the original filing's prose and were not independently re-verified against GitHub during this migration (no GitHub access in this pass) — see § Open Questions & Decisions Needed.
On completion, every visible multi-bit WireNet shows its numeric value as an on-canvas label reusing the existing paint-time value read, and a UI toggle governs whether on-canvas value rendering (color/stroke and the label) is active — with no .jls format change, no new sampling/recording mechanism, and no AWT/Swing import added to any headless-core package. Recording/history of wire values over time remains explicitly out of scope, owned by #527 whenever that work lands; an in-flight-event overlay drawn on top of this state is #695's scope, not this task's.
Open Questions & Decisions Needed
"Active radix" is not a concept that exists in the codebase for wires (O3).BitSetUtils.toDisplay always returns a fixed "0xN (N unsigned, N signed)"/"HiZ" composite string with no radix parameter; the only per-element radix settings that exist (Constant, Display) are each independently configured, not shared or wire-scoped. Options: (a) reuse toDisplay's existing fixed composite format as-is — no new state, automatically satisfies "no new per-element serialized state" (P4/§7.7) — recommended default; (b) add a new global "active radix" preference — new (session-only, non-persisted per H2) state, more work, matches the original AC's literal wording; (c) add a per-WireNet radix — would very likely require new persisted state, directly conflicting with the "no new per-element serialized state" criterion, not recommended. This blocks §8 step 1 (Method) but not filing.
Does the toggle persist across sessions? Left open in the original filing ("toggleable in the UI"). A session-only in-memory boolean is the safe default (avoids any .jls/preferences-file schema question); a persisted-preference version is a legitimate but larger alternative. Recommended default: session-only for this task; a persisted preference can be a fast-follow if requested. Does not block filing; must be resolved before §8 implementation.
The full observed-failure obligation (rule 3 / template line 23-26) was not discharged with an executed build or test run. Per the maintainer's 2026-08-17 evidence-standard ruling for enhancement issues, this filing pass derived structural evidence via git grep/file reads only (O1–O7) and did not run mvn verify or render the GUI. An executor must run the new regression tests (§8) against the pre-change commit to confirm they fail there, per rule 3, before relying on this filing's predictions as pre-verified.
The cross-issue edges in § Status & Dependencies (#693, #695, #504, #527, #533) are carried forward from the original body's prose, unverified against live GitHub state in this pass (no GitHub access during migration). Recommend the maintainer or the next executor confirm those issues' current numbers/status before treating blocks/related as authoritative.
14. Completion Criteria (Definition of Done)
Every post-fix prediction in §5 (Predictions) verified; command and output recorded in the PR
Every check in §10 (Falsification Criteria) performed post-fix; outcome (not refuted / refuted → action taken) recorded in the PR
Post-change code re-checked against §7 (Interface & Data Contract): interfaces provided/consumed, data structures, concurrency model, and compatibility claims hold as declared; any deviation recorded as an issue comment (rule 2), not silently absorbed
New regression tests fail at the pre-change commit and pass at the fix commit
Existing tests pass unmodified, including test/jls/elem/WireValueChannelTest.java (P3) — no asserted behavior in it is intentionally changed by this task
mvn verify green (tests + SpotBugs, warnings-as-errors)
No new entries in config/spotbugs-exclude.xml, or each new entry is Class-scoped with a justification
No new entries in test/jls/HeadlessCoreRatchetTest.java's BASELINE (P5)
No changes outside the scope of §8 (Method); adjacent work discovered en route is filed as new issues
Every blocked_by entry in Status & Dependencies has landed, or the dependency was waived per rule 10 — N/A, blocked_by is empty
Abstract
The schematic canvas already paints a wire's live 1-bit-style logic state through color and stroke (issues #76/#77): a
WireNetwith no value draws dashed and in the "off" color, an all-zero net draws thin and in the "zero" color, and a net carrying any non-zero bit draws thick and in the "non-zero" color. What the canvas does not do is show a numeric value for a multi-bit net — every non-zero multi-bit bus paints identically regardless of whether it carries1or0xFFFF, and there is no way to see a bus's actual value without openingElementValueDisplays' modal report or the trace window. This task closes that specific gap: an on-canvas numeric value label for multi-bitWireNets, plus a UI toggle for on-canvas value rendering (color/stroke and the new label together), reusing the paint-time read the coloring already performs — no new sampling tap, no new serialized state.Intended Audience & Impact
ElementValueDisplays.show,src/jls/edit/ElementValueDisplays.java), or opening the trace window — both break the student's focus on the live schematic. A numeric label drawn where the wire already is removes that detour for the common case of "what value is this bus carrying right now."-b) mode. No effect: batch mode never constructs theCircuitPanel/CircuitRendererpaint path this task touches (see § Observations, O5), so nothing changes for headless runs regardless of the toggle's default.Paletteplus a thin Swing consumer; this task's multi-bit label follows the same shape and is a template for any future per-wire annotation.Status & Dependencies
The
#693/#695/#504/#527relationships above are carried forward from the original filing's prose (maintainer directive, 2026-08-16); this migration did not and could not re-verify their current state on GitHub (out of scope for this pass — see § Open Questions & Decisions Needed).1. Background & Prior Work
Wire and wire-end rendering moved off the model classes and into the
jls.editrenderer registry in issue #77:ElementRenderers.draw(src/jls/edit/ElementRenderers.java:47-56 (quotes:* element's own {@code draw} if none is registered.;} else {)) dispatches to a registeredElementRenderer—WireRendererforWireandWireEndRendererforWireEnd— registered inBuiltinElementRenderers.install()(src/jls/edit/BuiltinElementRenderers.java:100-101). Issue #76 added the "second channel" principle this task extends: value state must be readable without color vision, soWire/WireEndalready carry both a color and a stroke/glyph encoding, pinned bytest/jls/elem/WireValueChannelTest.java.jls.sim.TraceGeometry(src/jls/sim/TraceGeometry.java:1-9) is the precedent this task's Outcome text points at for a "headless model, thin Swing consumer" split: pure display-geometry computation, deliberately free of AWT, unit-tested independently of the Swing trace viewer it feeds.ARCHITECTURE.md:224-226 (quotes:Layer 1 (present) is headless model assertions; layers 2 (Swing)names this the project's "Layer 1" (headless model assertions) versus "Layer 2/3" (Swing harness, render-to-image) split.Issue #527 is named by the original filing as the eventual owner of value recording (a
SampleSinkstream); noWaveModelorSampleSinktype exists anywhere in the tree atevidence_commit(git grep -rln "WaveModel\|SampleSink" -- '*.java'returns no results), so this task cannot attach to that stream and instead readsWireNet.getValue()directly at paint time, the same way the existing color/stroke encoding already does.2. Observations
O1 — the color/stroke value channel for 1-bit-shaped state already exists and is a live paint consumer, not a test fixture.
WireRenderer.draw(src/jls/edit/WireRenderer.java:58-91) reads the net's value every paint:(
src/jls/edit/WireRenderer.java:62), then selects aPalettecolor per state:(
src/jls/edit/WireRenderer.java:69-76), and a matching stroke viastrokeFor(src/jls/edit/WireRenderer.java:43-56): dashed fornull/HiZ, a thick round stroke for any non-empty value, a plain 1px stroke for an all-zero value. This is called from the real interactive paint path, not only from a test:CircuitRenderer.drawcallsElementRenderers.draw(g, el)for every visible wire (src/jls/edit/CircuitRenderer.java:144), andCircuitRenderer.drawis itself called fromSimpleEditor'spaintComponentoverride:(
src/jls/edit/SimpleEditor.java:2488, insidepaintComponentopening atsrc/jls/edit/SimpleEditor.java:2448). This refutes the original filing's Outcome claim that "Wirehas no draw path that consultsWireNet.value" — it does, and has since issues #76/#77.O2 — no numeric value label is drawn on the canvas for any wire, 1-bit or multi-bit.
BitSetUtils.toDisplayis the codebase's one value-to-string formatter (src/jls/BitSetUtils.java:237-244 (quotes:return str;)).git grep -n "BitSetUtils.toDisplay" -- '*.java'returns 14 call sites, all insidesrc/jls/elem/(Display.java:295,InputPin.java:128,JumpEnd.java:314,JumpStart.java:313,Memory.java:950-951,OutputPin.java:114,224,Pin.java:289,293,Register.java:467,681,684,Wire.java:342) — every one feeds a tooltip/infoText/TellUserdialog or aSystem.outtrace line, none aGraphicsdraw call.git grep -n "drawString" -- 'src/jls/edit/WireRenderer.java' 'src/jls/edit/WireEndRenderer.java'matches only the existing probe-name label (src/jls/edit/WireRenderer.java:106,112,123,128); there is no seconddrawStringfor a value.O3 —
Wire.infoTextalready formats a value string on click/hover, but only for that modal path, andtoDisplayhas no radix parameter.Wire.infoTextbuilds", value = " + BitSetUtils.toDisplay(getValue(),net.getBits())(src/jls/elem/Wire.java:342).BitSetUtils.toDisplay's signature istoDisplay(@Nullable BitSet value, int bits)(src/jls/BitSetUtils.java:237) — it takes no radix argument and always returns the fixed composite string"0x" + hex + " (" + decimal + " unsigned, " + signed + " signed)", or"HiZ"fornull(src/jls/BitSetUtils.java:239-243). There is no per-WireNetor global "active radix" setting anywhere this formatter consults; radix is instead a private, per-element display preference on individual elements — e.g.Constant's own default radix field (src/jls/edit/ConstantDialog.java:41) andDisplay's own radix radio buttons (src/jls/edit/DisplayDialog.java:79-120 (quotes:/** Radio button selecting binary display radix. */;radix.add(b16);)) are each configured independently per element instance, not from any shared or wire-scoped setting.O4 — no on-canvas value-rendering toggle exists.
git grep -n "showValue\|ShowValue\|valueRendering\|ValueRendering\|WireValueStyle" -- '*.java'returns no results. The color/stroke encoding of O1 is unconditional today: it runs on every paint of every wire with no way to turn it off from the UI.O5 — batch/headless runs never reach the paint path this task touches, independent of any toggle. Batch mode is documented as one of JLS's "headless one-shot modes" (
src/jls/ToolkitPolicy.java:24) and is offered as the-bflag "run in batch (headless) mode" (src/jls/JLSStart.java:763 (quotes:"run in batch (headless) mode"),)).WireRenderer,WireEndRenderer,CircuitRenderer, andSimpleEditorall live insrc/jls/edit/, a package excluded from the headless core by design (ARCHITECTURE.md's headless-core packages, enforced byHeadlessCoreRatchetTest,test/jls/HeadlessCoreRatchetTest.java:53), and no batch code path constructs aSimpleEditor/CircuitPanelto invokepaintComponent.HeadlessCoreRatchetTest'sFORBIDDEN_IMPORTpattern (test/jls/HeadlessCoreRatchetTest.java:56-58 (quotes:+ "(?:java\.awt\.|javax\.swing\.|jls\.edit\.)");)) forbidsjava.awt.*/javax.swing.*/jls.edit.*imports insideCORE_PACKAGE_PREFIXES, which includessrc/jls/sim/andsrc/jls/elem/(test/jls/HeadlessCoreRatchetTest.java:74-76) — i.e. the ratchet this task's AC2 cites is already the mechanism keeping value rendering out of headless code, and this task adds nothing tojls.simorjls.elemthat would trip it.O6 — no
SampleSink/WaveModelrecording layer exists yet.git grep -rln "WaveModel\|SampleSink" -- '*.java'returns no results atevidence_commit. The original filing's "or #527'sSampleSinkstream where one is already attached" alternative is therefore not available today; this task can only readWireNet.getValue()directly, the same accessWireRendereralready uses (O1).O7 — no
Wire-adjacent state is persisted today beyond connectivity and tri-state.Wire.saveis a documented no-op:"Wires don't get saved."/public void save(PrintWriter output) { // do nothing }(src/jls/elem/Wire.java:120-125).WireEnd.save(src/jls/elem/WireEnd.java:586-593 (quotes:if (isAttached()) {)) writes only atristateflag and, if attached, the connected put's name — no value, radix, or rendering-mode field of any kind.3. Research Question
Can a multi-bit
WireNet's current numeric value be shown on the schematic canvas, and on-canvas wire-value rendering as a whole be made user-toggleable, without adding a second sampling mechanism, without changing the.jlsfile format, and without adding an AWT/Swing import tojls.sim?4. Hypothesis (falsifiable)
WireRenderer.draw's existing per-wire paint call, reusing the already-fetchedBitSet value(src/jls/edit/WireRenderer.java:62) and the existing text-layout pattern the probe-name label already uses (src/jls/edit/WireRenderer.java:97-131 (quotes:} // end of draw method)), without any new field onWireorWireNetand without a newGraphicsacquisition path..jlsschema change — because no such state exists onWire/WireEnd/WireNettoday (O7) andsave()for both element types already ignores rendering concerns entirely.WireRenderer/WireEndRenderer/CircuitRendereralready sit entirely insidesrc/jls/edit/, outside every packageHeadlessCoreRatchetTestpolices (O5), this task can satisfy "no AWT/Swing import added tojls.sim" (the surviving, narrower form of the old AC2) without any special-casing — the ratchet already forbids it structurally.5. Predictions
evidence_commit,git grep -n "BitSetUtils.toDisplay\|drawString" -- 'src/jls/edit/WireRenderer.java'shows zero value-label draw calls (confirmed, O2). After the fix, it shows at least one, gated on the net being multi-bit (net.getBits() > 1) and on the new toggle being enabled.evidence_commit,git grep -n "showValue\|ShowValue\|valueRendering\|ValueRendering" -- '*.java'returns no results (confirmed, O4). After the fix, it resolves to a discoverable toggle (menu item and/or preference field) with its own unit test asserting the paint path is unchanged when the toggle is off.test/jls/elem/WireValueChannelTest.java's existing assertions (O1's color/stroke encoding) continue to pass unmodified — this task does not touch the 1-bit color/stroke channel, only adds the multi-bit label and the toggle around the whole value-rendering feature..jlsoutput, because neither state lives onWire,WireEnd, orWireNet(H2, O7) — no newsave()/load()branch is added.test/jls/HeadlessCoreRatchetTest.java'sBASELINEgains no new entries: the new label/toggle code lives insrc/jls/edit/, never insrc/jls/sim/orsrc/jls/elem/(H3).6. Materials & Apparatus
test/jls/elem/WireValueChannelTest.java'srender(Consumer<Graphics2D>)helper (renders to an off-screenBufferedImage, counts non-background pixels) — reusable for a new label-presence assertion without a display.mvn verify(tests + SpotBugs, warnings-as-errors) as the standing gate; not run as part of this filing pass per the enhancement evidence standard (no build executed — see § Open Questions & Decisions Needed).WireValueChannelTest's fixture-construction pattern (Circuit→WireEnds →Wire→WireNet→net.setValue(...)) already exercises exactly the object graph a multi-bit label test needs, just with a widerBitSet/bitsvalue.7. Interface & Data Contract
7.1 External interfaces modified
GUI surface only: the schematic canvas (
SimpleEditor's circuit panel) gains (a) a numeric value label drawn beside/along multi-bit wires and (b) a new toggle (menu item and/or preference) controlling whether on-canvas value rendering (existing color/stroke plus the new label) is active. No CLI/batch (-b) flag changes — batch mode never constructs the panel this touches (O5). No.jlsfile format change (docs/file-format.md) —Wire.save/WireEnd.saveare unaffected (O7, P4). No HDL export change (jls.hdlis untouched by this task's scope).7.2 External interfaces consumed
java.awt.Graphics/Graphics2D,FontMetricsfor text measurement anddrawStringfor the label — the same JDK surfacesWireRenderer.drawalready consumes for the probe-name label (src/jls/edit/WireRenderer.java:97-131 (quotes:} // end of draw method)). No new JDK API, environment variable, font, or OS service.7.3 Data consumed (structure)
The task reads
WireNet.getValue()(a@Nullable BitSet,src/jls/elem/WireNet.java:428) andWireNet.getBits()(int), both already public accessors on the in-memory circuit model — trusted, process-local state, not hostile input (the.jlsfile itself is untouched, see 7.1). No external schema.7.4 Internal interfaces provided — public
A value→style mapping in the spirit of
TraceGeometry(src/jls/sim/TraceGeometry.java:1-9): given aBitSet/nullvalue and a bit width, return the label text (reusingBitSetUtils.toDisplay,src/jls/BitSetUtils.java:237, or a narrower radix-free formatter — see Open Question on "active radix") and/or which of the existing three visual states (off/zero/non-zero) applies. Whether this becomes a standalone class (e.g.WireValueLabelalongsideWireRenderer's existingstrokeFor,src/jls/edit/WireRenderer.java:43) or stays a static method onWireRendereris a Method-time (§8) decision; either way it must be a pure function over(BitSet, int) -> String/state, callable and testable without aGraphicscontext — the same shapestrokeForalready has. Precondition: none (acceptsnull). Postcondition: total function, never throws for anyBitSet/bits combination.7.5 Internal interfaces provided — private
The toggle's read accessor inside the paint path (e.g. a static or instance boolean
WireRenderer/SimpleEditorconsults before drawing the label and/or the color/stroke) — implementation-private, enforced by keeping it package- or class-private the wayWireRenderer's existing fields already are; not part of any public API surface.7.6 Data provided (structure)
A drawn string on the
Graphicscanvas — visual output only, no new in-memory or on-disk structure. If §7.4's mapping is extracted as a standalone class, its return type (label text, and/or a value-state enum) is defined there, followingstrokeFor's existingBasicStrokereturn as precedent (src/jls/edit/WireRenderer.java:43-56).7.7 Data durably tracked
N/A — no new durable state. The toggle, if it is to persist across sessions (a preference), would be the one durable addition; whether it does is an Open Question below.
Wire/WireEnd/WireNetgain no new persisted field (O7, P4).7.8 Data ephemerally used
The toggle's in-memory state (if not persisted) lives for the session only, the same lifetime as other
SimpleEditorview preferences. Nothing is lost mid-operation if it resets — it only affects what the next paint draws, exactly as the existing color/stroke encoding already behaves with no persistence today (O4).7.9 Concurrency model
Synchronous, EDT-only, matching the existing pattern:
WireRenderer.drawalready reads liveWireNetvalue state from insidepaintComponent(src/jls/edit/SimpleEditor.java:2448-2488), which Swing invokes on the Event Dispatch Thread. This task adds no new thread, lock, orSwingWorker— the label read is the same unsynchronized read of shared mutable simulator state the color/stroke encoding already performs every repaint; this task introduces no new concurrency exposure beyond what O1's already-shipped code has.7.10 Data transformations
Let$w$ be a $n = w.\mathrm{net}$ its $v = n.\mathrm{getValue}() \in \mathrm{BitSet} \cup {\bot}$ ($\bot$ = HiZ/no value), and $b = n.\mathrm{getBits}()$ .
Wire,WireNet,Existing (O1, unchanged by this task):
New (this task):
where$\mathrm{toDisplay}$ is the existing total function at $\varnothing$ means "draw nothing" — 1-bit nets keep only $f_{\mathrm{style}}$ , matching O1/O2 exactly.
src/jls/BitSetUtils.java:237-244 (quotes:return str;)(or a replacement formatter, per the Open Question on "active radix" below), andEvery stage is total (no partiality) —$\bot$ and $b \le 1$ are both explicit cases, not omissions, so § 7.11 (Failure modes) has no undefined input to own for this pipeline specifically.
7.11 Failure modes & error handling
No I/O, no file parsing, no network — the only inputs are already-validated in-memory model state (
BitSet/int).toDisplayalready handlesnull(returns"HiZ",src/jls/BitSetUtils.java:239-240) and is total over all(BitSet, int)pairs, so there is no malformed-input case to guard against for the label itself. If §8 extracts a new pure model class, its constructor/static methods must not throw for any reachable(BitSet, int)combination (mirrorsstrokeFor's current total behavior,src/jls/edit/WireRenderer.java:43-56). An interrupted paint (e.g. window closed mid-repaint) is already handled by the existingtry { CircuitRenderer.of(circuit).draw(...) } catch (Exception e) { ... }wrapper (src/jls/edit/SimpleEditor.java:2486-2491 (quotes:// draw all elements, selected ones last;e.printStackTrace();)); this task adds no new exception path outside that existing envelope.7.12 Compatibility, versioning & migration
Old
.jlsfiles load unchanged — no field added toWire/WireEnd/WireNet's save/load contract (O7). Save output is byte-identical with the toggle on or off (P4) because no rendering-mode bit is written to the file. All existing callers ofWireRenderer/ElementRenderers/CircuitRendererkeep compiling — this task adds toWireRenderer.draw's body and possibly one new pure-function class, no signature of an existing public method changes.test/jls/elem/WireValueChannelTest.java's existing assertions hold unmodified (P3) — the 1-bit color/stroke round-trip is untouched.8. Method / Experimental Design
git grepcommands in § Observations and re-open the cited files at the current HEAD; if any citation has drifted, re-derive the line numbers before proceeding.f_label's definition in §7.10.WireValueLabelTestalongsideWireValueChannelTest) asserting: (a) a 1-bit net's rendered ink is unchanged fromWireValueChannelTest's existing baseline with the label feature present but inapplicable (b <= 1); (b) a multi-bit net with a distinguishing non-zero value renders additional ink versus the same net with the label suppressed; (c) the test fails at the pre-change commit (no label exists, O2) and passes post-change.f_label(§7.10) as a pure function, either a static method onWireRendererbesidestrokeForor a new small class — decide per the §7.4 note — and wire it intoWireRenderer.drawgated onnet.getBits() > 1and the new toggle.WireRenderer.draw(and, if the color/stroke channel is also meant to be gated per AC2's "with it off, the paint path is unchanged from today," the existing O1 branch too), plus its UI control (menu item and/or preference) and one test asserting the paint path is byte-for-byt identical to pre-change when the toggle is off..jlsoutput is byte-identical with the toggle on vs. off (P4), pinning §7.12's compatibility claim.mvn verifylocally; confirmHeadlessCoreRatchetTest'sBASELINEneeds no new entries (P5) andWireValueChannelTestpasses unmodified (P3).9. Data Collection & Analysis
Each new/changed behavior is asserted by a named JUnit test: the multi-bit label by the new
WireValueLabelTest(§8), the toggle's off-path no-op by a paint-path-unchanged test, and the save/load byte-identity by a round-trip test.mvn verify's SpotBugs pass and warnings-as-errors gate are the standing static-analysis check; their pass/fail is recorded in the PR, not re-derived here (no build was run during this filing pass — see § Open Questions & Decisions Needed).10. Falsification Criteria
Wire/WireNetor a newGraphicsacquisition path distinct fromWireRenderer.draw's existing one — investigate why the existing per-paint value read (O1) is insufficient before assuming a new sampling tap is needed..jlsschema change — if so, P4 fails and the toggle must be re-scoped to a session-only (non-persisted) preference, or a follow-up issue must own the format change explicitly (rule 4, atomic scope).src/jls/sim/,src/jls/elem/,src/jls/hdl/,src/jls/module/, orsrc/jls/core/and importsjava.awt.*/javax.swing.*—HeadlessCoreRatchetTestfails immediately (test/jls/HeadlessCoreRatchetTest.java:74-76), and the label/toggle logic must move intosrc/jls/edit/instead.11. Threats to Validity
mvn verify, no on-screen manual check); every O1–O7 observation above isgit grep/file-read evidence atevidence_commit, not an executed test run. An executor must re-verify at pickup per rule 6.WireValueChannelTest's off-screenBufferedImagerendering (no real display) is a good proxy for pixel-level assertions but does not exercise the realSimpleEditor/EDT paint cycle end-to-end; a manual GUI check (with platform) belongs in the PR per § Data Collection & Analysis.c5cee1baff3451a85787b4a09bd0b2b05af7dfddand will drift with any edit to the cited files; re-derive before trusting (rule 1, rule 6).#693/#695/#504/#527/#533cross-references in § Status & Dependencies are carried forward from the original filing's prose and were not independently re-verified against GitHub during this migration (no GitHub access in this pass) — see § Open Questions & Decisions Needed.12. Related Work
ElementRenderersplit this task extends (O1, Background).SampleSink); this task is a paint-time read only and takes no dependency on FEAT-C23-1: a docked chronogram opens on the live event stream — grouped signals, bus radix, cursor-delta measurement — and costs the kernel nothing while it stays closed #527's (not-yet-existing, O6) stream.part_of_feature); sibling tasks TASK-C533-1: the interactive simulator advances by exactly one event, or one wavefront, on demand — with simulated time shown and the event order unchanged #693 and TASK-C533-2: pending events render as an in-flight delay fill on their target elements, paced by a shared view-time clock #695 under the same feature are stated by the original filing to be ordered after this one.related-only on this task's side (see § Status & Dependencies note).13. Conclusion & Future Work
On completion, every visible multi-bit
WireNetshows its numeric value as an on-canvas label reusing the existing paint-time value read, and a UI toggle governs whether on-canvas value rendering (color/stroke and the label) is active — with no.jlsformat change, no new sampling/recording mechanism, and no AWT/Swing import added to any headless-core package. Recording/history of wire values over time remains explicitly out of scope, owned by #527 whenever that work lands; an in-flight-event overlay drawn on top of this state is #695's scope, not this task's.Open Questions & Decisions Needed
BitSetUtils.toDisplayalways returns a fixed"0xN (N unsigned, N signed)"/"HiZ"composite string with no radix parameter; the only per-element radix settings that exist (Constant,Display) are each independently configured, not shared or wire-scoped. Options: (a) reusetoDisplay's existing fixed composite format as-is — no new state, automatically satisfies "no new per-element serialized state" (P4/§7.7) — recommended default; (b) add a new global "active radix" preference — new (session-only, non-persisted per H2) state, more work, matches the original AC's literal wording; (c) add a per-WireNetradix — would very likely require new persisted state, directly conflicting with the "no new per-element serialized state" criterion, not recommended. This blocks §8 step 1 (Method) but not filing..jls/preferences-file schema question); a persisted-preference version is a legitimate but larger alternative. Recommended default: session-only for this task; a persisted preference can be a fast-follow if requested. Does not block filing; must be resolved before §8 implementation.git grep/file reads only (O1–O7) and did not runmvn verifyor render the GUI. An executor must run the new regression tests (§8) against the pre-change commit to confirm they fail there, per rule 3, before relying on this filing's predictions as pre-verified.#693,#695,#504,#527,#533) are carried forward from the original body's prose, unverified against live GitHub state in this pass (no GitHub access during migration). Recommend the maintainer or the next executor confirm those issues' current numbers/status before treatingblocks/relatedas authoritative.14. Completion Criteria (Definition of Done)
test/jls/elem/WireValueChannelTest.java(P3) — no asserted behavior in it is intentionally changed by this taskmvn verifygreen (tests + SpotBugs, warnings-as-errors)config/spotbugs-exclude.xml, or each new entry isClass-scoped with a justificationtest/jls/HeadlessCoreRatchetTest.java'sBASELINE(P5)blocked_byentry in Status & Dependencies has landed, or the dependency was waived per rule 10 — N/A,blocked_byis emptySTATUS:comment (part_of_featureis set), including any contract deviations the feature's plan must reconcileWAIVED:comment naming its successor issue (rule 10).jlsoutput (P4), confirmed by the round-trip test in §8