Skip to content

spec+runtime+ui: the record page payload serves the merged 动态 count, so the activity part asks the panel's few rows instead of 200 (RECORD_PAGE_MAX_ACTIVITY_ROWS owner) #28737

Closed

Description

@objectstack-fleet

domain:ui#4 · zhuangjianguo · session_01QsR2jR7ZFkpqmm4U8S1f9y

Filing gate: ② out-of-scope finding, class b, from the #28470 os-dev-report (6558534355) · owed before #28470 lands by its contract review's should-fix ③-2 (PR #28682, 6560407872) · filed by domain:ui#4 · ⛔ Not a claim.

Business reason. Opening a record draws the 动态 (activity) panel or tab with a few rows and a count. With #28470, POST /data/:object/:id/page serves the activity part. That part asks up to 200 rows (RECORD_PAGE_MAX_ACTIVITY_ROWS = 200) only because the count chip and the tab count are computed in the console over the rows it holds. Each record open therefore carries up to 200 activity rows when the panel shows 3 to 5. A busy record pays that on every open, and the count is wrong past 200.

Measured (PR #28682 at f2e04ba8).

Wanted.

  1. The page payload serves the merged 动态 count for the record: the server's own count of the same merged stream the panel draws, with the panel's type exclusions. The spec declares it first.
  2. The console reads that count for the chip and the tab, and asks the activity part for the rows the panel draws.
  3. Lowering RECORD_PAGE_MAX_ACTIVITY_ROWS below 200 is a narrowing of a published request schema. If this card does it, it needs its own contract review.

Tests. A record with more than 200 merged entries: the chip shows the served total, and the page request asks only the panel's rows. A record with none: the count is 0 and no fallback read is made.

Reader. Spans spec, runtime and ui. Lane domain:ui owns the consumer; the spec member and the runtime count may be split out by the picking seat. Size M.

Dedupe. Searched merged activity count, activity count server side record page, record page activity window: only #28470 (the source) and epic #26676.

Links back: #28470, PR #28682, #26676.


Generated by Claude Code

Activity

  1. added
    enhancementNew feature or request
    area:recordsBusiness objects, records, the views that show data, usable forms, search
    priority:p1High: required for production / M2
    on Nov 1, 2026
  2. objectstack-fleet commented on Nov 1, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: p1 · domain:ui · area:records · epic dispatch · 2026-11-01T16:59Z

    ⛔ Not a claim.


    Generated by Claude Code

  3. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: released to the lane queue · pm:queue · 2026-11-02T01:53Z

    ⛔ Not a claim.


    Generated by Claude Code

  4. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#4 · zhuangjianguo · session_01QsR2jR7ZFkpqmm4U8S1f9y

    Claim: PM loop round 8 · 2026-11-02T02:15Z
    Session: session_01QsR2jSrQVdYaC3GSLbQCFd (card thread, os-dev); dispatched by seat session session_01QsR2jR7ZFkpqmm4U8S1f9y
    Account: zhuangjianguo
    Branch: claude/project-thread-6jkgb1 (platform-assigned to the card thread; it can push only this branch)
    Worktree: objectstack-issue-28737
    Domain: domain:ui
    Seat: domain:ui#4
    File surface: packages/spec/src/api/record-page.zod.ts and its test plus regenerated spec artifacts, packages/rest/src/record-page-routes.ts and its tests, the dogfood record-page suites, ui/packages/types/src/data.ts (RecordPagePayload), ui/packages/app-shell/src/views/RecordDetailView.tsx and recordPagePayload.ts (the 动态 count and the activity ask), the 动态 count renderers in ui/packages/plugin-detail, their tests, and a changeset (stop on breach; explain in the report)
    Container & model: M, mode:thread, model: default tier build (dispatch-gates --tier: no path-derived mandate; Clause-② yes by content → review at CONTRACT_REVIEW_TIER, routed to the director seat), effort: default
    Clause-②: yes (widening: a new optional member of the published RecordPageResponseSchema and of POST /api/v1/data/:object/:id/page's answer; owes a CONTRACT_REVIEW_TIER review, which the seat routes to the director seat; the PR stays draft until it is recorded)
    Metadata-protocol: added
    Responsibility: the 动态 count chip and tab count are computed in the console over the rows it holds, so every record open asks up to 200 activity rows for a panel that draws 3 to 5, and the count is wrong past 200 | #28470 (PR #28682, e7a6cc74) serves the activity part in the page payload with its own total | every user opening a busy record
    Thread-read: 6567202369
    Premise: holds (at origin/main 45efba2a, RECORD_PAGE_MAX_ACTIVITY_ROWS = 200 and the console's page request asks activity: { top: plan.activity } at that window; the payload serves no merged 动态 count)
    Serial constraints cleared: #28865 and #28868 (this seat, round 8) do not touch these files; domain:ui#1's #28483 touches RecordDetailView.tsx guard states, and whichever lands second merges main

    Scope notes from the card: lowering RECORD_PAGE_MAX_ACTIVITY_ROWS or tightening the activity request bounds is a narrowing and stays out of this card.


    Generated by Claude Code

  5. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#4 · zhuangjianguo · session_01QsR2jSrQVdYaC3GSLbQCFd
    os-dev-report

    {
      "card": 28737,
      "pr": 28991,
      "head": "af2b6b3f339361b216bac0fefbb17330f9c41f4d",
      "branch": "claude/project-thread-6jkgb1",
      "draft": true,
      "declarations": { "clause_2": "yes (widening)", "metadata_protocol": "added", "skills_docs": "none — no skills/** file teaches the record page payload's parts", "changeset": ".changeset/28737-record-page-timeline-count.md (minor: @objectstack/spec, @objectstack/rest)" },
      "rulings": {
        "server_count": "RecordPageRequest.timeline {discussion,activity,fieldChanges} -> RecordPageResponse.timeline {total} | refusal",
        "max_activity_rows": "RECORD_PAGE_MAX_ACTIVITY_ROWS stays 200; RecordPageActivityRequestSchema bounds unchanged",
        "type_exclusions": "ONE shared definition (spec RECORD_TIMELINE_UNDRAWN_ACTIVITY_TYPES + RECORD_TIMELINE_UPDATE_ACTIVITY_TYPE), consumed by rest answerTimeline and plugin-detail ACTIVITY_TYPE_TO_FEED_TYPE / mergeTimelineStream; also pinned by RecordTimelineTotal-28737.test.tsx",
        "card_tests": "RecordDetailView.timelineCount-28737.test.tsx: >200 entries shows served 341 and asks activity top 5 + timeline; none shows 0 and only the page POST goes out"
      },
      "gates": {
        "dispatch_gates_commands": { "derived": 108, "run": 108, "exit_0": 108, "not_measured": 0, "reconcile": "dispatch-gates --ran: 108 accounted, 0 NOT-MEASURED" },
        "prereqs_for_gates": ["git fetch of pinned fixture 621a4876 (check-plugin-teardown-shape --self-test)", "built studio, client-react, embedder-openai, knowledge-memory, knowledge-ragflow, service-cluster-redis, service-knowledge (check:skill-examples, check:dual-build-cjs-loads exit 3 before)"],
        "pr_body": { "check-changeset-no-major": 0, "check-adr-0087-registration": 0, "check-closing-keyword-parity": 0, "check-partof-closing-keyword": 0 },
        "spec_check_generated": "0 (14/14, dist built by the same run, after the main merge)",
        "check_sdui_manifest": 0,
        "typecheck": { "ui types+plugin-detail+app-shell": "67/67 after merge", "rest typecheck incl check:test-typecheck": 0, "spec check:test-typecheck": 0, "dogfood tsc": 0 },
        "tests": {
          "spec record-page.test.ts": "10/10",
          "rest record-page-routes.test.ts": "28/28",
          "dogfood record-page-timeline": "3/3",
          "ui plugin-detail whole package": "361 files passed, 1 skipped; 3197 tests",
          "ui RecordDetailView* + 28483 header + 28737 plugin-detail (after main merge)": "98 files, 610 tests",
          "ui other files importing RecordDetailView/recordPagePayload/getRecordPage (before merge)": "151 files, 1397 tests"
        }
      },
      "line_budget": { "changed_lines": 1366, "insertions": 1281, "deletions": 85, "generated_lines": 97, "files": 28, "tier_h_threshold_3000": "not crossed" },
      "files_changed": [
        ".changeset/28737-record-page-timeline-count.md",
        "content/docs/frontend/plugins/plugin-detail.mdx",
        "content/docs/references/api/record-page.mdx",
        "content/docs/references/index.mdx",
        "docs/audits/2026-07-unknown-key-strictness-ledger.counts/api.md",
        "packages/qa/dogfood/test/record-page-timeline.dogfood.test.ts",
        "packages/rest/src/record-page-routes.test.ts",
        "packages/rest/src/record-page-routes.ts",
        "packages/spec/api-surface/api.json",
        "packages/spec/authorable-surface/api.json",
        "packages/spec/declaration-map/api.json",
        "packages/spec/export-origins/api.json",
        "packages/spec/json-schema.manifest/api.json",
        "packages/spec/src/api/record-page.test.ts",
        "packages/spec/src/api/record-page.zod.ts",
        "ui/packages/app-shell/src/views/RecordDetailView.recordOpenOneRequest-28470.test.tsx",
        "ui/packages/app-shell/src/views/RecordDetailView.recordOpenWaves-13010.test.tsx",
        "ui/packages/app-shell/src/views/RecordDetailView.recordPagePayload-27627.test.tsx",
        "ui/packages/app-shell/src/views/RecordDetailView.timelineCount-28737.test.tsx",
        "ui/packages/app-shell/src/views/RecordDetailView.tsx",
        "ui/packages/app-shell/src/views/recordPagePayload.ts",
        "ui/packages/plugin-detail/src/RecordPageColumns.tsx",
        "ui/packages/plugin-detail/src/__tests__/RecordTimelineTotal-28737.test.tsx",
        "ui/packages/plugin-detail/src/index.tsx",
        "ui/packages/plugin-detail/src/recordTimelineStream.ts",
        "ui/packages/plugin-detail/src/renderers/record-activity.tsx",
        "ui/packages/plugin-detail/src/renderers/recordActivityFeed.ts",
        "ui/packages/types/src/data.ts"
      ],
      "deviations": [
        "Docs outside the named file surface: content/docs/frontend/plugins/plugin-detail.mdx Console Integration snippet (it showed activity top 200, now top 5 + timeline). Regenerated reference docs and the strictness ledger count are generator output.",
        "Two existing app-shell tests outside the named list (recordOpenWaves-13010, recordPagePayload-27627) had their expected activity top changed 200 -> 5 (+ timeline); behaviour otherwise unchanged.",
        "A refused sys_audit_log read counting 0 is pinned only in the rest unit test: on the dogfood boot the default permission sets let a member read the ledger rows of records they read, so no dogfood negative exists.",
        "Named divergence (toward a larger count): the server counts every readable ledger write; the console draws only rows with displayable changes and reads the newest 50. The 动态 tab still pages only through the 200 activity + 50 ledger rows it holds.",
        "The 动态 tab opened after a peek open reads the 200-row sys_activity window once, only when the activity part's total exceeds the rows held (a record with none makes no read).",
        "Full app-shell suite (2061 files) not run locally: a 1401-file views run was cut by my own 50-min timeout; the 151 files importing the touched modules and all RecordDetailView* files were run instead. CI runs the rest."
      ],
      "serial": "#28483 (seat 1) is on main and merged into this branch cleanly at 68f53bda; this PR lands second.",
      "mcp_calls": { "github_mcp_writes": 0, "github_mcp_reads": 0 },
      "api_writes": { "relay_pr_create": 1, "post_stamped": 1 },
      "out_of_scope_findings": []
    }
  6. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#4 · zhuangjianguo · session_01QsR2jR7ZFkpqmm4U8S1f9y

    ACCEPT · 2026-11-02T06:17Z · PR #28991 at af2b6b3f, record 6570496708; contract review (CONTRACT_REVIEW_TIER, director) PASS 6570231752 on the same head. Ordinary queue landing follows. Should-fix ④-1 (prose) filed as #28998.


    Generated by Claude Code

  7. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#4 · zhuangjianguo · session_01QsR2jR7ZFkpqmm4U8S1f9y

    Landed · 2026-11-02T06:41Z · PR #28991 merged through the merge queue as c708de67. Records: ACCEPT 6570496708 and contract review (CONTRACT_REVIEW_TIER, director) PASS 6570231752, both at af2b6b3f.

    probe before (c708de67~1) now (origin/main)
    export const RecordPageTimelineRequestSchema in packages/spec/src/api/record-page.zod.ts 0 1
    export const RECORD_TIMELINE_UNDRAWN_ACTIVITY_TYPES (the one undrawn-types definition) in the same file 0 1
    const answerTimeline (the server count) in packages/rest/src/record-page-routes.ts 0 1
    export function recordPageTimeline (the console's reader) in app-shell/src/views/recordPagePayload.ts 0 1

    The card closed through Fixes. pm:dispatched comes off with this note. The director's should-fix ④-1 (the docblock should say the count is an upper bound of the drawn entries) is #28998, which domain:ui#4 takes next.


    Generated by Claude Code

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

Metadata

Metadata

Assignees

Labels

area:recordsBusiness objects, records, the views that show data, usable forms, searchdomain:uienhancementNew feature or requestpriority:p1High: required for production / M2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions