Skip to content

login: the page looks live when the server is unreachable — no error or retry, and it falls back to offering Sign up #11806

Description

@objectstack-fleet

Filing gate ① — product defect with a named location and a reproduction. reach: console login page served while the backend is stopped.

Who acts on it: objectui triage → the Studio / app-shell owner. ⛔ Not a claim. Found in a manual browser QA pass of Studio on 2026-10-07; filed one card per finding on the maintainer's word: 「你发现的问题全部提交 issue」, and on the one-card-per-finding question 「覆盖规则,逐条立卡」.

What happens

With the server unreachable, seven boot reads (runtime/config, auth/config, i18n/*, auth/get-session …) return 502 silently; the form looks normal and the user finds out only on submit. Because auth/config failed, the page also falls back to offering "Don't have an account? Sign up" (with the server up and registration closed it is correctly hidden — #11691).

Suggested direction (triage to rule)

When the config reads fail, show "Can't reach the server" with Retry instead of a live-looking form, and do not offer Sign up while the registration posture is unknown.

Environment

objectstack 879bd38c · examples/app-showcase booted with objectstack dev --ui --seed-admin on an isolated port and SQLite file · objectui 179f6fe9 (HEAD; the framework pin .objectui-sha is a58626c8) served by the console's Vite dev server, perf numbers from a vite build of the same commit · Chromium 141 at 1440×900 · signed in as the seeded platform admin admin@objectos.ai unless stated.

Duplicate check

Dedupe words: login page server unreachable no message · sign up shown invite only SELF_REGISTRATION_CLOSED

Filed by Claude Code (session session_01D76mrPJrSSdaKRxR2rvrMG) from that QA pass.


Generated by Claude Code

Activity

  1. added
    bugSomething isn't working
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    area:devpathThe road — create, dev, verify, publish/install, connect an agent, iterate
    on Oct 7, 2026
  2. objectstack-fleet commented on Oct 7, 2026

    @objectstack-fleet
    ContributorAuthor

    Path: the road — start: signing in when the server is down | 缺项 | P3

    Triage: first grade, bug · priority:p3 · domain:ui · area:devpath · pm:queue. Direction as the body proposes

    Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-07T17:29Z. ⛔ Not a claim, ⛔ not a dispatch.

    Triage: lands in packages/app-shell/src/console/auth/LoginPage.tsx and signUpOffer.ts ⇒ domain:ui; rationale: a Studio or console surface in objectui. Filed from the browser QA pass of 2026-10-07 (objectstack 879bd38c, objectui 179f6fe9); paths re-read on objectui main 9990f9e122.

    • Why p3: the user cannot sign in either way; the page only fails to say why.
    • Direction:
      • when the config reads fail, show "Can't reach the server" with Retry in place of the form
      • offer Sign up only once the registration posture is known
    • Clause-②: no. Patch changeset in objectui.
  3. objectstack-fleet commented on Oct 8, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1
    Session: session_01MgfduSkFrfM3eorB3UGfAU
    Account: os-bill
    Branch: claude/issue-11806-login-server-unreachable
    Worktree: objectui-issue-11806
    Domain: domain:ui
    Seat: domain:ui#2
    File surface (on b0aa892):

    • apps/console/src/pages/auth/LoginPage.tsx: the console's own login page, which the QA pass reached. When its config reads fail it shows "can't reach the server" with Retry instead of a live-looking form, and it offers Sign up only once the registration posture is known.
    • packages/app-shell/src/console/auth/LoginPage.tsx (DefaultLoginPage): the same rule, inside the component. Its props stay as they are.
    • The tests beside these, and .changeset/11806-*.md.

    ⛔ Not on it:

    • decideSignUpOffer, SignUpOfferContext and SignUpOffer in packages/app-shell/src/console/auth/signUpOffer.ts. They are exported from packages/app-shell/src/index.ts (:282–:288), so a change to their signature or answers is a published-surface change. The page decides whether to render the offer at all; it does not change the shared rule's answers.
    • RegisterPage.tsx / ForgotPasswordPage.tsx on either side, and packages/auth/** (LoginForm, useAuth).
    • packages/i18n/**. The strings come from existing keys: console.*.error.connectionFailed / serverUnreachable / checkServer and retry, at about :2087–:2095 of en.ts.
    • packages/components/src/ui/**.

    Any file outside this list: the dev reports it before opening the PR (stop on breach; explain in the report).
    Container & model: M, mode:subagent, model: opus (dispatch-gates --tier --repo objectstack-ai/objectui over these paths: no path-derived mandate; default tier)
    Clause-②: no
    Responsibility: objectui console login page: when the server's config reads (runtime/config, auth/config, i18n, get-session) fail, the form renders as if live and, with auth config unknown, offers Sign up | none: the page holds the failed reads itself and is the only place that can say so | every user who opens the console while the backend is down, measured by the filer in the 2026-10-07 QA pass (seven 502s, a live-looking form, Sign up offered)
    Thread-read: 6043228771
    Serial constraints cleared: none blocking.

    • In-flight pm:dispatched claims, read 2026-10-08T03:09Z: none names LoginPage, signUpOffer or console/auth.
    • apps/console: seat 1's objectui#11798 (chunking and routes) is no longer in flight.
    • Open objectui PRs, read 2026-10-08T03:09Z: none touches these files.

    Why Clause-②: no: no export, prop or accepted value changes, and the strings reuse existing published keys. If an existing key does not fit and a new packages/i18n key is needed, the dev reports it before opening the PR. The same goes for a change to the exported sign-up decision. In either case the seat re-claims with Clause-②: yes: a minor changeset and a contract-review record before the queue.


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 8, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 11806,
    "status": "done",
    "branch": "claude/issue-11806-login-server-unreachable",
    "pr": "#11882",
    "session": "session_01MgfduSkFrfM3eorB3UGfAU",
    "premise_still_valid": true,
    "summary": "The console's /login and app-shell's DefaultLoginPage now track the auth-config read as loading/failed/known. While loading or failed they offer no Sign up link. A failed read (getAuthConfig rejecting after createAuthClient's own 3 retries) replaces the form with 'Cannot connect to server', the check-server hint and a Retry that reads again; the panel stays up, button 'Retrying...', until an answer brings the form back with decideSignUpOffer's answer. decideSignUpOffer / SignUpOfferContext / SignUpOffer and DefaultLoginPage's props are untouched; strings reuse existing en keys console.error.connectionFailed, console.error.checkServer, console.actions.retry, console.actions.retrying (no packages/i18n change). H1: the only failure that drives the state is GET /api/v1/auth/config; get-session is absorbed by AuthProvider, runtime/config + auth/me/localization + i18n are main.tsx boot reads that absorb failure. H2: keys reach DefaultLoginPage through its own t (pins render pack text, no inline defaults). H3: browser + pins confirm the panel renders only after rejection.",
    "head": "e7c3cb2",
    "files_changed": [
    "apps/console/src/pages/auth/LoginPage.tsx",
    "packages/app-shell/src/console/auth/LoginPage.tsx",
    "apps/console/src/pages/auth/tests/LoginPage.server-unreachable-11806.test.tsx",
    "packages/app-shell/src/console/auth/tests/defaultLoginServerUnreachable-11806.test.tsx",
    ".changeset/11806-login-server-unreachable.md"
    ],
    "gates": [
    "HEAD e7c3cb2 (git rev-parse --short HEAD after the last commit); every row below ran at e7c3cb2 unless it says otherwise",
    "pnpm exec vitest run apps/console/src/pages/auth/ packages/app-shell/src/console/auth/ → 'Test Files 19 passed (19)' 'Tests 109 passed (109)'; lock 'VERDICT command-exit 0'",
    "turbo run build --filter='@object-ui/console^...' --concurrency=2 → BUILD_EXIT=0; pnpm --filter @object-ui/app-shell type-check → APP_SHELL_TYPECHECK_EXIT=0; pnpm --filter @object-ui/console type-check → CONSOLE_TYPECHECK_EXIT=0 (lock line reads 'batch-last-exit 0' because parts were joined with ';'; the last part ANDs both exits)",
    "tsc --listFiles: app-shell tsconfig.test.json (5112 files) reads defaultLoginServerUnreachable-11806 x1, the page x1, control defaultPagesFollowPosture-11705 x1; console tsc --noEmit (3914 files) reads LoginPage.server-unreachable-11806 x1, the page x1, control LoginPage.sign-up-gate-11634 x1",
    "node scripts/check-changeset-presence.mjs → exit 0 '4 source file(s) of 2 released package(s) changed, and this change declares 1 changeset(s): .changeset/11806-login-server-unreachable.md.'",
    "node scripts/check-changeset-no-major.mjs → exit 0 'No changeset declares a major bump.'",
    "pnpm check:i18n-keys → exit 0 'Every in-scope call-site key resolves against the en pack (3300 keys) ...'; positive controls via ablation-replace: app-shell page key misspelled → exit 1 [missing-key] console.error.connectionFailedX; console page default drifted → exit 1 [default-value-drift] console.actions.retry; both restored, blob == HEAD, git diff HEAD empty",
    "pnpm check:new-line-citations → 'VERDICT new-cross-file-line-citations: 0 new citation(s), enforcement report-only → exit 0'",
    "pnpm check:control-bytes → exit 0 'check-control-bytes: OK'",
    "pnpm check:changeset-claims / check:pending-changeset-literals / check:unreferenced-sources / check:test-path-roots / check:phantom-deps / check:i18n-dead-keys / check:i18n-drift → exit 0 each",
    "pnpm exec eslint (4 touched files, --format json) → exit 0, files 4, errors 0, warnings 2, both react-hooks/set-state-in-effect on untouched lines (hasBootstrapped latch, org auto-select); the cef0eee bytes of that file lint to the same 2",
    "ablation (fix committed first; both page files set to cef0eee bytes, trap restore from HEAD): 'Tests 8 failed (8)'; pending pins fail on an assertion that the Sign up anchor is absent finding it present on both pages; restore proven blob == HEAD and git diff HEAD empty; pins run at 4fe3b84 (same page bytes as e7c3cb2)",
    "browser (Chromium /opt/pw-browsers, 1440x900, console vite dev on a private port, DEV_PROXY_TARGET at a dead port; /api/v1/auth/config → 502): pending signUp 0 / unreachable 0; failed signUp 0 / unreachable 1 / retry 1 / email 0; after a stub answered /auth/config (open) + Retry: signUp 1 / unreachable 0 / email 1; 502 paths: runtime/config, auth/me/localization, auth/config, i18n/translations/en, i18n/locales, auth/get-session, dev/metadata-events",
    "NOT MEASURED: full suites 'pnpm exec vitest run --maxWorkers=2 packages/app-shell/ apps/console/' (1261 test files), reason: stopped by me after 31m holding the shared lock with 3 waiters and no verdict; declared narrowing below",
    "NOT MEASURED: apps/console/src/tests/App.agentChatLink-10640, App.docsPortalLazy, App.uploadAltitude-10131, internalFormShell, reason: lock 'VERDICT queue-timeout (exit 99)'; each vi.mocks ../pages/auth/LoginPage, so none executes either page",
    "NOT MEASURED: check:eager-closure, reason: needs a console vite build, run by CI performance-budget.yml; new imports come from the @object-ui/auth entry the page already imports for LoginForm"
    ],
    "tests": "New pins (3 per page, it.each makes 4 cases each): pending read → no Sign up and no unreachable state; failed read → alert with connectionFailed + checkServer, Retry enabled, no Email field, no Sign up; Retry → 'Retrying...' disabled with no form, then open → form + link /register, disableSignUp:true → form without link. Green 8/8; ablated to cef0eee page bytes 8/8 red. Auth test dirs 19 files / 109 tests green at e7c3cb2. Declared narrowing for the package suites: the test files that execute either page = importers of either LoginPage file + of DefaultLoginPage / the console/auth barrel + console tests importing App, enumerated by git grep over all *.test.ts(x); all of them are in the two auth dirs run green, except four App-level files that vi.mock LoginPage (NOT MEASURED, exit 99). Exported surface byte-unchanged, so no importer package owes tests. CI pnpm test runs the full population.",
    "mcp_calls": "0",
    "api_writes": "3 — all through the fleet-write relay (POST /repos/objectstack-ai/objectstack/dispatches each): pr_create → POST /repos/objectstack-ai/objectui/pulls (#11882, draft, 8396 bytes stored identical); label-write assign → POST /repos//issues/11882/assignees (os-bill, read back MATCHES); post-stamped → POST /repos//issues/11806/comments (this report). git push is not a REST write.",
    "deviations": [
    "Full app-shell + console suites stopped unmeasured after 31m holding the shared lock (3 agents queued, oldest near its 540s budget); replaced by the declared narrowing in tests. CI pnpm test covers the full population.",
    "PR #11882 body was written while that suite still ran; its gates row reads 'still running when this PR was opened; its verdict line is in the os-dev-report comment'. Seat may rewrite that cell to: 'NOT MEASURED: stopped after 31m holding the lock with 3 waiters; declared narrowing: the 19 auth test files that execute either page, green; full suites run in CI'.",
    "packages/app-shell/README.md not updated: the claim's file surface excludes it, while AGENTS.md commandment 2 asks for docs to move with the code; see open_questions.",
    "Commit trailers are the model-free pair AGENTS.md prescribes (Claude-Session + Co-authored-by: Claude), not the harness reminder's model-named Co-Authored-By; PR footer is the os-dev session-URL form, not the harness's form.",
    "Write budget: the PM notice (container at 40/40) arrived before any write; pr_create and assign went out once the window reopened, each on its first attempt, none refused."
    ],
    "open_questions": [
    {
    "question": "packages/app-shell/README.md 'Default auth pages and the sign-up offer' has no /login row for a pending or failed config read, and its useSignUpOffer host recipe still answers a null config as 'form'. The claim's surface excludes README.md. Add the docs in a patch round?",
    "options": [
    "A: widen the surface by README.md and add, after the table: 'Until GET /api/v1/auth/config answers, DefaultLoginPage offers no Sign up link. When that read fails (the auth client retries it first), the page shows Cannot connect to server with a Retry that reads it again, in place of the form (objectui#11806). A host following the recipe below can do the same: treat a pending or failed read as unknown, and consult decideSignUpOffer only once the read has answered.'",
    "B: leave the README as is; the table is silent on the new state rather than false"
    ],
    "recommendation": "A, because the README is the host-facing description of this page's behaviour and the recipe it offers now diverges from the default page on exactly this card's defect; it is a docs-only patch with no export or behaviour change"
    }
    ],
    "out_of_scope_findings": [
    "class: a · reach: public door /register on the console (vite dev, API target down so /api/v1/auth/config answers 502), measured in Chromium in this run: the full registration form ('Create Account', Name/Email/Password fields) renders after 12s, no unreachable state · evidence: apps/console RegisterPage and app-shell DefaultRegisterPage both store a failed config read as { config: null }, and decideSignUpOffer answers null as 'form'; same family as objectui#11806 (posture unknown answered as an offer, server down shown as a live form), so it belongs to this family's closing card, not a single-point card; RegisterPage on both sides is on this claim's Not-on-it list · dedupe words: register page server unreachable form shown · register auth config read failed posture unknown · sign up form offered backend down"
    ]
    }


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 8, 2026

    @objectstack-fleet
    ContributorAuthor

    Review: REWORK (patch round 1) — PR objectui#11882 · domain:ui seat 2 · 2026-10-08T04:21Z

    Reviewed-by: domain:ui seat 2 (session_01MgfduSkFrfM3eorB3UGfAU), against GitHub at head e7c3cb2. On that head CI reports 43 checks, all success or an expected skip.

    What holds, carried forward:

    • PR shape: draft, base main, first line Fixes #11806, no closing keyword next to another card, and Clause-②: no at the start of a line.
    • Scope: 5 files, both login pages plus their pins and the changeset. decideSignUpOffer / SignUpOfferContext / SignUpOffer and DefaultLoginPage's props are byte-unchanged.
    • Strings: they reuse existing pack keys console.error.connectionFailed / checkServer and console.actions.retry / retrying. check:i18n-keys positive controls went red as expected.
    • Hypotheses:
      • H1 measured: GET /api/v1/auth/config is the only failure that drives the state.
      • H3: the panel renders only after the read rejects.
    • Evidence:
      • The pins pass 8/8. Ablated to cef0eee's page bytes, they fail 8/8.
      • The auth directories pass, 19 files / 109 tests.
      • Chromium against a dead backend: the pending state shows neither Sign up nor the unreachable state, and Retry brings the form back.

    Claim surface amendment, recorded this round. Claim 6051369453's surface now also covers:

    • packages/app-shell/README.md: the Default auth pages and the sign-up offer section.
    • apps/console/src/pages/auth/RegisterPage.tsx and packages/app-shell/src/console/auth/RegisterPage.tsx (DefaultRegisterPage), both moved off the claim's "Not on it" list.

    The register fix uses the bounded in-place exemption. All four conditions hold:

    1. Same defect class: a failed config read is stored as null and answered as an offer; the server is down but the page shows a live form.
    2. The fix is mechanical, in the same shape as the login fix.
    3. No other claim holds either file. Every in-flight claim was read just before this comment, and none names them.
    4. Same gate family.

    The reach is measured: /register with auth/config answering 502 renders the full registration form after 12 s.

    Two items to fix in this round:

    1. README (objectui AGENTS.md Add automated testing infrastructure and CI/CD workflows #2, docs-driven). Add the pending and failed-read behaviour to Default auth pages and the sign-up offer. Also correct the useSignUpOffer host recipe, which still answers a null config as form.
      • That is your open_questions item, answered with option A: treat a pending or failed read as unknown, and consult decideSignUpOffer only once the read has answered.
      • ⛔ The recipe text must not describe a change to decideSignUpOffer's answers; they stay as they are.
    2. /register on both sides. Apply the same three-state treatment: no form and no offer while the read is pending, and the unreachable state with Retry when it fails.
      • Pin it the same way: a test that fails on cef0eee bytes and passes after the fix.
      • Update the changeset to name the register page.
      • Use the same existing keys. A new packages/i18n key is still a stop that you report before pushing.

    PR body. The seat writes the body corrections. Name in the report the cells to change: the Files list, the gates row that says "still running", and the verification head.


    Generated by Claude Code

  6. objectstack-fleet commented on Oct 8, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 11806,
    "round": "patch round 1 (REWORK comment 6052157223)",
    "status": "done",
    "branch": "claude/issue-11806-login-server-unreachable",
    "pr": "#11882",
    "session": "session_01MgfduSkFrfM3eorB3UGfAU",
    "premise_still_valid": true,
    "summary": "Both REWORK items done on top of e7c3cb2. (1) /register on both sides (console RegisterPage, app-shell DefaultRegisterPage) now tracks the auth-config read as loading/failed/known like /login: pending renders no form and no offer (as before), a failed read renders the same 'Cannot connect to server' panel with Retry in place of the form, Retry keeps the panel up ('Retrying…') until an answer, then that answer decides as before (form, by-invitation notice, or the /login bounce for disableSignUp). Each side's LoginPage module now exports its panel ServerUnreachable (with data-testid auth-server-unreachable) and its RegisterPage reuses it; the app-shell package entry is unchanged (only '.' is exported, by explicit names). Same four existing keys, no packages/i18n change. (2) packages/app-shell/README.md 'Default auth pages and the sign-up offer': two table rows (read pending, read failed) plus a Retry sentence; the useSignUpOffer recipe now tracks loading/failed/known, answers 'unreachable' for a failed read and 'pending' while loading, and asks decideSignUpOffer only once the read has answered; the prose states decideSignUpOffer itself is unchanged (still answers a null config with 'form'). Changeset now names /register and DefaultRegisterPage.",
    "head": "ce91f67",
    "files_changed": [
    "apps/console/src/pages/auth/LoginPage.tsx",
    "apps/console/src/pages/auth/RegisterPage.tsx",
    "packages/app-shell/src/console/auth/LoginPage.tsx",
    "packages/app-shell/src/console/auth/RegisterPage.tsx",
    "apps/console/src/pages/auth/tests/LoginPage.server-unreachable-11806.test.tsx",
    "apps/console/src/pages/auth/tests/RegisterPage.server-unreachable-11806.test.tsx",
    "packages/app-shell/src/console/auth/tests/defaultLoginServerUnreachable-11806.test.tsx",
    "packages/app-shell/src/console/auth/tests/defaultRegisterServerUnreachable-11806.test.tsx",
    "packages/app-shell/README.md",
    ".changeset/11806-login-server-unreachable.md"
    ],
    "commits_this_round": [
    "b380b7d fix: register pages + exported panels",
    "8bf6b7a test: register pins",
    "ce91f67 docs: README + changeset"
    ],
    "gates": [
    "HEAD ce91f67 (git rev-parse --short HEAD after the last commit); every row ran at ce91f67 unless it says otherwise",
    "pnpm exec vitest run apps/console/src/pages/auth/ packages/app-shell/src/console/auth/ packages/app-shell/src/views/metadata-admin/previews/readme-flow-canvas-draft.test.ts packages/types/src/tests/public-block-doc-examples-bag-11321.test.ts scripts/tests/markdown-test-inputs.test.ts → 'Test Files 24 passed (24)' 'Tests 175 passed (175)'; lock 'VERDICT command-exit 0' (the last three are the README's readers)",
    "the four 11806 pin files → 'Test Files 4 passed (4)' 'Tests 16 passed (16)'; ran with page bytes equal to ce91f67 (pages last changed in b380b7d)",
    "register ablation (fix committed first; both RegisterPage files set to cef0eee bytes, trap restore from HEAD; on disk: fix marker configReadAttempt 0/0, base comment 'when the read failed' 1/1) → 'Tests 6 failed | 2 passed (8)': failed-read and both Retry pins red on both pages ('Unable to find role=alert' / 'Unable to find role=button and name Retry'); the 2 pending pins stay green on base because both base register pages already withheld the form while the read was pending; restore proven blob == HEAD and git diff HEAD empty",
    "turbo run build --filter='@object-ui/console^...' --concurrency=2 → 'Tasks: 34 successful, 34 total' (33 cached, app-shell rebuilt); lock 'VERDICT command-exit 0'",
    "pnpm --filter @object-ui/app-shell type-check && pnpm --filter @object-ui/console type-check → APP_SHELL_TYPECHECK_EXIT=0, CONSOLE_TYPECHECK_EXIT=0, 0 'error TS' lines; lock 'VERDICT command-exit 0' (joined with &&, so it covers both)",
    "tsc --listFiles: app-shell tsconfig.test.json (5113 files) reads defaultRegisterServerUnreachable-11806 x1, defaultLoginServerUnreachable-11806 x1, RegisterPage.tsx x1; console tsc --noEmit (3915 files) reads RegisterPage.server-unreachable-11806 x1, LoginPage.server-unreachable-11806 x1, RegisterPage.tsx x1",
    "node scripts/check-changeset-presence.mjs → exit 0; node scripts/check-changeset-no-major.mjs → exit 0",
    "pnpm check:i18n-keys / check:new-line-citations / check:control-bytes / check:changeset-claims / check:pending-changeset-literals / check:unreferenced-sources / check:test-path-roots / check:phantom-deps / check:i18n-drift / check:doc-types → exit 0 each ('Every documented component type is registered.' for doc-types)",
    "pnpm check:readme-exports → exit 1 with population judged after the build: '579 of them self-imports judged (571 real, 0 wrong-path, 0 fabricated)'; the 8 unjudged are in packages/cli and packages/plugin-ai READMEs (dist not built: outside the console closure) → NOT MEASURED for those two packages; node scripts/check-readme-exports.mjs --list shows the recipe's five bindings in packages/app-shell/README.md (decideSignUpOffer, isInvitationRedirect, needsBootstrapProbe, useBootstrapStatus, SignUpOffer) as 'real'",
    "pnpm exec eslint on the 8 touched source and test files → exit 0, errors 0, warnings 4: react-hooks/set-state-in-effect, 2 in console LoginPage and 2 in console RegisterPage, all on untouched lines (hasBootstrapped latch, org auto-select); the cef0eee bytes of console RegisterPage lint to the same 2",
    "browser /register (Chromium /opt/pw-browsers 1440x900, console vite dev on a private port, DEV_PROXY_TARGET at a dead port; /api/v1/auth/config → 502): pending createAccount 0 / unreachable 0; failed unreachable 1 / retry 1 / createAccount 0 / email 0; stub answering /auth/config (open) + Retry → createAccount 1 / email 1 / unreachable 0. Round 1 measured the same door rendering the full form with the API down.",
    "NOT MEASURED: full app-shell and console suites, reason: declared narrowing carried from round 1 (every test file that executes either login or register page is in the two auth dirs run green above; the four App-level tests vi.mock both pages); CI pnpm test runs the full population",
    "NOT MEASURED: check:eager-closure, reason: needs a console vite build, run by CI performance-budget.yml; the register pages' new import is the console's own LoginPage module / app-shell's ./LoginPage.js, both already in the same closure"
    ],
    "tests": "New this round: RegisterPage.server-unreachable-11806 (console) and defaultRegisterServerUnreachable-11806 (app-shell), 4 cases each: pending → no form, no by-invitation notice, no unreachable state; failed → alert with connectionFailed + checkServer, Retry enabled, no Create Account, no Name field; Retry → 'Retrying…' disabled with no form, then open → the form; Retry → disableSignUp: true → the /login bounce, never the form. 16/16 pins green across all four 11806 files; register ablation 6 red / 2 green (direction explained in gates). Auth dirs + README readers 24 files / 175 tests green at ce91f67.",
    "mcp_calls": "0",
    "api_writes": "this round 1 — post-stamped → fleet-write relay (POST /repos/objectstack-ai/objectstack/dispatches) → POST /repos//issues/11806/comments (this report). Cumulative 4 with round 1's pr_create, assign and report. git push is not a REST write. PR body not PATCHed.",
    "pr_body_cells_for_the_seat": [
    "Files: the body names only the login pages and the two login pin files (in 'What changed' and 'Tests'). Add apps/console/src/pages/auth/RegisterPage.tsx, packages/app-shell/src/console/auth/RegisterPage.tsx, RegisterPage.server-unreachable-11806.test.tsx, defaultRegisterServerUnreachable-11806.test.tsx and packages/app-shell/README.md; the PR now has 10 files.",
    "Gates heading '## Gates, at e7c3cb2' → '## Gates, at ce91f67'. Row 1 (auth dirs) → 'Test Files 24 passed (24)', 'Tests 175 passed (175)', with the three README readers added to the command.",
    "Gates row 'pnpm exec vitest run --maxWorkers=2 packages/app-shell/ apps/console/' whose verdict reads 'still running when this PR was opened…' → 'NOT MEASURED: stopped after 31m holding the shared lock with 3 waiters; declared narrowing: every test file that executes a login or register page is in the two auth dirs, green; full suites run in CI'.",
    "Gates row 'check:i18n-keys' unchanged; add a row 'check:readme-exports → 571 judged real, 0 wrong, 0 fabricated; recipe bindings real; cli and plugin-ai unbuilt, not judged'.",
    "Ablation paragraph: add the register ablation, 6 red / 2 green, with the pending pins green on base because the base register pages already withheld the form while pending.",
    "Acceptance notes: the README bullet is resolved (README updated); the 'Sibling page, same shape, not changed here' bullet is resolved (/register fixed on both sides)."
    ],
    "deviations": [
    "Lock: three queue-timeouts (exit 99) this round before the test union acquired; one holder (issue-11816) held for over 18 minutes running a three-package full suite. Re-queued with the same OS_VERIFY_LOCK_SLOT and a lowered OS_VERIFY_LOCK_WAIT so the wait plus the run fit in one foreground call; every gate above was eventually measured on ce91f67.",
    "The shared panel is a named export from each side's LoginPage module, not a new file: a new file would be outside the claim's surface. app-shell's package entry is unchanged.",
    "The register pages' pending pins are green on cef0eee (expected and stated above); the red half of the PM's 'red on cef0eee' requirement comes from the failed-read and Retry pins."
    ],
    "open_questions": [
    {
    "question": "e2e/smoke.spec.ts 'should settle into a recognised boot state' runs a production bundle with no backend and accepts the login config spinner, #login-email or #login-phone. With this change the login page's final state there is the unreachable panel, which the set does not name. The test still passes on the ~5.5 s spinner window (round-1 CI was green), but that is the race the spec's own objectui#4086 comment says the closed set exists to remove. e2e/ is off the claim's surface.",
    "options": [
    "A: widen the surface by e2e/smoke.spec.ts and add [data-testid="auth-server-unreachable"] (the panel now carries it) to that spec's signInScreen locator, a one-line change",
    "B: leave it; it passes, and the next flake on that spec points here"
    ],
    "recommendation": "A, because the panel is now a legitimate final boot state for a backend-less run, and a closed set that omits it only passes by catching a transient state"
    }
    ],
    "out_of_scope_findings": []
    }


    Generated by Claude Code

  7. objectstack-fleet commented on Oct 8, 2026

    @objectstack-fleet
    ContributorAuthor

    Review: ACCEPT — PR objectui#11882 · domain:ui seat 2 · 2026-10-08T05:39Z

    Implemented-by: os-dev subagent of session_01MgfduSkFrfM3eorB3UGfAU, branch claude/issue-11806-login-server-unreachable, head ba3624a, after two patch rounds.
    Reviewed-by: domain:ui seat 2 (session_01MgfduSkFrfM3eorB3UGfAU), against GitHub and the branch diff, not against the report's prose.

    Rounds:

    • Round 1 answered REWORK 6052157223:
      • /register is fixed on both sides, the console's RegisterPage and app-shell's DefaultRegisterPage. Pending renders no form, a failed read renders the same panel with Retry, and the answer after Retry decides as before.
      • packages/app-shell/README.md gains rows for a pending and a failed config read and a Retry sentence. Its useSignUpOffer recipe asks decideSignUpOffer only once the read has answered.
      • The changeset names /register.
    • Round 2 answered the dev's open question with option A. e2e/smoke.spec.ts's boot-state set now names [data-testid="auth-server-unreachable"], the sign-in screen's final state with no backend. Without it, the closed set objectui#4086 built passed only by catching the transient config spinner.

    Checklist:

    • PR shape: draft, base main, first line Fixes #11806. No closing keyword sits next to another card. Clause-②: no is at the start of a line. The body was refreshed by the seat to match ba3624a.

    • Scope: 11 files. The claim surface is amended to cover:

      • the two register pages and their pins (REWORK 6052157223);
      • the README (AGENTS.md's docs-driven rule);
      • e2e/smoke.spec.ts, the same defect's new final state, as one locator plus its comments.

      No other claim or open PR holds any of them. packages/i18n/**, packages/auth/** and signUpOffer.ts's exported rule are untouched.

    • Clause-②: no holds: decideSignUpOffer, SignUpOfferContext and SignUpOffer are unchanged. The panel is a named export of each side's LoginPage module, not of the package. app-shell's entry (src/index.ts:275–:277) exports only DefaultLoginPage and DefaultRegisterPage, by name. The strings come from the four existing keys.

    • Evidence:

      • The auth directories plus the README's readers pass: 24 files, 175 tests, at ce91f67.
      • Reverse checks: with the base login pages, all 8 login pins fail. With the base register pages, 6 fail and 2 pass; the 2 are the pending pins, because the base register pages already withheld the form while pending.
      • The type-checks for app-shell, the console and e2e all pass. check:readme-exports judges the recipe's bindings real.
      • In Chromium with the API down, /login and /register render the panel, and Retry against a live config brings the form.
      • The smoke spec, run against a production bundle with no backend, gives 6 passed. At 20 s the old locator set matches nothing and the panel matches.
    • CI: all 43 checks were green on ce91f67. ba3624a changes only the e2e spec, and the PR lands through the merge queue only when every check on that head is green.

    Acceptance notes:

    • Break-glass trade-off, in the PR body: a server whose /auth/config fails while sign-in works now shows the panel, and Retry is the way back. The triage direction asked for exactly this.
    • Full suites: the full app-shell and console suites were not run locally. They were stopped while holding the shared lock, and CI runs them.

    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:devpathThe road — create, dev, verify, publish/install, connect an agent, iteratebugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions