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
{{ message }}
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Repository navigation
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Settings pages: a refused save shows the server message verbatim in the toast — namespace and field keys plus the word "incomplete" ("Settings for 'localization' are incomplete: timezone — …"), and for Authentication the whole help paragraph #13146
Localization:toast "Settings for 'localization' are incomplete: timezone — Default timezone must be a valid IANA time zone identifier, e.g. Europe/Zurich (got "Mars/Olympus")"。
Authentication:toast 是 "Settings for 'auth' are incomplete: api_key_policy_started_at — Key policy started at does not match the expected format. Recorded automatically (UTC, ISO 8601) the first time …" 一整段帮助文字。
Claim: PM loop round 1 (priority:p3, bug)
Session: session_01GL347th7aWQUnY2k8diSLG
Account: os-support-ai (the seat's linked user as GET /user answers it; the card's assignee)
Branch: claude/issue-13146-settings-refusal-toast
Worktree: objectui-issue-13146
Domain: domain:ui
Seat: domain:ui#3
File surface: apps/console/src/pages/settings/SettingsView.tsx (read at objectui main7d497de), onSave's refusal branch: when the server's refusal carries per-field errors (extractFieldErrors already reads them, with labels), the toast says in product words which settings need attention, by label, with no namespace or field machine name and no "incomplete" for an invalid value; the field rows keep showing their own messages. The generic branch for a refusal with no field errors keeps a readable message. New copy goes in the console locale packs the parity gates require. Tests beside the page; one .changeset/13146-settings-refusal-toast.md (@object-ui/consolepatch). ⛔ Not the leave-with-unsaved-edits prompt (objectui#13163, landed as 7a5f267) and not the clear-to-unset control (objectui#13145). ⛔ No server change and ⛔ no new package export. Stop on breach; explain in the report.
Container & model: M, mode:subagent, model: opus (default tier; dispatch-gates --tier --repo objectstack-ai/objectui over this surface reads no path-derived mandate)
Clause-②: no
Responsibility: the risk is produced by objectui's own settings page, which puts the server's developer-facing sentence (namespace, field keys, "incomplete", and for Authentication a whole help paragraph) into the toast although the page already holds the per-field errors with labels. The platform path that covers it: the save is refused correctly and the field rows show readable errors. Who reaches it: every admin whose settings save is refused.
Thread-read: none
Serial constraints cleared: open objectui PRs touching apps/console/src/pages/settings/: none (the twelve open PRs' file lists were read at this claim). objectui#13163 changed SettingsView.tsx today (7a5f267); this card works on top of it.
Why Clause-②: no: a console page's own message. No export, prop, schema key or accept set of a published package moves.
{
"issue": 13146,
"status": "done",
"branch": "claude/issue-13146-settings-refusal-toast",
"pr": "https://github.com/objectstack-ai/objectui/pull/13227",
"session": "session_01GL347th7aWQUnY2k8diSLG — subagent run, the dispatching seat's id",
"premise_still_valid": true,
"summary": "SettingsView onSave's generic refusal branch no longer toasts err.message (the server's SettingsValidationError sentence: namespace, machine keys, 'incomplete', every row message incl. Authentication's help paragraph) when the refusal carries field errors. It toasts the new console.settingsView.fieldErrorsToast count-plural family, e.g. '1 setting needs attention: Default timezone', naming each refused setting by the label its row draws (manifest literal through labels.fieldLabel, the same lookup SettingsField uses), joined with validation.formInvalidJoiner. Field errors naming no setting on the page toast console.settingsView.saveFailed; a refusal with no field errors keeps the server message unchanged. PM mechanism assumption 1 was half true: extractFieldErrors returns only field+message (it drops FieldError.label), so labels come from the page manifest; that is also the correct source, because service-settings fills FieldError.label from the registered (untranslated) manifest literal while rows translate client-side. Assumptions 2 and 3 held (SettingsValidationError at objectstack origin/main 5fcc79497 composes the quoted sentence; settings-routes sends details: namespace + fields; work is on top of 7a5f267). No server change, no package export.",
"tests": "New apps/console/src/pages/settings/__tests__/SettingsView.refusalToast-13146.test.tsx (real I18nProvider over shipped packs, real wire body, expected sentences read from the en pack): 7 passed. Ablation once on committed head via objectstack scripts/ablation-replace.mjs (anchor = the new toast block, replacement = the pre-fix toast.error(err?.message ?? saveFailed)): 'mutation landed: anchor 1 → 0, blob 966434655d67 → c229d1a16d66', run 'Tests 6 failed | 1 passed (7)' (the 1 = the unchanged no-field-error case, expected green), 'ok restored: blob == HEAD (966434655d67) and git diff HEAD is empty'. Direction observed: red (normal). Note: a first ablation on 870a5d5 read 5 failed | 2 passed — the row-label case was vacuous against the pre-fix sentence (the server message also contains the label), so it was tightened to pin the whole toast (c453716) and the ablation re-run gave 6|1. Directory run at c453716: pnpm exec vitest run --maxWorkers=2 apps/console/src/pages/settings/ packages/i18n/ → 'Test Files 108 passed (108) / Tests 1518 passed | 13 skipped (1531)', lock VERDICT command-exit 0 (includes all-locales-key-parity, plural-categories-11432, count-families-11445, settingsPage.noBareLiterals-12821, SettingsView.field-errors).",
"gates": "Local, all at c453716, exit captured before any pipe: closure build pnpm turbo run build --filter='@object-ui/console^...' --concurrency=2 → 'Tasks: 34 successful, 34 total / Cached: 8', VERDICT command-exit 0; pnpm --filter @object-ui/console type-check EXIT=0 (script echoed 'tsc --noEmit && tsc -b tsconfig.node.json --force'; tsc --listFiles includes the new test: 1 hit); pnpm --filter @object-ui/i18n type-check EXIT=0; node scripts/check-changeset-presence.mjs EXIT=0 ('12 source file(s) of 2 released package(s) changed, and this change declares 1 changeset(s)'); pnpm check:new-line-citations EXIT=0 ('0 new citation(s)'); pnpm check:control-bytes EXIT=0; pnpm check:i18n-keys EXIT=0; pnpm check:i18n-drift EXIT=0 ('0 en value(s) changed (3 key(s) added)'); pnpm check:i18n-dead-keys EXIT=0 (report; new keys not among candidates); check:changeset-claims, check:pending-changeset-literals, check:vi-mock-specifiers, check:vi-mock-inherit, check:vi-mock-override-shape, check:test-path-roots all EXIT=0. NOT MEASURED: check:eager-locale-catalogues, reason: exit 2 PREREQUISITE NOT MET (needs a built apps/console/dist/eager-closure.json); left to CI. --ran reconciliation: n/a (dispatch-gates.mjs is objectstack-only; objectui list hand-derived per dispatch). PR #13227 check-runs at head c4537167 when read (35): success = Changeset Fixed Group Check, Changeset Bump Policy, label; skipped = Test (coverage), Test (coverage shard matrix), dependabot; in_progress = Repo Gates, Line Citation Gate, Type Check, Lint, Build & E2E, Build Docs, Bundle Analysis, Test (dist pins), Test shards 1-16/16, Changeset Claim Re-read, Changeset Overwrite Report, Changeset Declaration, Governed Surface Queue Guard, Live E2E (informational). Not waited on.",
"line_budget": "n/a: no skills/** or line-ratcheted ledger touched",
"files_changed": [
".changeset/13146-settings-refusal-toast.md +8 -0",
"apps/console/src/pages/settings/SettingsView.tsx +57 -5",
"apps/console/src/pages/settings/__tests__/SettingsView.refusalToast-13146.test.tsx +296 -0",
"packages/i18n/src/locales/ar.ts +7 -0",
"packages/i18n/src/locales/de.ts +3 -0",
"packages/i18n/src/locales/en.ts +7 -0",
"packages/i18n/src/locales/es.ts +4 -0",
"packages/i18n/src/locales/fr.ts +4 -0",
"packages/i18n/src/locales/ja.ts +3 -0",
"packages/i18n/src/locales/ko.ts +3 -0",
"packages/i18n/src/locales/pt.ts +4 -0",
"packages/i18n/src/locales/ru.ts +5 -0",
"packages/i18n/src/locales/zh.ts +3 -0"
],
"head": "c453716",
"deviations": [
"Changeset lists '@object-ui/i18n': patch beside the claim's '@object-ui/console': patch, because the diff edits i18n's published src (the ten locale packs); same fixed group, no extra bump.",
"Label source differs from the dispatch mechanism assumption 1 (extractFieldErrors carries no label): labels come from the page manifest via labels.fieldLabel; @object-ui/react untouched (no export or type moved).",
"Commit trailers are the model-free pair (Co-authored-by: Claude + Claude-Session) per objectui AGENTS.md; the harness reminder asked for a model-named Co-Authored-By, which was not used.",
"check:eager-locale-catalogues not run to a verdict locally (prerequisite: built console bundle); declared NOT MEASURED, CI owns it.",
"Worktree /home/user/objectui-issue-13146 removed after the PR opened (node_modules deleted first; git worktree remove succeeded without --force)."
],
"mcp_calls": "0",
"api_writes": "2 relay strokes — (1) pr_create via fleet-write/dispatch.mjs: POST /repos/objectstack-ai/objectstack/dispatches (relay) executing POST /repos/objectstack-ai/objectui/pulls and POST /repos/objectstack-ai/objectui/issues/13227/assignees (read-back: 7519 bytes sent, 7519 stored, identical; assignee os-support-ai; no labels sent — the path labels on the PR are labeler.yml's); (2) this os-dev-report comment via post-stamped.mjs: POST /repos/objectstack-ai/objectui/issues/13146/comments. Plus 3 git pushes (empty branch, 870a5d5, c453716), not REST.",
"open_questions": [],
"out_of_scope_findings": [
"carrier: none (承接者:无) · noted, not filed · apps/console/src/pages/settings/WorkspaceTimezonePrompt.tsx onConfirm toasts failure?.message on a non-locked refusal, i.e. the same SettingsValidationError sentence for the timezone it writes (it already puts the field message in its own slot); reach not measured — its draft is the browser's own IANA zone · in PR Acceptance notes · dedupe words: WorkspaceTimezonePrompt toast, timezone prompt refusal message, are incomplete",
"carrier: none (承接者:无) · noted, not filed, read-only inference · the kept no-field-error branch still toasts the server sentence for SETTINGS_FORBIDDEN, whose message names the namespace and capability (\"Access denied: writing to settings namespace 'auth' requires the 'X' capability\"); not measured at a public door · NOT in the PR body (written once); a seat may add it to Acceptance notes · dedupe words: settings forbidden toast namespace, SETTINGS_FORBIDDEN console toast"
]
}
ACCEPT → PR #13227 comment 6288935858 · domain:ui seat 3, session_01GL347th7aWQUnY2k8diSLG · 2026-10-20T10:36Z · head c453716 · live reading in the record · landing through the merge queue.
MERGED through the merge queue, merge commit 52907d7 on main
queue branch gh-readonly-queue/main/pr-13227-*
absent (git ls-remote: 0 refs)
origin/main52907d7
SettingsView.tsx: function refusedSettingLabels (1) · packages/i18n/src/locales/en.ts: fieldErrorsToast_one (1)
State: the card closed completed by the PR's Fixes; pm:dispatched is removed in this pass. The live Localization reading ("1 setting needs attention: Default timezone" at the head; the server's sentence at the parent) is in the ACCEPT, 6288935858.
Activity
objectstack-fleet commentedon Oct 20, 2026
Claim: PM loop round 1 (
priority:p3,bug)Session:
session_01GL347th7aWQUnY2k8diSLGAccount:
os-support-ai(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-13146-settings-refusal-toastWorktree:
objectui-issue-13146Domain:
domain:uiSeat:
domain:ui#3File surface:
apps/console/src/pages/settings/SettingsView.tsx(read at objectuimain7d497de),onSave's refusal branch: when the server's refusal carries per-field errors (extractFieldErrorsalready reads them, with labels), the toast says in product words which settings need attention, by label, with no namespace or field machine name and no "incomplete" for an invalid value; the field rows keep showing their own messages. The generic branch for a refusal with no field errors keeps a readable message. New copy goes in the console locale packs the parity gates require. Tests beside the page; one.changeset/13146-settings-refusal-toast.md(@object-ui/consolepatch). ⛔ Not the leave-with-unsaved-edits prompt (objectui#13163, landed as7a5f267) and not the clear-to-unset control (objectui#13145). ⛔ No server change and ⛔ no new package export. Stop on breach; explain in the report.Container & model:
M,mode:subagent,model: opus(default tier;dispatch-gates --tier --repo objectstack-ai/objectuiover this surface reads no path-derived mandate)Clause-②: no
Responsibility: the risk is produced by objectui's own settings page, which puts the server's developer-facing sentence (namespace, field keys, "incomplete", and for Authentication a whole help paragraph) into the toast although the page already holds the per-field errors with labels. The platform path that covers it: the save is refused correctly and the field rows show readable errors. Who reaches it: every admin whose settings save is refused.
Thread-read: none
Serial constraints cleared: open objectui PRs touching
apps/console/src/pages/settings/: none (the twelve open PRs' file lists were read at this claim). objectui#13163 changedSettingsView.tsxtoday (7a5f267); this card works on top of it.Why
Clause-②: no: a console page's own message. No export, prop, schema key or accept set of a published package moves.Claimed at: 2026-10-20T09:46Z
objectstack-fleet commentedon Oct 20, 2026
os-dev-report
{ "issue": 13146, "status": "done", "branch": "claude/issue-13146-settings-refusal-toast", "pr": "https://github.com/objectstack-ai/objectui/pull/13227", "session": "session_01GL347th7aWQUnY2k8diSLG — subagent run, the dispatching seat's id", "premise_still_valid": true, "summary": "SettingsView onSave's generic refusal branch no longer toasts err.message (the server's SettingsValidationError sentence: namespace, machine keys, 'incomplete', every row message incl. Authentication's help paragraph) when the refusal carries field errors. It toasts the new console.settingsView.fieldErrorsToast count-plural family, e.g. '1 setting needs attention: Default timezone', naming each refused setting by the label its row draws (manifest literal through labels.fieldLabel, the same lookup SettingsField uses), joined with validation.formInvalidJoiner. Field errors naming no setting on the page toast console.settingsView.saveFailed; a refusal with no field errors keeps the server message unchanged. PM mechanism assumption 1 was half true: extractFieldErrors returns only field+message (it drops FieldError.label), so labels come from the page manifest; that is also the correct source, because service-settings fills FieldError.label from the registered (untranslated) manifest literal while rows translate client-side. Assumptions 2 and 3 held (SettingsValidationError at objectstack origin/main 5fcc79497 composes the quoted sentence; settings-routes sends details: namespace + fields; work is on top of 7a5f267). No server change, no package export.", "tests": "New apps/console/src/pages/settings/__tests__/SettingsView.refusalToast-13146.test.tsx (real I18nProvider over shipped packs, real wire body, expected sentences read from the en pack): 7 passed. Ablation once on committed head via objectstack scripts/ablation-replace.mjs (anchor = the new toast block, replacement = the pre-fix toast.error(err?.message ?? saveFailed)): 'mutation landed: anchor 1 → 0, blob 966434655d67 → c229d1a16d66', run 'Tests 6 failed | 1 passed (7)' (the 1 = the unchanged no-field-error case, expected green), 'ok restored: blob == HEAD (966434655d67) and git diff HEAD is empty'. Direction observed: red (normal). Note: a first ablation on 870a5d5 read 5 failed | 2 passed — the row-label case was vacuous against the pre-fix sentence (the server message also contains the label), so it was tightened to pin the whole toast (c453716) and the ablation re-run gave 6|1. Directory run at c453716: pnpm exec vitest run --maxWorkers=2 apps/console/src/pages/settings/ packages/i18n/ → 'Test Files 108 passed (108) / Tests 1518 passed | 13 skipped (1531)', lock VERDICT command-exit 0 (includes all-locales-key-parity, plural-categories-11432, count-families-11445, settingsPage.noBareLiterals-12821, SettingsView.field-errors).", "gates": "Local, all at c453716, exit captured before any pipe: closure build pnpm turbo run build --filter='@object-ui/console^...' --concurrency=2 → 'Tasks: 34 successful, 34 total / Cached: 8', VERDICT command-exit 0; pnpm --filter @object-ui/console type-check EXIT=0 (script echoed 'tsc --noEmit && tsc -b tsconfig.node.json --force'; tsc --listFiles includes the new test: 1 hit); pnpm --filter @object-ui/i18n type-check EXIT=0; node scripts/check-changeset-presence.mjs EXIT=0 ('12 source file(s) of 2 released package(s) changed, and this change declares 1 changeset(s)'); pnpm check:new-line-citations EXIT=0 ('0 new citation(s)'); pnpm check:control-bytes EXIT=0; pnpm check:i18n-keys EXIT=0; pnpm check:i18n-drift EXIT=0 ('0 en value(s) changed (3 key(s) added)'); pnpm check:i18n-dead-keys EXIT=0 (report; new keys not among candidates); check:changeset-claims, check:pending-changeset-literals, check:vi-mock-specifiers, check:vi-mock-inherit, check:vi-mock-override-shape, check:test-path-roots all EXIT=0. NOT MEASURED: check:eager-locale-catalogues, reason: exit 2 PREREQUISITE NOT MET (needs a built apps/console/dist/eager-closure.json); left to CI. --ran reconciliation: n/a (dispatch-gates.mjs is objectstack-only; objectui list hand-derived per dispatch). PR #13227 check-runs at head c4537167 when read (35): success = Changeset Fixed Group Check, Changeset Bump Policy, label; skipped = Test (coverage), Test (coverage shard matrix), dependabot; in_progress = Repo Gates, Line Citation Gate, Type Check, Lint, Build & E2E, Build Docs, Bundle Analysis, Test (dist pins), Test shards 1-16/16, Changeset Claim Re-read, Changeset Overwrite Report, Changeset Declaration, Governed Surface Queue Guard, Live E2E (informational). Not waited on.", "line_budget": "n/a: no skills/** or line-ratcheted ledger touched", "files_changed": [ ".changeset/13146-settings-refusal-toast.md +8 -0", "apps/console/src/pages/settings/SettingsView.tsx +57 -5", "apps/console/src/pages/settings/__tests__/SettingsView.refusalToast-13146.test.tsx +296 -0", "packages/i18n/src/locales/ar.ts +7 -0", "packages/i18n/src/locales/de.ts +3 -0", "packages/i18n/src/locales/en.ts +7 -0", "packages/i18n/src/locales/es.ts +4 -0", "packages/i18n/src/locales/fr.ts +4 -0", "packages/i18n/src/locales/ja.ts +3 -0", "packages/i18n/src/locales/ko.ts +3 -0", "packages/i18n/src/locales/pt.ts +4 -0", "packages/i18n/src/locales/ru.ts +5 -0", "packages/i18n/src/locales/zh.ts +3 -0" ], "head": "c453716", "deviations": [ "Changeset lists '@object-ui/i18n': patch beside the claim's '@object-ui/console': patch, because the diff edits i18n's published src (the ten locale packs); same fixed group, no extra bump.", "Label source differs from the dispatch mechanism assumption 1 (extractFieldErrors carries no label): labels come from the page manifest via labels.fieldLabel; @object-ui/react untouched (no export or type moved).", "Commit trailers are the model-free pair (Co-authored-by: Claude + Claude-Session) per objectui AGENTS.md; the harness reminder asked for a model-named Co-Authored-By, which was not used.", "check:eager-locale-catalogues not run to a verdict locally (prerequisite: built console bundle); declared NOT MEASURED, CI owns it.", "Worktree /home/user/objectui-issue-13146 removed after the PR opened (node_modules deleted first; git worktree remove succeeded without --force)." ], "mcp_calls": "0", "api_writes": "2 relay strokes — (1) pr_create via fleet-write/dispatch.mjs: POST /repos/objectstack-ai/objectstack/dispatches (relay) executing POST /repos/objectstack-ai/objectui/pulls and POST /repos/objectstack-ai/objectui/issues/13227/assignees (read-back: 7519 bytes sent, 7519 stored, identical; assignee os-support-ai; no labels sent — the path labels on the PR are labeler.yml's); (2) this os-dev-report comment via post-stamped.mjs: POST /repos/objectstack-ai/objectui/issues/13146/comments. Plus 3 git pushes (empty branch, 870a5d5, c453716), not REST.", "open_questions": [], "out_of_scope_findings": [ "carrier: none (承接者:无) · noted, not filed · apps/console/src/pages/settings/WorkspaceTimezonePrompt.tsx onConfirm toasts failure?.message on a non-locked refusal, i.e. the same SettingsValidationError sentence for the timezone it writes (it already puts the field message in its own slot); reach not measured — its draft is the browser's own IANA zone · in PR Acceptance notes · dedupe words: WorkspaceTimezonePrompt toast, timezone prompt refusal message, are incomplete", "carrier: none (承接者:无) · noted, not filed, read-only inference · the kept no-field-error branch still toasts the server sentence for SETTINGS_FORBIDDEN, whose message names the namespace and capability (\"Access denied: writing to settings namespace 'auth' requires the 'X' capability\"); not measured at a public door · NOT in the PR body (written once); a seat may add it to Acceptance notes · dedupe words: settings forbidden toast namespace, SETTINGS_FORBIDDEN console toast" ] }objectstack-fleet commentedon Oct 20, 2026
ACCEPT → PR #13227 comment 6288935858 ·
domain:uiseat 3,session_01GL347th7aWQUnY2k8diSLG· 2026-10-20T10:36Z · headc453716· live reading in the record · landing through the merge queue.Generated by Claude Code
objectstack-fleet commentedon Oct 20, 2026
Landed ·
domain:uiseat 3,session_01GL347th7aWQUnY2k8diSLG· 2026-10-20T10:46Z52907d7onmaingh-readonly-queue/main/pr-13227-*git ls-remote: 0 refs)origin/main52907d7SettingsView.tsx:function refusedSettingLabels(1) ·packages/i18n/src/locales/en.ts:fieldErrorsToast_one(1)State: the card closed
completedby the PR'sFixes;pm:dispatchedis removed in this pass. The live Localization reading ("1 setting needs attention: Default timezone" at the head; the server's sentence at the parent) is in the ACCEPT,6288935858.Generated by Claude Code
fix(console): a refused settings save toasts the settings by label, n…