Skip to content

skills/objectstack-ui: the kind: 'html' page example writes <object-metric aggregate="count">, a string the html tier only warns on and the tile cannot draw #21627

Description

@objectstack-fleet

Filing gate: ① a defect, class (c), an authoring trap in a published skill. reach: a named producer, the published skill skills/objectstack-ui (it ships to customer projects via npx skills add), plus the public door the dev measured: the html-tier compile that objectstack build wires. Filed by the domain:spec seat 1 (session_01T9u38rswFp5Rw8DswRUReJ, seat post #6017) from the #21464 stage-4 dev report (5972873924, out_of_scope_findings[0]), re-read by the seat on origin/main. ⛔ Filed bare: grading and routing are triage's. ⛔ Not a claim.

Reader who acts: triage grades and routes it. The fix is one line in skills/**, a Tier H surface, so it lands by the maintainer's hand or an authorized approval.

The trap

  • skills/objectstack-ui/rules/pages.md:160 (on origin/main), in the kind: 'html' example, reads verbatim: <object-metric objectName="ticket" aggregate="count" label="Open tickets" />.
  • The tile reads aggregate as an object (aggregate.field, aggregate.function). At the objectui pin 89cad75d557, ObjectMetricWidget.tsx computeOne (about :403–:443) asks the server for a measure built from those two members. A bare string gives both as undefined.
  • Measured by the dev through the html tier's own compile with the committed component manifest (the path objectstack build wires at packages/cli/src/commands/compile.ts:543): one warning (type-mismatch, "prop "aggregate" expected an object"). The compiled node still carries aggregate: "count". The same tag with aggregate={{"function":"count"}} compiles clean.
  • So the published skill teaches an AI author a value that builds green (a warning only), renders no number, and that the skill presents as the canonical example.
  • The sibling surfaces are spelled correctly: skills/objectstack-ui/rules/dashboards.md:125 (aggregate={{ field: 'total', function: 'sum', groupBy: 'status' }}) and the analytics-inline-vs-dataset eval (aggregate={{ function: 'count', groupBy: 'status' }}).

Landing site

Dedupe

MCP search_issues, repo-scoped, open and closed together:

Dedupe words: object-metric aggregate count skill pages.md · html tier type-mismatch warning aggregate · kind html object-metric example

Activity

  1. objectstack-fleet commented on Oct 3, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade — documentation · priority:p2 · domain:skills · area:reports · pm:queue. One line in the published skill: the html example's aggregate takes the object form

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

    Measured now: skills/objectstack-ui/rules/pages.md:160 on origin/main still reads aggregate="count". The sibling surfaces (dashboards.md:125 and the eval) use the object form.

    Why p2. It is the canonical example of a published skill, and the reader is an AI author who copies it. It builds green with only a warning, then renders no number. That is a silent failure taught by the skill itself, the grade #21583 took for the same class.

    Routing. skills/**, so domain:skills (Tier H, governed). It is a one-line change that lands with an authorized approval.

    Direction: the card's own landing, confirmed.

    • aggregate={{"function":"count"}}, in the html tier's own expression spelling, as the example's other attributes use.
    • ⛔ No other line in pages.md changes.
    • ⛔ The html tier's type-mismatch severity is not in scope, as the card says.

    Generated by Claude Code

  2. objectstack-fleet commented on Oct 4, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1
    Session: session_01CB6W87z22K2yjUCDyVrJRk
    Account: os-project-manager (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-21627-pages-html-metric-aggregate
    Worktree: objectstack-issue-21627
    Domain: domain:skills
    Seat: domain:skills#1
    File surface: skills/objectstack-ui/rules/pages.md — the one object-metric line of the kind: 'html' example (about :160 on origin/main); ⛔ no other line, no other file (stop on breach; explain in the report)
    Container & model: M, mode:subagent, model: CONTRACT_REVIEW_TIER — MANDATORY per dispatch-gates --tier --repo objectstack-ai/objectstack skills/objectstack-ui/rules/pages.md, which prints "skills/objectstack-ui/rules/pages.md ⇢ 'skills/**' — clause ①"; Tier H landing (an authorized APPROVED review, then this seat lands)
    Clause-②: no
    Thread-read: 5973387223
    Serial constraints cleared: none — no open objectstack PR touches rules/pages.md (this seat's own PRs #21650 / #21651 / #21652 / #21656 / #21657 read at 2026-10-04T01:23Z hold other files); no in-flight claim on it; same-day churn none (last touch 63d1a7c). Token ratchet: 5676 / 5692 at 0c50b5d (headroom 16; the object form adds about 15 bytes). NORTH-STAR rule 3: the lane's P1 cards are all dispatched. Readings taken at 2026-10-04T01:27Z.

  3. objectstack-fleet commented on Oct 4, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 21627,
      "status": "done",
      "branch": "claude/issue-21627-pages-html-metric-aggregate",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/21667",
      "session": "session_01CB6W87z22K2yjUCDyVrJRk",
      "premise_still_valid": true,
      "summary": "One attribute value changed on skills/objectstack-ui/rules/pages.md:160: the kind 'html' example's object-metric line now reads aggregate={{\"function\":\"count\"}} instead of aggregate=\"count\", the object form the tile reads and the html tier's own expression spelling the example's sibling attributes use. Premise verified on origin/main eea82af67 before the edit: :160 read the string form; :59 and :146 untouched; dashboards.md:125 and the analytics-inline-vs-dataset eval already spell the object form. The card cites the objectui pin 89cad75d557 but .objectui-sha at eea82af67 is ab187972; the computeOne reading holds there (ObjectMetricWidget.tsx :452-:497 sends field/function from aggregate to ds.aggregate and reads a count back through r.count, so count needs function and no field). Positive control through the html tier's own compile (sdui-parser compile with the committed sdui.manifest.json, whose object-metric aggregate input is type object): before, ok=true with one warning type-mismatch (object-metric prop aggregate expected an object) and aggregate stored as the string count; after, ok=true with zero diagnostics and aggregate stored as the object. Draft PR opened, left draft (Tier H, skills/**); skip-changeset and PR assignee requested through label-write.mjs: landed (relay run 37169379927); read-back labels documentation, size/xs, skip-changeset and assignee os-project-manager match the target.",
      "tests": "All at d5e95044e (the one commit on the branch; worktree clean, remote head = d5e95044e). Derived list: node scripts/pm/dispatch-gates.mjs --commands (no paths; change set vs merge base eea82af67) = 23 commands; --ran reconciliation with exit codes recorded: 'Run reconciliation — 23 derived, 23 run, 0 NOT-MEASURED, 0 UNRUN' and '0 NOT-MEASURED (a DERIVED zero — all 23 recorded an exit code and none of them is 3)'. Every exit captured by redirect-then-$? before any pipe. exit 0 each: check-ci-filter-parity ('OK: all 193 declared cross-package glob(s) … covered'); check-closing-keyword-parity and its --self-test ('40 assertions, 5 mutations … each driven to red'); check-comment-mask-corpus ('8127 files, 0 disagree, 0 unparseable'); check-doc-route-spelling --advisory ('population clean') and --self-test; check-skills-token-ratchet ('54 authored bundle file(s) within their ceilings'; pages.md 5679 tokens, ceiling 5692, headroom 13; before at eea82af67: 5676, headroom 16) and --self-test ('65 cases pass'); check:doc-formula-expressions (after building the @objectstack/lint closure under os-verify-lock.sh, 'VERDICT command-exit 0 · held the lock 126s'); check:agent-test-spelling; check:corpus-claim-drift; check:cross-package-test-inputs; check:doc-authoring ('53 published skill files clean'); check:driver-memory-census; check:gitlink-declared; check:nul-bytes ('scanned 10035 text file(s) … no raw ASCII control bytes'); check:pm-governed-merges; check:refd-timer-probe; check:role-word; check:skill-compatibility ('10 SKILL.md file(s) reconciled'); check:skill-frame-sync; check:skill-identifier-liveness ('457 citation(s) over 53 published file(s)'); check:watch-hint-literal. Dispatch-named leads outside the derived set: check:skill-docs exit 0 ('Skill docs in sync'); check:skill-examples first run exit 3 PREREQUISITE NOT MET (no client-react dist; measured nothing), then after building the @objectstack/client-react closure under the lock ('VERDICT command-exit 0 · held the lock 210s') exit 0 ('260 prose examples type-check across 3 surface(s)'); the edited block carries no os:check marker (markers at pages.md:64 and :211), so that gate reads no byte of this diff. Positive control (scratchpad script positive-control.mjs, importing packages/sdui-parser/dist/index.mjs after the build, manifest = repo-root sdui.manifest.json, base passed as eea82af67 not a moving ref): before 'ok=true diagnostics=1 — [warning] type-mismatch: object-metric prop \"aggregate\" expected an object — compiled object-metric aggregate: \"count\"'; after 'ok=true diagnostics=0 — compiled object-metric aggregate: {\"function\":\"count\"}'. Line readings: pages.md 453 → 453 lines; sum of all 10 skills/**/SKILL.md 4397 → 4397; bytes 22701 → 22716. No ablation: a docs-only change with no guard to delete; the compile control is the measurement. NOT MEASURED locally, CI's own: Test Core shards, the four type-check lanes, 11 whole-tree families, 55 artifact-roster families, 15 changeset-derived families (no changeset: no published package's files[] lists skills/, measured over every tracked package.json with spec's files[] as the positive control). Not run: pnpm lint (repo-wide, CI's).",
      "mcp_calls": "0 — no MCP tool was called; reads were gh api GET (issue, comments) and git; writes were scripts/pm/ tools over the fleet-write relay",
      "api_writes": "3 — three fleet-write relay dispatches (each one POST /repos/objectstack-ai/objectstack/dispatches, executed by the relay as objectstack-fleet[bot]): ① pr_create → POST /repos/objectstack-ai/objectstack/pulls (PR #21667, run 37169332000, read-back identical 7837/7837 bytes); ② label-write → POST /repos/objectstack-ai/objectstack/issues/21667/labels (skip-changeset) and POST /repos/objectstack-ai/objectstack/issues/21667/assignees (os-project-manager) (run 37169379927, read-back matches); ③ comment → POST /repos/objectstack-ai/objectstack/issues/21627/comments (this os-dev-report, via post-stamped.mjs). git push ×2 (the empty-branch probe, then d5e95044e) are git, not REST writes. No PATCH, no PR-body edit, no MCP, no bare curl/gh write.",
      "open_questions": [],
      "out_of_scope_findings": [
        "class: c (candidate; the card and the triage ruling both scope it out of THIS card, so it is reported for the seat, not fixed here) · reach: public door `os build` html-tier compile, measured in the positive control: a string handed to object-metric's object-typed `aggregate` input compiles with exit 0 and one `type-mismatch` warning while the compiled node still carries aggregate: \"count\" (packages/sdui-parser/src/validate.ts checkType: severity is 'warning' unless an enum arm is present); the tile then draws no number · producer: any kind 'html' page author (stored page source) · dedupe words: sdui-parser type-mismatch warning severity object input html tier object-metric aggregate",
        "carrier: none · noted, not filed · the card cites the objectui pin 89cad75d557; .objectui-sha at eea82af67 is ab187972 and the computeOne reading holds at that pin (:452-:497) — a stale citation in card text, not a repo defect"
      ],
      "gates": [
        { "cmd": "node scripts/check-ci-filter-parity.mjs", "exit": 0 },
        { "cmd": "node scripts/check-closing-keyword-parity.mjs", "exit": 0 },
        { "cmd": "node scripts/check-closing-keyword-parity.mjs --self-test", "exit": 0 },
        { "cmd": "node scripts/check-comment-mask-corpus.mjs", "exit": 0 },
        { "cmd": "node scripts/check-doc-route-spelling.mjs --advisory", "exit": 0 },
        { "cmd": "node scripts/check-doc-route-spelling.mjs --self-test", "exit": 0 },
        { "cmd": "node scripts/check-skills-token-ratchet.mjs", "exit": 0, "reading": "pages.md 5679 / 5692 (headroom 13)" },
        { "cmd": "node scripts/check-skills-token-ratchet.mjs --self-test", "exit": 0 },
        { "cmd": "pnpm --filter @objectstack/lint run check:doc-formula-expressions", "exit": 0 },
        { "cmd": "pnpm check:agent-test-spelling", "exit": 0 },
        { "cmd": "pnpm check:corpus-claim-drift", "exit": 0 },
        { "cmd": "pnpm check:cross-package-test-inputs", "exit": 0 },
        { "cmd": "pnpm check:doc-authoring", "exit": 0 },
        { "cmd": "pnpm check:driver-memory-census", "exit": 0 },
        { "cmd": "pnpm check:gitlink-declared", "exit": 0 },
        { "cmd": "pnpm check:nul-bytes", "exit": 0 },
        { "cmd": "pnpm check:pm-governed-merges", "exit": 0 },
        { "cmd": "pnpm check:refd-timer-probe", "exit": 0 },
        { "cmd": "pnpm check:role-word", "exit": 0 },
        { "cmd": "pnpm check:skill-compatibility", "exit": 0 },
        { "cmd": "pnpm check:skill-frame-sync", "exit": 0 },
        { "cmd": "pnpm check:skill-identifier-liveness", "exit": 0 },
        { "cmd": "pnpm check:watch-hint-literal", "exit": 0 },
        { "cmd": "pnpm --filter @objectstack/spec run check:skill-docs", "exit": 0, "note": "dispatch lead, outside the derived set" },
        { "cmd": "pnpm --filter @objectstack/spec run check:skill-examples", "exit": 0, "note": "dispatch lead, outside the derived set; first run exit 3 PREREQUISITE NOT MET until the client-react closure was built" },
        { "cmd": "node scripts/pm/dispatch-gates.mjs --ran ran-exit.txt", "exit": 0, "reading": "23 derived, 23 run, 0 NOT-MEASURED (derived zero), 0 UNRUN" },
        { "cmd": "ci", "exit": null, "reading": "in_progress — not waited on, per contract" }
      ],
      "line_budget": {
        "file": "skills/objectstack-ui/rules/pages.md",
        "lines_before": 453, "lines_after": 453, "net_lines": 0,
        "bytes_before": 22701, "bytes_after": 22716,
        "tokens_before": 5676, "tokens_after": 5679, "ceiling": 5692, "headroom_after": 13, "ceiling_moved": false,
        "package_skill_md_lines_before": 4397, "package_skill_md_lines_after": 4397, "package_skill_md_files": 10
      },
      "deviations": [
        "check:skill-examples: the dispatch lead said build @objectstack/spec first; the gate also refused without @objectstack/client-react and @objectstack/client dist, so the whole client-react closure (36 workspace packages, 210s under os-verify-lock.sh, slot issue-21627) was built in the worktree — heavier than the lead, declared here; within the lock budget, no retry loop.",
        "Gate runner housekeeping: the scratchpad runner's first invocation died on a bash typo after running one command per group; the ledger was reset and all three groups re-run in full, so every exit code reported comes from the second, complete run.",
        "Commit trailer: the commit carries the model-free pair AGENTS.md prescribes (Claude-Session URL + Co-authored-by: Claude); the harness reminder's model-named Co-Authored-By form yields to the repo rule per the dispatch contract. Reported, not a deviation."
      ],
      "files_changed": ["skills/objectstack-ui/rules/pages.md"]
    }
  4. objectstack-fleet commented on Oct 4, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT — PR #21667 (head d5e95044) · skills seat 1, session_01CB6W87z22K2yjUCDyVrJRk · 2026-10-04T02:05Z

    Reviewed against GitHub, not the report (references/review-checklist.md); a governed skills/** PR (Tier H), contract review record PASS at 5975630211 on the PR (served tier = CONTRACT_REVIEW_TIER, in seat):

    • PR form: draft, base main, first line Fixes #21627, Clause-②: no at line start; ## 维护者速读(草稿) present; one session-URL footer; labels documentation, size/xs, skip-changeset; assignee os-project-manager. Files: skills/objectstack-ui/rules/pages.md +1/−1 (:160) — the claimed surface, nothing else.
    • Ruling, each line read by this seat off the diff: aggregate={{"function":"count"}} in the html tier's own expression spelling, as the example's sibling attributes already use — yes; no other line of pages.md changes — the diff is that one line, 453 → 453 lines; the html tier's type-mismatch severity untouched — no other file in the diff.
    • Mechanism, verified by this seat at the live pin: .objectui-sha on origin/main is ab187972; packages/plugin-dashboard/src/ObjectMetricWidget.tsx computeOne (:452–:497) sends aggregate.field / aggregate.function to ds.aggregate and sums r.count for a count; the committed sdui.manifest.json declares object-metric's aggregate as type: "object"; rules/dashboards.md:125 and evals/analytics-inline-vs-dataset.json:49 already spell the object form. The card's cited pin 89cad75d557 is not served by objectui's remote; the reading holds at the live pin.
    • Gates: 23 derived families, --ran reconciled 23/23 exit 0 at the head; the two dispatch-named leads (check:skill-docs, check:skill-examples after the client-react closure build under the lock) exit 0; the edited block carries no os:check marker, so the compile positive control (1 type-mismatch warning → 0) is the measurement, the dev's. Ratchet, this seat's own reading: 5676 → 5679 tokens (ceiling 5692, headroom 13), 22701 → 22716 bytes, no SKILL.md touched. No changeset owed (skills/** outside every files[]). Report comment 5975567173 present and parses; mcp_calls 0; api_writes 3 as listed; deviations read, none a route change.
    • Out-of-scope findings: [0] class (c), the html tier's type-mismatch staying a warning for a string literal handed to an object-typed input, measured at the os build compile — filed #21671 (bare finding, triage grades; declared-and-not-enforced, the enforce-or-remove channel). [1] the stale objectui pin in the card text — Acceptance notes (card text, not a repo defect; no card).
    • CI at this write: 19 success, 11 expected skips, 3 in progress (Test Core 1/6, Lint & Repo Gates, Type Check · workspace).

    Landing (Tier H): the PR stays draft with needs-user-decision on it and the final 维护者速读 as the next comment there; review requested from os-zhuang and hotlong. On an authorized APPROVED review this seat runs the pre-landing checks, strips the label, flips ready and arms auto-merge; Fixes closes this card on merge, then the seat strips pm:dispatched + assignee and posts the landing note.

  5. objectstack-fleet commented on Oct 4, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed — skills seat 1, session_01CB6W87z22K2yjUCDyVrJRk · 2026-10-04T03:18Z

    PR #21667 MERGED through the queue at 2026-10-04T03:16Z as 8ad9694f (one parent: squash), approved, readied, auto-merged and enqueued by os-zhuang himself (2026-10-04T02:40Z to 2026-10-04T02:42Z) on the unchanged head d5e95044, so the seat's landing stroke was the label strip only; in-seat contract review PASS 5975630211 and ACCEPT 5975633776 on that head are the record. Confirmed on origin/main by content: skills/objectstack-ui/rules/pages.md:160 carries aggregate={{"function":"count"}} (1 hit) and the string form aggregate="count" is gone (0 hits). Fixes #21627 closed this card completed; pm:dispatched and the assignee are stripped in this stroke (the PR's needs-user-decision was stripped at 2026-10-04T02:42Z). The html-tier severity question this card scoped out is filed as #21671 and stays with triage. The lane's open set matches expectation (no other card closed by a keyword).

  6. added a commit that references this issue on Oct 7, 2026
    8ad9694
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