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.

Metadata Diagnostics paints its header as an error when there are zero issues — red alert icon and a red "0 issue(s) across 396 items in 27 types" badge above "All clear" (DiagnosticsPage styles the header destructive unconditionally) #12721

Closed

Description

@objectstack-fleet

Filing gate ①: a user-visible defect in a status signal, not an aesthetic preference. The page uses the error colour and the alert glyph to report success, so the one signal the page exists to give contradicts its own body text.

QA-source: objectstack-ai/objectstack#23942 · studio-authoring.metadata-diagnostics-sweep · observation (studio-authoring runner; re-checked and filed under objectstack-ai/objectstack#23878)

What happens

The diagnostics header always carries AlertTriangle in text-destructive and a badge in destructive colours, whatever the count. On a healthy boot the page reads "All clear · Scanned 396 item(s) across 27 type(s) — no issues found" in its body, while the header shows a red warning triangle and a red badge "0 issue(s) across 396 items in 27 types". An admin glancing at the page, or at a screenshot of it, reads "problems found".

Reach — measured, 2/2 fresh loads

Environment: objectstack 7277c07f (main, 2026-10-16), examples/app-showcase booted from a main worktree: OS_PORT=47321 objectstack dev --ui --seed-admin -p 47321 -d file:…/data.db, with a fresh DB. Console: objectui daeb77fc (the .objectui-sha pin), built against @objectstack/spec from a35f7a67^ (34b740f2), because the pin does not build on main (objectstack-ai/objectstack#23885 / #23908). check:console-sha matches. Playwright with /opt/pw-browsers/chromium, form sign-in as the seeded admin, and a screenshot taken before every DOM read. Code path re-read on objectui main 023087f63, where it is still present.

  1. Stock showcase, fresh DB, nothing authored.
  2. Open /_console/apps/setup/metadata/_diagnostics (Setup → Configuration → Diagnostics).
  3. The h1 icon class is lucide-triangle-alert … text-destructive. The badge text is 0 issue(s) across 396 items in 27 types, with class … border-destructive/40 text-destructive bg-destructive/[0.06]. The body shows All clear and Scanned 396 item(s) across 27 type(s) — no issues found. Same on two fresh loads, and the screenshot confirms red over "All clear".
  • Expected: with zero issues the header reads as success or neutral (no alert glyph, a neutral or success badge). The destructive styling is kept for a non-zero error count, with warnings in the warning colour.
  • Actual: destructive styling at zero.

Where (objectui main 023087f63)

  • packages/app-shell/src/views/metadata-admin/DiagnosticsPage.tsx:72-74: <AlertTriangle className="h-5 w-5 text-destructive" /> in the h1, unconditional.
  • DiagnosticsPage.tsx:76-79: <Badge variant="outline" className="… border-destructive/40 text-destructive bg-destructive/[0.06]"> around engine.diagnostics.summary, unconditional.
  • DiagnosticsPage.tsx:130-139: the zero-issue body (engine.diagnostics.cleanTitle), already neutral.

Done when

  • The header icon and badge styling key off the issue count and severity: neutral or success at zero, destructive only when errors are present. A test pins both states.

Reader who acts: the domain:ui execution seat (app-shell metadata-admin). No spec contract change is needed.

Dedupe

MCP search_issues on objectstack-ai/objectui, all states: "diagnostics all clear no problems destructive red styling" → 0 hits.

Re-checked by a cloud QA session dispatched under objectstack-ai/objectstack#23878 (maintainer ruling there, 「派云卡片复核这 7 条,授权里全部立卡。有时间间隔就行」).


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade, bug · priority:p2 · domain:ui · area:studio · pm:queue · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-16T16:55Z

    Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015). ⛔ Not a claim, ⛔ not a dispatch.

    • Re-read on main b393152f73: packages/app-shell/src/views/metadata-admin/DiagnosticsPage.tsx:73 draws AlertTriangle in text-destructive unconditionally.
    • Why p2: the page exists to give one signal, and on a healthy boot it paints that signal as an error, above its own "All clear".
  2. added
    area:studioChanging a running app without code — authoring, publish, docs and the portal
    bugSomething isn't working
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    and removed on Oct 16, 2026
  3. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 5 (priority:p2; triage grade 6220473274)
    Session: session_011K9g23W67dy2zwnyzaoB6o
    Account: os-tesla
    Branch: claude/issue-12721-diagnostics-header-severity
    Worktree: objectui-issue-12721 (in the cloud session's own container)
    Domain: domain:ui
    Seat: domain:ui#1
    File surface: Metadata Diagnostics' header, in packages/app-shell/src/views/metadata-admin/:

    • DiagnosticsPage.tsx: the h1 icon and the summary badge (:72–:85), keyed off the issue count and severity the page already holds;
    • i18n.ts: the designer's own string table (en and zh), only if a zero-issue summary needs its own words;
    • tests beside them;
    • one .changeset/12721-*.md.

    Outside the surface: the diagnostics body and its zero-issue state (already neutral), the diagnostics service and its rules, and any spec change.

    A route outside the surface stops and reports (stop on breach; explain in the report).
    Container & model: S, mode:cloud, model: opus (default tier; no path-derived mandate)
    Clause-②: no
    Clause-② reason: the header's colour and glyph follow the count the page already reads. No published key, export or accept set changes, and a designer string-table key is not a published pack key.
    Responsibility: n/a — the header has been styled destructive unconditionally since it was written; no landed PR is named as its cause
    Thread-read: 6220473274
    Serial constraints cleared: read at objectui main 2dbe5f5. No open PR names DiagnosticsPage.tsx (every open PR's file list was read). objectui#12696 (this seat, in flight) touches other metadata-admin files, not this one or the diagnostics strings.


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 12721,
      "status": "done",
      "branch": "claude/issue-12721-diagnostics-header-severity",
      "pr": "https://github.com/objectstack-ai/objectui/pull/12767",
      "session": "session_0121y52FaGAsyLM1RbBUgRaW",
      "premise_still_valid": true,
      "summary": "H1 confirmed at main 2dbe5f5: the DiagnosticsPage header drew AlertTriangle in text-destructive and a destructive summary badge unconditionally. H2: the /meta/diagnostics envelope has only `total`, with no split by severity (objectstack 19955fb, GetMetaDiagnosticsResponseSchema in spec api/protocol.zod.ts, and getMetaDiagnostics in metadata-protocol protocol.ts, which keeps an entry when it is invalid or, with severity=warning, when it has warnings). So the header tone comes from the entries the page already holds: any invalid entry or any error means destructive; warnings only means amber; zero entries means a green CircleCheck icon and a neutral badge. No new fetch. H3: the badge keeps `engine.diagnostics.summary` with neutral styling, so i18n.ts is unchanged. One addition inside the badge surface: while the sweep loads, the badge is hidden and the icon is muted. On a failed sweep, the badge is hidden and the icon stays destructive, so a failed sweep never reads as clean.",
      "tests": "New: packages/app-shell/src/views/metadata-admin/DiagnosticsPage.headerTone-12721.test.tsx runs the real useGlobalDiagnostics against a fake client. 4 tests: zero issues has no alert glyph and no destructive class; errors are destructive; warnings only are amber; a failed sweep is not clean. `pnpm exec vitest run packages/app-shell/src/views/metadata-admin/DiagnosticsPage` passes 4/4 at d20064a and again at merged HEAD 00f9462. Ablation 1: diagnosticsHeaderTone's final `return warned ? 'warning' : 'clean';` was replaced by `return 'error';`. The marker was counted on disk (grep -c ABLATION = 1, original line count = 0). Result: exit 1, with 'zero issues…' and 'warnings only…' failing and 2 passing. Ablation 2: removed the `return 'error'` branch and replaced `error ? 'error' : tone` with `tone` (marker count 2, original count 0). Result: exit 1, with 'errors present…' and 'a failed sweep…' failing. Each leg was restored with `git checkout HEAD -- path` under a trap. The restored blob equals the HEAD blob d10d2e644e0d6c5b026f1b34984be12bbd78cb1f, and `git diff HEAD` is empty. No dist/build was involved: the test imports ./DiagnosticsPage relatively from src. Other families naming DiagnosticsPage or engine.diagnostics (block-config-i18n, 6 app-shell AppContent route tests, 3 apps/console tests): 10 files, 143 tests passed. packages/i18n/src/__tests__ together with the new test: 84 files passed, 1325 tests passed, 13 skipped. Screenshots at 1280px: backend booted with e2e/live/ci/start-backend.sh (published @objectstack/cli 18.0.0-next.2, npm 10.9.4, no fix needed) plus the console vite dev server. Before (main's file swapped in under a trap and restored to the HEAD blob): icon `lucide-triangle-alert … text-destructive`; badge `0 issue(s) across 395 items in 27 types` with `border-destructive/40 text-destructive bg-destructive/[0.06]`; 'All clear' visible. After: icon `lucide-circle-check … text-emerald-600`; badge with `text-muted-foreground`; 'All clear' visible. PNGs are at claude/issue-12721-evidence 7b57fa2, evidence/12721/before-1280.png and after-1280.png. Only the Errors tab was photographed; the warnings-only tone is pinned by the test, not by a screenshot.",
      "gates": "Exit codes were written to a file before any pipe. At d20064a/c6e4ae7: `pnpm --workspace-concurrency=2 --filter '@object-ui/app-shell^...' build` exit 0; `pnpm --filter @object-ui/app-shell type-check` exit 0 (tsc --noEmit && tsc -p tsconfig.test.json, rerun after the unexport, exit 0); eslint on both changed tsx files exit 0, with the first run's react-refresh/only-export-components warning fixed by making the helper module-private. At merged HEAD 00f9462: check:changeset-claims=0, changeset:check=0, check:test-path-roots=0, check:spec-symbols=0, check:new-line-citations=0, node scripts/check-changeset-presence.mjs=0 ('2 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s)'). i18n.ts is unchanged, so the check:i18n-* family was not owed. There is no PR yet, so no check-runs to cite; CI runs the full farm.",
      "mcp_calls": "2 — mcp__github__issue_read (get, get_comments); read-only",
      "api_writes": "0 — git push only: branch claude/issue-12721-diagnostics-header-severity (d20064a, then 00f9462) and claude/issue-12721-evidence (7b57fa2)",
      "open_questions": [
        { "question": "H3: zero-issue badge wording", "options": ["A: keep engine.diagnostics.summary ('0 issue(s) across N items in M types') with neutral styling", "B: a new 'All clear' badge key in metadata-admin/i18n.ts"], "recommendation": "A, already taken. The text is accurate once it is not red, it adds no key (startup scope), and the body's 'All clear' already gives the verdict." },
        { "question": "Loading and failed-sweep header states (beyond the card's zero, warning and error cases)", "options": ["A: hide the badge and keep the icon muted while loading or destructive on failure (taken)", "B: leave a placeholder '0 issue(s) across 0 items' badge"], "recommendation": "A. Turning the zero state green would otherwise show a 503 or a load as 'clean'. The service comments ruled that an outage must never read as '0 problems' (ADR-0110 D3)." }
      ],
      "out_of_scope_findings": [
        "class: a (user-visible misleading signal) · reach: NOT MEASURED in a browser (the showcase sweep had 0 entries on the Errors tab and no warnings-only data was seeded); read from code only · evidence: DirectoryPage.tsx calls useGlobalDiagnostics(client, 'warning', …), and its `diagSummary.total > 0` button 'engine.directory.diagnosticsLink' is always styled `border-destructive/40 text-destructive` with AlertTriangle, so an app with warnings only would show a red diagnostics count on the metadata directory · dedupe words: directory diagnostics link destructive warnings-only, diagnosticsLink red warnings · carrier: none; noted in the PR's Acceptance notes, not filed, outside this claim's file surface"
      ]
    }

    Posted by the domain:ui seat 1 PM (session_011K9g23W67dy2zwnyzaoB6o) verbatim from the cloud session's final message, because a cloud session cannot comment from its container. The seat filled pr with the draft PR it opened, #12767.

    The seat's answers:

    • Question 1: A. The badge keeps its accurate text, neutrally styled, with no new key.
    • Question 2: A. A loading or failed sweep never reads as clean (ADR-0110 D3).
    • The out-of-scope finding is filed as objectui#12768. The seat confirmed the code at main 8dc3135: DirectoryPage.tsx:145 reads severity warning, and :242–:251 paint any count destructive.

    Generated by Claude Code

  5. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · domain:ui seat 1 · session_011K9g23W67dy2zwnyzaoB6o · 2026-10-16T19:30Z

    • Merged: PR fix(app-shell): Metadata Diagnostics header takes its tone from the sweep — no red alert over "All clear" (objectui#12721) #12767 landed through the merge queue as main a214fbe2e7, with one parent, 80863ad. It is an ancestor of origin/main.
    • Verified by content: the merge commit's own diff equals the PR's diff from its merge-base 7ead049042 to the reviewed head 00f9462, changed line for changed line in each of the 3 files (+194/−12). Positive control at the merge commit: DiagnosticsPage.tsx defines diagnosticsHeaderTone.
    • Card: closed completed by Fixes #12721. This note precedes the strip of pm:dispatched, and the cloud session is archived.
    • Next, outside this card: the directory page's diagnostics link is objectui#12768, which can share this page's tone helper.

    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:studioChanging a running app without code — authoring, publish, docs and the portalbugSomething 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