fix(ir): the wheel says which passage it is and nothing about what is in it, and Spanish comes off the air - #362
Conversation
…s in it Fourteen lines per language were written from each map's `pericope-title`, which is a summary and not a name, so the wheel told a team what it was about to find before it had chosen anything. P07 went furthest and handed over the redeemer. None of it passes a validator — the file says so of itself — and none of it had her word. They are the map's own H1 reference now, the way her menu takes it: `# P07 — Ruth 2:17-23` becomes `Ruth 2:17-23`, with the book named in the language being spoken. The verse dash is copied from the canon rather than normalized, because the canon is not consistent about it — an en dash through P05 and a hyphen from P06 on — and a line that disagrees with the map it came from is the thing this is trying to stop. The expected lines are transcribed into the test from the fourteen maps rather than derived from the file under test, so a rewrite that carries story again has nothing to agree with. The no-digit assertion the old lines earned is inverted for the same reason: a reference is numbers, and what must stay out is the id the canon files the passage under. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LFVR6cTXVgy52QskCAWfN9
…from The Spanish block was fourteen more authored lines, and the supplement it belongs beside says of itself that nothing in it has been approved to be spoken to a team. She ruled on 04/09 that the language is not approved and comes off the air rather than being held equivalent, so the block goes rather than being rewritten from the map with the other two. The lock that takes it out is the one the wheel was missing: every line the file carries has to be its map's own reference with the book renamed for the language, and the name comes out of the label catalogue rather than being written down again here. It reads the maps and the catalogue, so it has nothing to agree with when a line is rewritten to carry story — and it covers whatever language the file grows next, not only the two it has today. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LFVR6cTXVgy52QskCAWfN9
Spanish was one of the three the room answered for, so a tablet set to it opened a session, turned a wheel and met every failure in lines from two files that say of themselves that nothing in them has been approved to be spoken to a team. Her ruling of 04/09 is that the language is not offered until she decides to offer it. Taking it out of the claim is the whole of the change: `normalize` is the one gate the wire passes through, so a locale the tuple does not carry now comes back as nothing, and the three doors that ask it — the wheel, the session open, the voice route — already answer 400 rather than quietly speaking another language. `LANGUAGE_NAMES` and the Spanish voice keep their entries: they are how a row already written as `es` is read back, and a session that is open stays open rather than turning into a 500 on its next turn. The two tests that were written against the claim move with it. The locale table now says a Spanish region resolves to nothing, and the wheel's refusal is asked of `es` and `es-419` beside the French it already had. The whole-stretch request proved it speaks the session's language by contrasting Spanish with Portuguese, and contrasts English with it now. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LFVR6cTXVgy52QskCAWfN9
…t is there The loader globbed `_fail_safe_*_supplement.md` and concatenated whatever it found, so the Spanish supplement — which says of itself, in bold, that nothing in it has been approved to be spoken to a team — was one of the files the room answered its failures from. Being read was the default, and putting a draft beside the authored file was enough to ship it. The supplements are named off `ROOM_LANGUAGES` now. Claiming a language is already the one deliberate act in this area, and reading a language's lines follows it instead of following the directory listing. The Spanish file stays exactly where it is, banner and all, for the day she decides to offer the language: returning `es` to the tuple is the whole of what turning it back on takes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LFVR6cTXVgy52QskCAWfN9
The header claimed "Reviewed and approved by Marcia (2026-08-10)" and nothing in the repository stood behind it. The sentence was written thirteen seconds after one line of chat reporting that she had agreed, replacing "Pending Marcia's review."; the Portuguese it vouches for had been written fifty-eight seconds before that, in the same session, from the authored English. No commit body records the approval, and her repository has no commit on that date, none touching fail-safe utterances, and none mentioning it — while she stamps her rulings in commit subjects as a matter of habit. Asked on 04/09, she did not confirm from memory and asked for the text, which she has not yet been sent. So the header now says what it actually has: an oral approval, relayed, on a date, with her written confirmation outstanding. The record sits beside the file rather than in the header, because provenance is longer than a clause and a team hearing these lines deserves it to be written down somewhere other than a conversation. The lines themselves are untouched. Whether the Portuguese B, C and E stand is her call once she has the text, and it is not this change. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LFVR6cTXVgy52QskCAWfN9
The wheel's expected lines are transcribed from the fourteen maps, and the canon is not consistent about the dash inside a verse range — an en dash through P05, a hyphen from P06 on. Ruff reads the en dash as a hyphen somebody typed wrong, which is exactly the character the table exists to hold: a test that normalizes it stops disagreeing with a file that has drifted, and the drift is what it is for. Exempted the way `doctrine_allowlist.py` already is, for the same reason and in the same words. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LFVR6cTXVgy52QskCAWfN9
| > ⚠️ **STATUS: DRAFT — awaiting validation.** These were derived from each map's | ||
| > `pericope-title`. Nothing here has been approved to be spoken to a team. | ||
| > ⚠️ **STATUS: DRAFT — awaiting validation.** These are each map's own H1 reference. | ||
| > Nothing here has been approved to be spoken to a team. |
There was a problem hiding this comment.
Line 22 says "Nothing here has been approved to be spoken to a team", and passages.py:82 speaks these lines to a team on the wheel. This PR treats that exact sentence as disqualifying for a file in the same directory: test_internalization_room_fixed_lines.py:104 asserts it against the Spanish draft before asserting the draft reaches no mouth. Pick one — drop the banner because a bare map reference needs no approval, narrow it to what is actually pending, or keep the file off the wheel until she rules. I cannot read her 4 September ruling from here; whether the reference form is approved needs Henok.
There was a problem hiding this comment.
Narrowed it. What is settled is that the lines are the maps' own references, which is her 4 September rule applied and the form her menu shows; what still awaits her word is whether the wheel speaks a reference aloud at all. The banner now says that, and the ticket's instruction not to delete it quietly is kept. de2b1fc.
| room.draft = VERDICT_DRAFT_ES | ||
| session_id, _ = await _two_stretches_told(client, language="es") | ||
| room.draft = VERDICT_DRAFT_EN | ||
| session_id, _ = await _two_stretches_told(client, language="en") |
There was a problem hiding this comment.
en is FLOOR (languages.py:23), and first falls back through utterances to the untagged authored English (fail_safe.py:57), so this case can no longer separate "honoured the session language" from "ignored it and took the floor" — with es it could. Both assertions hold either way. The fallback is one dropped argument away: language_code: str = FLOOR, back_translation.py:992. Not firing today, the pt case at line 402 still catches it. The helper above states the standard itself: "no case could fail for the reason it exists". Run this one with language="pt" and swap the assertions, or drop it and say the pair needs a third language.
There was a problem hiding this comment.
Right: with English being the floor, that case could not fail for the reason it exists. Dropped it; the Portuguese case stands alone, and the docstring of the commit says a second contrast needs a third claimed language. de2b1fc.
There was a problem hiding this comment.
Read the whole diff: the language gate, the fail-safe loader, the rewritten passage lines and the tests. Two findings, and neither breaks the room today — one banner that contradicts what the wheel does with the file it sits on, one test case that stopped being able to fail when es became en. Not checking the provenance record's account of 10 August against the session logs, and not the pronunciation of the new references either; that one is your morning UI pass. Those two are the whole list.
…at proved nothing goes The banner still said nothing here was approved to be spoken to a team, on the same day this branch treats that sentence as disqualifying for the Spanish draft beside it. The lines are now each map's own reference, which is her rule of 4 September applied; what still awaits her word is only whether the wheel speaks a reference aloud at all. The banner says exactly that instead. The whole-stretch test proved the room asks in the session's language by contrasting Spanish with Portuguese. With Spanish gone the case ran in English, which is the floor: a room that ignored the session language and fell to the floor would have passed it too. The Portuguese case beside it is the one that can fail for the reason it exists, so it stands alone; a second contrast needs a third claimed language. Found by the review bot on the PR. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AucpnrSDAiaKpcsBCNH7C2
There was a problem hiding this comment.
Second pass, ledger from pass 1 re-read against de2b1fc. Both points are closed. The four banner lines are the only lines added since c86194ea, and they cannot reach a mouth: passage_lines.py:10-11 matches only ### Pnn-xx headings and - "…" bullets, and the banner sits above the first heading; the STATUS: DRAFT string asserted at tests/test_internalization_room_fixed_lines.py:104 belongs to _fail_safe_es_supplement.md, not this file. Nothing new raised and nothing left open from me. Not covering the app half stacked behind this. Approval is Henok's.
A team turned the passage wheel and heard fourteen lines per language that we wrote from each map's
pericope-title, a summary rather than a name, so the wheel told the team what it was about to find before it had chosen anything; P07 handed over the redeemer. The file says of itself that nothing in it has been approved to be spoken to a team and that no validator sees it. A Spanish tablet, meanwhile, met every failure of the room in lines from a second draft file, and opened sessions in a language Marcia has not approved. Her ruling of 4 September settles both: nothing about a passage may be said outside the map, and Spanish is not offered until she decides to offer it.The wheel now says which passage it is and nothing about what is in it. Every line is the map's own H1 reference, the way her menu takes it:
# P07 — Ruth 2:17-23becomesRuth 2:17-23, with the book named in the language being spoken,Rutein Portuguese from the label catalogue. The verse dash is copied from the canon rather than normalized (an en dash through P05, a hyphen from P06 on), because a line that disagrees with the map it came from is the thing this stops. The lock is a test that reads the fourteen maps and the catalogue and demands that every line in the file, in every language, be its map's reference with the book renamed, so a rewrite that carries story again has nothing to agree with; the expected lines are transcribed from the maps, not derived from the file under test. The old no-digit assertion is inverted: a reference is numbers, and what must stay out is the canon's own file id.Spanish comes out of what a team can reach.
ROOM_LANGUAGESloseses, and sincenormalizeis the one gate the wire passes through, the wheel, the session open and the voice route answer 400 for it, beside the French they already refused.LANGUAGE_NAMESand the Spanish voice keep their entries so a session already written asesis read back rather than turning into a 500. The wheel's Spanish block goes. The fail-safe supplements are no longer globbed from the directory: they are named offROOM_LANGUAGES, so the Spanish draft stays exactly where it is, banner intact, unreachable from any path that speaks, and returningesto the tuple is the whole of turning it back on. The passage-lines DRAFT banner stays where it is.Scope 6 asked for the 2026-08-10 approval of the Portuguese supplement as an artifact beside the file. There was nothing to archive: the header's "Reviewed and approved by Marcia (2026-08-10)" was written thirteen seconds after one line of chat relaying that she had agreed, the Portuguese it vouches for had been written fifty-eight seconds earlier in the same session, no commit records an approval, her repository has none on that date, and on 4 September she asked for the text rather than confirming from memory. So the header now says what it has, an oral approval relayed by João with her written confirmation pending, and the record sits beside the file in
_fail_safe_pt_supplement_provenance.md. The lines themselves are untouched; whether the Portuguese B, C and E stand is her call once she has the text. João: confirm your recollection of 10 August in the morning.Verified against this worktree, host-run backend, speech through a local stub: the wheel in Portuguese and in English speaks six lines (P07 still gated), each the bare reference,
Rute 1:1–5…Rute 2:8-16andRuth 1:1–5…Ruth 2:8-16;esandfranswer 400. The app half is the next PR, stacked on this one.Verificação
tests/test_internalization_room_passages.py(28 literais transcritos dos catorze mapas)esnão é reivindicado:normalizedevolve nada; roda, sessão e voz respondem 400 (es,es-419,fr)tests/test_internalization_room_language.pyesalcançável depassages.py/fail_safe.py; suplementos nomeados porROOM_LANGUAGEStests/test_internalization_room_fixed_lines.pyesé lida de volta sem 500Gates:
uv run ruff check .,ruff format --check .,mypy app/,boots,alembic heads(uma),python scripts/check_doctrine.pyverdes; suíte inteira 2602 passed, 4 skipped, 1 xfailed. Revisor interno (joao-review): 0 achados sobreviventes. 6 commits, 10 arquivos, +212 −90.Muda o que a equipe ouve na roda (referência falada em vez de frase): não entra sem o teste de UI do João (portão de teste manual, de manhã). ENG-787 (P07 re-vendor) stacks on the same line rule.
Ticket: ENG-759.
🤖 Generated with Claude Code
https://claude.ai/code/session_01AucpnrSDAiaKpcsBCNH7C2