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 }}
Repository navigation
Setup: datasource and storage results reach the toast in English, and a refused delete does not name the objects #30335
Filing gate: ③ the maintainer's direct order, verbatim: 「你发现的问题都立卡,安全问题总专用的安全密卡通道,需要进一步分析的进一步测试,还是没有把握的用决策卡。」 (2026-11-05). Found in a real-user browser walkthrough of Setup on main04f36b63f8, with a test app and a local test deployment.
Business reason. A Chinese-speaking administrator gets a sentence they may not read, at the moment it tells them what to do next. The refused delete also leaves them to work out which objects are in the way.
Reader. The UI lane dev for the two result toasts; the server lane if the message must carry the object names.
Duplicates. Searched datasource delete bound objects message (183 hits) and storage round-trip toast English (12 hits). They are QA run anchors; none has this subject.
Measured
With a zh-CN console:
Deleting a datasource that has a synced object shows 删除 parts_db 失败:Cannot remove datasource 'parts_db': 1 object(s) are still bound to it. The refusal is correct, and the object is not named. The confirm before it also says nothing about bound objects.
Both read in the console's language. The refusal names the bound objects and says what to do. The confirm warns before the attempt if the page can know.
Claim: PM loop round 1
Session: session_01L6bhgVwQZbHRRM9CaXeKif
Account: os-sales
Branch: claude/project-thread-x1xjpw (card thread of this project; a thread can push only its designated branch — measured platform exception to claude/issue-<n>-<slug>)
Worktree: objectstack-issue-30335
Domain: domain:ui
Seat: domain:ui#5
File surface: ui/packages/app-shell/src/views/metadata-admin/datasource/** (the delete confirm and the refused-delete toast, their tests) + ui/packages/i18n/src/namespaces/studio/{en,zh}.ts + one root .changeset/. ⛔ packages/** (server lane), ⛔ ui/apps/console/src/pages/settings/** and ui/packages/i18n/src/locales/** (held by #30329, domain:ui#2).
Container & model: M, mode:thread, model: default — dispatch-gates --tier: no path-derived mandate, effort: high
Clause-②: yes
Metadata-protocol: none
Responsibility: the datasource admin service refuses a bound delete with an untranslated sentence carrying a count and no object names, and the Setup page forwards it verbatim inside a localized frame; the delete confirm does not mention bound objects | object metadata names each object's datasource, which the page can read; no server code or details list exists today | every non-English administrator who deletes a datasource that objects still use
Thread-read: 6652077088
Premise: holds
Serial constraints cleared: #30329 (domain:ui#2) holds the storage half's files, so that half is out of this claim and stays on the card; #30327 and #30328 (queue, unclaimed) share DatasourceResourcePage.tsx and serialise after this card; #30331 (domain:server#4) excludes ui/**.
Scope: the datasource half only (Clause-② yes (widening): new studio i18n keys; the seat's TIER_DEFAULT review before the queue). The storage half is the card's remainder at landing. Server work the dev reports (a refusal code with the bound objects, a locale-aware settings action result) is filed by the seat. Dispatch order lives in the card thread's opening message.
Card thread session_01L6bhgW7fTeU6tAZXwiAJnW, datasource half of #30335 only, report at 2026-11-05T11:37Z.
{
"issue": 30335,
"status": "done",
"branch": "claude/project-thread-x1xjpw",
"pr": "https://github.com/objectstack-ai/objectstack/pull/30442",
"session": "session_01L6bhgW7fTeU6tAZXwiAJnW",
"premise_still_valid": true,
"summary": "Mechanism measured live on base fdd06415 (showcase, runtime sqlite datasource parts_db with two objects naming it): DELETE /api/v1/datasources/parts_db answers 400 DATASOURCE_ADMIN_ERROR with the count-only English sentence, the zh toast wraps it verbatim, the confirm says nothing of bound objects; GET /api/v1/meta/object serves each object's datasource. DatasourceResourcePage now reads object metadata when the delete confirm opens and lists the bound objects (label (name)) with a zh/en sentence that the delete is refused until each is deleted or moved; api() keeps status and error.code on the thrown error, and a 400 re-reads the bound objects and toasts engine.datasource.deleteBoundRefused naming them and the next step. Other failures and a 400 with no bound object keep the server message in the existing frame. No English text is matched. Three new studio rows (en+zh). Storage half untouched, stays on the card.",
"tests": "head d3697faa (tree identical to de1864eb, where everything ran). DatasourceResourcePage.deleteConfirm-13333.test.tsx gains a second describe on the existing harness (5 cases: zh-row guard, confirm list, zh 400 refusal, 2 CONTROLs): 8/8 passed. vitest packages/app-shell/src/views/metadata-admin/datasource/ + packages/i18n/src/__tests__/studio-namespace.test.ts: 8 files, 61 tests passed (VERDICT command-exit 0). Ablation via ablation-replace (anchor 1 -> 0, restored blob == HEAD 44e6774b): A1 refusal re-read -> [] : 1 failed | 7 passed; A2 confirmBound forced [] : 3 failed | 5 passed. Live before/after zh-CN 1440 shots at evidence commit e3cffec4 (removed in d3697faa), linked in the PR body.",
"gates": "type-check @object-ui/i18n + @object-ui/app-shell exit 0 (VERDICT command-exit 0); eslint on the 4 changed source files exit 0 (2 warnings on unchanged lines); ui check:new-line-citations exit 0; dispatch-gates --commands 35 derived at de1864eb, all 35 exit 0 (vitest ui scripts/: 170 files passed, 2 skipped); --ran: 35 derived, 35 run, 0 NOT-MEASURED (derived zero). CI check-runs: in_progress at report time.",
"line_budget": "5 files, +203 / -6 vs merge base fdd06415 (under 3000)",
"files_changed": [".changeset/30335-datasource-delete-names-bound-objects.md", "ui/packages/app-shell/src/views/metadata-admin/datasource/DatasourceResourcePage.tsx", "ui/packages/app-shell/src/views/metadata-admin/datasource/DatasourceResourcePage.deleteConfirm-13333.test.tsx", "ui/packages/i18n/src/namespaces/studio/en.ts", "ui/packages/i18n/src/namespaces/studio/zh.ts"],
"deviations": "PR body: seat signature on line 1, then the harness attribution marker and requester line (the session asks those two first; followed the dispatch and the precedent of earlier card-thread PRs). The first push was refused by the commit-card-trailers hook for a Refs line in the commit message; amended before anything landed. Two commits on the branch carry only the evidence PNGs and their removal (squash merge keeps them off main). No assignee or reviewer on the PR, per the dispatch. Delete button stays enabled while objects are listed: the server stays the judge.",
"dogfood_battery": "n/a — no ! in the PR title and Clause-② is yes (widening), no (narrowing) arm",
"mcp_calls": "0 — GitHub reads went through gh api REST; no GitHub MCP tool called",
"api_writes": "2 — fleet-write relay pr_create (POST /repos/objectstack-ai/objectstack/dispatches, run 42020242383 -> #30442, body read back identical); this os-dev-report comment via post-stamped",
"open_questions": [],
"security_findings": "withheld",
"out_of_scope_findings": [
"class: a · reach: public door DELETE /api/v1/datasources/NAME answers 400 DATASOURCE_ADMIN_ERROR with the English sentence Cannot remove datasource 'parts_db': 2 object(s) are still bound to it. and no object names, no details and no refusal-specific code (measured on fdd06415, showcase rig) · evidence: DatasourceAdminService.removeDatasource throws a plain Error after countBoundObjects; a client that does not read object metadata (CLI, MCP, an AI caller) cannot learn which objects block the delete · server lane: a refusal code plus details.objects (names) · dedupe words: datasource delete bound objects details, removeDatasource refusal code, DATASOURCE_ADMIN_ERROR bound count",
"carrier: #30335 (storage half, serial behind #30329) · not measured in this run: the settings runAction result text (Storage round-trip succeeded) that a locale-aware server answer would fix"
]
}
Landed (datasource half) at 2026-11-05T12:35Z: PR #30442 merged as ab12a3b9de (seat ACCEPT 6657469324 on head d5982ffe, TIER_DEFAULT contract review PASS 6657087845 + delta 6657123793). The merge itself read 2026-11-05T12:30Z on the PR. The PR said Part of #30335, so the card stays open.
DatasourceResourcePage.tsx 1, studio en/zh 1 each, test 2 (the bound-object confirm and refusal are on main)
git grep -n "round-trip succeeded" origin/main
packages/services/service-storage/src/storage-service-plugin.ts:910 (the storage half is untouched)
Server follow-up for the refusal's code and details.objects: #30444.
Release: session session_01L6bhgVwQZbHRRM9CaXeKif · because the datasource half has landed and only the storage half remains · back to pm:queue, assignee cleared.
Remainder: the Storage 测试连接 toast (Storage round-trip succeeded (adapter=…)) reads in the console's language. Its serial constraint has cleared: #30329 closed 2026-11-05T11:49Z via PR #30428.
Re-routed to domain:server · 2026-11-05T14:21Z · ⛔ not a claim. The storage half has no ui-only fix.
Read on origin/mainfa9c0aa2a0:
The 测试连接 toast prints the settings action's own message. packages/services/service-storage/src/storage-service-plugin.ts:910 returns message: \Storage round-trip succeeded (adapter=${adapter}).`` (and the English failure sentences above it).
SettingsActionResultSchema (packages/spec/src/system/settings-manifest.zod.ts:826) carries ok, message, severity and an untyped details, with no message key or params. So the console can only print the server's sentence or match its English text, and the ui lane does not match English text.
The fix is the server's: either the action answers in the request's language, or the action result gains a key the console can translate (a spec change, domain:spec first). Which of the two is the server lane's call; the console change that follows, if any, goes back to domain:ui as its own card.
The datasource half landed in PR #30442 (Landed 6658133994); its server follow-up is #30444.
Claim: PM loop round 11 — storage half only (the datasource half landed in PR #30442 and #30444 / PR #30513)
Session: session_01Utp6Cbvcmv8YWFhFJwzjKL (seat) · dev thread session_01Utp6CaWLG2RrgKub5oRNjC
Account: os-bill
Branch: claude/project-thread-flbs42 (harness-pinned thread branch; platform exception to claude/issue-<n>-<slug>)
Worktree: objectstack-issue-30335
Domain: domain:server
Seat: domain:server#2
File surface: packages/services/service-storage/src/storage-service-plugin.ts (the storage/test settings action only), the string home the localisation precedent uses inside service-storage, tests under packages/services/service-storage/src/**, one changeset .changeset/30335-storage-test-message-locale.md. ⛔ packages/spec/**, packages/services/service-settings/**, ui/**, apps/**, skills/**, docs/adr/**, content/docs/releases/**, .claude/** (stop on breach; explain in the report)
Container & model: M, mode:thread, model: default tier (opus) — dispatch-gates --tier: no path-derived mandate, effort: high
Clause-②: no expected — the action's message is prose written in the caller's language; ok, severity and the probe behaviour are unchanged
Metadata-protocol: none
Responsibility: the storage/test action writes its result sentences in English whatever the caller's language | the settings action result shape, the route, the adapter's own error text (unchanged) | administrators using Setup → Storage 测试连接 in a non-English console
Thread-read: 6660369226
Premise: read, to be measured first — at 35a8f088: storage/test returns Storage round-trip succeeded (adapter=…) and Probe download did not match upload. as fixed English strings
Serial constraints cleared: seat 6 yielded this half (it had announced it first); its PR #30551 (#30208 server half) adds the optional locale on the settings action handler input that this change reads — this PR opens only after #30551 merges. Seat 4 does not touch service-storage. This seat's #30512service-storage locale backfill carries the new keys — whichever lands second covers the other's keys.
Order: project file server-seat2/dispatch-30335.md, delivered as the card thread's opening message.
Card thread session_01Utp6CaWLG2RrgKub5oRNjC, storage half of #30335 only.
{
"issue": 30335,
"status": "done",
"branch": "claude/project-thread-flbs42",
"pr": "https://github.com/objectstack-ai/objectstack/pull/30627",
"session": "session_01Utp6CaWLG2RrgKub5oRNjC",
"premise_still_valid": true,
"summary": "Storage half only. Measured on base c23eafa8: the storage/test handler answered English for locale zh-CN and none, and the dispatch's ctx.locale did not exist (SettingsContext has no locale; the action route did not pass one) - reported to the seat, which routed the hop to #30551 (merged bdbaf80c, adds the handler input locale). storage/test now reads input locale and answers from a new module-level copy table (storage-test-copy.ts, #30376 precedent) carrying all 11 platform locale table languages (seat note 16:45Z): success, probe mismatch, incomplete S3 settings (new S3SettingsIncompleteError, English log text unchanged), and a lead-in before an adapter's own verbatim error outside English. Lookup goes through spec platformLocaleTagOf then RFC 4647 subtag shortening instead of core resolveLocale, because zh-CN plus zh-Hant breaks resolveLocale's variant ladder (#30538; seat approved 16:52Z). ok/severity/probe/cleanup/logs unchanged; English and locale-less answers byte-identical.",
"tests": "head 47c43908c: pnpm --filter @objectstack/service-storage test = Test Files 73 passed (73), Tests 1353 passed (1353); new storage-test-locale.test.ts 10/10 through the real registered handler on a real local adapter. Ablations via scripts/ablation-replace.mjs on committed head 700b4dcf, each restored (git diff HEAD empty, ABLATE marker count 0): A1 ignore input locale -> 5 failed | 5 passed; A2 fallback en->zh-CN -> 4 failed | 6 passed; A3 S3 type check off -> 1 failed | 9 passed; A4 drop ko entry -> 1 failed | 9 passed; A5 no subtag shortening -> 1 failed | 9 passed. Imports resolve to src (relative), no dist preflight needed.",
"gates": "head 47c43908c: dispatch-gates --commands 62 derived, all 62 exit 0 (each captured before any pipe); --ran: 62 derived, 62 run, 0 NOT-MEASURED. pnpm --filter @objectstack/service-storage typecheck exit 0; node scripts/check-i18n-bundles.mjs exit 0 (10 packages in sync); eslint --no-inline-config on the 3 changed source files exit 0 (repo-wide pnpm lint left to CI per os-dev). CI check-runs: in_progress at report time.",
"dogfood_battery": "47c43908c - os-verify-lock VERDICT command-exit 0 (held 33m09s) - Test Files 420 passed | 3 skipped (423) - Tests 3496 passed | 36 skipped (3532) - no failures",
"line_budget": "4 files, +396 / -6 vs merge base (under 3000)",
"files_changed": [
".changeset/30335-storage-test-message-locale.md",
"packages/services/service-storage/src/storage-service-plugin.ts",
"packages/services/service-storage/src/storage-test-copy.ts",
"packages/services/service-storage/src/storage-test-locale.test.ts"
],
"deviations": "1) Dispatch rule 1 premise false (SettingsContext.locale absent): stopped, reported, seat re-ruled to the handler input locale of #30551 (seat note 15:43Z). 2) Locales widened from 4 to 11 at the seat's request (16:45Z). 3) Lookup via platformLocaleTagOf + subtag shortening, not resolveLocale (seat approved, names #30538). 4) First push refused by check:commit-card-trailers (model name in Co-Authored-By); amended to the model-free pair before anything was published. 5) An uncommitted 11-locale edit was reverted by ablation-replace's HEAD restore; re-applied and committed before re-running all ablations. 6) Harness assign/review step skipped per dispatch; PR opened with no assignee. 7) No SettingsService end-to-end pin (service-storage has no service-settings dependency; #30551 pins the route hop).",
"mcp_calls": "4 - github issue_read get + get_comments (#30335), pull_request_read get (#30627); no MCP write tool",
"api_writes": "2 - fleet-write relay pr_create (POST /repos/objectstack-ai/objectstack/dispatches, run 42087478612 -> #30627, body read back identical 7685 bytes); this os-dev-report comment via post-stamped. Plus git push (not REST).",
"open_questions": [],
"security_findings": "none",
"out_of_scope_findings": [
"class: a - reach: exception: maintainer (seat 2 note 16:45Z) - module-level copy tables serve 4 of the 11 platform locales and look up with core resolveLocale: plugin-auth mfa-required-enrollment-predicate.ts (#30376), organization-mfa-enrollment-guard.ts, allowed-ip-ranges.ts, sign-in-method-floor.ts; plugin-email live-transport-status.ts; service-settings localization-currency-lock.ts, localization-locale-options.ts - carrier: seat 2 files; family with #30538 - dedupe words: COPY_LOCALES resolveLocale four locales, settings prose copy table platform locales",
"class: a - reach: public door POST /api/v1/settings/sms/test with Accept-Language zh-CN answers English (sms-plugin.ts registerAction sms/test: missing-config, build-failure, log-only transport, sent-to sentences; handler does not read input locale) - not measured live, code read on 47c43908c - dedupe words: sms test toast English, settings action locale sms",
"class: a - reach: public door POST /api/v1/settings/NAMESPACE/reset and an unknown action id answer English (settings-service.ts runAction built-in reset: Cleared N saved value(s)... / No saved values to clear...; No handler registered for action ...) - code read on 47c43908c - dedupe words: settings reset action English message, runAction no handler registered"
]
}
storage half: Setup → Storage 测试连接 now answers in the admin's console language (the eleven platform languages, read from the settings action input's locale); English and callers without a locale read the same bytes as before. The datasource half landed earlier (PR #30442, server follow-up #30444 / PR #30513). Both halves done, so the seat closes the card.
Next
the same gap in seven other module copy tables, sms/test and two built-in settings answers: #30630
Release
rides the next release by its changeset
State change: pm:dispatched removed; card closed (completed).
Activity
objectstack-fleet commentedon Nov 5, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: first-touch audit · p3 ·
domain:ui·pm:queue· 2026-11-05T07:12Z⛔ Not a claim.
Generated by Claude Code
objectstack-fleet commentedon Nov 5, 2026
domain:ui#5 · os-sales · session_01L6bhgVwQZbHRRM9CaXeKif
Claim: PM loop round 1
Session:
session_01L6bhgVwQZbHRRM9CaXeKifAccount:
os-salesBranch:
claude/project-thread-x1xjpw(card thread of this project; a thread can push only its designated branch — measured platform exception toclaude/issue-<n>-<slug>)Worktree:
objectstack-issue-30335Domain:
domain:uiSeat:
domain:ui#5File surface:
ui/packages/app-shell/src/views/metadata-admin/datasource/**(the delete confirm and the refused-delete toast, their tests) +ui/packages/i18n/src/namespaces/studio/{en,zh}.ts+ one root.changeset/. ⛔packages/**(server lane), ⛔ui/apps/console/src/pages/settings/**andui/packages/i18n/src/locales/**(held by #30329,domain:ui#2).Container & model:
M,mode:thread,model: default — dispatch-gates --tier: no path-derived mandate,effort: highClause-②: yes
Metadata-protocol: none
Responsibility: the datasource admin service refuses a bound delete with an untranslated sentence carrying a count and no object names, and the Setup page forwards it verbatim inside a localized frame; the delete confirm does not mention bound objects | object metadata names each object's datasource, which the page can read; no server code or details list exists today | every non-English administrator who deletes a datasource that objects still use
Thread-read: 6652077088
Premise: holds
Serial constraints cleared: #30329 (
domain:ui#2) holds the storage half's files, so that half is out of this claim and stays on the card; #30327 and #30328 (queue, unclaimed) shareDatasourceResourcePage.tsxand serialise after this card; #30331 (domain:server#4) excludesui/**.Scope: the datasource half only (Clause-②
yes (widening): new studio i18n keys; the seat's TIER_DEFAULT review before the queue). The storage half is the card's remainder at landing. Server work the dev reports (a refusal code with the bound objects, a locale-aware settings action result) is filed by the seat. Dispatch order lives in the card thread's opening message.objectstack-fleet commentedon Nov 5, 2026
domain:ui#5 · os-sales · session_01L6bhgW7fTeU6tAZXwiAJnW
os-dev-report
Card thread session_01L6bhgW7fTeU6tAZXwiAJnW, datasource half of #30335 only, report at 2026-11-05T11:37Z.
{ "issue": 30335, "status": "done", "branch": "claude/project-thread-x1xjpw", "pr": "https://github.com/objectstack-ai/objectstack/pull/30442", "session": "session_01L6bhgW7fTeU6tAZXwiAJnW", "premise_still_valid": true, "summary": "Mechanism measured live on base fdd06415 (showcase, runtime sqlite datasource parts_db with two objects naming it): DELETE /api/v1/datasources/parts_db answers 400 DATASOURCE_ADMIN_ERROR with the count-only English sentence, the zh toast wraps it verbatim, the confirm says nothing of bound objects; GET /api/v1/meta/object serves each object's datasource. DatasourceResourcePage now reads object metadata when the delete confirm opens and lists the bound objects (label (name)) with a zh/en sentence that the delete is refused until each is deleted or moved; api() keeps status and error.code on the thrown error, and a 400 re-reads the bound objects and toasts engine.datasource.deleteBoundRefused naming them and the next step. Other failures and a 400 with no bound object keep the server message in the existing frame. No English text is matched. Three new studio rows (en+zh). Storage half untouched, stays on the card.", "tests": "head d3697faa (tree identical to de1864eb, where everything ran). DatasourceResourcePage.deleteConfirm-13333.test.tsx gains a second describe on the existing harness (5 cases: zh-row guard, confirm list, zh 400 refusal, 2 CONTROLs): 8/8 passed. vitest packages/app-shell/src/views/metadata-admin/datasource/ + packages/i18n/src/__tests__/studio-namespace.test.ts: 8 files, 61 tests passed (VERDICT command-exit 0). Ablation via ablation-replace (anchor 1 -> 0, restored blob == HEAD 44e6774b): A1 refusal re-read -> [] : 1 failed | 7 passed; A2 confirmBound forced [] : 3 failed | 5 passed. Live before/after zh-CN 1440 shots at evidence commit e3cffec4 (removed in d3697faa), linked in the PR body.", "gates": "type-check @object-ui/i18n + @object-ui/app-shell exit 0 (VERDICT command-exit 0); eslint on the 4 changed source files exit 0 (2 warnings on unchanged lines); ui check:new-line-citations exit 0; dispatch-gates --commands 35 derived at de1864eb, all 35 exit 0 (vitest ui scripts/: 170 files passed, 2 skipped); --ran: 35 derived, 35 run, 0 NOT-MEASURED (derived zero). CI check-runs: in_progress at report time.", "line_budget": "5 files, +203 / -6 vs merge base fdd06415 (under 3000)", "files_changed": [".changeset/30335-datasource-delete-names-bound-objects.md", "ui/packages/app-shell/src/views/metadata-admin/datasource/DatasourceResourcePage.tsx", "ui/packages/app-shell/src/views/metadata-admin/datasource/DatasourceResourcePage.deleteConfirm-13333.test.tsx", "ui/packages/i18n/src/namespaces/studio/en.ts", "ui/packages/i18n/src/namespaces/studio/zh.ts"], "deviations": "PR body: seat signature on line 1, then the harness attribution marker and requester line (the session asks those two first; followed the dispatch and the precedent of earlier card-thread PRs). The first push was refused by the commit-card-trailers hook for a Refs line in the commit message; amended before anything landed. Two commits on the branch carry only the evidence PNGs and their removal (squash merge keeps them off main). No assignee or reviewer on the PR, per the dispatch. Delete button stays enabled while objects are listed: the server stays the judge.", "dogfood_battery": "n/a — no ! in the PR title and Clause-② is yes (widening), no (narrowing) arm", "mcp_calls": "0 — GitHub reads went through gh api REST; no GitHub MCP tool called", "api_writes": "2 — fleet-write relay pr_create (POST /repos/objectstack-ai/objectstack/dispatches, run 42020242383 -> #30442, body read back identical); this os-dev-report comment via post-stamped", "open_questions": [], "security_findings": "withheld", "out_of_scope_findings": [ "class: a · reach: public door DELETE /api/v1/datasources/NAME answers 400 DATASOURCE_ADMIN_ERROR with the English sentence Cannot remove datasource 'parts_db': 2 object(s) are still bound to it. and no object names, no details and no refusal-specific code (measured on fdd06415, showcase rig) · evidence: DatasourceAdminService.removeDatasource throws a plain Error after countBoundObjects; a client that does not read object metadata (CLI, MCP, an AI caller) cannot learn which objects block the delete · server lane: a refusal code plus details.objects (names) · dedupe words: datasource delete bound objects details, removeDatasource refusal code, DATASOURCE_ADMIN_ERROR bound count", "carrier: #30335 (storage half, serial behind #30329) · not measured in this run: the settings runAction result text (Storage round-trip succeeded) that a locale-aware server answer would fix" ] }objectstack-fleet commentedon Nov 5, 2026
domain:ui#5 · os-sales · session_01L6bhgVwQZbHRRM9CaXeKif
Landed (datasource half) at 2026-11-05T12:35Z: PR #30442 merged as
ab12a3b9de(seat ACCEPT 6657469324 on headd5982ffe, TIER_DEFAULT contract review PASS 6657087845 + delta 6657123793). The merge itself read 2026-11-05T12:30Z on the PR. The PR saidPart of #30335, so the card stays open.git grep -c deleteBoundRefused origin/main -- ui/packagesgit grep -n "round-trip succeeded" origin/mainpackages/services/service-storage/src/storage-service-plugin.ts:910(the storage half is untouched)Server follow-up for the refusal's code and
details.objects: #30444.Release: session
session_01L6bhgVwQZbHRRM9CaXeKif· because the datasource half has landed and only the storage half remains · back topm:queue, assignee cleared.Remainder: the Storage 测试连接 toast (
Storage round-trip succeeded (adapter=…)) reads in the console's language. Its serial constraint has cleared: #30329 closed 2026-11-05T11:49Z via PR #30428.objectstack-fleet commentedon Nov 5, 2026
domain:ui#6 · os-sales · session_01L6bhgUR8Nu4M7tbtgES7q2
Re-routed to
domain:server· 2026-11-05T14:21Z · ⛔ not a claim. The storage half has no ui-only fix.Read on
origin/mainfa9c0aa2a0:message.packages/services/service-storage/src/storage-service-plugin.ts:910returnsmessage: \Storage round-trip succeeded (adapter=${adapter}).`` (and the English failure sentences above it).SettingsActionResultSchema(packages/spec/src/system/settings-manifest.zod.ts:826) carriesok,message,severityand an untypeddetails, with no message key or params. So the console can only print the server's sentence or match its English text, and the ui lane does not match English text.domain:specfirst). Which of the two is the server lane's call; the console change that follows, if any, goes back todomain:uias its own card.The datasource half landed in PR #30442 (Landed 6658133994); its server follow-up is #30444.
objectstack-fleet commentedon Nov 5, 2026
domain:server#2 · os-bill · session_01Utp6Cbvcmv8YWFhFJwzjKL
Claim: PM loop round 11 — storage half only (the datasource half landed in PR #30442 and #30444 / PR #30513)
Session:
session_01Utp6Cbvcmv8YWFhFJwzjKL(seat) · dev threadsession_01Utp6CaWLG2RrgKub5oRNjCAccount:
os-billBranch:
claude/project-thread-flbs42(harness-pinned thread branch; platform exception toclaude/issue-<n>-<slug>)Worktree:
objectstack-issue-30335Domain:
domain:serverSeat:
domain:server#2File surface:
packages/services/service-storage/src/storage-service-plugin.ts(thestorage/testsettings action only), the string home the localisation precedent uses insideservice-storage, tests underpackages/services/service-storage/src/**, one changeset.changeset/30335-storage-test-message-locale.md. ⛔packages/spec/**,packages/services/service-settings/**,ui/**,apps/**,skills/**,docs/adr/**,content/docs/releases/**,.claude/**(stop on breach; explain in the report)Container & model:
M,mode:thread,model: default tier (opus) — dispatch-gates --tier: no path-derived mandate,effort: highClause-②: no expected — the action's
messageis prose written in the caller's language;ok,severityand the probe behaviour are unchangedMetadata-protocol: none
Responsibility: the
storage/testaction writes its result sentences in English whatever the caller's language | the settings action result shape, the route, the adapter's own error text (unchanged) | administrators using Setup → Storage 测试连接 in a non-English consoleThread-read: 6660369226
Premise: read, to be measured first — at
35a8f088:storage/testreturnsStorage round-trip succeeded (adapter=…)andProbe download did not match upload.as fixed English stringsSerial constraints cleared: seat 6 yielded this half (it had announced it first); its PR #30551 (#30208 server half) adds the optional
localeon the settings action handler input that this change reads — this PR opens only after #30551 merges. Seat 4 does not touchservice-storage. This seat's #30512service-storagelocale backfill carries the new keys — whichever lands second covers the other's keys.Order: project file
server-seat2/dispatch-30335.md, delivered as the card thread's opening message.objectstack-fleet commentedon Nov 5, 2026
domain:server#2 · os-bill · session_01Utp6CaWLG2RrgKub5oRNjC
os-dev-report
Card thread session_01Utp6CaWLG2RrgKub5oRNjC, storage half of #30335 only.
{ "issue": 30335, "status": "done", "branch": "claude/project-thread-flbs42", "pr": "https://github.com/objectstack-ai/objectstack/pull/30627", "session": "session_01Utp6CaWLG2RrgKub5oRNjC", "premise_still_valid": true, "summary": "Storage half only. Measured on base c23eafa8: the storage/test handler answered English for locale zh-CN and none, and the dispatch's ctx.locale did not exist (SettingsContext has no locale; the action route did not pass one) - reported to the seat, which routed the hop to #30551 (merged bdbaf80c, adds the handler input locale). storage/test now reads input locale and answers from a new module-level copy table (storage-test-copy.ts, #30376 precedent) carrying all 11 platform locale table languages (seat note 16:45Z): success, probe mismatch, incomplete S3 settings (new S3SettingsIncompleteError, English log text unchanged), and a lead-in before an adapter's own verbatim error outside English. Lookup goes through spec platformLocaleTagOf then RFC 4647 subtag shortening instead of core resolveLocale, because zh-CN plus zh-Hant breaks resolveLocale's variant ladder (#30538; seat approved 16:52Z). ok/severity/probe/cleanup/logs unchanged; English and locale-less answers byte-identical.", "tests": "head 47c43908c: pnpm --filter @objectstack/service-storage test = Test Files 73 passed (73), Tests 1353 passed (1353); new storage-test-locale.test.ts 10/10 through the real registered handler on a real local adapter. Ablations via scripts/ablation-replace.mjs on committed head 700b4dcf, each restored (git diff HEAD empty, ABLATE marker count 0): A1 ignore input locale -> 5 failed | 5 passed; A2 fallback en->zh-CN -> 4 failed | 6 passed; A3 S3 type check off -> 1 failed | 9 passed; A4 drop ko entry -> 1 failed | 9 passed; A5 no subtag shortening -> 1 failed | 9 passed. Imports resolve to src (relative), no dist preflight needed.", "gates": "head 47c43908c: dispatch-gates --commands 62 derived, all 62 exit 0 (each captured before any pipe); --ran: 62 derived, 62 run, 0 NOT-MEASURED. pnpm --filter @objectstack/service-storage typecheck exit 0; node scripts/check-i18n-bundles.mjs exit 0 (10 packages in sync); eslint --no-inline-config on the 3 changed source files exit 0 (repo-wide pnpm lint left to CI per os-dev). CI check-runs: in_progress at report time.", "dogfood_battery": "47c43908c - os-verify-lock VERDICT command-exit 0 (held 33m09s) - Test Files 420 passed | 3 skipped (423) - Tests 3496 passed | 36 skipped (3532) - no failures", "line_budget": "4 files, +396 / -6 vs merge base (under 3000)", "files_changed": [ ".changeset/30335-storage-test-message-locale.md", "packages/services/service-storage/src/storage-service-plugin.ts", "packages/services/service-storage/src/storage-test-copy.ts", "packages/services/service-storage/src/storage-test-locale.test.ts" ], "deviations": "1) Dispatch rule 1 premise false (SettingsContext.locale absent): stopped, reported, seat re-ruled to the handler input locale of #30551 (seat note 15:43Z). 2) Locales widened from 4 to 11 at the seat's request (16:45Z). 3) Lookup via platformLocaleTagOf + subtag shortening, not resolveLocale (seat approved, names #30538). 4) First push refused by check:commit-card-trailers (model name in Co-Authored-By); amended to the model-free pair before anything was published. 5) An uncommitted 11-locale edit was reverted by ablation-replace's HEAD restore; re-applied and committed before re-running all ablations. 6) Harness assign/review step skipped per dispatch; PR opened with no assignee. 7) No SettingsService end-to-end pin (service-storage has no service-settings dependency; #30551 pins the route hop).", "mcp_calls": "4 - github issue_read get + get_comments (#30335), pull_request_read get (#30627); no MCP write tool", "api_writes": "2 - fleet-write relay pr_create (POST /repos/objectstack-ai/objectstack/dispatches, run 42087478612 -> #30627, body read back identical 7685 bytes); this os-dev-report comment via post-stamped. Plus git push (not REST).", "open_questions": [], "security_findings": "none", "out_of_scope_findings": [ "class: a - reach: exception: maintainer (seat 2 note 16:45Z) - module-level copy tables serve 4 of the 11 platform locales and look up with core resolveLocale: plugin-auth mfa-required-enrollment-predicate.ts (#30376), organization-mfa-enrollment-guard.ts, allowed-ip-ranges.ts, sign-in-method-floor.ts; plugin-email live-transport-status.ts; service-settings localization-currency-lock.ts, localization-locale-options.ts - carrier: seat 2 files; family with #30538 - dedupe words: COPY_LOCALES resolveLocale four locales, settings prose copy table platform locales", "class: a - reach: public door POST /api/v1/settings/sms/test with Accept-Language zh-CN answers English (sms-plugin.ts registerAction sms/test: missing-config, build-failure, log-only transport, sent-to sentences; handler does not read input locale) - not measured live, code read on 47c43908c - dedupe words: sms test toast English, settings action locale sms", "class: a - reach: public door POST /api/v1/settings/NAMESPACE/reset and an unknown action id answer English (settings-service.ts runAction built-in reset: Cleared N saved value(s)... / No saved values to clear...; No handler registered for action ...) - code read on 47c43908c - dedupe words: settings reset action English message, runAction no handler registered" ] }Report taken 2026-11-05T18:47Z.
Generated by Claude Code
objectstack-fleet commentedon Nov 5, 2026
domain:server#2 · os-bill · session_01Utp6Cbvcmv8YWFhFJwzjKL
Landed · 2026-11-05T19:33Z
fabd2595, reviewed head47c43908(seat ACCEPT 6666378777)TIER_DEFAULT(Clause-②: no), seat-written in the ACCEPTlocale); English and callers without a locale read the same bytes as before. The datasource half landed earlier (PR #30442, server follow-up #30444 / PR #30513). Both halves done, so the seat closes the card.sms/testand two built-in settings answers: #30630State change:
pm:dispatchedremoved; card closed (completed).