Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

record page History: an activity row with no actor at all (actor_id and actor_name both null: seed and system writes) reads "Unknown user" with a "?" avatar — it reads System #12527

Closed

Description

@objectstack-fleet

Filing gate ① (a product defect, measured on main), filed on the maintainer's word (chat, 2026-10-15, session session_019YFzJp4o8Ck4NsT1toC4UP, seat account os-bill): the seat ran a functional audit of the HotCRM console on objectui main 720f6d4 (report, private to the maintainer: https://claude.ai/artifact/XPrn5eZMsQaKUgasMJEMmR, finding F9, figure 10), and the maintainer answered 「同意开卡,使用 pm-dispatch 创建卡片」. Quota note: the audit's cards exceed the filing gate's three-per-fire quota on that word, which approved the report's card list as a set.

Parent: objectstack-ai/objectstack#25945. The third pin of #12067 (closed by PR #12070) covers the row this card measures: "a row with neither renders the existing fallback". This card changes what that fallback says. Blocks nothing; nothing blocks it.

Reader who acts: the domain:ui lane's next dispatch (seat post #9800), one dev round in @object-ui/plugin-detail (HistoryTimeline.tsx, renderers/record-history.tsx) and the ten @object-ui/i18n packs, size S.

Dedupe (MCP search_issues, scope objectstack-ai/objectui, all states, read 2026-10-15T14:14Z): "record history timeline Unknown user for system or seed writes actor missing show System" → 3, all closed: #12067 (rows with actor_id and no actor_name read Unknown user; fixed by PR #12070, which resolves actor_id), #11701, #11697 (the audit log's actor column). None is this card: #12067 left the no-actor row on the fallback by design and this card names that row.

What happens

The HotCRM lead "Mira Costa" → History shows three entries, each with a "?" avatar and the name "Unknown user": 「UPDATED · Lead Owner: ∅ → Dev Admin」, 「UPDATED · Updated Lead "Mira Costa - Atlas Construction"」, 「CREATED · Created Lead "Mira Costa - Atlas Construction"」. A reader is told a person they cannot identify changed the record; the writer was the seed's owner backfill, with no user in context.

Readings (objectui origin/main 720f6d4, read 2026-10-15T14:15Z)

  1. API reading (HotCRM backend, admin): GET /api/v1/data/sys_activity?filter=["object_name","=","crm_lead"]&sort=-timestamp → 28 rows, each with actor_id: null, actor_name: null, actor_avatar_url: null, created_by: null; summary "Lead Owner: ∅ → Dev Admin", metadata {"old":{"owner_id":null},"new":{"owner_id":"ZgyhVWT4…"}}. A login's sys_user row, by contrast, carries actor_id and actor_name "Dev Admin".
  2. packages/plugin-detail/src/renderers/record-history.tsx line 147 reads schema.unknownUserText; line 217 passes it to HistoryTimeline; HistoryTimeline.tsx lines 60, 168 and 213: the fallback label for an entry with no user, defaulting to the "Unknown user" string (i18n unknownUser at packages/i18n/src/locales/en.ts line 1468 is the shorter "Unknown" used elsewhere).
  3. PR fix(plugin-detail): name the actor of an activity row that carries only actor_id (objectui#12067) #12070 (record:history maps the entry's user from actor_name only, so activity rows written without it (every row before objectstack#22510's fix) read "Unknown user" although actor_id is set #12067): an entry with actor_id only now resolves the user's name; an entry with neither keeps the fallback.

What to build

  1. An entry whose row carries neither actor_id nor actor_name is a system write: it renders the label "System" (new i18n key in all ten packs, e.g. detail.history.systemActor) with a system glyph (a cog or the platform mark) in place of the "?" avatar, never a person-shaped unknown.
  2. "Unknown user" stays for the only case that is unknown: an actor_id the user lookup cannot resolve (a deleted user).
  3. unknownUserText keeps overriding the unknown case; a new systemActorText override is not added unless the schema already has a slot for it.

Acceptance

Out of scope

Attribution: written by the domain:ui seat in session session_019YFzJp4o8Ck4NsT1toC4UP (account os-bill) on the maintainer's words quoted above.

Screenshots (added 2026-10-15T14:41Z, on the maintainer's word 「专用分支存图,卡里嵌 raw 链接」)

The images live on the attachment branch claude/ui-audit-2026-10-15-shots of objectstack-ai/objectui (commit 918a251, never merged; index at https://github.com/objectstack-ai/objectui/blob/918a2510a54bd6875b90eb6996d098c3ec0451dd/docs/design/console-audit-2026-10-15/README.md). Full set and figure numbers: the audit report linked above.

History tab: three "Unknown user" entries with "?" avatars for the seed's writes

record-history.png

Activity

  1. added
    bugSomething isn't working
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    area:recordsBusiness objects, records, the views that show data, usable forms, search
    and removed on Oct 15, 2026
  2. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1
    Session: session_01XVp19E1MYUTFM3dnkwz8gB
    Account: baozhoutao (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-12527-history-system-actor
    Worktree: objectui-issue-12527
    Domain: domain:ui
    Seat: domain:ui#2 (the card names the lane's next dispatch under seat 3's post #9800, which is vacant)
    File surface: packages/plugin-detail/src/HistoryTimeline.tsx and packages/plugin-detail/src/renderers/record-history.tsx (the no-actor label and glyph), packages/i18n/src/locales/*.ts (one new key in all ten packs), the tests beside each, and one .changeset/12527-*.md (stop on breach; explain in the report)
    Container & model: S, mode:subagent, model: opus (default tier; dispatch-gates --tier --repo objectstack-ai/objectui reads no path-derived mandate)
    Clause-②: no
    Responsibility: objectui's record History timeline, which labels an entry with neither actor_id nor actor_name as "Unknown user" | none: PR objectstack-ai/objectui#12070 resolves an actor_id, and an entry with no actor at all keeps the person-shaped fallback | every reader of a record page's History whose rows were written by the system (measured on HotCRM: every seeded lead's owner backfill and create rows)
    Thread-read: none
    Serial constraints cleared: at main b51242899, no in-flight claim or open PR touches HistoryTimeline.tsx, record-history.tsx or the i18n packs' history keys. objectui#12529 (claimed alongside, RecordDetailView.tsx) and objectui#12530 (this seat, sharedUserFeeds.ts) are disjoint.


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 12527,
    "status": "done",
    "branch": "claude/issue-12527-history-system-actor",
    "pr": "#12547",
    "session": "session_01XVp19E1MYUTFM3dnkwz8gB",
    "premise_still_valid": true,
    "summary": "HistoryTimeline now has three actor faces: a resolved name; no name and no user_id = System (detail.systemActor) with a lucide Cog glyph in place of the ? avatar; a user_id with no name = unknownUserText or Unknown user with ?. The record:history self-fetch now carries each row's actor id (bare actor_id or the expanded user record's id) onto HistoryEntry.user_id, which the type already declared, so the timeline can tell the two apart; activityActorName (#12067) untouched. No systemActorText override (no schema slot). Deviation: no new i18n key. detail.systemActor already exists, is translated in all ten packs and is what record:activity renders for the same no-actor row; reusing it avoids forking one word across ten packs, so no locale pack is touched and the changeset covers @object-ui/plugin-detail only.",
    "tests": "HEAD c18550e. vitest HistoryTimeline.test.tsx + record-history.{actorId-12067,contractEnvelope-6726,rowLimitRefusal-10005}: Test Files 4 passed, Tests 39 passed. vitest --maxWorkers=2 packages/plugin-detail/ (lock): Test Files 271 passed | 1 skipped, Tests 2630 passed | 14 skipped, VERDICT command-exit 0. Ablation (fix committed first; objectstack ablation-replace.mjs, anchor 1to0, blob 4adf08c8to20a50380): isSystemActor forced false gives 3 failed | 10 passed (two System pins in HistoryTimeline.test.tsx + the re-ruled #12067 third pin); Unknown-user pin stays green as expected; restore verified blob == HEAD 4adf08c8, git diff HEAD empty. Tests import HistoryTimeline by relative src path, so no dist rebuild was in the ablation path. Closure build pnpm --filter '@object-ui/plugin-detail^...' build exit 0; type-check plugin-detail + i18n exit 0 (both legs echoed type-check: Done). ESLint narrowed to the 4 changed ts/tsx files (count from --format json): 0 errors, warnings pre-existing (record-history.tsx 8 at base, 8 now); config has no type-aware linting, so untouched files cannot change verdict.",
    "gates": {
    "check:phantom-deps": 0, "check:self-import": 0, "check:unreferenced-sources": 0, "check:doc-example-readers": 0,
    "check:handler-key-reads": 0, "check:side-effects-array": 0, "check:element-data-source-declaration": 0,
    "check:spec-symbols": 0, "check:action-forward-parity": 0, "check:designer-field-key-parity": 0,
    "check:icon-record-names": 0, "check:i18n-keys": 0, "check:i18n-drift": 0, "check:i18n-designer-parity": 0,
    "check:control-bytes": 0, "check-changeset-fixed": 0, "check-changeset-presence": 0,
    "type-check plugin-detail+i18n": 0, "closure build": 0, "vitest touched": 0, "vitest plugin-detail": 0, "eslint narrowed": 0,
    "CI": "in_progress (not awaited, per contract)"
    },
    "line_budget": "n/a (no skills/** or governed surface touched)",
    "files_changed": [
    "packages/plugin-detail/src/HistoryTimeline.tsx",
    "packages/plugin-detail/src/renderers/record-history.tsx",
    "packages/plugin-detail/src/tests/HistoryTimeline.test.tsx",
    "packages/plugin-detail/src/renderers/tests/record-history.actorId-12067.test.tsx",
    ".changeset/12527-history-system-actor.md"
    ],
    "deviations": [
    "Section-1 ruling said one NEW i18n key in all ten packs; measured that detail.systemActor already exists, translated in all ten packs and used by record:activity for the same row. Reused it: no locale file edited, changeset is @object-ui/plugin-detail patch only (dispatch named @object-ui/i18n patch too). The ruling's end (properly translated System in all ten packs) holds; a zh pin proves the pack lookup. If the seat wants a distinct detail.history.* key anyway, that is a ten-pack follow-up the seat can order.",
    "The #12067 third pin (row with neither renders the existing fallback) is changed, not unchanged: the card re-rules exactly that row. The other #12067 pins are untouched.",
    "objectstack scripts/pm/dispatch-gates.mjs not run: it answers for the objectstack tree only; objectui gate list taken from the dispatch.",
    "Lock: first closure-build attempt was queue-timeout exit 99 (holder: another objectui worktree's vitest); re-acquired under the same slot and ran green."
    ],
    "mcp_calls": "0",
    "api_writes": "2 relay strokes + 2 git pushes: fleet-write dispatch pr_create (POST /repos/objectstack-ai/objectui/pulls draft + POST issues/12547/assignees) to PR #12547, read-back 4614 bytes identical, assignee baozhoutao; fleet-write dispatch comment (POST /repos//issues/12527/comments, this report). git push x2 (empty branch probe, c18550e). Zero label writes (dispatch named none; objectui labels via labeler.yml).",
    "open_questions": [],
    "out_of_scope_findings": []
    }

  4. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Review: ACCEPT — objectui PR #12547 · domain:ui seat 2 · session_01XVp19E1MYUTFM3dnkwz8gB · 2026-10-15T16:45Z

    Reviewed on GitHub at head c18550e, against the card's What to build 1–3 and Acceptance, and the claim (6196021892), not against the dev's report.

    • Shape: the PR is a draft against main. Its body opens Fixes objectstack-ai/objectui#12527, the only closing keyword, followed by Clause-②: no. 5 files.
    • Three actor faces in HistoryTimeline:
    • Deviation, measured and accepted: the dispatch asked for a new i18n key in all ten packs. The dev reused the existing detail.systemActor instead: the seat read it in all ten packs (en "System", zh "系统", ar "النظام", de "System", es "Sistema", fr "Système", ja "システム", ko "시스템", pt "Sistema", ru "Система"), and record:activity already renders it for the same no-actor row. One word is not forked across ten packs, so no locale file changes, and a zh pin proves the pack lookup.
    • Pins and ablation:
    • Changeset: @object-ui/plugin-detail: patch only, since no i18n pack changed.
    • Evidence: the closure build and the plugin-detail and i18n type-checks exit 0. packages/plugin-detail/ gives 2630 passed and 14 skipped under the lock. The battery exits 0, including check:i18n-keys and check:i18n-drift.
    • Acceptance note (not filed): the HotCRM browser reading (the seeded lead's three entries read "System") is the maintainer's check.
    • CI at head: 34 success, 3 skipped, 0 failures (filter=latest, 37 runs), all 16 test shards included.

    Next: pr_ready + automerge_enable.


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · domain:ui seat 2 · session_01XVp19E1MYUTFM3dnkwz8gB · 2026-10-15T17:01Z

    • Merged: PR fix(plugin-detail): a History entry with no actor reads "System", not "Unknown user" #12547 merged through the merge queue as main 165f8ff. The card closed by the PR's Fixes objectstack-ai/objectui#12527, which is the only closing keyword.
    • Verified by content: on origin/main, all 5 files the PR touches are blob-identical to the accepted head c18550e. They are HistoryTimeline.tsx, record-history.tsx, the two pin files and .changeset/12527-history-system-actor.md.
    • The HotCRM browser reading (the seeded lead's three History entries read "System") is the maintainer's check.
    • Label: pm:dispatched is removed in the same stroke as this comment.

    Generated by Claude Code

  6. added a commit that references this issue on Oct 28, 2026
    165f8ff
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, searchbugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpriority:p2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions