Repository navigation
t27c: gen-json backend -- print own_model_board.t27 as the IGLA board's JSON event (needs owner-approved-foreign) #10050
Description
Problem
PR #10048 (issue #10037) added specs/igla/own_model_board.t27: the 27-cell own-model map (specs/igla/own_model.t27) stated as one IGLA board event, {job, stage, msg, progress, metrics}. The board takes that event as a JSON POST body. No t27c backend can print it:
gen-js(bootstrap/src/codegen_js.rs) prints the same values as an ES module ofexport constlines. That is a module, not a JSON body.- Hand-writing the JSON, or a script that converts the module, would be the deciding-generator hole that
gen-jswas written to close.
So nothing can reach the board from the spec yet. The next step, a config-only Railway cron in igla-judge that POSTs the body to board.railway.internal:8081/event, is blocked on this issue and is not part of it.
Proposal
Add t27c gen-json <spec>. It reuses the codegen_js value layer (const_value, js_string, the array-length check) through a new Target, spells the values as compact JSON, and builds the event from the key consts the spec declares:
{"job":JOB,"stage":STAGE,"msg":MSG,"progress":PROGRESS,
"metrics":{KEY_LENS:LENS_PCT,KEY_CELLS:[{KEY_STATUS:CELL_STATUS[c],KEY_PCT:CELL_PCT[c]} for c in 0..27]}}
The 27 pairs come from zipping CELL_STATUS with CELL_PCT. The output is not committed: whatever posts the event runs t27c gen-json at post time, so the event has no second home beside the spec.
Done when
t27c gen-json specs/igla/own_model_board.t27prints the event.- The
metricsobject is exactlyMETRICS_BYTESbytes on current master, the value the spec'sthe_metrics_fit_the_boardtest computes. - The compile and the test sweep run on the Railway lab, and their output goes in the PR body.
Gate: this is Rust under bootstrap/, so it needs the owner
The only-t27 rule (specs/policy/own_language.t27) denies this change unless the owner adds the owner-approved-foreign label. @gHashTag: may this issue have the label? Without it, nothing is written and the work stays parked.
Even with the label, the gate has three limits that no label or exception lifts:
- At most 40 added hand-written foreign lines in one file (Only-t27 gate: a foreign-line budget the label cannot lift; local hook reads exceptions from origin/master #7371).
- At most 80 added in the whole diff (Only-t27 gate: a foreign-line budget the label cannot lift; local hook reads exceptions from origin/master #7371).
- Over the whole diff, hand-written foreign code must lose at least as many lines as it gains (owner rule 2026-10-09).
My estimate for the smallest glue is about 15 lines in main.rs (subcommand, dispatch, handler) and about 35 in a new codegen_json.rs. That is roughly 50 added lines. Limits 1 and 2 can be met. Limit 3 needs the same PR to port at least that many hand-written foreign lines to .t27 and delete them. I have not yet found a natural candidate for that. If the owner grants the label, please also say which foreign code to port as the offset, or whether this should stay parked until t27core self-hosts (#5980).
A design question for the owner: the backend as proposed knows this event's shape, job/stage/msg/progress/metrics. A general alternative is for gen-json to print struct-literal consts as JSON objects, so the shape lives in the spec. That needs struct-literal and array-of-struct const support, which is a larger change.
Owner decision, 2026-10-18 (translated from chat): the label is approved. For the offset, delete docs/reports/data/W564-harness.sh and tools/jtag/read_user1.py, and keep the glue to 46 lines or fewer.
Boundary
- bootstrap/src/codegen_json.rs
- bootstrap/src/main.rs
- docs/reports/data/W564-harness.sh
- tools/jtag/read_user1.py
- tools/devhome_baseline.txt
User Scenarios
- Given
specs/igla/own_model_board.t27, whent27c gen-jsonruns on it, then it prints one JSON object{job, stage, msg, progress, metrics}whosemetricsis exactly the spec'sMETRICS_BYTESbytes. - Given a spec without one of the key consts, when
t27c gen-jsonruns on it, then it exits non-zero and names the missing const.
Requirements
- FR-001:
t27c gen-jsonMUST take every value from the spec through thecodegen_jsvalue layer; no value is written in Rust. - FR-002: the hand-written Rust added MUST be 46 lines or fewer, and the same diff MUST delete
docs/reports/data/W564-harness.sh(26 lines) andtools/jtag/read_user1.py(20 lines) as the offset the owner named, so hand-written foreign code does not grow. - FR-003: the generated event MUST NOT be committed under
gen/; it is printed at post time. (Changed 2026-10-18. A committed copy went stale every time the map moved, from 621 to 622 to 626 bytes within a day, and the L2 GENERATION rule refusesgen/json/as an unknown backend directory.)
Success criteria
- On current master, the
metricsobjectt27c gen-jsonprints is exactlyMETRICS_BYTESbytes. - The own-language gate exits 0 on the diff.
Activity
github-actions commentedon Oct 17, 2026
Closed by the issue-shape gate (specs/policy/issue_shape.t27, #7498): an issue must have the template's sections. Edit the body; an edit that passes reopens it.
- specs/x.t27); without it the Queen reserves nothing and no bee can take the issueFR-001: ... MUST ...github-actions commentedon Oct 17, 2026
The shape check passes now (specs/policy/issue_shape.t27); reopened.
feat(t27c): gen-json -- print a spec's IGLA board event as one JSON o…
gen(json): own_model_board.json, the IGLA board event t27c gen-json p…
feat(t27c): gen-json -- print a spec's IGLA board event as one JSON o…
gen(json): own_model_board.json, the IGLA board event t27c gen-json p…
gen(json): own_model_board.json, the IGLA board event t27c gen-json p…
spec(policy): l2_generation -- gen/json/ is t27c gen-json's backend d…
spec(policy): l2_generation -- gen/json/ is t27c gen-json's backend d…
gen(json): drop the committed board event; t27c gen-json prints it at…
feat(t27c): gen-json -- the IGLA board event a spec states, as one JS…