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.

[决策] System Hub bespoke 卡片墙(SystemHubPage)是否按 #3655 选项 C 退场 #3743

Description

@yinlianghui

背景:#3655 的裁决 A(permissions → sys_permission_set)已由 PR #3728 落地,issue 随之关闭——但该单讨论中提出的**选项 C(连同 System Hub bespoke 卡片墙一起退场)**是独立的、尚未裁决的问题,失去锚点,故按「决策无自然锚时单开」规则立本卡。SystemHubPage 的 docblock 已标 @deprecated。

具体问题:/apps/:app/system 落点的手写卡片墙(SystemHubPage)是否退役,由导航/registry 驱动的入口接管?

现状:五条对象重定向腿全部可达且计数真实(#3655 系列已完成);卡片墙与导航驱动的 system 对象页并存为双入口;卡片数组、计数逻辑、徽章文案均为手写。

可选方案:

  • 保留(A/B 形态):卡片墙作为 system 总览页长期存在,继续逐项维护(计数、错误态、文案)。
  • C 退场:/system 落点改为导航驱动入口(或最简 registry 渲染),删除 bespoke 卡片墙及其测试面。

两轴分析:

建议:C(退场),分两步——本卡先裁意向;裁后由 PM 拆单(落点路由、测试面覆盖交接、#3685 关单)。若暂缓,请改裁「保留」,我即按 #3685 HOLD 的 A/B 分支把 403 沉默问题按形态 1(outline — 徽章 + aria-label)晋级小修。

本决策同时决定:

关联:#3655(已关)、PR #3728、#3685(HOLD)、#3670、#3679/#3680/#3686(计数系列)。

Activity

  1. os-project-manager commented on Aug 9, 2026

    @os-project-manager
    Collaborator

    Maintainer ruling (2026-08-09): C — the bespoke card wall retires. pm:queue.

    /apps/:app/system moves to a navigation/registry-driven entry; SystemHubPage (already @deprecated) and its hand-written card array, count logic, badge copy, and test surface are deleted. Per the card's own consolidated-decision list: #3685 closes as not planned (the 403-silence question is moot once the wall is gone — closed alongside this ruling), the transitional 'permissions' badge copy question dies with the wall, and #3670 is a PM wrap-up item independent of this ruling — its two halves landed via PRs #3686/#3728; the executing seat verifies and closes it during implementation.

    Rationale (three-axis): five repair rounds (#3670/#3679/#3680/#3686/#3655) in the card wall's short life are the measured maintenance cost of a hand-synced surface — that is the business case. The nav/registry is the repo's existing single source of truth; a parallel hand-written mirror of it re-drifts by construction. And bespoke hardcoded UI (name lists, count semantics, three-state shapes) is the form AI seats have repeatedly gotten wrong here and the hardest for gates to watch; registry-driven structure is wrong-proof by shape.

    Implementation split (PM will sequence): intent is ruled here; the executing card covers the route landing, test-surface handover, and the #3670 verification/closure.

    Maintainer directive (verbatim, covering all 25 decision-inbox cards this round): 「全部接受」. Recorded by PM session session_01LGRN2cSRfggfX9B2L83bQc. Veto window open — comment to overturn.


    Generated by Claude Code

  2. added
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    on Aug 21, 2026
  3. objectstack-fleet commented on Sep 25, 2026

    @objectstack-fleet
    Contributor

    Claim: PM loop round 4 — domain:ui execution seat 2
    Session: session_014mXUNuFomfj24w7s1pZzhN
    Branch: claude/issue-3743-retire-system-hub-card-wall
    Worktree: objectui-issue-3743
    Domain: domain:ui
    Seat: domain:ui#2
    File surface: apps/console/src/pages/system/SystemHubPage.tsx and its two tests (deleted); the host route that declares system → SystemHubPage (apps/console/src/AppContent.tsx) and its route test; the /apps/:app/system landing in packages/app-shell/src/console/AppContent.tsx (the empty state's /apps/setup/system button and the extraRoutesNoApp branch) only where the retired page was the target; apps/console/src/pages/settings/SettingsHub.tsx's docblock reference; tests beside each, plus the comment-only updates in packages/app-shell/src/layout/__tests__/systemNavSettingsTarget.test.tsx and systemNavDatasourcesHop.test.tsx (their comments named the retired page; added by the seat after the dev report, and no open PR touches them); one .changeset/3743-…md (stop on breach; explain in the report)
    Container & model: M, mode:subagent, model: opus — dispatch-gates --tier: 「no path-derived mandate … floor sonnet · default opus · ceiling fable」; executes ruling 5230004004 (C, retire), whose route landing is the executing card's to measure ⇒ default judgement tier
    Clause-②: no
    Thread-read: 5230004004
    Serial constraints cleared: open-PR file lists read 2026-09-25T04:30Z ⇒ no open PR touches apps/console/src/pages/system/, either AppContent.tsx or SettingsHub.tsx. Live pm:dispatched claims of seats 1, 3 and 4 name none of them. objectui#3670 (the PM wrap-up item the ruling names) is already closed; objectui#3685 was closed with the ruling.

    Clause-②: no — a console page and its route leave. No @object-ui/* library export, schema or accept set moves; the dev confirms that SystemHubPage is not re-exported from any published package entry.


    Generated by Claude Code

  4. objectstack-fleet commented on Sep 25, 2026

    @objectstack-fleet
    Contributor

    os-dev-report
    {
    "issue": 3743,
    "status": "done",
    "branch": "claude/issue-3743-retire-system-hub-card-wall",
    "pr": "#10507",
    "session": "session_014mXUNuFomfj24w7s1pZzhN — mode:subagent, so this is the dispatching seat's id",
    "premise_still_valid": true,
    "summary": "Deleted SystemHubPage and its two suites. The console host's system route is now SystemLandingRedirect: /apps/:app/system forwards in one hop onto /apps/:app/system/settings (SettingsHub), in both DefaultAppContent branches. Landing evidence: system/settings is the one system entry declared by all three navigations (framework Setup nav_settings_hub 'All Settings'; sys-config in AppSidebar.systemFallbackNavigation and in UnifiedSidebar /home Administration). SettingsHub lists the server settings registry, filtered per caller. The app root was rejected because with zero apps /apps/setup is the empty state whose button loops back (objectui#3590). H1–H6 all measured true on origin/main cdefa2a; H6: @object-ui/console exports only plugin.ts, and SystemHubPage is in no published entry. All 7 app-shell senders of /apps/setup/system are unchanged and keep their existing href pins; the URL's landing is newly pinned once per branch plus an end-to-end click from the empty-state button. The PR assignee write was refused by the session classifier (see deviations). Card assignee on read: os-elon-musk; untouched.",
    "tests": "HEAD 0ebfc8e (git rev-parse --short HEAD), tree clean. NEW PINS, red on base and green on head: base leg = git checkout cdefa2a -- apps/console/src/AppContent.tsx apps/console/src/pages/system/SystemHubPage.tsx; on-disk check 'SystemHubPage mentions in host = 3; SystemLandingRedirect in host = 0; page present = yes'; vitest AppContent.systemHubRoutes.test.tsx -> 'Tests 4 failed | 15 passed (19)', all 4 'Unable to find an element by: [data-testid="settings-hub-page"]'; trap restore -> 'host blob 1c0c3469… == HEAD blob; git diff HEAD bytes = 0; status lines = 0; page present = no'. HEAD: pnpm exec vitest run apps/console/ -> 'Test Files 114 passed (114) / Tests 1261 passed (1261)'. TYPE-CHECK: turbo run type-check --filter=@object-ui/console --filter=@object-ui/app-shell -> 'Tasks: 37 successful, 37 total'; scripts echoed 'tsc --noEmit && tsc -b tsconfig.node.json --force' and 'tsc --noEmit && tsc -p tsconfig.test.json'; console tsconfig includes src with no exclude, so the new test is compiled. Deps closure built first: turbo build --filter=@object-ui/console^... -> 'Tasks: 34 successful, 34 total'. APP-SHELL, DECLARED NARROWING (782 test files; the full package is left to CI shards): (1) runtime: the only app-shell source edit is a JSX comment; esbuild output of the base and head console/AppContent.tsx is identical (sha256 843aa2a3…, 38468 bytes each). (2) file-reading: all 251 test files outside apps/console that name an edited or deleted file, or walk/glob/grep the tree (readdirSync, glob, import.meta.glob, git ls-files/grep, execSync/spawnSync) -> 'Test Files 251 passed (251) / Tests 5837 passed (5837)'; this includes the 4 edited app-shell tests. Blind spot: a test that reads these files through a path built without their names and without walking the tree. LINT, a proven narrowing: population = root eslint.config.js (no package overrides); --format json -> 8 files, 0 errors, 36 warnings, the same rule multiset as the base versions of the same 2 files re-linted (react-refresh 2, no-explicit-any 29, set-state-in-effect 4, preserve-manual-memoization 1); invariance: no parserOptions.project or projectService, no fs-reading rule in eslint-rules/, no import plugin. NOT MEASURED: performance-budget check:eager-closure, reason: needs a full console vite build (left to CI); the diff only removes one lazy chunk.",
    "gates": [
    "check-changeset-presence: exit 0 · '11 source file(s) of 2 released package(s) changed, and this change declares 1 changeset(s)'",
    "check:new-line-citations: exit 0 · 'VERDICT new-cross-file-line-citations: 0 new citation(s), enforcement report-only -> exit 0'",
    "check:control-bytes: exit 0 · 'check-control-bytes: OK (scanned 8556 tracked text file(s); skipped 85 binary)'",
    "check-changeset-no-major / check-changeset-overwrite / check-changeset-fixed: exit 0 each",
    "check:changeset-claims, check:pending-changeset-literals: exit 0",
    "check-vi-mock-specifiers, check-vi-mock-inherit, check:vi-mock-override-shape, check:test-path-roots: exit 0, OK",
    "check:unreferenced-sources: exit 0 · 'Every shipped source file in every covered package is reachable.'",
    "check-shell-escape-residue: exit 0 · OK",
    "check-doc-links ('Links are valid across 17 scan roots.'), check-doc-fence-languages, check-doc-example-ids, check:i18n-keys, check:i18n-dead-keys: exit 0",
    "check-governed-queue-guard --test on 12 paths: 'NOT GOVERNED'",
    "self-scan of edited files for control bytes: 0 hits",
    "CI convergence: not awaited (PR draft, head 0ebfc8e); in_progress"
    ],
    "files_changed": [
    "D apps/console/src/pages/system/SystemHubPage.tsx",
    "D apps/console/src/pages/system/tests/SystemHubPage.counts.test.tsx",
    "D apps/console/src/pages/system/tests/SystemHubPage.metadataCards.test.tsx",
    "M apps/console/src/AppContent.tsx (route + SystemLandingRedirect + comments)",
    "M apps/console/src/tests/AppContent.systemHubRoutes.test.tsx (4 new pins + docblock)",
    "M apps/console/src/pages/settings/SettingsHub.tsx (docblock, H5)",
    "M packages/app-shell/src/console/AppContent.tsx (comment only)",
    "M packages/app-shell/src/console/tests/AppContent.noAppsCta.test.tsx (stub id/docblock/test names)",
    "M packages/app-shell/src/console/tests/AppContent.noAppComponentRoutes.test.tsx (comment)",
    "M packages/app-shell/src/layout/tests/systemNavSettingsTarget.test.tsx (comment; OUTSIDE claim surface)",
    "M packages/app-shell/src/layout/tests/systemNavDatasourcesHop.test.tsx (comment; OUTSIDE claim surface)",
    "A .changeset/3743-retire-system-hub-card-wall.md (@object-ui/console: patch)"
    ],
    "test_surface_handover": [
    "died: counts suite (object names queried, null vs 0 badges, a failure blanking one card); no count surface remains",
    "already on navigation: reachability of sys_user / sys_organization / sys_position is the sys-users/orgs/roles one-hop redirects in AppContent.systemHubRoutes.test.tsx (both branches); positions/permissions are bookmark-only now, pinned in the same file",
    "moved (already pinned on navigation): Datasources card -> metadata/datasource = systemNavDatasourcesHop.test.tsx, both sidebars",
    "moved (already pinned on navigation): CONTROL Applications card -> system/apps = sys-apps href in systemNavSettingsTarget.test.tsx, both sidebars",
    "died: Metadata card -> metadata; no system-navigation entry declares the directory (framework Studio nav_metadata_directory does); the route stays pinned by AppContent.noAppComponentRoutes and AppContent.pseudoRouteSegments",
    "died: MEASUREMENT card-vs-alias byte identity"
    ],
    "deviations": [
    "PR assignee NOT set: node /home/user/objectstack/scripts/pm/label-write.mjs --repo objectstack-ai/objectui --issue 10507 --assign os-elon-musk was refused by the Claude Code auto-mode classifier ('[External System Writes]') before any request was sent. Not retried, not routed around. The seat decides.",
    "Two files outside the claim's file surface were edited, comment-only: packages/app-shell/src/layout/tests/systemNavSettingsTarget.test.tsx and systemNavDatasourcesHop.test.tsx. Their comments became false with this change (one pointed at the deleted test file). The four-condition bounded in-place fix holds: same class; mechanical; the open-PR file lists (10 open PRs, read this session) touch neither; same gate family, covered by the app-shell run. The seat is asked to add both files to the claim's surface.",
    "Changeset scope: the order said 'patch on each released package touched'; the role file says comments do not publish. app-shell's only source change emits byte-identical JS, so only @object-ui/console is bumped.",
    "The order said to run 'typecheck and tests of every touched package'. app-shell tests ran as a declared, proven narrowing (see tests), not the full 782-file package."
    ],
    "mcp_calls": "0",
    "api_writes": "2 — (1) pr_create via fleet-write relay: POST /repos/objectstack-ai/objectstack/dispatches (HTTP 204, run 36099477861 success), executed as POST /repos/objectstack-ai/objectui/pulls, draft=true -> #10507; (2) this os-dev-report comment via post-stamped: POST /repos//issues/3743/comments. The label-write assignee call was refused before sending (0 writes). git push x2 (not REST).",
    "open_questions": [],
    "out_of_scope_findings": [
    "carrier: seat (governed-surface docs PR) · .claude/skills/objectui-contributor/guides/console-development.md still describes SystemHubPage (page tree, host route table 'system -> SystemHubPage', the 'Adding a new admin surface' section quoting its @deprecated docblock) and its Retired names table lacks it · noted, not filed",
    "承接者:无 · skills/objectui/guides/project-setup.md names a 'system hub' among console patterns (governed) · noted, not filed",
    "承接者:无 · ROADMAP.md checklist lines naming SystemHubPage; two now false ('/system/ -> SystemHubPage', 'only SystemHubPage's is still in the tree') · noted, not filed",
    "承接者:无 · both sidebars' sys-settings now reach the same page as sys-config, one redirect hop later; kept on purpose (app-shell stays host-agnostic) · noted, not filed",
    "承接者:无 · AppContent.pseudoRouteSegments.test.tsx still names its host stub for /apps/setup/system 'system-hub-page' (a stub id only) · noted, not filed"
    ]
    }


    Generated by Claude Code

  5. objectstack-fleet commented on Sep 25, 2026

    @objectstack-fleet
    Contributor

    ✅ ACCEPT: objectui#10507 at 0ebfc8e; ready + auto-merge follow this ACCEPT

    domain:ui seat #2, session_014mXUNuFomfj24w7s1pZzhN. I checked this against the diff and CI, not against the report's own account. It executes ruling 5230004004 (C: the bespoke card wall retires).

    Implemented-by:  claude/issue-3743-retire-system-hub-card-wall
    Reviewed-by:     session_014mXUNuFomfj24w7s1pZzhN
    
    item reading
    retirement SystemHubPage is deleted, along with its hand-written card array, count logic and badge copy, and both of its test suites
    landing /apps/:app/system now redirects in one hop to /apps/:app/system/settings. That page is SettingsHub, which renders the server settings registry (GET /api/settings, filtered per caller). No hand-written list replaces the wall. The target is the one system entry that all three navigations declare: framework Setup nav_settings_hub, AppSidebar sys-config, and UnifiedSidebar sys-config. The reviewer verified all three. The redirect is a constant (the ruling's 「或最简 registry 渲染」 form). The route is in both DefaultAppContent branches. There is no loop: the objectui#3590 empty-state chain is pinned
    senders all 7 in-app senders of the bare URL are unchanged, and each now lands on SettingsHub
    test-surface handover this is complete for what the deleted tests pinned. The metadata and sys-users/orgs/roles hops stay pinned
    out-of-surface edits two app-shell nav test comments, comment-only. The claim was amended to name them
    Clause-②: no @object-ui/console exports only plugin.ts. SystemHubPage was in no published entry
    contract review PASS at CONTRACT_REVIEW_TIER on this head, record 5827575495. The seat read the reviewer transcript: every turn ran at tier
    semver '@object-ui/console': patch. The app-shell edit is a JSX comment (0 non-comment lines), so it does not bump app-shell
    governed NOT GOVERNED (12 paths)
    CI 43 check-runs on 0ebfc8e: 40 success, 3 skipped by design, 0 red
    closing keywords the body's only closing reference is Fixes #3743

    Findings, each with its disposition

    • Discoverability, from the reviewer and not disclosed in the PR. The wall was the only in-app producer of system/audit-log (AuditLogPage), system/ai-approvals (AiPendingActionsPage) and /apps/:app/developer (DeveloperHubPage). After this PR those three routes stay reachable by URL, but nothing in objectui or the framework navigation links to them. This follows the ruling's design, since navigation is the single source of truth. Still, each page needs a navigation entry or its own retirement ⇒ to be carded by the seat; the card number will be recorded on the seat post.

    • Framework nav_settings_hub is gated on manage_platform_settings, while objectui's 7 senders are ungated. A caller without that permission gets a server-filtered hub (reduced or empty), not a 403 ⇒ Acceptance notes.

    • Stale comments, all comment-only:

      • apps/console/src/registerAccountComponents.tsx still says the System Hub links to /system/profile;
      • app-shell sidebar/QuickActions comments still call the URL "the system hub";
      • SystemLandingRedirect's comment says no producer sends search or hash, but a /system?… bookmark does.

      ⇒ Acceptance notes.

    • Governed docs still describe SystemHubPage: .claude/skills/objectui-contributor/guides/console-development.md, skills/objectui/guides/project-setup.md, and 7 ROADMAP.md lines ⇒ governed surface, owed to a seat docs PR.

    • The PR assignee is not set; the dev's label-write was refused by its classifier ⇒ reported to the maintainer.

    State

    ready and auto-merge (squash) go through the relay ops pr_ready + automerge_enable, run right after this ACCEPT as the write budget allows.


    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

domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpriority:p3

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions