Skip to content

i18n layer 3: sign-in, claim, recovery and invitation pages, Doctor and capability words, the pseudo-locale check; round four accepted - #322

Merged
wms2537 merged 9 commits into
mainfrom
i18n-l3
Oct 1, 2026
Merged

wms2537 merged 9 commits into
mainfrom
i18n-l3

Conversation

@wms2537

@wms2537 wms2537 commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

The last layer of the interface's languages. zh-Hans stays preview here; ending it is a separate change.

  • Pre-auth pages (app/session/theme scripts) from the catalog; UNMIGRATED is empty. 淼达 lockup on sign-in/claim, a language switch in the pre-auth strip, a bilingual <noscript>, localized headlines for 18 pre-auth error codes (PREAUTH_ERRORS) with the Node's English kept and marked.
  • Server words by code: 46 Doctor check titles, 14 capability descriptions (CAPABILITY_IDS), the reader's body notices (BODY_PROBLEMS), audit outcomes and approval subjects as contract lists.
  • T4: a test-only pseudo-locale renders every route with its error states and every pre-auth page, and fails on any visible English not marked as the Node's.
  • Bugs fixed (own commits): a refused audit Verify read as a broken chain; Doctor's Acknowledge hung on an empty field; the gate looped for a member whose provider read fails; after a real claim the recovery codes vanished before anyone could copy them.
  • Round four: the owner accepted every proposed row and question in the working session on 2 October 2026 (OWNER_ROUND_FOUR); "Bootstrap secret" is now "Claim secret"; a Butler run's state is keyed (已终止, never 已停止).

Verified: full worker run (workerd 2,110, node 863, DOM 847 before merging main; node 863 / DOM 848 after), axe and spacing clean in both locales, 36 screenshots.

🤖 Generated with Claude Code

wms2537 and others added 9 commits October 2, 2026 02:23
…renders every route: layer 3

Layer 3 of the interface's languages (ADR 46), three agents' work integrated.

Before sign-in: app.client.js, session.client.js and theme.client.js take every
word from the preauth table in /app/locale.js, so UNMIGRATED is empty. The
Node's English is marked by nodeWords(), the DOM twin of <NodeWords>. A
refusal's code is keyed by PREAUTH_ERRORS (a closed list in the contract, no
imports): a headline in the viewer's language above the Node's sentence,
marked (D34). The status strip has a language switch (?locale=, no storage),
the claim and sign-in pages draw the 淼达 lockup, and <noscript> is one block
per locale, English first.

Server words keyed by code: the Doctor's check titles (DOCTOR_CHECKS), a
capability's description (CAPABILITY_IDS) and a body's problem (BODY_PROBLEMS).

T4, the pseudo-locale en-XA: every route populated, empty and failed, every
button pressed against a Node that refuses, and the pre-sign-in pages with each
refusal. Its fifteen findings are fixed: identifiers in <code> (audit action,
log event, scope, SPF/DKIM/DMARC results, yaml/json, bounce type moved out of
a title), audit outcomes and an approval's subject keyed by new contract lists
(AUDIT_OUTCOMES, APPROVAL_SUBJECT_KINDS), the notices band's instants through
format.ts (D37), KB/MB as catalog words, a recipient's last_error marked. The
fixtures now have the Node's shapes. Audit's Verify refusal is fixed in the
next change, where /audit goes green.

Glossary: 25 new rows, proposed, bound to their keys; bindings to confirmed
rows where the English agrees. catalog.test.ts expects exactly those rows
proposed. zh-Hans stays a preview. CSS for the lockup and the switch.
docs/i18n.md, README, Blueprint ADR 30 and 46, history; the bundle receipt
remeasured (/app/locale.js 15,903 raw / 6,470 gzip).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… chain

verify() read the response body as a verdict whatever the status, so a
refused POST /api/audit/verify (a member's 403, a 409) rendered "Chain broken
at entry undefined. undefined entries checked.": a false integrity verdict
(AGENTS.md §3). It now goes through act() (verifyAudit in api.ts) and shows a
refusal with marked(), as a bad notice. Found by the pseudo-locale (T4); with
it /audit's every-button case is green, and so is T4.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…n empty one

Pressed with an empty Restore id, Acknowledge built
POST /api/recovery/conflicts/:restoreId/acknowledge with an empty parameter,
which at() refuses by throwing before any request: an unhandled rejection,
and OneAct's button stayed busy for ever. The act is now disabled until a
restore id is typed (OneAct's own disabled, as the recovery-code confirm
does). The pseudo-locale's Doctor fixture has the conflict finding back, so
T4 presses that screen whole.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ember's refused provider read is not re-read in a loop

For anyone whose GET /api/provider fails (a member gets 404), the gate let
the shell through on the error. The shell's setup notice (SetupUnfinished)
reads the provider too, and a reader mounting on a failed query refetches it,
which puts the query back to pending; the gate then showed loading and
unmounted the shell, the read failed, the shell mounted again: about one
provider read a second and a screen flipping between loading and the shell.
The gate now remembers that it has decided, and a read going back to pending
keeps the children. Found by the pseudo-locale (T4); first-run.test.tsx holds
it with the real notice under the gate.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…, rather than being replaced by the shell at once

The claim adopted the session before showing the codes, and adopt() emits
"signed-in", whose listener hands the page to the shell; the shell then
replaced the ten codes (#134, ADR 29: shown once, never produced again)
before anybody could copy them. Older than layer 3; found on screen in its
verification on a local Node, where the claim went straight to the first-run
screen. The tests never saw it because the session stub's adopt() is silent.

The handler now decides whether it holds codes before adopting, the
signed-in listener does not hand over while they are held, and "I have saved
these" releases the hold and routes. preauth-words.test.ts sends the
signed-in event as the real adopt() does and fails without the hold.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…e, and each context signs in on its own

Two things stopped layer 3's sweeps from measuring what they claim. axe.mjs
found the invitation link and the sign-in form by English literals, so under
--locale zh-Hans, now that those pages are translated, "join" and "sign-in
refused" could not open; wordsFor() returns the preauth table too and the
locators read it. And every context shared one session snapshot, so one
refresh token: the first context to renew rotated it, the next presented the
old one as a reuse, and the family was signed out. A run longer than the
access token's life (both halves of a local run) skipped every screen after
that, 62 in English. Each context now signs in for itself, in axe.mjs and
spacing.mjs.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… bundle is remeasured at the layer's last change

docs/i18n.md listed H1 to H7 of the fourteen questions the review data
carries; H8 to H14 join them. The receipt's shell figure was taken at the
integration commit; the four fixes after it moved the shell 240 bytes raw
(762,939 / 216,442 gzip). /app/locale.js and both tables are unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…sary row is confirmed, the claim's field says Claim secret, and a Butler run's state is keyed

The owner said "just accept them" in the working session on 2 October 2026.
OWNER_ROUND_FOUR records exactly that: every proposed row and question accepted
as proposed, in the working session, without a review page. Layer 3's 25 rows
carry it, and one more, butler-run.stopped (已终止, avoiding 停止), which holds
H7's word. No row is proposed now; catalog.test.ts holds that, round four's
record, and put-backs of evidence, claim-secret and butler-run.stopped.

H1: the English field says "Claim secret", bound to the claim-secret row. The
Node's bad_secret and not_installed messages still say bootstrap: a follow-up.
H7: butlers.run.* over BUTLER_RUN_STATES in the runs table, the dry run's
verdict and the dry run's run line (trigger event in <code>); fixtures moved to
the Node's states (finished, refused). H2, H3, H5 kept; H4, H9, H10, H11
confirmed; H6, H8, H12, H13, H14 listed in docs/i18n.md as accepted follow-ups.
Ending the preview is not decided here.

Receipt remeasured (shell 763,056 / 216,488; locale.js 15,900 / 6,472; tables
92,778 / 93,122), budgets regenerated; README, ADR 30 and 46, history updated.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
# Conflicts:
#	docs/history.md
#	docs/i18n.md
@wms2537
wms2537 merged commit 72ed109 into main Oct 1, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant