Skip to content

skills(objectstack-ui): the dashboards rule tells authors to override a compareTo series with series.dashArray / series.opacity — a dashboard widget's chartConfig.series is a tombstone the schema refuses by name #21211

Description

@objectstack-fleet

Filing gate: ① a defect, class (c) (a metadata-authoring trap in a published skill), reach: a named real producer: the published skill text itself, skills/objectstack-ui/rules/dashboards.md, which ships to customer projects through npx skills add objectstack-ai/objectstack/skills and instructs an AI author to write the key. Filed by the domain:spec seat 1 (session_01UtnxvdiN376GF3sgXwAw4d, seat post #6017) from the #21131 dev report (5935805280, out_of_scope_findings 3), which the at-tier contract review of PR #21205 (5936107820, ③ OOS-3) escalated for a domain:skills card. ⛔ Filed bare: routing and grading are triage's. ⛔ Not a claim.

Who acts on it: the domain:skills lane (skills/** is Tier H; a docs-only PR for the maintainer's click). ⚠️ PR #21205 (Part of #21131, Tier H, open) edits two other sites of the same file; whoever takes this works after or beside it.

The text

skills/objectstack-ui/rules/dashboards.md, the compareTo "Cartesian charts" bullet (about :257-:262 on origin/main 2c1cef3345):

muted per family (dashed '4 4' on line/area only; reduced opacity on all). Override per-series with series.dashArray / series.opacity.

Why it is a trap

  • On a dataset-bound dashboard widget, chartConfig.series is a retiredKey tombstone (packages/spec/src/ui/dashboard.zod.ts, about :963): "Per-series appearance (label, colour, mark type, stacking) is not authorable on a dataset-bound widget; colors on this same chart config is the palette channel that remains."
  • The chart config's own describe (about :968) states that type, xAxis, yAxis and series "are refused here".
  • content/docs/ui/dashboards.mdx ("What chartConfig does not carry") says the same.
  • So an AI following the skill writes a key the schema refuses at parse. The refusal is loud and carries a prescription, but the skill is the source of the wrong instruction (NORTH-STAR priority 4: a wrong sentence in a skill is a product defect).

Not measured

  • A served os validate run on a stack carrying chartConfig.series: the refusal is read from the tombstone and its describe, not from a run.
  • Whether the bullet means the dashboard widget at all, or a renderer-internal series option. The section is the dashboards rule's compareTo guidance, which is about dashboard widgets; the taker confirms.

Direction (for triage, not a ruling)

Delete the override sentence, or replace it with the one channel that remains (chartConfig.colors), within the skills token ratchet (net lines ≤ 0).

Dedupe

Open issues (152, REST, all pages) and the 183 most recently updated closed issues, grepped locally: dashArray 0, series.opacity 0; compareTo 1 hit, #20760 (a different concern); dashboards.md 1 hit, #21131 (the source). Control: chartConfig 2 hits in the same corpus.

Dedupe words: dashboards skill series dashArray opacity · compareTo override per-series chartConfig.series tombstone · skill teaches refused chartConfig key

Activity

  1. objectstack-fleet commented on Oct 1, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade — documentation · priority:p2 · domain:skills · area:reports · pm:queue. The skill stops teaching a tombstoned key

    Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-01T16:56Z. ⛔ Not a claim, ⛔ not a dispatch.

    Why p2. A published skill tells an AI author to write chartConfig.series. The schema refuses that key by name on a dataset-bound widget, so the author gets a refusal from following the skill.

    Routing. skills/** is a governed surface, so this is domain:skills, done as a Tier H docs-only PR.

    Direction. The bullet says the per-series muting is the renderer's default, and names colors as the one palette channel that remains. ⛔ It names no retired key.

    Serial. PR #21205 edits two other sites of the same file. Whichever lands second merges.


    Generated by Claude Code

  2. objectstack-fleet commented on Oct 1, 2026

    @objectstack-fleet
    ContributorAuthor

    Deferred, not dropped — skills seat 1, session_01FNKm1SmPpuJASnbjxWGtsJ (os-elon-musk), 2026-10-01T23:41Z. ⛔ Not a claim.

    Serial constraint (the seat's hot-file queue, recorded on #7623): PR #21205 (#21131, Tier H draft awaiting an authorized approval) edits the same file, skills/objectstack-ui/rules/dashboards.md, at about :185, :254 and :341; this card's bullet sits at about :261–:262, adjacent to the :254 hunk. Per triage (5936295626, 「Whichever lands second merges」) this card waits for PR #21205 to read MERGED and then bases on the merged text. It stays pm:queue, unassigned, next in this lane's take-order once that lands.

    Known pitfalls, written down now so the eventual claim does not rediscover them:

    1. One bullet, net lines ≤ 0: the file is under check-skills-token-ratchet (ceiling 6252; PR docs(skills): the dashboards rule stops teaching unread widget options extras #21205 leaves 18 tokens of headroom at its head b5b45306) — read the ratchet at claim time, not from here.
    2. The replacement names chartConfig.colors as the one remaining channel on a dataset-bound widget and ⛔ names no retired key (chartConfig.series is a retiredKey tombstone, packages/spec/src/ui/dashboard.zod.ts about :963).
    3. Not measured on the card: a served os validate run against a stack carrying chartConfig.series, and whether the bullet means the dashboard widget at all — the taker confirms both on the tree before editing.
    4. Tier H (skills/**): draft, four-piece, the maintainer's click; the ceiling tier is mandatory for the dev.
  3. objectstack-fleet commented on Oct 2, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1 (wave 3)
    Session: session_01FNKm1SmPpuJASnbjxWGtsJ
    Account: os-elon-musk (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-21211-dashboards-compareto-series-override
    Worktree: objectstack-issue-21211
    Domain: domain:skills
    Seat: domain:skills#1
    File surface: skills/objectstack-ui/rules/dashboards.md, the compareTo 「Cartesian charts」 bullet only — its 「Override per-series with series.dashArray / series.opacity」 sentence (about :261–:262 on origin/main 4bf4e7e7); ⛔ no other bullet, ⛔ no other file. Stop on breach; explain in the report.
    Container & model: S, mode:subagent, model: CONTRACT_REVIEW_TIER (dispatch-gates --repo objectstack-ai/objectstack --tier skills/objectstack-ui/rules/dashboards.md at 4bf4e7e7: MANDATORY — 'skills/**', clause ①, the published catalog; no one-line exemption under this root; Tier H ⇒ draft until an authorized APPROVED review, then the seat lands)
    Clause-②: no
    Thread-read: 5942806060
    Serial constraints cleared: the serial predecessor PR #21205 (#21131) MERGED as f14885275 (2026-10-02T00:15Z) — same-day churn on this file, the dev bases on the merged text (the bullet still reads at :261–:262 there); no open objectstack PR touches skills/objectstack-ui/rules/dashboards.md (all 12 open PRs' file lists read in this claim's minute); the seat's other in-flight objectstack card #21181 touches scripts/pm/fleet-write/ only; the deferral note 5942806060 on this card holds the known pitfalls (token ratchet headroom, no retired key named, measure the refusal before editing).

  4. objectstack-fleet commented on Oct 2, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 21211,
      "status": "done",
      "branch": "claude/issue-21211-dashboards-compareto-series-override",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/21283",
      "session": "session_01FNKm1SmPpuJASnbjxWGtsJ (mode:subagent — the parent's harness-stamped id)",
      "premise_still_valid": true,
      "summary": "Replaced the one false sentence in skills/objectstack-ui/rules/dashboards.md (the compareTo 'Cartesian charts' bullet, :261-:262 on c7396f1a): 'Override per-series with series.dashArray / series.opacity' is now 'That muting is the renderer's default; chartConfig.colors is the one palette channel that remains.' Nothing else in the file moved (+2/-2, net 0 lines; the three PR #21205 sites untouched; 0 hits left for dashArray, series.opacity, chartConfig.series). Draft PR #21283 on main, first line Fixes #21211, Clause-②: no, Tier H so it stays draft for the maintainer's click; skip-changeset + PR assignee os-elon-musk NOT applied: the label-write stroke was refused by the auto-mode permission classifier before any request (see deviations), so the seat applies both on PR #21283.",
      "reach": "safeParse probe, DashboardWidgetSchema from packages/spec/src/ui/dashboard.zod.ts at c7396f1a (tsx against source; not a built dist, not a served os validate run): a dataset-bound line widget with compareTo and chartConfig { colors, series: [{ name, dashArray: '2 2', opacity: 0.3 }] } is REFUSED with one issue code=invalid_type expected=never path=[chartConfig, series], message = the tombstone prescription ('... Per-series appearance ... is not authorable on a dataset-bound widget; colors on this same chart config is the palette channel that remains.'); positive control (series removed, colors kept) ACCEPTED. Hypothesis 2-ii confirmed: the section opens 'Set compareTo on any data-bound widget' and compareTo is a DashboardWidgetSchema key (:1116). Hypothesis 4 confirmed from the renderer, not the card: objectui at pinned .objectui-sha 31971ff1, packages/plugin-charts/src/AdvancedChartImpl.tsx:118-132 seriesStyle — muted = variant === 'comparison'; '4 4' dash on line/area-like only; stroke/fill opacity reduced on every cartesian kind. chartConfig.colors reaches the dataset widget: DatasetWidget.tsx:1800 -> chartConfigPresentation, core chart-presentation.ts:451 reads colors as the palette. Hypothesis 1 line numbers on c7396f1a: series tombstone :961 (dispatch said about :956), prescription :964-:967, describe :970-:975. Hypothesis 3 confirmed: content/docs/ui/dashboards.mdx 'What chartConfig does not carry' already says colors is the palette channel that remains; not edited.",
      "tests": "Gates: node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands at 5dfa2034 derived 23 families (identical to the dispatch list); all 23 run, exit codes captured before any pipe, all 0; --ran reconciled '23 derived, 23 run, 0 NOT-MEASURED, 0 UNRUN' (exit 0). check:doc-formula-expressions first exited 3 (PREREQUISITE: @objectstack/formula and @objectstack/lint not built; nothing measured), then exit 0 after 'turbo run build --filter=@objectstack/formula --filter=@objectstack/lint --concurrency=2' under os-verify-lock (VERDICT command-exit 0, held 83s, waited 0s). check-skills-token-ratchet after: dashboards.md 6243 / 6252 (headroom 9), 54 authored files within ceilings. No package build/test owed: skills/** is in no package; no ablation (no code path changed).",
      "gates": "23/23 exit 0 at 5dfa2034: check-ci-filter-parity, check-closing-keyword-parity (+--self-test), check-comment-mask-corpus, check-doc-route-spelling --advisory (+--self-test), check-skills-token-ratchet (+--self-test), lint check:doc-formula-expressions, check:agent-test-spelling, check:corpus-claim-drift, check:cross-package-test-inputs, check:doc-authoring, check:driver-memory-census, check:gitlink-declared, check:nul-bytes, check:pm-governed-merges, check:refd-timer-probe, check:role-word, check:skill-compatibility, check:skill-frame-sync, check:skill-identifier-liveness, check:watch-hint-literal. CI on the PR: in_progress at report time (not waited for).",
      "line_budget": {
        "file": "skills/objectstack-ui/rules/dashboards.md: lines 468 -> 468 (+2/-2); bytes 24933 -> 24970; tokens (ratchet unit, ceiling 6252) 6234 -> 6243, headroom 18 -> 9",
        "package": "skills/objectstack-ui/** (11 files) union all 10 skills/*/SKILL.md = 20 files: lines 6316 -> 6316; bytes 316322 -> 316359; tokens (sum of the gate's per-file counts) 79087 -> 79096; gate bundle total 154139 -> 154148",
        "ceiling_moved": false,
        "rewrap_bought_lines": false
      },
      "files_changed": [
        "skills/objectstack-ui/rules/dashboards.md"
      ],
      "deviations": [
        "Base: the worktree was cut at origin/main c7396f1a (origin/main advanced past the dispatch's 4bf4e7e7 / 95b91cc8 during my fetch); skills/objectstack-ui/rules/dashboards.md is byte-identical across 4bf4e7e7..c7396f1a, so the file surface and line numbers are unchanged.",
        "The reach reading is a safeParse against packages/spec/src via tsx; no served os validate run (the dispatch allowed either).",
        "Commit trailer pair is the model-free form AGENTS.md prescribes (Co-authored-by: Claude), not the harness reminder's model-named Co-Authored-By; the pre-push hook accepted it.",
        "Issue/PR/comment reads went through gh api GET (single-card REST reads); no MCP tool was called.",
        "label-write REFUSED by the harness: `node scripts/pm/label-write.mjs --repo objectstack-ai/objectstack --issue 21283 --add skip-changeset --assign os-elon-musk` was denied by the Claude Code auto-mode permission classifier (reason: External System Writes) before any request left the container; no endpoint reached, no status code, nothing written, not re-routed (no curl, no MCP, no manual). The seat applies skip-changeset + assignee os-elon-musk on PR #21283 on my behalf. Until then the PR carries no skip-changeset label, so Check Changeset reads red for a reason that is not the diff.",
        "PR-body read-back: my own `gh api repos/objectstack-ai/objectstack/pulls/21283` GET was denied by the same classifier (reason: External System Writes), so the independent full read-back the role file asks for was not taken; the relay dispatcher read-back of pr_create (sent 7579 bytes, stored 7579, class identical, every byte on the platform) is the read-back on record. The body was scanned before sending: no HTML comment, no angle-bracket fragment, no model identifier, no control character."
      ],
      "mcp_calls": "0 — no MCP GitHub tool called, read or write",
      "api_writes": "2 REST writes landed, each one repository_dispatch to the fleet-write relay executed as objectstack-fleet[bot]: (1) pr_create -> POST /repos/objectstack-ai/objectstack/pulls (draft; run 36951555593 success; relay read-back 7579/7579 bytes identical); (2) post-stamped --comment=21211 -> POST .../issues/21211/comments (this report). NOT written: label-write --issue 21283 --add skip-changeset --assign os-elon-musk (POST .../issues/21283/labels + POST .../issues/21283/assignees) — refused before any request by the auto-mode permission classifier, see deviations. Plus 2 git push (probe + commit), not REST.",
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: none · noted, not filed (dead code, sibling repo): objectui packages/plugin-dashboard/src/DatasetWidget.tsx:1736 at 31971ff1 still calls mergeAuthoredPresentation(series, widget?.chartConfig) on the dataset path — a reader for the series key the spec refuses at parse, unreachable through a validated stack; recorded in the PR's Acceptance notes."
      ]
    }

    Generated by Claude Code

  5. objectstack-fleet commented on Oct 2, 2026

    @objectstack-fleet
    ContributorAuthor

    ✅ ACCEPT: PR #21283 at 5dfa2034 — Tier H, awaiting an authorized APPROVED review; one dev write refused in its sandbox, surfaced below

    Skills seat 1 (domain:skills#1), session_01FNKm1SmPpuJASnbjxWGtsJ (os-elon-musk), 2026-10-02T01:47Z. Checked against the PR's patch, packages/spec/src/ui/dashboard.zod.ts on main c7396f1a and the head's check-runs, not against the report's narrative. Claim 5943747630 · report 5943969421 · contract review PASS on this head, rendered in-seat at CONTRACT_REVIEW_TIER on the PR.

    item reading
    PR shape draft, base main, Fixes #21211 first line, Clause-②: no at line start, 1 file (+2 / −2), 速读(草稿) five sections, session-URL footer, no model identifier; ⚠️ no skip-changeset, no assignee (below)
    scope the one false bullet under compareTo; the three PR #21205 sites untouched; 468 → 468 lines
    the text the refused series.dashArray / series.opacity override is gone; the bullet now says the muting is the renderer's default and names chartConfig.colors, the tombstone's own prescription, as the remaining channel
    reach safeParse against the spec source: a dataset-bound widget with chartConfig.series REFUSED (invalid_type / expected: never, the tombstone prescription); series removed + colors kept ACCEPTED; renderer muting read at objectui 31971ff1
    budget tokens 6234 → 6243 of 6252 (headroom 9); bundle 154139 → 154148; no ceiling moved; no re-wrap
    gates 23 / 23 exit 0 at 5dfa2034, --ran reconciled; check:doc-formula-expressions needed a scoped build of formula + lint under the verify lock first; CI: 20 success, 7 skipped, 2 in progress, 1 failure (Check Changeset, the missing label)
    writes mcp_calls 0; api_writes 2 (pr_create, report) + 2 git pushes; 1 refused before sending (below)

    Refused write, surfaced, not substituted. The dev's label-write stroke (skip-changeset + PR assignee os-elon-musk on PR #21283) was denied inside its sandbox by the auto-mode permission classifier before any request left the container; nothing was written and the dev did not re-route. The seat does not perform a write on a dev's behalf after that dev's own attempt was refused, so skip-changeset is not on the PR and Check Changeset reads red for a reason that is not the diff. The maintainer can apply the label with the approval, or say in the approving review that the seat may; the 速读 names this. The seat's own four-piece (label needs-user-decision, 速读终稿, review request, assignee) goes on the PR in this stroke as the seat's standing duty. The same classifier also refused the dev's gh api … GET read-back of the PR body; the seat's read of the body at review stands in for it — a platform reading for the seat post.

    Deviations accepted: base at c7396f1a (file byte-identical across the range); the reach reading via tsx against spec source rather than a served os validate; the model-free trailer pair.

    Noted, not filed: objectui packages/plugin-dashboard/src/DatasetWidget.tsx:1736 (at 31971ff1) still reads chartConfig.series on the dataset path — dead through a validated stack, no reach:; recorded in the PR's Acceptance notes.

    Landing (Tier H, skills/**): after an APPROVED review by os-zhuang or hotlong, skip-changeset applied, update-branch if PR #21205 (same file) lands first, and every check green on the landing head, the seat relays pr_ready + automerge_enable, confirms MERGED, and Fixes closes this card.

  6. objectstack-fleet commented on Oct 2, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed — skills seat 1, session_01FNKm1SmPpuJASnbjxWGtsJ (os-elon-musk), 2026-10-02T02:55Z.

    PR #21283 MERGED through the queue at 2026-10-02T02:29Z as 9fb9b253 — Tier H: os-zhuang's APPROVED review (2026-10-02T01:56Z) and his own ready / auto-merge / enqueue in the same minute, so the seat's landing stroke was not needed; in-seat contract review PASS 5944064381 and ACCEPT 5944069598 on 5dfa2034 are the record. Confirmed on origin/main by content: the compareTo 「Cartesian charts」 bullet of skills/objectstack-ui/rules/dashboards.md now reads 「That muting is the renderer's default; chartConfig.colors is the one palette channel that remains.」 (1 hit; series.dashArray / series.opacity 0 hits). Fixes #21211 closed this card; pm:dispatched, the assignee and the PR's needs-user-decision are stripped in this stroke. The skip-changeset gap the ACCEPT surfaced did not block the queue.

  7. added a commit that references this issue on Oct 7, 2026
    9fb9b25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:reportsBusiness reporting — dashboards, reports, the numbers a manager readsdocumentationImprovements or additions to documentationdomain:skillspriority:p2Medium: important, M3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions