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
record page: a failed comments or attachments read (500) shows as 「暂无评论」 and an empty attachment count; only a refusal is flagged, so a server error is silent #29188
Filing gate ①: a product defect, measured on staging by cloud#3485 (every filtered sys_comment / sys_attachment read on hosted environments answers 500 DATABASE_ERROR; card filed by the maintainer's session 2026-11-02). Cloud is fixing its server half. This card is the Console half (cloud#3485 acceptance 3).
What happens
On a record page, when the comments read or the attachments read fails with a server error, the discussion panel shows 「暂无评论」 and the attachments tab shows an empty count. The user sees no sign of the failure; it is visible only in developer tools. On staging this has hidden a 500 on every hosted environment since at least 2026-10-29, so comments and attachments users wrote looked lost.
Cause (objectstack main)
ui/packages/app-shell/src/views/RecordDetailView.tsx: the feed reads end in .catch((err) => { recordRefusal('comments', isRefusedFeedRead(err)); }) (around lines 3098 and 3175). Only a refusal is recorded (feedRefusalByRecord, around 2899 and 2970), and any other failure falls through to the empty state. The attachments read has the same shape.
Ask
Tell a failed read apart from an empty one: a server error (5xx, network) shows a load-failure state with a retry, not the empty state. Refusals keep today's handling.
The same for the attachments tab and its count.
Tests: a 500 on each read renders the failure state; an empty 200 still renders 「暂无评论」.
Business reason
Comments and attachments sit on every business record. A silent empty state makes data look lost and hides outages from users and from support.
Reader
The Console record-page owner, through objectstack triage. No cloud change is needed for this half.
Dedup
Searched open objectstack issues for "暂无评论 load failure", "feed read error empty state" and "RecordDetailView refusal 500": none open.
Read fresh. A 5xx on the comments or attachments read renders as the empty state, so a server error is silent. On staging this hid cloud#3485. p2 kept; this is the Console half. The card had no state (H13).
Claim: PM loop round 19 · 2026-11-02T11:35Z
Session: session_01QsR2jT854xvoBjntpsRE1F (card thread, os-dev); dispatched by seat session session_01QsR2jUJ19MstFvFhjgiYTu
Account: zhuangjianguo
Branch: claude/project-thread-rcy6ga (platform-assigned to the card thread; it can push only this branch)
Worktree: objectstack-issue-29188
Domain: domain:ui
Seat: domain:ui#1
File surface: ui/packages/app-shell/src/views/RecordDetailView.tsx (the comments and activity feed reads record a per-source verdict answered | refused | failed; failed = classifyLoadError 'network', i.e. 5xx or network; refusal, api-disabled and 400 keep today's handling; retry re-reads only the failed sources directly), ui/packages/react/src/context/DiscussionContext.tsx (new optional DiscussionContextValue members for the failed verdict and retry), ui/packages/plugin-detail/src/RecordActivityTimeline.tsx, RecordChatterPanel.tsx, renderers/record-chatter.tsx, renderers/record-activity.tsx (a load-failure notice with Retry in the panel, stream and peek; the count is null while failed), ui/packages/plugin-detail/src/useDetailTranslation.ts, ui/packages/i18n/src/locales/en.ts and zh.ts (the notice and Retry keys), new ui/packages/app-shell/src/views/RecordDetailView.feedLoadFailure-29188.test.tsx and ui/packages/plugin-detail/src/__tests__/RecordActivityTimeline.loadFailed-29188.test.tsx (including a payload-path attachments pin, no attachments code), ui/packages/app-shell/src/views/RecordDetailView.feedRefusal-11195.test.tsx (the activity-read 500 row now expects the failure notice, not the empty state), and a root .changeset. Any other file is declared by a claim amendment before code (stop on breach; explain in the report)
Container & model: M, mode:thread, model: default tier (dispatch-gates --tier: no path-derived mandate), effort: high
Clause-②: yes (widening)
Metadata-protocol: none
Responsibility: On a record page a 5xx or network failure of the comments or activity read shows a load-failure notice with Retry instead of the empty state, and the tab count shows no number while failed; a refusal keeps its handling and an empty 200 still renders the empty state
Thread-read: 6575552954
Premise: holds (at origin/mainf125ce40: the dev measured at db6b408 on the real-adapter rig: a comments 500 (payload part and direct GET) renders No activity recorded with a 0 badge; the attachments 500 already shows a load-failure notice with Retry and no count, so the attachments half gets a pin only)
Serial constraints cleared: PR #29273 (#29074) also edits RecordDetailView.tsx (the Back block, not the feed catches): whichever lands second merges main.
The two rows where sys_comment answers 403 FEEDS_DISABLED assert the settled state (no spinner) and the comments no-permission line instead of the empty copy.
The file's purpose stays: a rejected read settles and never spins forever.
{
"issue": 29188,
"status": "done",
"branch": "claude/project-thread-rcy6ga",
"pr": "https://github.com/objectstack-ai/objectstack/pull/29358",
"head": "89ec072d83cd286843141a2014d8f59a17ca14ec",
"session": "session_01QsR2jT854xvoBjntpsRE1F",
"premise_still_valid": true,
"summary": "The record page's comments and activity reads now record answered | refused | failed per source. failed = classifyLoadError 'network' less 4xx, i.e. a 5xx or a statusless rejection. A failed read draws a load-failure notice with a Retry in RecordActivityTimeline (panel, stream, peek) instead of the empty state, and the count is unknown while failed. Retry re-reads only the failed sources directly, not the payload. Wiring: three optional DiscussionContextValue members, forwarded by record:activity / record:chatter / RecordChatterPanel; en+zh keys. Attachments half premise-false on main (panel already shows unavailable + Retry, no badge): pinned only.",
"tests": "Measured on main db6b4084 first (temp copy of the 28470 real-adapter rig): comments 500 -> 'No activity recorded' + Activity0 badge; attachments 500 -> unavailable + Retry, no count. New RecordDetailView.feedLoadFailure-29188 (10) and RecordActivityTimeline.loadFailed-29188 (9) green. Ablation via scripts/ablation-replace.mjs (feedReadVerdictOf 5xx -> answered): 7/17 red (six failure rows + flipped 11195 row), controls/refusal/attachments pin green; restored blob == HEAD, git diff HEAD empty. Sweep at merged head 89ec072d under os-verify-lock, --maxWorkers=2: 111 files / 2609 tests exit 0, plus apps/console record-block-record-reach 13/13. First sweep found 3 stale pins in RecordDetailView.feedLoading.test.tsx (statusless rejections); fixed under claim amendment 1. eslint on 13 changed files: 0 errors.",
"gates": "At 89ec072d: dispatch-gates --ran 34 derived, 34 run, 0 NOT-MEASURED, 0 UNRUN, all exit 0 (incl. check-sdui-manifest 0). pnpm --dir ui exec vitest run scripts/: 169 passed, 2 skipped. check-new-cross-file-line-citations: 0 new. turbo type-check app-shell+react+i18n+plugin-detail: 68/68 exit 0. PR-body gates with the body as the event: changeset-no-major 0, adr-0087-registration 0, closing-keyword-parity 0, partof-closing-keyword 0. PR check-runs: queued at report time; the seat reads them.",
"dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
"files_changed": [
"ui/packages/app-shell/src/views/RecordDetailView.tsx",
"ui/packages/react/src/context/DiscussionContext.tsx",
"ui/packages/plugin-detail/src/RecordActivityTimeline.tsx",
"ui/packages/plugin-detail/src/RecordChatterPanel.tsx",
"ui/packages/plugin-detail/src/renderers/record-activity.tsx",
"ui/packages/plugin-detail/src/renderers/record-chatter.tsx",
"ui/packages/plugin-detail/src/useDetailTranslation.ts",
"ui/packages/i18n/src/locales/en.ts",
"ui/packages/i18n/src/locales/zh.ts",
"ui/packages/app-shell/src/views/RecordDetailView.feedLoadFailure-29188.test.tsx (new)",
"ui/packages/plugin-detail/src/__tests__/RecordActivityTimeline.loadFailed-29188.test.tsx (new)",
"ui/packages/app-shell/src/views/RecordDetailView.feedRefusal-11195.test.tsx",
"ui/packages/app-shell/src/views/RecordDetailView.feedLoading.test.tsx (amendment 1, test only)",
".changeset/29188-feed-load-failure.md"
],
"deviations": [
"The verdict excludes 4xx from classifyLoadError's 'network' kind (status >= 500 or no status): needed so a status-carrying 404 stays the empty answer the existing pins describe. It matches the claim's '5xx or network'.",
"PR body lines 1-2 are the harness attribution block, so `Fixes #29188` is line 4.",
"No assignees or reviewers set on the PR (os-dev rule), although the harness asks for them best-effort.",
"PR #29273 had not landed at merge time; whichever lands second merges main."
],
"mcp_calls": "reads only — issue_read x4 (get/get_comments 29188), pull_request_read x2 (get_files 29273, get 29220)",
"api_writes": "git push x3 (not REST); relay x1 pr_create (#29358, 11184 bytes read back identical); this report comment x1 via post-stamped",
"open_questions": [],
"security_findings": "none",
"out_of_scope_findings": [
"none"
]
}
Claim amended (2) · 2026-11-02T13:11Z · after CI, before the fix. This adds to the claim 6576137247 and amendment 1. Branch, session, size and effort are unchanged.
File surface (added):ui/packages/i18n/src/locales/ar.ts, de.ts, es.ts, fr.ts, ja.ts, ko.ts, pt.ts and ru.ts. The three new keys go in at their en place, translated, and no other key moves.
Landed · 2026-11-02T13:53Z · PR #29358 merged through the merge queue as e5a24dd0 at 2026-11-02T13:53Z (GitHub's clock). ACCEPT 6578506162 at head 53d0b774. Clause-② yes (widening), contract self-review passed in that ACCEPT.
probe
before (e5a24dd0~1)
now (origin/main)
feedReadVerdictOf in ui/packages/app-shell/src/views/RecordDetailView.tsx
0
4
onRetryFeed in ui/packages/react/src/context/DiscussionContext.tsx
0
2
commentsLoadFailed in ui/packages/i18n/src/locales/ja.ts (one of the eight amended packs)
0
1
Fixes #29188 closed this card. pm:dispatched comes off in the same stroke as this note. No seat card waited on this PR.
Activity
objectstack-fleet commentedon Nov 2, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: p2 kept ·
pm:queue· 2026-11-02T11:04Z⛔ Not a claim.
Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:ui#1 · zhuangjianguo · session_01QsR2jUJ19MstFvFhjgiYTu
Claim: PM loop round 19 · 2026-11-02T11:35Z
Session:
session_01QsR2jT854xvoBjntpsRE1F(card thread, os-dev); dispatched by seat sessionsession_01QsR2jUJ19MstFvFhjgiYTuAccount:
zhuangjianguoBranch:
claude/project-thread-rcy6ga(platform-assigned to the card thread; it can push only this branch)Worktree:
objectstack-issue-29188Domain:
domain:uiSeat:
domain:ui#1File surface:
ui/packages/app-shell/src/views/RecordDetailView.tsx(the comments and activity feed reads record a per-source verdict answered | refused | failed; failed = classifyLoadError 'network', i.e. 5xx or network; refusal, api-disabled and 400 keep today's handling; retry re-reads only the failed sources directly),ui/packages/react/src/context/DiscussionContext.tsx(new optional DiscussionContextValue members for the failed verdict and retry),ui/packages/plugin-detail/src/RecordActivityTimeline.tsx,RecordChatterPanel.tsx,renderers/record-chatter.tsx,renderers/record-activity.tsx(a load-failure notice with Retry in the panel, stream and peek; the count is null while failed),ui/packages/plugin-detail/src/useDetailTranslation.ts,ui/packages/i18n/src/locales/en.tsandzh.ts(the notice and Retry keys), newui/packages/app-shell/src/views/RecordDetailView.feedLoadFailure-29188.test.tsxandui/packages/plugin-detail/src/__tests__/RecordActivityTimeline.loadFailed-29188.test.tsx(including a payload-path attachments pin, no attachments code),ui/packages/app-shell/src/views/RecordDetailView.feedRefusal-11195.test.tsx(the activity-read 500 row now expects the failure notice, not the empty state), and a root.changeset. Any other file is declared by a claim amendment before code (stop on breach; explain in the report)Container & model: M,
mode:thread,model: default tier (dispatch-gates --tier: no path-derived mandate),effort: highClause-②: yes (widening)
Metadata-protocol: none
Responsibility: On a record page a 5xx or network failure of the comments or activity read shows a load-failure notice with Retry instead of the empty state, and the tab count shows no number while failed; a refusal keeps its handling and an empty 200 still renders the empty state
Thread-read: 6575552954
Premise: holds (at
origin/mainf125ce40: the dev measured at db6b408 on the real-adapter rig: a comments 500 (payload part and direct GET) renders No activity recorded with a 0 badge; the attachments 500 already shows a load-failure notice with Retry and no count, so the attachments half gets a pin only)Serial constraints cleared: PR #29273 (#29074) also edits RecordDetailView.tsx (the Back block, not the feed catches): whichever lands second merges main.
objectstack-fleet commentedon Nov 2, 2026
domain:ui#1 · zhuangjianguo · session_01QsR2jUJ19MstFvFhjgiYTu
Claim amended (1) · 2026-11-02T12:00Z · before code in that file. This adds to the claim 6576137247. Branch, session, size and effort are unchanged.
ui/packages/app-shell/src/views/RecordDetailView.feedLoading.test.tsx(fix(spec): trim dead webhook triggers undelete + api #3209), test only.new Error('403 FEEDS_DISABLED')ornew Error('404 sys_activity'), with no status. A statusless rejection is what a network failure looks like, so under this card it now shows the load-failure notice. The real adapter sendshttpStatus, and with it a 403 has been a refusal since spec(ui):UserActionsConfigSchemaadoptsgroup/hideFields/rowColor— the three toolbar affordancesListViewhonours but no spec-valid document can declare (ruled A on objectui#5435) #11195. These rows passed only because the stub dropped the status.UserActionsConfigSchemaadoptsgroup/hideFields/rowColor— the three toolbar affordancesListViewhonours but no spec-valid document can declare (ruled A on objectui#5435) #11195 shape:Object.assign(new Error(…), { httpStatus, code }).sys_activityrows keep the empty copy.sys_commentanswers 403FEEDS_DISABLEDassert the settled state (no spinner) and the comments no-permission line instead of the empty copy.objectstack-fleet commentedon Nov 2, 2026
domain:ui#1 · zhuangjianguo · session_01QsR2jT854xvoBjntpsRE1F
os-dev-report
{ "issue": 29188, "status": "done", "branch": "claude/project-thread-rcy6ga", "pr": "https://github.com/objectstack-ai/objectstack/pull/29358", "head": "89ec072d83cd286843141a2014d8f59a17ca14ec", "session": "session_01QsR2jT854xvoBjntpsRE1F", "premise_still_valid": true, "summary": "The record page's comments and activity reads now record answered | refused | failed per source. failed = classifyLoadError 'network' less 4xx, i.e. a 5xx or a statusless rejection. A failed read draws a load-failure notice with a Retry in RecordActivityTimeline (panel, stream, peek) instead of the empty state, and the count is unknown while failed. Retry re-reads only the failed sources directly, not the payload. Wiring: three optional DiscussionContextValue members, forwarded by record:activity / record:chatter / RecordChatterPanel; en+zh keys. Attachments half premise-false on main (panel already shows unavailable + Retry, no badge): pinned only.", "tests": "Measured on main db6b4084 first (temp copy of the 28470 real-adapter rig): comments 500 -> 'No activity recorded' + Activity0 badge; attachments 500 -> unavailable + Retry, no count. New RecordDetailView.feedLoadFailure-29188 (10) and RecordActivityTimeline.loadFailed-29188 (9) green. Ablation via scripts/ablation-replace.mjs (feedReadVerdictOf 5xx -> answered): 7/17 red (six failure rows + flipped 11195 row), controls/refusal/attachments pin green; restored blob == HEAD, git diff HEAD empty. Sweep at merged head 89ec072d under os-verify-lock, --maxWorkers=2: 111 files / 2609 tests exit 0, plus apps/console record-block-record-reach 13/13. First sweep found 3 stale pins in RecordDetailView.feedLoading.test.tsx (statusless rejections); fixed under claim amendment 1. eslint on 13 changed files: 0 errors.", "gates": "At 89ec072d: dispatch-gates --ran 34 derived, 34 run, 0 NOT-MEASURED, 0 UNRUN, all exit 0 (incl. check-sdui-manifest 0). pnpm --dir ui exec vitest run scripts/: 169 passed, 2 skipped. check-new-cross-file-line-citations: 0 new. turbo type-check app-shell+react+i18n+plugin-detail: 68/68 exit 0. PR-body gates with the body as the event: changeset-no-major 0, adr-0087-registration 0, closing-keyword-parity 0, partof-closing-keyword 0. PR check-runs: queued at report time; the seat reads them.", "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm", "files_changed": [ "ui/packages/app-shell/src/views/RecordDetailView.tsx", "ui/packages/react/src/context/DiscussionContext.tsx", "ui/packages/plugin-detail/src/RecordActivityTimeline.tsx", "ui/packages/plugin-detail/src/RecordChatterPanel.tsx", "ui/packages/plugin-detail/src/renderers/record-activity.tsx", "ui/packages/plugin-detail/src/renderers/record-chatter.tsx", "ui/packages/plugin-detail/src/useDetailTranslation.ts", "ui/packages/i18n/src/locales/en.ts", "ui/packages/i18n/src/locales/zh.ts", "ui/packages/app-shell/src/views/RecordDetailView.feedLoadFailure-29188.test.tsx (new)", "ui/packages/plugin-detail/src/__tests__/RecordActivityTimeline.loadFailed-29188.test.tsx (new)", "ui/packages/app-shell/src/views/RecordDetailView.feedRefusal-11195.test.tsx", "ui/packages/app-shell/src/views/RecordDetailView.feedLoading.test.tsx (amendment 1, test only)", ".changeset/29188-feed-load-failure.md" ], "deviations": [ "The verdict excludes 4xx from classifyLoadError's 'network' kind (status >= 500 or no status): needed so a status-carrying 404 stays the empty answer the existing pins describe. It matches the claim's '5xx or network'.", "PR body lines 1-2 are the harness attribution block, so `Fixes #29188` is line 4.", "No assignees or reviewers set on the PR (os-dev rule), although the harness asks for them best-effort.", "PR #29273 had not landed at merge time; whichever lands second merges main." ], "mcp_calls": "reads only — issue_read x4 (get/get_comments 29188), pull_request_read x2 (get_files 29273, get 29220)", "api_writes": "git push x3 (not REST); relay x1 pr_create (#29358, 11184 bytes read back identical); this report comment x1 via post-stamped", "open_questions": [], "security_findings": "none", "out_of_scope_findings": [ "none" ] }objectstack-fleet commentedon Nov 2, 2026
domain:ui#1 · zhuangjianguo · session_01QsR2jUJ19MstFvFhjgiYTu
Claim amended (2) · 2026-11-02T13:11Z · after CI, before the fix. This adds to the claim 6576137247 and amendment 1. Branch, session, size and effort are unchanged.
ui/packages/i18n/src/locales/ar.ts,de.ts,es.ts,fr.ts,ja.ts,ko.ts,pt.tsandru.ts. The three new keys go in at theirenplace, translated, and no other key moves.89ec072dis red on Test UI 14/16 inall-locales-key-parity.test.ts(objectui#2872). Each of the eight packs is missingdetail.activityLoadFailed,detail.commentsLoadFailedanddetail.retryLoadFeed. The claim named onlyenandzh.objectstack-fleet commentedon Nov 2, 2026
domain:ui#1 · zhuangjianguo · session_01QsR2jUJ19MstFvFhjgiYTu
Landed · 2026-11-02T13:53Z · PR #29358 merged through the merge queue as
e5a24dd0at 2026-11-02T13:53Z (GitHub's clock). ACCEPT 6578506162 at head53d0b774. Clause-② yes (widening), contract self-review passed in that ACCEPT.e5a24dd0~1)origin/main)feedReadVerdictOfinui/packages/app-shell/src/views/RecordDetailView.tsxonRetryFeedinui/packages/react/src/context/DiscussionContext.tsxcommentsLoadFailedinui/packages/i18n/src/locales/ja.ts(one of the eight amended packs)Fixes #29188closed this card.pm:dispatchedcomes off in the same stroke as this note. No seat card waited on this PR.