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
plugin-approvals: the admin_rescue system comment is written into the approval timeline as English prose, so a zh-CN viewer reads it untranslated #25576
sys_approval_request.current_step_label is also 初审人审批. So the data is right; the console timeline renders step_name (humanized) rather than step_label.
A related case: the admin_rescue system comment is written into the timeline as English prose ("Routed to this organization's administrators because the approver slate named no one: position 'srm_procurement_director' has no holder."). It shows up untranslated on a zh-CN console.
Re-filed as objectstack-fleet[bot] from #25471, same body and labels. #25471 was written off the fleet relay, under the maintainer's personal account, by a project-thread session through GitHub MCP; pm-dispatch allows content writes only through the relay. #25471's thread (triage, ruling, comments) stays there for reference; this card replaces it in the queue.
Session: session_018fnREjMeK9XQeHDwkJXKMW
Claim: PM loop round 1
Session: session_01JVTd3PprStGa26aez5omLB
Account: sunhaolin (the seat's linked user as GET /user answers it; the card's assignee)
Branch: claude/issue-25576-admin-rescue-comment-i18n
Worktree: objectstack-issue-25576
Domain: domain:server
Seat: domain:server#2
File surface: packages/plugins/plugin-approvals/src/** (the admin_rescue system comment near approval-service.ts:3905 on e649c2d91 and its read path; ⛔ not the SLA-reassign region PR #25600 edits), the plugin's translation bundles if it has them, tests, one changeset (stop on breach; explain in the report)
Container & model: S, not mechanical (the stored shape is a design call), so M treatment; mode:cloud (maintainer: 「并发加到5,可以用云卡片」), model: TIER_DEFAULT (dispatch-gates --tier: "no path-derived mandate … the tier stays the PM's per-card judgment call"), effort: high
Clause-②: no
Metadata-protocol: none
Responsibility: plugin-approvals writes the sentence as stored English prose when the admin-rescue route fires | the platform's localized-text path for server-written system text; the dev names the precedent it reuses | a zh-CN (or any non-English) viewer of an approval timeline, whenever the admin-rescue route fires; measured in the hotsrm evaluation on 18.0.0
Thread-read: none
Serial constraints cleared: PR #25600 (seat 1, #25598) edits approval-service.ts in the SLA-reassign bodies (hunks near :5604 and :7040–:7131), away from :3905; whichever lands second merges main. #25573's runtime half is pm:blocked on #25609, not in flight.
Premise: triage's audit is 6371325002 on #25471 (the card this one re-files). Re-read on origin/maine649c2d91: approval-service.ts:3905 still composes `Routed to this organization's administrators because the approver slate named no one: ${routedToAdministrators}.` as the stored comment.
os-dev-report
{
"issue": 25576,
"status": "done",
"branch": "claude/issue-25576-admin-rescue-comment-i18n",
"pr": "#25627",
"session": "session_01QeMwrPsf2zjo2pQLBzdWFV — this run's harness-stamped id (dispatched by domain:server seat 2, session_01JVTd3PprStGa26aez5omLB)",
"premise_still_valid": true,
"summary": "Premise held on origin/main e649c2d: openNodeRequest composed the admin_rescue note as English prose stored in sys_approval_action.comment, and listActions served it as stored. The note is now stored as a code plus parameters on the request's node-config snapshot (__adminRescueNote: {action_id, abandoned, fallback?}; no column, object schema or spec contract moves). Its sentence and clauses are new entries in the plugin's existing messages catalog (en/zh-CN/ja-JP/es-ES). listActions overlays the named row's comment, in place, at the reader's ExecutionContext.locale through the existing reader-locale-labels.ts path (#24863), extended by one member ReaderLabels.sentence. The stored comment stays the byte-identical English (one source: the en catalog entries). Rows stored before this change carry no snapshot entry and are served as stored; no migration. #25600 landed mid-flight and main was merged cleanly at b9c264f.",
"tests": "Head b9c264f, through os-verify-lock: pnpm --filter @objectstack/plugin-approvals typecheck exit 0; pnpm --filter @objectstack/plugin-approvals test -> Test Files 96 passed (96), Tests 1259 passed (1259), VERDICT command-exit 0. New: admin-rescue-note.test.ts (4 cases) and 5 cases in admin-rescue-named-slate.integration.test.ts on real ObjectQL+SqlDriver+createMemoryI18n loaded with ApprovalsTranslations: zh-CN listActions reads '审批人名单未指向任何人,因此已转交本组织管理员处理:岗位「sales_manager」无人任职。'; the stored row keeps the English; en/no-locale readers get the English; CONTROL: a pre-change request and a neighbouring system comment stay as stored. Ablation, via scripts/ablation-replace.mjs: deleting the localizeAdminRescueNote call (anchor 1->0, blob 3527886551f8->0c2167e97d4a) gave 3 failed | 13 passed (zh-CN, fallback, CONTROL red). Restore: blob 3527886551f8 = HEAD, git diff HEAD empty. Source imports resolve to src (relative import), so no dist build was needed for the ablation leg.",
"gates": "Local, head b9c264f: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack -> 72 commands (same list pre- and post-merge); all 72 run, every exit 0, codes captured per command before any pipe. --ran reconciliation: '72 derived, 72 run, 0 NOT-MEASURED, 0 UNRUN' exit 0. Pre-merge run on f40e836 had check-plugin-teardown-shape --self-test exit 3 (shallow clone: pinned fixture commit 621a487 unreachable; fixed by fetching that one commit) and check:dts-closure exit 1 (plugin-approvals dist cleaned mid-turbo-rebuild running concurrently; 0 on re-run). check:i18n: 'check-i18n-bundles: OK (10 package(s) — all bundles in sync, no undeclared authoring keys)'. eslint --no-inline-config on the 8 touched .ts files: exit 0. CI check-runs on #25627: not yet concluded at report time (in_progress is the honest value; the seat reads them).",
"line_budget": "S card; 9 files, +426 / -45 = 471 changed lines vs origin/main (dispatch-gates: under the 3000 human-merge threshold)",
"files_changed": [
".changeset/25576-admin-rescue-comment-i18n.md",
"packages/plugins/plugin-approvals/src/admin-rescue-named-slate.integration.test.ts",
"packages/plugins/plugin-approvals/src/admin-rescue-note.test.ts",
"packages/plugins/plugin-approvals/src/admin-rescue-note.ts",
"packages/plugins/plugin-approvals/src/approval-notification-text.ts",
"packages/plugins/plugin-approvals/src/approval-service.ts",
"packages/plugins/plugin-approvals/src/approver-address-readers.test.ts",
"packages/plugins/plugin-approvals/src/reader-locale-labels.ts",
"packages/plugins/plugin-approvals/src/translations/messages.ts"
],
"deviations": [
"Worktree: the harness had already created the outcome branch on the primary checkout (at e649c2d), so worktree add -b was refused. I detached the primary checkout and added ../objectstack-issue-25576 on the existing branch. The branch is platform-specified, so no empty probe push.",
"File surface: approver-address-readers.test.ts (same package, outside src/** only in being a test ledger) gained one PERSON_SITES classification for the new actor_id presence read. That pin requires every read of the column to be classified; no gate was weakened.",
"Commit trailers are the model-free pair AGENTS.md prescribes (Claude-Session + Co-authored-by: Claude); the harness reminder's model-named trailer was not used.",
"Closure build #1 was pnpm --filter '@objectstack/plugin-approvals^...' build --concurrency=2; that flag after the filter is forwarded to the scripts (a toolchain trap), harmless here."
],
"fixed_overhead": "pnpm install --frozen-lockfile: 40 s (Done in 36.6s). Build closure via the os-dev recipe (pnpm --filter plugin-approvals^... build, 34 projects, no turbo): 446 s. Turbo remote cache: NOT AVAILABLE in this container. The i18n gate's prescribed turbo closure printed 'Remote caching disabled, using shared worktree cache' with 0 cached / 61 tasks, 703 s, so the remote-cache pull is 0 s by absence, not a measured pull. Post-merge turbo rebuild: 17/33 cached (local), inside a 384 s locked run that also did typecheck + test.",
"dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
"mcp_calls": "3 — mcp__github__issue_read x3 (get #25576, get_comments #25576, get_comments #25471); no write tool",
"api_writes": "2 relay dispatches (POST /repos/objectstack-ai/objectstack/dispatches), executed as objectstack-fleet[bot]: (1) pr_create -> POST /repos/objectstack-ai/objectstack/pulls (draft #25627) + POST /repos//issues/25627/assignees; (2) this report -> POST /repos//issues/25576/comments. git push is not counted.",
"open_questions": [
{
"question": "Stored shape (implementation trade-off made in-card; recorded, not blocking): where do the code and parameters live?",
"options": [
"A — request node-config snapshot __adminRescueNote naming the action row (chosen): no column, no object-schema/bundle churn, no API shape change; precedent __flowLabel/__round/__resolvedFrom ('Stamped on the snapshot ... so no schema migration').",
"B — new columns on sys_approval_action (comment_key/comment_params): the code sits on the row itself, but it grows a platform object served by the generic data door, plus 4-locale field labels, for one system sentence."
],
"recommendation": "A, because it reuses the existing open-time snapshot and reader-locale overlay with no contract surface added (start-up axis: no new declaration surface). A second system note needing a code would be the pull for B."
},
{
"question": "objectui half (not measured: objectui not attached): does the console's record Approvals tab read the timeline through GET /api/v1/approvals/requests/:id/actions (localized now) or through the generic data door on sys_approval_action (still the stored English)?",
"options": [
"A — it uses the approvals actions route: nothing more to do",
"B — it reads sys_approval_action directly: objectui switches the timeline to the approvals door"
],
"recommendation": "Seat to check RecordApprovalsPanel's read in objectui and file the objectui half only if B."
}
],
"out_of_scope_findings": [
"carrier: domain:server seat 2 (sunhaolin) — the objectui read-path question above; noted, not filed (unmeasured from this container)"
]
}
merged: true, merge commit ca80f05ec5c6aab22f31553cb5f8737a17450563, merged 2026-10-24T12:11:03Z through the merge queue
origin/main
ca80f05ec is an ancestor of origin/main, single parent (squash)
queue branch
no gh-readonly-queue/main/* head for PR 25627 remains
State: closed completed by Fixes #25576 on merge. pm:dispatched stripped in this act.
Delivered: the admin_rescue timeline note is stored as a code and parameters, and GET /api/v1/approvals/requests/:id/actions renders it in the reader's language (en, zh-CN, ja-JP, es-ES). The console's record Approvals tab reads that door (objectui useRecordApprovals.ts), so nothing is owed in objectui. Older requests keep their stored English.
Cloud sessionsession_01QeMwrPsf2zjo2pQLBzdWFV archived in this act.
Activity
objectstack-fleet commentedon Oct 24, 2026
Claim: PM loop round 1
Session:
session_01JVTd3PprStGa26aez5omLBAccount:
sunhaolin(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-25576-admin-rescue-comment-i18nWorktree:
objectstack-issue-25576Domain:
domain:serverSeat:
domain:server#2File surface:
packages/plugins/plugin-approvals/src/**(theadmin_rescuesystem comment nearapproval-service.ts:3905one649c2d91and its read path; ⛔ not the SLA-reassign region PR #25600 edits), the plugin's translation bundles if it has them, tests, one changeset (stop on breach; explain in the report)Container & model:
S, not mechanical (the stored shape is a design call), so M treatment;mode:cloud(maintainer: 「并发加到5,可以用云卡片」),model: TIER_DEFAULT(dispatch-gates --tier: "no path-derived mandate … the tier stays the PM's per-card judgment call"),effort: highClause-②: no
Metadata-protocol: none
Responsibility:
plugin-approvalswrites the sentence as stored English prose when the admin-rescue route fires | the platform's localized-text path for server-written system text; the dev names the precedent it reuses | a zh-CN (or any non-English) viewer of an approval timeline, whenever the admin-rescue route fires; measured in the hotsrm evaluation on 18.0.0Thread-read: none
Serial constraints cleared: PR #25600 (seat 1, #25598) edits
approval-service.tsin the SLA-reassign bodies (hunks near:5604and:7040–:7131), away from:3905; whichever lands second mergesmain. #25573's runtime half ispm:blockedon #25609, not in flight.Premise: triage's audit is 6371325002 on #25471 (the card this one re-files). Re-read on
origin/maine649c2d91:approval-service.ts:3905still composes`Routed to this organization's administrators because the approver slate named no one: ${routedToAdministrators}.`as the stored comment.Generated by Claude Code
objectstack-fleet commentedon Oct 24, 2026
os-dev-report
{
"issue": 25576,
"status": "done",
"branch": "claude/issue-25576-admin-rescue-comment-i18n",
"pr": "#25627",
"session": "session_01QeMwrPsf2zjo2pQLBzdWFV — this run's harness-stamped id (dispatched by domain:server seat 2, session_01JVTd3PprStGa26aez5omLB)",
"premise_still_valid": true,
"summary": "Premise held on origin/main e649c2d: openNodeRequest composed the admin_rescue note as English prose stored in sys_approval_action.comment, and listActions served it as stored. The note is now stored as a code plus parameters on the request's node-config snapshot (__adminRescueNote: {action_id, abandoned, fallback?}; no column, object schema or spec contract moves). Its sentence and clauses are new entries in the plugin's existing messages catalog (en/zh-CN/ja-JP/es-ES). listActions overlays the named row's comment, in place, at the reader's ExecutionContext.locale through the existing reader-locale-labels.ts path (#24863), extended by one member ReaderLabels.sentence. The stored comment stays the byte-identical English (one source: the en catalog entries). Rows stored before this change carry no snapshot entry and are served as stored; no migration. #25600 landed mid-flight and main was merged cleanly at b9c264f.",
"tests": "Head b9c264f, through os-verify-lock: pnpm --filter @objectstack/plugin-approvals typecheck exit 0; pnpm --filter @objectstack/plugin-approvals test -> Test Files 96 passed (96), Tests 1259 passed (1259), VERDICT command-exit 0. New: admin-rescue-note.test.ts (4 cases) and 5 cases in admin-rescue-named-slate.integration.test.ts on real ObjectQL+SqlDriver+createMemoryI18n loaded with ApprovalsTranslations: zh-CN listActions reads '审批人名单未指向任何人,因此已转交本组织管理员处理:岗位「sales_manager」无人任职。'; the stored row keeps the English; en/no-locale readers get the English; CONTROL: a pre-change request and a neighbouring system comment stay as stored. Ablation, via scripts/ablation-replace.mjs: deleting the localizeAdminRescueNote call (anchor 1->0, blob 3527886551f8->0c2167e97d4a) gave 3 failed | 13 passed (zh-CN, fallback, CONTROL red). Restore: blob 3527886551f8 = HEAD, git diff HEAD empty. Source imports resolve to src (relative import), so no dist build was needed for the ablation leg.",
"gates": "Local, head b9c264f: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack -> 72 commands (same list pre- and post-merge); all 72 run, every exit 0, codes captured per command before any pipe. --ran reconciliation: '72 derived, 72 run, 0 NOT-MEASURED, 0 UNRUN' exit 0. Pre-merge run on f40e836 had check-plugin-teardown-shape --self-test exit 3 (shallow clone: pinned fixture commit 621a487 unreachable; fixed by fetching that one commit) and check:dts-closure exit 1 (plugin-approvals dist cleaned mid-turbo-rebuild running concurrently; 0 on re-run). check:i18n: 'check-i18n-bundles: OK (10 package(s) — all bundles in sync, no undeclared authoring keys)'. eslint --no-inline-config on the 8 touched .ts files: exit 0. CI check-runs on #25627: not yet concluded at report time (in_progress is the honest value; the seat reads them).",
"line_budget": "S card; 9 files, +426 / -45 = 471 changed lines vs origin/main (dispatch-gates: under the 3000 human-merge threshold)",
"files_changed": [
".changeset/25576-admin-rescue-comment-i18n.md",
"packages/plugins/plugin-approvals/src/admin-rescue-named-slate.integration.test.ts",
"packages/plugins/plugin-approvals/src/admin-rescue-note.test.ts",
"packages/plugins/plugin-approvals/src/admin-rescue-note.ts",
"packages/plugins/plugin-approvals/src/approval-notification-text.ts",
"packages/plugins/plugin-approvals/src/approval-service.ts",
"packages/plugins/plugin-approvals/src/approver-address-readers.test.ts",
"packages/plugins/plugin-approvals/src/reader-locale-labels.ts",
"packages/plugins/plugin-approvals/src/translations/messages.ts"
],
"deviations": [
"Worktree: the harness had already created the outcome branch on the primary checkout (at e649c2d), so worktree add -b was refused. I detached the primary checkout and added ../objectstack-issue-25576 on the existing branch. The branch is platform-specified, so no empty probe push.",
"File surface: approver-address-readers.test.ts (same package, outside src/** only in being a test ledger) gained one PERSON_SITES classification for the new actor_id presence read. That pin requires every read of the column to be classified; no gate was weakened.",
"Commit trailers are the model-free pair AGENTS.md prescribes (Claude-Session + Co-authored-by: Claude); the harness reminder's model-named trailer was not used.",
"Closure build #1 was pnpm --filter '@objectstack/plugin-approvals^...' build --concurrency=2; that flag after the filter is forwarded to the scripts (a toolchain trap), harmless here."
],
"fixed_overhead": "pnpm install --frozen-lockfile: 40 s (Done in 36.6s). Build closure via the os-dev recipe (pnpm --filter plugin-approvals^... build, 34 projects, no turbo): 446 s. Turbo remote cache: NOT AVAILABLE in this container. The i18n gate's prescribed turbo closure printed 'Remote caching disabled, using shared worktree cache' with 0 cached / 61 tasks, 703 s, so the remote-cache pull is 0 s by absence, not a measured pull. Post-merge turbo rebuild: 17/33 cached (local), inside a 384 s locked run that also did typecheck + test.",
"dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
"mcp_calls": "3 — mcp__github__issue_read x3 (get #25576, get_comments #25576, get_comments #25471); no write tool",
"api_writes": "2 relay dispatches (POST /repos/objectstack-ai/objectstack/dispatches), executed as objectstack-fleet[bot]: (1) pr_create -> POST /repos/objectstack-ai/objectstack/pulls (draft #25627) + POST /repos//issues/25627/assignees; (2) this report -> POST /repos//issues/25576/comments. git push is not counted.",
"open_questions": [
{
"question": "Stored shape (implementation trade-off made in-card; recorded, not blocking): where do the code and parameters live?",
"options": [
"A — request node-config snapshot __adminRescueNote naming the action row (chosen): no column, no object-schema/bundle churn, no API shape change; precedent __flowLabel/__round/__resolvedFrom ('Stamped on the snapshot ... so no schema migration').",
"B — new columns on sys_approval_action (comment_key/comment_params): the code sits on the row itself, but it grows a platform object served by the generic data door, plus 4-locale field labels, for one system sentence."
],
"recommendation": "A, because it reuses the existing open-time snapshot and reader-locale overlay with no contract surface added (start-up axis: no new declaration surface). A second system note needing a code would be the pull for B."
},
{
"question": "objectui half (not measured: objectui not attached): does the console's record Approvals tab read the timeline through GET /api/v1/approvals/requests/:id/actions (localized now) or through the generic data door on sys_approval_action (still the stored English)?",
"options": [
"A — it uses the approvals actions route: nothing more to do",
"B — it reads sys_approval_action directly: objectui switches the timeline to the approvals door"
],
"recommendation": "Seat to check RecordApprovalsPanel's read in objectui and file the objectui half only if B."
}
],
"out_of_scope_findings": [
"carrier: domain:server seat 2 (sunhaolin) — the objectui read-path question above; noted, not filed (unmeasured from this container)"
]
}
objectstack-fleet commentedon Oct 24, 2026
ACCEPT → PR #25627 comment 6383830466 (head
b9c264fd8f; landing in the same act) ·domain:serverseat 2 ·session_01JVTd3PprStGa26aez5omLBGenerated by Claude Code
objectstack-fleet commentedon Oct 24, 2026
Landed: PR #25627 →
ca80f05ec·domain:serverseat 2 ·sunhaolin·session_01JVTd3PprStGa26aez5omLB· 2026-10-24T12:11Zmerged: true, merge commitca80f05ec5c6aab22f31553cb5f8737a17450563, merged 2026-10-24T12:11:03Z through the merge queueorigin/mainca80f05ecis an ancestor oforigin/main, single parent (squash)gh-readonly-queue/main/*head for PR 25627 remainscompletedbyFixes #25576on merge.pm:dispatchedstripped in this act.admin_rescuetimeline note is stored as a code and parameters, andGET /api/v1/approvals/requests/:id/actionsrenders it in the reader's language (en,zh-CN,ja-JP,es-ES). The console's record Approvals tab reads that door (objectuiuseRecordApprovals.ts), so nothing is owed in objectui. Older requests keep their stored English.session_01QeMwrPsf2zjo2pQLBzdWFVarchived in this act.Generated by Claude Code