skills(ui): optimization flight — date macros/relationships pointed at their anchors, searchableFields and timeSegments cut, dashboards consolidated, retired widget keys removed (net −2,585 tokens) - #14338

Merged
os-zhuang merged 5 commits into
mainfrom
claude/issue-14298-skills-ui-optimization
Sep 2, 2026
Merged

Conversation

@os-litant

@os-litantos-litant commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Part of #14298

Governed surface (skills/**) ⇒ this PR stays draft; needs:contract-review is on both carriers because falsehoods 1–2 are contract-semantics corrections. Head sha for every gate figure below: 684415c3.

Review round 1 — one FAIL, fixed

In-seat contract review flagged the UI-D-08 retitle ### Cube Rules (enforced) as asserting enforcement that does not exist. Correct, and the evidence is stronger than the review cited — re-verified at source:

  • granularities: z.array(TimeUpdateInterval).optional() (packages/spec/src/data/analytics.zod.ts:147), and that file contains zero.refine( / superRefine occurrences, so nothing requires it on a time dimension.
  • Cube sql: z.string().describe('Base SQL statement or Table Name') (:216) — the describe string itself admits raw SQL; nothing rejects it at parse time, and no gate script under scripts/ or packages/*/scripts/ references cube.sql.

There is no gate or schema refinement to cite, so the word is dropped, not defended: the heading is now ### Cube Rules. The two body items are unchanged — they are prescriptions with a stated mechanism (cube.sql.trim() read as the object name), not claims of enforcement. Shipping an unbacked "(enforced)" would have been the same defect class this flight exists to remove.

Open questions ruled by the seat: Q1 → C (UI-E-04 deprecated objectName/viewType, filed by the seat as its own card — nothing done here); Q2 → A (the two CJK trigger phrases stay).

Per-file token delta (ratchet convention, ceil(utf8 bytes / 4))

filebeforeafterdeltaceiling
skills/objectstack-ui/SKILL.md25,44122,856−2,58525,445 (headroom 4 → 2,589)
package total36,54233,957−2,585
whole shipped bundle187,854185,269−2,585

Generated package members untouched and unchanged: contracts/react-blocks.contract.json 5,352 · references/react-blocks.md 3,153 · references/_index.md 1,205. evals/** untouched (1,102 + 289). The ceiling is left at 25,445: the ratchet header says a ceiling "may be LOWERED by any PR that shrinks its file … always legitimate and encouraged", but the card's flight constraint forbids touching the ratchet script, so the 2,589 tokens of new headroom are deliberately NOT claimed here — a follow-up may lower the row to the measurement.

Against the card's target. The card targets ≈ −9,170, of which −5,352 is UI-B-04's duplicated generated JSON — explicitly DEFERRED to #14296 item 3 and not mine. The in-file target was −4,199 prose against +385 of additions; landed −2,585. The gap is itemised below rather than smoothed over: the three funded additions cost +838 against the estimated +385 (the filterBindings and widget-options constructs are each roughly double their estimate), and UI-D-01 returned −387 against an estimated −900. Every number below is a measured byte delta.

Per-item: 落点 | before | after

Deletions and merges

id落点beforeafter
UI-C-01## Date Macros — Filter Placeholders (whole section + ## Context Tokens)1,288 tok265 tok (−1,023)
UI-D-02### Shift segmentation — timeSegments581 tok0 (−581)
UI-C-04master-detail inlineEdit ladder + line-item grid behaviours643 tok193 tok (−450)
UI-D-01### Toolbar Search (searchableFields)1,381 tok994 tok (−387)
UI-D-05the options.drillDown renderer note235 tok0 (−235)
UI-C-02action ctx org-isolation + positions narration371 tok154 tok (−217)
UI-B-06## When to Use This Skill136 tok0 (−136)
UI-D-06the "Removed in v17" compareTo blockquote106 tok0 (−106)
UI-D-08### Cube Best Practices (5 items)159 tok74 tok (−85), retitled ### Cube Rules — see Review round 1
UI-D-04the metadata fence rationale145 tok75 tok (−70)
UI-D-03"Why this model" (build-independent / collision-free / responsive-correct)79 tok22 tok (−57)
UI-C-03the visibleWhen/readonlyWhen/requiredWhen table149 tok103 tok (−46)
UI-D-07the removed-inline-query history86 tok68 tok (−18)
UI-B-05the 4th Tailwind className restatement67 tok52 tok (−15)
UI-B-03the dateGranularity bucket table under ### Drilldown273 tok273 tok (0 — moved under its own heading; reorder is free)

The three funded additions

idwhat landedcostnamed payersactual
UI-F-01 + UI-F-03### Dashboard filters — globalFilters + per-widget filterBindings: the broadcast rule, name (defaults to field; name it for the vocabulary, not the column), scope: 'widget' + targetWidgets, re-target, false opt-out, the absent-default incl. dateRange.field ?? 'created_at', plus a 2-widget example+371UI-D-05 (−235) + UI-D-06 (−106)−341, so +30 over
UI-F-02### Widget options — the five declared keys (dateGranularity / sortBy / sortOrder / limit / stageOrder), with the top-N spelling that had no documented form+357UI-D-08 (−85) + UI-D-03 (−57)−142, so +215 over
UI-E-01os:check marks on the four highest-traffic examples (+ UI-E-03's inlined action)+110UI-E-02 (−18)+92 over

The three additions cost +838 against −501 of named payers. They are nonetheless fully paid in the same file: the flight's total deletions are −3,423, so SKILL.md ends 2,585 tokens smaller and the ratchet is green with 2,589 tokens of headroom. Flagging the per-item overrun rather than re-cutting the payer list to fit, because the card's funding lines are its ruling and I would rather show them broken than silently re-derive them.

Falsehoods

#落点beforeafter
1canonical dashboard widgetactionType: 'url', actionUrl: '/objects/opportunity?filter=open'line deleted. dashboard.zod.ts:382-384 retires all three via retiredKey(...) = z.never(); prescription :309-320 "a dashboard widget has NO action button, and never had one".
2### Server-side date bucketing"Date bucketing lives on the dataset dimension, not the widget.""The dataset dimension carries the default; a widget's options.dateGranularity overrides it for that widget only." (dashboard.zod.ts:217-225)
3frontmatter"the React renderer implementation (lives in packages/client-react, not metadata)"clause deleted. packages/client-react is "React hooks for ObjectStack Client SDK"; the renderer is @object-ui/react-runtime, in objectui.
4 (new)the Tokens-in-filters blockquote on the canonical dashboard{current_user.id}{current_user_id}. current_user.id is the RLS expression root, not a filter token — spec/src/data/context-tokens.zod.ts:44,49 names this exact near-miss and :85 lists the real token. Found inside a span this flight was already rewriting, same defect class as 1–2, mechanically fixed against the spec; taken under the bounded-in-place rule.

Also deleted, never ported (card ruling): this package's claim that "unknown placeholders silently pass through as literal strings". It is false and the file contradicted itself 37 lines earlier. packages/core/src/utils/filter-tokens.ts:378 throws UnknownFilterTokenError, and the module header at :44 is titled "An unknown token throws".

Deliberate deviations from the routed plan

  1. UI-C-01 keeps its ## heading. The ruling says delete :1659-1768. Two in-file links (:1074, :1507) target #date-macros--filter-placeholders; deleting the heading breaks both, so the heading survives carrying the pointer. Also kept: two rules objectstack-query does not own — a filter token is presentation scope, not security; and AppContextSelector ids resolve in navigation recordId/params only, never in a filter. Both were their last mention in the package.
  2. UI-C-02 keeps ctx.session.positions in compact form. The routed anchor does not carry it (see follow-ups). Kept with the "not an authorization input" guard; the org-isolation half is deleted and pointed.
  3. UI-G-03 translates 1 of 3 CJK lines, not 3label: '打印总表(A3)''Print Summary Sheet (A3)'. The two at :755-756 are non-English user phrasings the router matches on; translating a phrase whose only job is to match untranslated input destroys it. Seat ruled A: they stay.
  4. The ratchet ceiling is not lowered — see the token table.

Not implemented (and why)

premise_false

None. git diff --stat a59f78d origin/main -- skills/objectstack-ui is empty, so every audit span was byte-identical at the branch point. Two PM mechanical assumptions were refined rather than confirmed — below.

PM mechanical assumptions — measured

  1. Confirmed.skills/objectstack-ui/** byte-identical between a59f78d and origin/main. (origin/main had already moved past the dispatch's d63c8a25 to 909a4417, which does not touch skills/; the branch is cut from 909a4417.)
  2. Refined — the predicted file is the wrong one.check:skill-docs does run in CI and the frontmatter edit does force a regeneration, but skills/README.md came back green on its own (✓ skills/README.md) — it does not embed the description. The out-of-date artifact was content/docs/ai/skills-reference.mdx. Regenerated with the one generator the card names; the diff is 2 lines, both the frontmatter's own text.
  3. Confirmed for tsc; the parse half not measured. Reverse-verified against a committed tree: re-injecting actionType/actionUrl on the widget turns check:skill-examplesred with two error TS2322: Type 'string' is not assignable to type 'undefined' — one per retired key, z.never() surfacing as undefined in the input type. Mutation proven on disk before measuring (injected-text grep count 1; blob 4a5d1e256b5d8296), restore proven the same way (git diff HEAD empty, blob back to 4a5d1e25, injected count 0) — neither leg read from an editor's exit code. This gate exercises tsc only, so the Zod parse failure is asserted from the schema source, not measured here.
  4. Confirmed, with one restructure. Marked count 259 → 263, "every marked block parsed, so tsc ran the SEMANTIC pass on all of them". Two needed more than a marker: the record-detail page carried UI-E-03's unresolvable relative import (replaced with an inlined 4-line defineAction), and the defineDataset block was a fragment — it now imports defineDataset + type DashboardWidget and binds the trailing widget literal to a typed const.
  5. Not exercised — no finding's premise was false.

follow-up for objectstack-query

rules/filters.md is the anchor and is strong: it already carries the fixed tokens, the parameterised form, both session tokens, both resolvers, the calendar-DAY *_end trap, and — decisively — "Unknown tokens are rejected, not ignored". These TRUE rows from the deleted objectstack-ui text are not in it and were not ported:

  1. Both {token} and ${token} spellings are acceptedspec/src/data/date-macros.zod.ts:200,207 and context-tokens.zod.ts:101. rules/filters.md shows only the bare form.
  2. Two more near-misses: {user_id} (a valid titleFormat field interpolation elsewhere) and {organization_id} (the real column name). Query names {current_user} and {this_quarter_start} only.
  3. A token embedded in a larger string is not substituted ('user-{current_user_id}'). Query states only the converse; filter-tokens.ts:44 states this half directly — "Values that merely CONTAIN braces are left untouched."
  4. isDateMacroToken(tok) from @objectstack/spec/data as the author-time type check.
  5. The build rule's name, filter-token-unknown, and why it exists: an unresolved token reaches SQL as a literal, matches nothing, and the widget renders 0 — indistinguishable from a genuine zero.

follow-up for objectstack-data

references/data-hooks.md carries the org-isolation half completely — UI-C-02's deletion is safely routed there. It does not document ctx.session.positions at all; :368 says only that ctx.session has "No role listsession.roles was retired in 17.0.0". So the ADR-0090 D3 spelling and the "not an authorization input" guard have no anchor to point at, and a compact form was kept here rather than deleted into a gap.

Gates — all 42 families, all at head 684415c3

⚠️Correcting a stale figure this PR body previously carried. It claimed 16 families. That derivation ran at 0f937dcc, when the changeset was SKILL.md alone; the next commit added content/docs/ai/skills-reference.mdx and scripts/skill-identifier-liveness-ledger.json, and I did not re-derive. Re-derived at the current head, node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack names 42 — the 26 extra are the docs family the .mdx pulls in. All 42 have now been run; every one of the 26 that had never been run passes. The earlier "16" was wrong and is retracted here rather than quietly overwritten.

41 of 42 exit 0. Each exit code captured by redirecting before any pipe. The full list, in the order the harvester prints it:

check-ci-filter-parity · check-cross-package-test-inputs · check-doc-frontmatter · check-doc-route-spelling · check-docs-section-name · check-section-landing-index · check-shard-attestation · check-skills-token-ratchet · doc-formula-expressions · doc-security-posture · check:docs · check:empty-state · check:liveness · check:skill-docs · check:skill-examples · check:strictness-ledger · check:variant-docs · check:yaml-examples · agent-test-spelling · bash32-floor · cli-command-ids · corpus-claim-drift · cross-package-test-inputs · doc-anchors · doc-authoring · docs-audit-scope · docs-redirects · docs-single-h1 · entry-guard · merge-driver · parse-guard · pm-governed-merges · pnpm-filter-targets · published-readme-links · react-page-adapter-contract · role-word · skill-compatibility · skill-frame-sync · skill-identifier-liveness · vendor-version-stamps · watch-hint-literal — all exit 0.

Named verdict lines for the two the review asked for:

  • node scripts/check-skills-token-ratchet.mjsexit 0, "skills/objectstack-ui/SKILL.md is 22856 tokens (ceiling 25445; headroom 2589)" · "38 authored bundle file(s) within their ceilings".
  • pnpm --filter @objectstack/spec check:skill-examplesexit 0, "✅ 263 prose examples type-check across 3 surface(s) — every marked block parsed, so tsc ran the SEMANTIC pass on all of them".

The 42nd, node scripts/check-test-completeness.mjs, exits 3 = NOT MEASURED by its own verdict text ("Nothing was measured… It is not a red, and there is nothing here to fix") — it needs a saved turbo run test log. Recorded as NOT MEASURED: not a pass, not a red.

Heavy runs went through scripts/pm/os-verify-lock.sh with OS_VERIFY_LOCK_SLOT=issue-14298. Prerequisite builds re-run at this head, not assumed: @objectstack/spec and the @objectstack/client-react / @objectstack/client dependency closure — without the latter check:skill-examples refuses to run rather than reporting green ("packages/client-react/dist holds no .d.ts declarations… a FALSE GREEN on exactly the change it exists to catch").

Repo-wide pnpm lint (eslint over the whole tree) was NOT run — it is CI's own step, in this derivation's unnarrowable "always runs" tail. A plain omission, not a measured narrowing; I claim none of the three evidence items a narrowing would need.

Two consequences outside SKILL.md

Both generator/tool output, neither hand-written, each the mechanical consequence of a funded edit:

  • content/docs/ai/skills-reference.mdxgen:skill-docs, forced by the frontmatter edit (assumption 2). Not content/docs/releases/.
  • scripts/skill-identifier-liveness-ledger.jsoncheck-skill-identifier-liveness.mjs --update, pruning dayStart and showMidnight. Both existed only to excuse the timeSegments block this flight deleted, and each ledger note independently records the implementation living in objectui plugin-gantt — the same measurement UI-D-02 rests on. --update never adds an exemption.

Changeset

skip-changeset applies and is on the PR. Checked against the repo's own rule: the exemption means "this PR declares no release of its own", and no package publishes skills/, content/docs/ or scripts/. The Check Changeset job reads labels live; the label cannot be applied before the PR exists, so it was applied immediately after creation and read back.


🤖 Generated with Claude Code

https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1

os-litantand others added 4 commits September 2, 2026 01:59
…e/drilldown trims, filterBindings + widget options funded
UI-C-01 delete the date-macro + context-token block; keep the heading (two
in-file anchors resolve to it) and point at objectstack-query
rules/filters.md. Two UI-owned rules stay: presentation-scope-not-
security, and AppContextSelector ids never resolving in a filter.
UI-C-02 drop the org-isolation narration; keep the blessed-name pointer at
objectstack-data's hooks reference. `ctx.session.positions` stays in
compact form -- the anchor does not carry it (see PR follow-up list).
UI-D-08 Cube Best Practices -> the two enforced facts.
UI-D-05 delete the renderer note that ends by telling the reader to ignore it.
UI-D-06 delete the v17 `compareTo` removal narration.
UI-B-03 move the dateGranularity bucket table out of `### Drilldown` and under
its own heading (reorder only).
UI-G-02 falsehood 2: the dataset dimension is the DEFAULT; options.dateGranularity
overrides it per widget (dashboard.zod.ts:217-225).
UI-E-02 falsehood 1: delete the retired `actionType`/`actionUrl` pair from the
canonical dashboard widget (dashboard.zod.ts:382-384, retiredKey =
z.never()).
falsehood 4 (found in span, same defect class): `{current_user.id}` ->
`{current_user_id}`; `current_user.id` is the RLS expression root, not
a filter token (spec/src/data/context-tokens.zod.ts:44,49,85).
UI-F-01/F-03 ADD the globalFilters/filterBindings construct (paid by D-05+D-06).
UI-F-02 ADD the five declared widget `options` keys (paid by D-08+D-03-to-come).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…etired, relationships/conditional-rules pointed at objectstack-data
UI-D-01 keep the two tables and the `userActions: { search: false }` example;
delete the two verbatim `os validate` diagnostics, the empty-array
essay (folded into the row that already existed) and the related-title
prose (reduced to its objectstack-data pointer).
UI-D-02 delete the `timeSegments` block -- self-declared NOT part of
GanttConfigSchema, zero implementation in this repo (every hit is in
objectui plugin-gantt), and 10 of the package's 13 CJK lines.
UI-C-04 the inlineEdit ladder and the modelled grid behaviours point at
objectstack-data rules/relationships.md, which carries them verbatim.
Kept the three UI-authored facts the anchor does NOT carry: the ghost
row, `autofill: false`, and the form's `taxRateField`.
UI-C-03 delete the visibleWhen/readonlyWhen/requiredWhen table; keep the
routing line, the row-by-row inline-grid note and the retired
`conditionalRequired` guard.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…our highest-traffic examples gated
UI-A-01 add `*.page.ts` / `*.report.ts` / `*.dataset.ts` to the trigger list --
`*.page.ts` is the corpus's most-authored kind (29 definitions) and had
no filename trigger at all.
UI-A-02 falsehood 3: drop "the React renderer implementation (lives in
packages/client-react)". That package is React hooks for the client SDK
(package.json description; src/index.tsx exports hooks + provider). The
renderer is @object-ui/react-runtime, in objectui.
UI-A-03 wizards: a stepped form over ONE object is this skill's `formViews`
`type: 'wizard'`; only step-branching flows route to automation.
UI-D-07 keep the requirement, drop the removal history.
UI-D-03 delete the "Why this model" justification.
UI-D-04 reduce the metadata-fence rationale to the two facts the table lacks
(live-not-a-screenshot; data-not-code).
UI-B-06 delete "When to Use This Skill" -- it restated the frontmatter.
UI-B-05 the Tailwind rule now states the rule once and points at ADR-0065.
UI-G-03 translate the CJK example label. The two remaining CJK lines are
non-English USER PHRASINGS the router matches on -- see the PR body.
UI-E-03 inline a minimal defineAction so the record-detail page block stands
alone (the relative import could never resolve in the gate build dir).
UI-E-01 mark four highest-traffic examples `os:check`: structured definePage,
the Dashboard literal, defineDataset, the react source tier.
Gate: pnpm --filter @objectstack/spec check:skill-examples -- 259 -> 263 marked
blocks, "every marked block parsed, so tsc ran the SEMANTIC pass on all of them".
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…nd the timeSegments deletion
Two mechanical consequences, neither hand-written:
- `content/docs/ai/skills-reference.mdx` — `pnpm --filter @objectstack/spec
gen:skill-docs`. The dispatch predicted `skills/README.md` would be the file
the drift gate demands; it is not. README came back green on its own (it does
not embed the description); the out-of-date artifact is the reference page.
Both are outputs of the one generator the card names.
- `scripts/skill-identifier-liveness-ledger.json` — `node
scripts/check-skill-identifier-liveness.mjs --update`, pruning the now-stale
`dayStart` / `showMidnight` exemptions. Both existed only to excuse the
`timeSegments` block this flight deleted, and each ledger note independently
records that the implementation lives in objectui plugin-gantt -- the same
measurement UI-D-02 rests on. `--update` never ADDS an exemption.
Gates: check:skill-docs 0 (both artifacts ✓); check:skill-identifier-liveness 0
("Leg 1: 498 citations over 48 published files ... 3 ledgered exemptions").
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
@github-actionsgithub-actionsBot added size/l documentation Improvements or additions to documentation labels Sep 2, 2026
@os-litantos-litant added skip-changeset PR has no user-facing published change; bypasses the changeset gate needs:contract-review and removed documentation Improvements or additions to documentation labels Sep 2, 2026 — with Claude
…ding
In-seat contract review is right: my UI-D-08 retitle asserted enforcement that
does not exist, which is the same defect class this flight exists to remove.
Re-verified against the source, and the evidence is stronger than the review
cited:
- `granularities: z.array(TimeUpdateInterval).optional()`
(packages/spec/src/data/analytics.zod.ts:147) — optional, and the file
contains ZERO `.refine(` / `superRefine` occurrences, so nothing requires it
on a `time` dimension.
- Cube `sql: z.string().describe('Base SQL statement or Table Name')` (:216).
The describe string itself admits raw SQL; nothing rejects it at parse time,
and no gate script under scripts/ or packages/*/scripts/ references
`cube.sql`.
So there is no gate or schema refinement to cite, and the word is dropped rather
than defended. The two body items are unchanged: they are prescriptions with a
stated mechanism (`cube.sql.trim()` read as the object name), not claims of
enforcement.
Gates at this head: node scripts/check-skills-token-ratchet.mjs exit 0 --
SKILL.md 22856 tokens (ceiling 25445, headroom 2589); pnpm --filter
@objectstack/spec check:skill-examples exit 0 -- "263 prose examples type-check
across 3 surface(s)".
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
@github-actionsgithub-actionsBot added the documentation Improvements or additions to documentation label Sep 2, 2026
@os-litantos-litant changed the title skills(ui): optimization flight — date macros/relationships pointed at their anchors, searchableFields and timeSegments cut, dashboards consolidated, retired widget keys removed (net −2,583 tokens)skills(ui): optimization flight — date macros/relationships pointed at their anchors, searchableFields and timeSegments cut, dashboards consolidated, retired widget keys removed (net −2,585 tokens)Sep 2, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review September 2, 2026 06:18
@os-zhuang
os-zhuang added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit 54a1125Sep 2, 2026
45 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-14298-skills-ui-optimization branch September 2, 2026 06:41
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/lskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@os-litant@os-zhuang
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

skills(ui): optimization flight — date macros/relationships pointed at their anchors, searchableFields and timeSegments cut, dashboards consolidated, retired widget keys removed (net −2,585 tokens) - #14338

Merged
os-zhuang merged 5 commits into
mainfrom
claude/issue-14298-skills-ui-optimization
Sep 2, 2026
Merged

Conversation

@os-litant

@os-litantos-litant commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Part of #14298

Governed surface (skills/**) ⇒ this PR stays draft; needs:contract-review is on both carriers because falsehoods 1–2 are contract-semantics corrections. Head sha for every gate figure below: 684415c3.

Review round 1 — one FAIL, fixed

In-seat contract review flagged the UI-D-08 retitle ### Cube Rules (enforced) as asserting enforcement that does not exist. Correct, and the evidence is stronger than the review cited — re-verified at source:

  • granularities: z.array(TimeUpdateInterval).optional() (packages/spec/src/data/analytics.zod.ts:147), and that file contains zero.refine( / superRefine occurrences, so nothing requires it on a time dimension.
  • Cube sql: z.string().describe('Base SQL statement or Table Name') (:216) — the describe string itself admits raw SQL; nothing rejects it at parse time, and no gate script under scripts/ or packages/*/scripts/ references cube.sql.

There is no gate or schema refinement to cite, so the word is dropped, not defended: the heading is now ### Cube Rules. The two body items are unchanged — they are prescriptions with a stated mechanism (cube.sql.trim() read as the object name), not claims of enforcement. Shipping an unbacked "(enforced)" would have been the same defect class this flight exists to remove.

Open questions ruled by the seat: Q1 → C (UI-E-04 deprecated objectName/viewType, filed by the seat as its own card — nothing done here); Q2 → A (the two CJK trigger phrases stay).

Per-file token delta (ratchet convention, ceil(utf8 bytes / 4))

filebeforeafterdeltaceiling
skills/objectstack-ui/SKILL.md25,44122,856−2,58525,445 (headroom 4 → 2,589)
package total36,54233,957−2,585
whole shipped bundle187,854185,269−2,585

Generated package members untouched and unchanged: contracts/react-blocks.contract.json 5,352 · references/react-blocks.md 3,153 · references/_index.md 1,205. evals/** untouched (1,102 + 289). The ceiling is left at 25,445: the ratchet header says a ceiling "may be LOWERED by any PR that shrinks its file … always legitimate and encouraged", but the card's flight constraint forbids touching the ratchet script, so the 2,589 tokens of new headroom are deliberately NOT claimed here — a follow-up may lower the row to the measurement.

Against the card's target. The card targets ≈ −9,170, of which −5,352 is UI-B-04's duplicated generated JSON — explicitly DEFERRED to #14296 item 3 and not mine. The in-file target was −4,199 prose against +385 of additions; landed −2,585. The gap is itemised below rather than smoothed over: the three funded additions cost +838 against the estimated +385 (the filterBindings and widget-options constructs are each roughly double their estimate), and UI-D-01 returned −387 against an estimated −900. Every number below is a measured byte delta.

Per-item: 落点 | before | after

Deletions and merges

id落点beforeafter
UI-C-01## Date Macros — Filter Placeholders (whole section + ## Context Tokens)1,288 tok265 tok (−1,023)
UI-D-02### Shift segmentation — timeSegments581 tok0 (−581)
UI-C-04master-detail inlineEdit ladder + line-item grid behaviours643 tok193 tok (−450)
UI-D-01### Toolbar Search (searchableFields)1,381 tok994 tok (−387)
UI-D-05the options.drillDown renderer note235 tok0 (−235)
UI-C-02action ctx org-isolation + positions narration371 tok154 tok (−217)
UI-B-06## When to Use This Skill136 tok0 (−136)
UI-D-06the "Removed in v17" compareTo blockquote106 tok0 (−106)
UI-D-08### Cube Best Practices (5 items)159 tok74 tok (−85), retitled ### Cube Rules — see Review round 1
UI-D-04the metadata fence rationale145 tok75 tok (−70)
UI-D-03"Why this model" (build-independent / collision-free / responsive-correct)79 tok22 tok (−57)
UI-C-03the visibleWhen/readonlyWhen/requiredWhen table149 tok103 tok (−46)
UI-D-07the removed-inline-query history86 tok68 tok (−18)
UI-B-05the 4th Tailwind className restatement67 tok52 tok (−15)
UI-B-03the dateGranularity bucket table under ### Drilldown273 tok273 tok (0 — moved under its own heading; reorder is free)

The three funded additions

idwhat landedcostnamed payersactual
UI-F-01 + UI-F-03### Dashboard filters — globalFilters + per-widget filterBindings: the broadcast rule, name (defaults to field; name it for the vocabulary, not the column), scope: 'widget' + targetWidgets, re-target, false opt-out, the absent-default incl. dateRange.field ?? 'created_at', plus a 2-widget example+371UI-D-05 (−235) + UI-D-06 (−106)−341, so +30 over
UI-F-02### Widget options — the five declared keys (dateGranularity / sortBy / sortOrder / limit / stageOrder), with the top-N spelling that had no documented form+357UI-D-08 (−85) + UI-D-03 (−57)−142, so +215 over
UI-E-01os:check marks on the four highest-traffic examples (+ UI-E-03's inlined action)+110UI-E-02 (−18)+92 over

The three additions cost +838 against −501 of named payers. They are nonetheless fully paid in the same file: the flight's total deletions are −3,423, so SKILL.md ends 2,585 tokens smaller and the ratchet is green with 2,589 tokens of headroom. Flagging the per-item overrun rather than re-cutting the payer list to fit, because the card's funding lines are its ruling and I would rather show them broken than silently re-derive them.

Falsehoods

#落点beforeafter
1canonical dashboard widgetactionType: 'url', actionUrl: '/objects/opportunity?filter=open'line deleted. dashboard.zod.ts:382-384 retires all three via retiredKey(...) = z.never(); prescription :309-320 "a dashboard widget has NO action button, and never had one".
2### Server-side date bucketing"Date bucketing lives on the dataset dimension, not the widget.""The dataset dimension carries the default; a widget's options.dateGranularity overrides it for that widget only." (dashboard.zod.ts:217-225)
3frontmatter"the React renderer implementation (lives in packages/client-react, not metadata)"clause deleted. packages/client-react is "React hooks for ObjectStack Client SDK"; the renderer is @object-ui/react-runtime, in objectui.
4 (new)the Tokens-in-filters blockquote on the canonical dashboard{current_user.id}{current_user_id}. current_user.id is the RLS expression root, not a filter token — spec/src/data/context-tokens.zod.ts:44,49 names this exact near-miss and :85 lists the real token. Found inside a span this flight was already rewriting, same defect class as 1–2, mechanically fixed against the spec; taken under the bounded-in-place rule.

Also deleted, never ported (card ruling): this package's claim that "unknown placeholders silently pass through as literal strings". It is false and the file contradicted itself 37 lines earlier. packages/core/src/utils/filter-tokens.ts:378 throws UnknownFilterTokenError, and the module header at :44 is titled "An unknown token throws".

Deliberate deviations from the routed plan

  1. UI-C-01 keeps its ## heading. The ruling says delete :1659-1768. Two in-file links (:1074, :1507) target #date-macros--filter-placeholders; deleting the heading breaks both, so the heading survives carrying the pointer. Also kept: two rules objectstack-query does not own — a filter token is presentation scope, not security; and AppContextSelector ids resolve in navigation recordId/params only, never in a filter. Both were their last mention in the package.
  2. UI-C-02 keeps ctx.session.positions in compact form. The routed anchor does not carry it (see follow-ups). Kept with the "not an authorization input" guard; the org-isolation half is deleted and pointed.
  3. UI-G-03 translates 1 of 3 CJK lines, not 3label: '打印总表(A3)''Print Summary Sheet (A3)'. The two at :755-756 are non-English user phrasings the router matches on; translating a phrase whose only job is to match untranslated input destroys it. Seat ruled A: they stay.
  4. The ratchet ceiling is not lowered — see the token table.

Not implemented (and why)

premise_false

None. git diff --stat a59f78d origin/main -- skills/objectstack-ui is empty, so every audit span was byte-identical at the branch point. Two PM mechanical assumptions were refined rather than confirmed — below.

PM mechanical assumptions — measured

  1. Confirmed.skills/objectstack-ui/** byte-identical between a59f78d and origin/main. (origin/main had already moved past the dispatch's d63c8a25 to 909a4417, which does not touch skills/; the branch is cut from 909a4417.)
  2. Refined — the predicted file is the wrong one.check:skill-docs does run in CI and the frontmatter edit does force a regeneration, but skills/README.md came back green on its own (✓ skills/README.md) — it does not embed the description. The out-of-date artifact was content/docs/ai/skills-reference.mdx. Regenerated with the one generator the card names; the diff is 2 lines, both the frontmatter's own text.
  3. Confirmed for tsc; the parse half not measured. Reverse-verified against a committed tree: re-injecting actionType/actionUrl on the widget turns check:skill-examplesred with two error TS2322: Type 'string' is not assignable to type 'undefined' — one per retired key, z.never() surfacing as undefined in the input type. Mutation proven on disk before measuring (injected-text grep count 1; blob 4a5d1e256b5d8296), restore proven the same way (git diff HEAD empty, blob back to 4a5d1e25, injected count 0) — neither leg read from an editor's exit code. This gate exercises tsc only, so the Zod parse failure is asserted from the schema source, not measured here.
  4. Confirmed, with one restructure. Marked count 259 → 263, "every marked block parsed, so tsc ran the SEMANTIC pass on all of them". Two needed more than a marker: the record-detail page carried UI-E-03's unresolvable relative import (replaced with an inlined 4-line defineAction), and the defineDataset block was a fragment — it now imports defineDataset + type DashboardWidget and binds the trailing widget literal to a typed const.
  5. Not exercised — no finding's premise was false.

follow-up for objectstack-query

rules/filters.md is the anchor and is strong: it already carries the fixed tokens, the parameterised form, both session tokens, both resolvers, the calendar-DAY *_end trap, and — decisively — "Unknown tokens are rejected, not ignored". These TRUE rows from the deleted objectstack-ui text are not in it and were not ported:

  1. Both {token} and ${token} spellings are acceptedspec/src/data/date-macros.zod.ts:200,207 and context-tokens.zod.ts:101. rules/filters.md shows only the bare form.
  2. Two more near-misses: {user_id} (a valid titleFormat field interpolation elsewhere) and {organization_id} (the real column name). Query names {current_user} and {this_quarter_start} only.
  3. A token embedded in a larger string is not substituted ('user-{current_user_id}'). Query states only the converse; filter-tokens.ts:44 states this half directly — "Values that merely CONTAIN braces are left untouched."
  4. isDateMacroToken(tok) from @objectstack/spec/data as the author-time type check.
  5. The build rule's name, filter-token-unknown, and why it exists: an unresolved token reaches SQL as a literal, matches nothing, and the widget renders 0 — indistinguishable from a genuine zero.

follow-up for objectstack-data

references/data-hooks.md carries the org-isolation half completely — UI-C-02's deletion is safely routed there. It does not document ctx.session.positions at all; :368 says only that ctx.session has "No role listsession.roles was retired in 17.0.0". So the ADR-0090 D3 spelling and the "not an authorization input" guard have no anchor to point at, and a compact form was kept here rather than deleted into a gap.

Gates — all 42 families, all at head 684415c3

⚠️Correcting a stale figure this PR body previously carried. It claimed 16 families. That derivation ran at 0f937dcc, when the changeset was SKILL.md alone; the next commit added content/docs/ai/skills-reference.mdx and scripts/skill-identifier-liveness-ledger.json, and I did not re-derive. Re-derived at the current head, node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack names 42 — the 26 extra are the docs family the .mdx pulls in. All 42 have now been run; every one of the 26 that had never been run passes. The earlier "16" was wrong and is retracted here rather than quietly overwritten.

41 of 42 exit 0. Each exit code captured by redirecting before any pipe. The full list, in the order the harvester prints it:

check-ci-filter-parity · check-cross-package-test-inputs · check-doc-frontmatter · check-doc-route-spelling · check-docs-section-name · check-section-landing-index · check-shard-attestation · check-skills-token-ratchet · doc-formula-expressions · doc-security-posture · check:docs · check:empty-state · check:liveness · check:skill-docs · check:skill-examples · check:strictness-ledger · check:variant-docs · check:yaml-examples · agent-test-spelling · bash32-floor · cli-command-ids · corpus-claim-drift · cross-package-test-inputs · doc-anchors · doc-authoring · docs-audit-scope · docs-redirects · docs-single-h1 · entry-guard · merge-driver · parse-guard · pm-governed-merges · pnpm-filter-targets · published-readme-links · react-page-adapter-contract · role-word · skill-compatibility · skill-frame-sync · skill-identifier-liveness · vendor-version-stamps · watch-hint-literal — all exit 0.

Named verdict lines for the two the review asked for:

  • node scripts/check-skills-token-ratchet.mjsexit 0, "skills/objectstack-ui/SKILL.md is 22856 tokens (ceiling 25445; headroom 2589)" · "38 authored bundle file(s) within their ceilings".
  • pnpm --filter @objectstack/spec check:skill-examplesexit 0, "✅ 263 prose examples type-check across 3 surface(s) — every marked block parsed, so tsc ran the SEMANTIC pass on all of them".

The 42nd, node scripts/check-test-completeness.mjs, exits 3 = NOT MEASURED by its own verdict text ("Nothing was measured… It is not a red, and there is nothing here to fix") — it needs a saved turbo run test log. Recorded as NOT MEASURED: not a pass, not a red.

Heavy runs went through scripts/pm/os-verify-lock.sh with OS_VERIFY_LOCK_SLOT=issue-14298. Prerequisite builds re-run at this head, not assumed: @objectstack/spec and the @objectstack/client-react / @objectstack/client dependency closure — without the latter check:skill-examples refuses to run rather than reporting green ("packages/client-react/dist holds no .d.ts declarations… a FALSE GREEN on exactly the change it exists to catch").

Repo-wide pnpm lint (eslint over the whole tree) was NOT run — it is CI's own step, in this derivation's unnarrowable "always runs" tail. A plain omission, not a measured narrowing; I claim none of the three evidence items a narrowing would need.

Two consequences outside SKILL.md

Both generator/tool output, neither hand-written, each the mechanical consequence of a funded edit:

  • content/docs/ai/skills-reference.mdxgen:skill-docs, forced by the frontmatter edit (assumption 2). Not content/docs/releases/.
  • scripts/skill-identifier-liveness-ledger.jsoncheck-skill-identifier-liveness.mjs --update, pruning dayStart and showMidnight. Both existed only to excuse the timeSegments block this flight deleted, and each ledger note independently records the implementation living in objectui plugin-gantt — the same measurement UI-D-02 rests on. --update never adds an exemption.

Changeset

skip-changeset applies and is on the PR. Checked against the repo's own rule: the exemption means "this PR declares no release of its own", and no package publishes skills/, content/docs/ or scripts/. The Check Changeset job reads labels live; the label cannot be applied before the PR exists, so it was applied immediately after creation and read back.


🤖 Generated with Claude Code

https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1

os-litantand others added 4 commits September 2, 2026 01:59
…e/drilldown trims, filterBindings + widget options funded
UI-C-01 delete the date-macro + context-token block; keep the heading (two
in-file anchors resolve to it) and point at objectstack-query
rules/filters.md. Two UI-owned rules stay: presentation-scope-not-
security, and AppContextSelector ids never resolving in a filter.
UI-C-02 drop the org-isolation narration; keep the blessed-name pointer at
objectstack-data's hooks reference. `ctx.session.positions` stays in
compact form -- the anchor does not carry it (see PR follow-up list).
UI-D-08 Cube Best Practices -> the two enforced facts.
UI-D-05 delete the renderer note that ends by telling the reader to ignore it.
UI-D-06 delete the v17 `compareTo` removal narration.
UI-B-03 move the dateGranularity bucket table out of `### Drilldown` and under
its own heading (reorder only).
UI-G-02 falsehood 2: the dataset dimension is the DEFAULT; options.dateGranularity
overrides it per widget (dashboard.zod.ts:217-225).
UI-E-02 falsehood 1: delete the retired `actionType`/`actionUrl` pair from the
canonical dashboard widget (dashboard.zod.ts:382-384, retiredKey =
z.never()).
falsehood 4 (found in span, same defect class): `{current_user.id}` ->
`{current_user_id}`; `current_user.id` is the RLS expression root, not
a filter token (spec/src/data/context-tokens.zod.ts:44,49,85).
UI-F-01/F-03 ADD the globalFilters/filterBindings construct (paid by D-05+D-06).
UI-F-02 ADD the five declared widget `options` keys (paid by D-08+D-03-to-come).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…etired, relationships/conditional-rules pointed at objectstack-data
UI-D-01 keep the two tables and the `userActions: { search: false }` example;
delete the two verbatim `os validate` diagnostics, the empty-array
essay (folded into the row that already existed) and the related-title
prose (reduced to its objectstack-data pointer).
UI-D-02 delete the `timeSegments` block -- self-declared NOT part of
GanttConfigSchema, zero implementation in this repo (every hit is in
objectui plugin-gantt), and 10 of the package's 13 CJK lines.
UI-C-04 the inlineEdit ladder and the modelled grid behaviours point at
objectstack-data rules/relationships.md, which carries them verbatim.
Kept the three UI-authored facts the anchor does NOT carry: the ghost
row, `autofill: false`, and the form's `taxRateField`.
UI-C-03 delete the visibleWhen/readonlyWhen/requiredWhen table; keep the
routing line, the row-by-row inline-grid note and the retired
`conditionalRequired` guard.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…our highest-traffic examples gated
UI-A-01 add `*.page.ts` / `*.report.ts` / `*.dataset.ts` to the trigger list --
`*.page.ts` is the corpus's most-authored kind (29 definitions) and had
no filename trigger at all.
UI-A-02 falsehood 3: drop "the React renderer implementation (lives in
packages/client-react)". That package is React hooks for the client SDK
(package.json description; src/index.tsx exports hooks + provider). The
renderer is @object-ui/react-runtime, in objectui.
UI-A-03 wizards: a stepped form over ONE object is this skill's `formViews`
`type: 'wizard'`; only step-branching flows route to automation.
UI-D-07 keep the requirement, drop the removal history.
UI-D-03 delete the "Why this model" justification.
UI-D-04 reduce the metadata-fence rationale to the two facts the table lacks
(live-not-a-screenshot; data-not-code).
UI-B-06 delete "When to Use This Skill" -- it restated the frontmatter.
UI-B-05 the Tailwind rule now states the rule once and points at ADR-0065.
UI-G-03 translate the CJK example label. The two remaining CJK lines are
non-English USER PHRASINGS the router matches on -- see the PR body.
UI-E-03 inline a minimal defineAction so the record-detail page block stands
alone (the relative import could never resolve in the gate build dir).
UI-E-01 mark four highest-traffic examples `os:check`: structured definePage,
the Dashboard literal, defineDataset, the react source tier.
Gate: pnpm --filter @objectstack/spec check:skill-examples -- 259 -> 263 marked
blocks, "every marked block parsed, so tsc ran the SEMANTIC pass on all of them".
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…nd the timeSegments deletion
Two mechanical consequences, neither hand-written:
- `content/docs/ai/skills-reference.mdx` — `pnpm --filter @objectstack/spec
gen:skill-docs`. The dispatch predicted `skills/README.md` would be the file
the drift gate demands; it is not. README came back green on its own (it does
not embed the description); the out-of-date artifact is the reference page.
Both are outputs of the one generator the card names.
- `scripts/skill-identifier-liveness-ledger.json` — `node
scripts/check-skill-identifier-liveness.mjs --update`, pruning the now-stale
`dayStart` / `showMidnight` exemptions. Both existed only to excuse the
`timeSegments` block this flight deleted, and each ledger note independently
records that the implementation lives in objectui plugin-gantt -- the same
measurement UI-D-02 rests on. `--update` never ADDS an exemption.
Gates: check:skill-docs 0 (both artifacts ✓); check:skill-identifier-liveness 0
("Leg 1: 498 citations over 48 published files ... 3 ledgered exemptions").
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
@github-actionsgithub-actionsBot added size/l documentation Improvements or additions to documentation labels Sep 2, 2026
@os-litantos-litant added skip-changeset PR has no user-facing published change; bypasses the changeset gate needs:contract-review and removed documentation Improvements or additions to documentation labels Sep 2, 2026 — with Claude
…ding
In-seat contract review is right: my UI-D-08 retitle asserted enforcement that
does not exist, which is the same defect class this flight exists to remove.
Re-verified against the source, and the evidence is stronger than the review
cited:
- `granularities: z.array(TimeUpdateInterval).optional()`
(packages/spec/src/data/analytics.zod.ts:147) — optional, and the file
contains ZERO `.refine(` / `superRefine` occurrences, so nothing requires it
on a `time` dimension.
- Cube `sql: z.string().describe('Base SQL statement or Table Name')` (:216).
The describe string itself admits raw SQL; nothing rejects it at parse time,
and no gate script under scripts/ or packages/*/scripts/ references
`cube.sql`.
So there is no gate or schema refinement to cite, and the word is dropped rather
than defended. The two body items are unchanged: they are prescriptions with a
stated mechanism (`cube.sql.trim()` read as the object name), not claims of
enforcement.
Gates at this head: node scripts/check-skills-token-ratchet.mjs exit 0 --
SKILL.md 22856 tokens (ceiling 25445, headroom 2589); pnpm --filter
@objectstack/spec check:skill-examples exit 0 -- "263 prose examples type-check
across 3 surface(s)".
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
@github-actionsgithub-actionsBot added the documentation Improvements or additions to documentation label Sep 2, 2026
@os-litantos-litant changed the title skills(ui): optimization flight — date macros/relationships pointed at their anchors, searchableFields and timeSegments cut, dashboards consolidated, retired widget keys removed (net −2,583 tokens)skills(ui): optimization flight — date macros/relationships pointed at their anchors, searchableFields and timeSegments cut, dashboards consolidated, retired widget keys removed (net −2,585 tokens)Sep 2, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review September 2, 2026 06:18
@os-zhuang
os-zhuang added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit 54a1125Sep 2, 2026
45 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-14298-skills-ui-optimization branch September 2, 2026 06:41
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/lskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@os-litant@os-zhuang
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

skills(ui): optimization flight — date macros/relationships pointed at their anchors, searchableFields and timeSegments cut, dashboards consolidated, retired widget keys removed (net −2,585 tokens) - #14338

Merged
os-zhuang merged 5 commits into
mainfrom
claude/issue-14298-skills-ui-optimization
Sep 2, 2026
Merged

Conversation

@os-litant

@os-litantos-litant commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Part of #14298

Governed surface (skills/**) ⇒ this PR stays draft; needs:contract-review is on both carriers because falsehoods 1–2 are contract-semantics corrections. Head sha for every gate figure below: 684415c3.

Review round 1 — one FAIL, fixed

In-seat contract review flagged the UI-D-08 retitle ### Cube Rules (enforced) as asserting enforcement that does not exist. Correct, and the evidence is stronger than the review cited — re-verified at source:

  • granularities: z.array(TimeUpdateInterval).optional() (packages/spec/src/data/analytics.zod.ts:147), and that file contains zero.refine( / superRefine occurrences, so nothing requires it on a time dimension.
  • Cube sql: z.string().describe('Base SQL statement or Table Name') (:216) — the describe string itself admits raw SQL; nothing rejects it at parse time, and no gate script under scripts/ or packages/*/scripts/ references cube.sql.

There is no gate or schema refinement to cite, so the word is dropped, not defended: the heading is now ### Cube Rules. The two body items are unchanged — they are prescriptions with a stated mechanism (cube.sql.trim() read as the object name), not claims of enforcement. Shipping an unbacked "(enforced)" would have been the same defect class this flight exists to remove.

Open questions ruled by the seat: Q1 → C (UI-E-04 deprecated objectName/viewType, filed by the seat as its own card — nothing done here); Q2 → A (the two CJK trigger phrases stay).

Per-file token delta (ratchet convention, ceil(utf8 bytes / 4))

filebeforeafterdeltaceiling
skills/objectstack-ui/SKILL.md25,44122,856−2,58525,445 (headroom 4 → 2,589)
package total36,54233,957−2,585
whole shipped bundle187,854185,269−2,585

Generated package members untouched and unchanged: contracts/react-blocks.contract.json 5,352 · references/react-blocks.md 3,153 · references/_index.md 1,205. evals/** untouched (1,102 + 289). The ceiling is left at 25,445: the ratchet header says a ceiling "may be LOWERED by any PR that shrinks its file … always legitimate and encouraged", but the card's flight constraint forbids touching the ratchet script, so the 2,589 tokens of new headroom are deliberately NOT claimed here — a follow-up may lower the row to the measurement.

Against the card's target. The card targets ≈ −9,170, of which −5,352 is UI-B-04's duplicated generated JSON — explicitly DEFERRED to #14296 item 3 and not mine. The in-file target was −4,199 prose against +385 of additions; landed −2,585. The gap is itemised below rather than smoothed over: the three funded additions cost +838 against the estimated +385 (the filterBindings and widget-options constructs are each roughly double their estimate), and UI-D-01 returned −387 against an estimated −900. Every number below is a measured byte delta.

Per-item: 落点 | before | after

Deletions and merges

id落点beforeafter
UI-C-01## Date Macros — Filter Placeholders (whole section + ## Context Tokens)1,288 tok265 tok (−1,023)
UI-D-02### Shift segmentation — timeSegments581 tok0 (−581)
UI-C-04master-detail inlineEdit ladder + line-item grid behaviours643 tok193 tok (−450)
UI-D-01### Toolbar Search (searchableFields)1,381 tok994 tok (−387)
UI-D-05the options.drillDown renderer note235 tok0 (−235)
UI-C-02action ctx org-isolation + positions narration371 tok154 tok (−217)
UI-B-06## When to Use This Skill136 tok0 (−136)
UI-D-06the "Removed in v17" compareTo blockquote106 tok0 (−106)
UI-D-08### Cube Best Practices (5 items)159 tok74 tok (−85), retitled ### Cube Rules — see Review round 1
UI-D-04the metadata fence rationale145 tok75 tok (−70)
UI-D-03"Why this model" (build-independent / collision-free / responsive-correct)79 tok22 tok (−57)
UI-C-03the visibleWhen/readonlyWhen/requiredWhen table149 tok103 tok (−46)
UI-D-07the removed-inline-query history86 tok68 tok (−18)
UI-B-05the 4th Tailwind className restatement67 tok52 tok (−15)
UI-B-03the dateGranularity bucket table under ### Drilldown273 tok273 tok (0 — moved under its own heading; reorder is free)

The three funded additions

idwhat landedcostnamed payersactual
UI-F-01 + UI-F-03### Dashboard filters — globalFilters + per-widget filterBindings: the broadcast rule, name (defaults to field; name it for the vocabulary, not the column), scope: 'widget' + targetWidgets, re-target, false opt-out, the absent-default incl. dateRange.field ?? 'created_at', plus a 2-widget example+371UI-D-05 (−235) + UI-D-06 (−106)−341, so +30 over
UI-F-02### Widget options — the five declared keys (dateGranularity / sortBy / sortOrder / limit / stageOrder), with the top-N spelling that had no documented form+357UI-D-08 (−85) + UI-D-03 (−57)−142, so +215 over
UI-E-01os:check marks on the four highest-traffic examples (+ UI-E-03's inlined action)+110UI-E-02 (−18)+92 over

The three additions cost +838 against −501 of named payers. They are nonetheless fully paid in the same file: the flight's total deletions are −3,423, so SKILL.md ends 2,585 tokens smaller and the ratchet is green with 2,589 tokens of headroom. Flagging the per-item overrun rather than re-cutting the payer list to fit, because the card's funding lines are its ruling and I would rather show them broken than silently re-derive them.

Falsehoods

#落点beforeafter
1canonical dashboard widgetactionType: 'url', actionUrl: '/objects/opportunity?filter=open'line deleted. dashboard.zod.ts:382-384 retires all three via retiredKey(...) = z.never(); prescription :309-320 "a dashboard widget has NO action button, and never had one".
2### Server-side date bucketing"Date bucketing lives on the dataset dimension, not the widget.""The dataset dimension carries the default; a widget's options.dateGranularity overrides it for that widget only." (dashboard.zod.ts:217-225)
3frontmatter"the React renderer implementation (lives in packages/client-react, not metadata)"clause deleted. packages/client-react is "React hooks for ObjectStack Client SDK"; the renderer is @object-ui/react-runtime, in objectui.
4 (new)the Tokens-in-filters blockquote on the canonical dashboard{current_user.id}{current_user_id}. current_user.id is the RLS expression root, not a filter token — spec/src/data/context-tokens.zod.ts:44,49 names this exact near-miss and :85 lists the real token. Found inside a span this flight was already rewriting, same defect class as 1–2, mechanically fixed against the spec; taken under the bounded-in-place rule.

Also deleted, never ported (card ruling): this package's claim that "unknown placeholders silently pass through as literal strings". It is false and the file contradicted itself 37 lines earlier. packages/core/src/utils/filter-tokens.ts:378 throws UnknownFilterTokenError, and the module header at :44 is titled "An unknown token throws".

Deliberate deviations from the routed plan

  1. UI-C-01 keeps its ## heading. The ruling says delete :1659-1768. Two in-file links (:1074, :1507) target #date-macros--filter-placeholders; deleting the heading breaks both, so the heading survives carrying the pointer. Also kept: two rules objectstack-query does not own — a filter token is presentation scope, not security; and AppContextSelector ids resolve in navigation recordId/params only, never in a filter. Both were their last mention in the package.
  2. UI-C-02 keeps ctx.session.positions in compact form. The routed anchor does not carry it (see follow-ups). Kept with the "not an authorization input" guard; the org-isolation half is deleted and pointed.
  3. UI-G-03 translates 1 of 3 CJK lines, not 3label: '打印总表(A3)''Print Summary Sheet (A3)'. The two at :755-756 are non-English user phrasings the router matches on; translating a phrase whose only job is to match untranslated input destroys it. Seat ruled A: they stay.
  4. The ratchet ceiling is not lowered — see the token table.

Not implemented (and why)

premise_false

None. git diff --stat a59f78d origin/main -- skills/objectstack-ui is empty, so every audit span was byte-identical at the branch point. Two PM mechanical assumptions were refined rather than confirmed — below.

PM mechanical assumptions — measured

  1. Confirmed.skills/objectstack-ui/** byte-identical between a59f78d and origin/main. (origin/main had already moved past the dispatch's d63c8a25 to 909a4417, which does not touch skills/; the branch is cut from 909a4417.)
  2. Refined — the predicted file is the wrong one.check:skill-docs does run in CI and the frontmatter edit does force a regeneration, but skills/README.md came back green on its own (✓ skills/README.md) — it does not embed the description. The out-of-date artifact was content/docs/ai/skills-reference.mdx. Regenerated with the one generator the card names; the diff is 2 lines, both the frontmatter's own text.
  3. Confirmed for tsc; the parse half not measured. Reverse-verified against a committed tree: re-injecting actionType/actionUrl on the widget turns check:skill-examplesred with two error TS2322: Type 'string' is not assignable to type 'undefined' — one per retired key, z.never() surfacing as undefined in the input type. Mutation proven on disk before measuring (injected-text grep count 1; blob 4a5d1e256b5d8296), restore proven the same way (git diff HEAD empty, blob back to 4a5d1e25, injected count 0) — neither leg read from an editor's exit code. This gate exercises tsc only, so the Zod parse failure is asserted from the schema source, not measured here.
  4. Confirmed, with one restructure. Marked count 259 → 263, "every marked block parsed, so tsc ran the SEMANTIC pass on all of them". Two needed more than a marker: the record-detail page carried UI-E-03's unresolvable relative import (replaced with an inlined 4-line defineAction), and the defineDataset block was a fragment — it now imports defineDataset + type DashboardWidget and binds the trailing widget literal to a typed const.
  5. Not exercised — no finding's premise was false.

follow-up for objectstack-query

rules/filters.md is the anchor and is strong: it already carries the fixed tokens, the parameterised form, both session tokens, both resolvers, the calendar-DAY *_end trap, and — decisively — "Unknown tokens are rejected, not ignored". These TRUE rows from the deleted objectstack-ui text are not in it and were not ported:

  1. Both {token} and ${token} spellings are acceptedspec/src/data/date-macros.zod.ts:200,207 and context-tokens.zod.ts:101. rules/filters.md shows only the bare form.
  2. Two more near-misses: {user_id} (a valid titleFormat field interpolation elsewhere) and {organization_id} (the real column name). Query names {current_user} and {this_quarter_start} only.
  3. A token embedded in a larger string is not substituted ('user-{current_user_id}'). Query states only the converse; filter-tokens.ts:44 states this half directly — "Values that merely CONTAIN braces are left untouched."
  4. isDateMacroToken(tok) from @objectstack/spec/data as the author-time type check.
  5. The build rule's name, filter-token-unknown, and why it exists: an unresolved token reaches SQL as a literal, matches nothing, and the widget renders 0 — indistinguishable from a genuine zero.

follow-up for objectstack-data

references/data-hooks.md carries the org-isolation half completely — UI-C-02's deletion is safely routed there. It does not document ctx.session.positions at all; :368 says only that ctx.session has "No role listsession.roles was retired in 17.0.0". So the ADR-0090 D3 spelling and the "not an authorization input" guard have no anchor to point at, and a compact form was kept here rather than deleted into a gap.

Gates — all 42 families, all at head 684415c3

⚠️Correcting a stale figure this PR body previously carried. It claimed 16 families. That derivation ran at 0f937dcc, when the changeset was SKILL.md alone; the next commit added content/docs/ai/skills-reference.mdx and scripts/skill-identifier-liveness-ledger.json, and I did not re-derive. Re-derived at the current head, node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack names 42 — the 26 extra are the docs family the .mdx pulls in. All 42 have now been run; every one of the 26 that had never been run passes. The earlier "16" was wrong and is retracted here rather than quietly overwritten.

41 of 42 exit 0. Each exit code captured by redirecting before any pipe. The full list, in the order the harvester prints it:

check-ci-filter-parity · check-cross-package-test-inputs · check-doc-frontmatter · check-doc-route-spelling · check-docs-section-name · check-section-landing-index · check-shard-attestation · check-skills-token-ratchet · doc-formula-expressions · doc-security-posture · check:docs · check:empty-state · check:liveness · check:skill-docs · check:skill-examples · check:strictness-ledger · check:variant-docs · check:yaml-examples · agent-test-spelling · bash32-floor · cli-command-ids · corpus-claim-drift · cross-package-test-inputs · doc-anchors · doc-authoring · docs-audit-scope · docs-redirects · docs-single-h1 · entry-guard · merge-driver · parse-guard · pm-governed-merges · pnpm-filter-targets · published-readme-links · react-page-adapter-contract · role-word · skill-compatibility · skill-frame-sync · skill-identifier-liveness · vendor-version-stamps · watch-hint-literal — all exit 0.

Named verdict lines for the two the review asked for:

  • node scripts/check-skills-token-ratchet.mjsexit 0, "skills/objectstack-ui/SKILL.md is 22856 tokens (ceiling 25445; headroom 2589)" · "38 authored bundle file(s) within their ceilings".
  • pnpm --filter @objectstack/spec check:skill-examplesexit 0, "✅ 263 prose examples type-check across 3 surface(s) — every marked block parsed, so tsc ran the SEMANTIC pass on all of them".

The 42nd, node scripts/check-test-completeness.mjs, exits 3 = NOT MEASURED by its own verdict text ("Nothing was measured… It is not a red, and there is nothing here to fix") — it needs a saved turbo run test log. Recorded as NOT MEASURED: not a pass, not a red.

Heavy runs went through scripts/pm/os-verify-lock.sh with OS_VERIFY_LOCK_SLOT=issue-14298. Prerequisite builds re-run at this head, not assumed: @objectstack/spec and the @objectstack/client-react / @objectstack/client dependency closure — without the latter check:skill-examples refuses to run rather than reporting green ("packages/client-react/dist holds no .d.ts declarations… a FALSE GREEN on exactly the change it exists to catch").

Repo-wide pnpm lint (eslint over the whole tree) was NOT run — it is CI's own step, in this derivation's unnarrowable "always runs" tail. A plain omission, not a measured narrowing; I claim none of the three evidence items a narrowing would need.

Two consequences outside SKILL.md

Both generator/tool output, neither hand-written, each the mechanical consequence of a funded edit:

  • content/docs/ai/skills-reference.mdxgen:skill-docs, forced by the frontmatter edit (assumption 2). Not content/docs/releases/.
  • scripts/skill-identifier-liveness-ledger.jsoncheck-skill-identifier-liveness.mjs --update, pruning dayStart and showMidnight. Both existed only to excuse the timeSegments block this flight deleted, and each ledger note independently records the implementation living in objectui plugin-gantt — the same measurement UI-D-02 rests on. --update never adds an exemption.

Changeset

skip-changeset applies and is on the PR. Checked against the repo's own rule: the exemption means "this PR declares no release of its own", and no package publishes skills/, content/docs/ or scripts/. The Check Changeset job reads labels live; the label cannot be applied before the PR exists, so it was applied immediately after creation and read back.


🤖 Generated with Claude Code

https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1

os-litantand others added 4 commits September 2, 2026 01:59
…e/drilldown trims, filterBindings + widget options funded
UI-C-01 delete the date-macro + context-token block; keep the heading (two
in-file anchors resolve to it) and point at objectstack-query
rules/filters.md. Two UI-owned rules stay: presentation-scope-not-
security, and AppContextSelector ids never resolving in a filter.
UI-C-02 drop the org-isolation narration; keep the blessed-name pointer at
objectstack-data's hooks reference. `ctx.session.positions` stays in
compact form -- the anchor does not carry it (see PR follow-up list).
UI-D-08 Cube Best Practices -> the two enforced facts.
UI-D-05 delete the renderer note that ends by telling the reader to ignore it.
UI-D-06 delete the v17 `compareTo` removal narration.
UI-B-03 move the dateGranularity bucket table out of `### Drilldown` and under
its own heading (reorder only).
UI-G-02 falsehood 2: the dataset dimension is the DEFAULT; options.dateGranularity
overrides it per widget (dashboard.zod.ts:217-225).
UI-E-02 falsehood 1: delete the retired `actionType`/`actionUrl` pair from the
canonical dashboard widget (dashboard.zod.ts:382-384, retiredKey =
z.never()).
falsehood 4 (found in span, same defect class): `{current_user.id}` ->
`{current_user_id}`; `current_user.id` is the RLS expression root, not
a filter token (spec/src/data/context-tokens.zod.ts:44,49,85).
UI-F-01/F-03 ADD the globalFilters/filterBindings construct (paid by D-05+D-06).
UI-F-02 ADD the five declared widget `options` keys (paid by D-08+D-03-to-come).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…etired, relationships/conditional-rules pointed at objectstack-data
UI-D-01 keep the two tables and the `userActions: { search: false }` example;
delete the two verbatim `os validate` diagnostics, the empty-array
essay (folded into the row that already existed) and the related-title
prose (reduced to its objectstack-data pointer).
UI-D-02 delete the `timeSegments` block -- self-declared NOT part of
GanttConfigSchema, zero implementation in this repo (every hit is in
objectui plugin-gantt), and 10 of the package's 13 CJK lines.
UI-C-04 the inlineEdit ladder and the modelled grid behaviours point at
objectstack-data rules/relationships.md, which carries them verbatim.
Kept the three UI-authored facts the anchor does NOT carry: the ghost
row, `autofill: false`, and the form's `taxRateField`.
UI-C-03 delete the visibleWhen/readonlyWhen/requiredWhen table; keep the
routing line, the row-by-row inline-grid note and the retired
`conditionalRequired` guard.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…our highest-traffic examples gated
UI-A-01 add `*.page.ts` / `*.report.ts` / `*.dataset.ts` to the trigger list --
`*.page.ts` is the corpus's most-authored kind (29 definitions) and had
no filename trigger at all.
UI-A-02 falsehood 3: drop "the React renderer implementation (lives in
packages/client-react)". That package is React hooks for the client SDK
(package.json description; src/index.tsx exports hooks + provider). The
renderer is @object-ui/react-runtime, in objectui.
UI-A-03 wizards: a stepped form over ONE object is this skill's `formViews`
`type: 'wizard'`; only step-branching flows route to automation.
UI-D-07 keep the requirement, drop the removal history.
UI-D-03 delete the "Why this model" justification.
UI-D-04 reduce the metadata-fence rationale to the two facts the table lacks
(live-not-a-screenshot; data-not-code).
UI-B-06 delete "When to Use This Skill" -- it restated the frontmatter.
UI-B-05 the Tailwind rule now states the rule once and points at ADR-0065.
UI-G-03 translate the CJK example label. The two remaining CJK lines are
non-English USER PHRASINGS the router matches on -- see the PR body.
UI-E-03 inline a minimal defineAction so the record-detail page block stands
alone (the relative import could never resolve in the gate build dir).
UI-E-01 mark four highest-traffic examples `os:check`: structured definePage,
the Dashboard literal, defineDataset, the react source tier.
Gate: pnpm --filter @objectstack/spec check:skill-examples -- 259 -> 263 marked
blocks, "every marked block parsed, so tsc ran the SEMANTIC pass on all of them".
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…nd the timeSegments deletion
Two mechanical consequences, neither hand-written:
- `content/docs/ai/skills-reference.mdx` — `pnpm --filter @objectstack/spec
gen:skill-docs`. The dispatch predicted `skills/README.md` would be the file
the drift gate demands; it is not. README came back green on its own (it does
not embed the description); the out-of-date artifact is the reference page.
Both are outputs of the one generator the card names.
- `scripts/skill-identifier-liveness-ledger.json` — `node
scripts/check-skill-identifier-liveness.mjs --update`, pruning the now-stale
`dayStart` / `showMidnight` exemptions. Both existed only to excuse the
`timeSegments` block this flight deleted, and each ledger note independently
records that the implementation lives in objectui plugin-gantt -- the same
measurement UI-D-02 rests on. `--update` never ADDS an exemption.
Gates: check:skill-docs 0 (both artifacts ✓); check:skill-identifier-liveness 0
("Leg 1: 498 citations over 48 published files ... 3 ledgered exemptions").
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
@github-actionsgithub-actionsBot added size/l documentation Improvements or additions to documentation labels Sep 2, 2026
@os-litantos-litant added skip-changeset PR has no user-facing published change; bypasses the changeset gate needs:contract-review and removed documentation Improvements or additions to documentation labels Sep 2, 2026 — with Claude
…ding
In-seat contract review is right: my UI-D-08 retitle asserted enforcement that
does not exist, which is the same defect class this flight exists to remove.
Re-verified against the source, and the evidence is stronger than the review
cited:
- `granularities: z.array(TimeUpdateInterval).optional()`
(packages/spec/src/data/analytics.zod.ts:147) — optional, and the file
contains ZERO `.refine(` / `superRefine` occurrences, so nothing requires it
on a `time` dimension.
- Cube `sql: z.string().describe('Base SQL statement or Table Name')` (:216).
The describe string itself admits raw SQL; nothing rejects it at parse time,
and no gate script under scripts/ or packages/*/scripts/ references
`cube.sql`.
So there is no gate or schema refinement to cite, and the word is dropped rather
than defended. The two body items are unchanged: they are prescriptions with a
stated mechanism (`cube.sql.trim()` read as the object name), not claims of
enforcement.
Gates at this head: node scripts/check-skills-token-ratchet.mjs exit 0 --
SKILL.md 22856 tokens (ceiling 25445, headroom 2589); pnpm --filter
@objectstack/spec check:skill-examples exit 0 -- "263 prose examples type-check
across 3 surface(s)".
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
@github-actionsgithub-actionsBot added the documentation Improvements or additions to documentation label Sep 2, 2026
@os-litantos-litant changed the title skills(ui): optimization flight — date macros/relationships pointed at their anchors, searchableFields and timeSegments cut, dashboards consolidated, retired widget keys removed (net −2,583 tokens)skills(ui): optimization flight — date macros/relationships pointed at their anchors, searchableFields and timeSegments cut, dashboards consolidated, retired widget keys removed (net −2,585 tokens)Sep 2, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review September 2, 2026 06:18
@os-zhuang
os-zhuang added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit 54a1125Sep 2, 2026
45 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-14298-skills-ui-optimization branch September 2, 2026 06:41
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/lskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@os-litant@os-zhuang
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

skills(ui): optimization flight — date macros/relationships pointed at their anchors, searchableFields and timeSegments cut, dashboards consolidated, retired widget keys removed (net −2,585 tokens) - #14338

Merged
os-zhuang merged 5 commits into
mainfrom
claude/issue-14298-skills-ui-optimization
Sep 2, 2026
Merged

Conversation

@os-litant

@os-litantos-litant commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Part of #14298

Governed surface (skills/**) ⇒ this PR stays draft; needs:contract-review is on both carriers because falsehoods 1–2 are contract-semantics corrections. Head sha for every gate figure below: 684415c3.

Review round 1 — one FAIL, fixed

In-seat contract review flagged the UI-D-08 retitle ### Cube Rules (enforced) as asserting enforcement that does not exist. Correct, and the evidence is stronger than the review cited — re-verified at source:

  • granularities: z.array(TimeUpdateInterval).optional() (packages/spec/src/data/analytics.zod.ts:147), and that file contains zero.refine( / superRefine occurrences, so nothing requires it on a time dimension.
  • Cube sql: z.string().describe('Base SQL statement or Table Name') (:216) — the describe string itself admits raw SQL; nothing rejects it at parse time, and no gate script under scripts/ or packages/*/scripts/ references cube.sql.

There is no gate or schema refinement to cite, so the word is dropped, not defended: the heading is now ### Cube Rules. The two body items are unchanged — they are prescriptions with a stated mechanism (cube.sql.trim() read as the object name), not claims of enforcement. Shipping an unbacked "(enforced)" would have been the same defect class this flight exists to remove.

Open questions ruled by the seat: Q1 → C (UI-E-04 deprecated objectName/viewType, filed by the seat as its own card — nothing done here); Q2 → A (the two CJK trigger phrases stay).

Per-file token delta (ratchet convention, ceil(utf8 bytes / 4))

filebeforeafterdeltaceiling
skills/objectstack-ui/SKILL.md25,44122,856−2,58525,445 (headroom 4 → 2,589)
package total36,54233,957−2,585
whole shipped bundle187,854185,269−2,585

Generated package members untouched and unchanged: contracts/react-blocks.contract.json 5,352 · references/react-blocks.md 3,153 · references/_index.md 1,205. evals/** untouched (1,102 + 289). The ceiling is left at 25,445: the ratchet header says a ceiling "may be LOWERED by any PR that shrinks its file … always legitimate and encouraged", but the card's flight constraint forbids touching the ratchet script, so the 2,589 tokens of new headroom are deliberately NOT claimed here — a follow-up may lower the row to the measurement.

Against the card's target. The card targets ≈ −9,170, of which −5,352 is UI-B-04's duplicated generated JSON — explicitly DEFERRED to #14296 item 3 and not mine. The in-file target was −4,199 prose against +385 of additions; landed −2,585. The gap is itemised below rather than smoothed over: the three funded additions cost +838 against the estimated +385 (the filterBindings and widget-options constructs are each roughly double their estimate), and UI-D-01 returned −387 against an estimated −900. Every number below is a measured byte delta.

Per-item: 落点 | before | after

Deletions and merges

id落点beforeafter
UI-C-01## Date Macros — Filter Placeholders (whole section + ## Context Tokens)1,288 tok265 tok (−1,023)
UI-D-02### Shift segmentation — timeSegments581 tok0 (−581)
UI-C-04master-detail inlineEdit ladder + line-item grid behaviours643 tok193 tok (−450)
UI-D-01### Toolbar Search (searchableFields)1,381 tok994 tok (−387)
UI-D-05the options.drillDown renderer note235 tok0 (−235)
UI-C-02action ctx org-isolation + positions narration371 tok154 tok (−217)
UI-B-06## When to Use This Skill136 tok0 (−136)
UI-D-06the "Removed in v17" compareTo blockquote106 tok0 (−106)
UI-D-08### Cube Best Practices (5 items)159 tok74 tok (−85), retitled ### Cube Rules — see Review round 1
UI-D-04the metadata fence rationale145 tok75 tok (−70)
UI-D-03"Why this model" (build-independent / collision-free / responsive-correct)79 tok22 tok (−57)
UI-C-03the visibleWhen/readonlyWhen/requiredWhen table149 tok103 tok (−46)
UI-D-07the removed-inline-query history86 tok68 tok (−18)
UI-B-05the 4th Tailwind className restatement67 tok52 tok (−15)
UI-B-03the dateGranularity bucket table under ### Drilldown273 tok273 tok (0 — moved under its own heading; reorder is free)

The three funded additions

idwhat landedcostnamed payersactual
UI-F-01 + UI-F-03### Dashboard filters — globalFilters + per-widget filterBindings: the broadcast rule, name (defaults to field; name it for the vocabulary, not the column), scope: 'widget' + targetWidgets, re-target, false opt-out, the absent-default incl. dateRange.field ?? 'created_at', plus a 2-widget example+371UI-D-05 (−235) + UI-D-06 (−106)−341, so +30 over
UI-F-02### Widget options — the five declared keys (dateGranularity / sortBy / sortOrder / limit / stageOrder), with the top-N spelling that had no documented form+357UI-D-08 (−85) + UI-D-03 (−57)−142, so +215 over
UI-E-01os:check marks on the four highest-traffic examples (+ UI-E-03's inlined action)+110UI-E-02 (−18)+92 over

The three additions cost +838 against −501 of named payers. They are nonetheless fully paid in the same file: the flight's total deletions are −3,423, so SKILL.md ends 2,585 tokens smaller and the ratchet is green with 2,589 tokens of headroom. Flagging the per-item overrun rather than re-cutting the payer list to fit, because the card's funding lines are its ruling and I would rather show them broken than silently re-derive them.

Falsehoods

#落点beforeafter
1canonical dashboard widgetactionType: 'url', actionUrl: '/objects/opportunity?filter=open'line deleted. dashboard.zod.ts:382-384 retires all three via retiredKey(...) = z.never(); prescription :309-320 "a dashboard widget has NO action button, and never had one".
2### Server-side date bucketing"Date bucketing lives on the dataset dimension, not the widget.""The dataset dimension carries the default; a widget's options.dateGranularity overrides it for that widget only." (dashboard.zod.ts:217-225)
3frontmatter"the React renderer implementation (lives in packages/client-react, not metadata)"clause deleted. packages/client-react is "React hooks for ObjectStack Client SDK"; the renderer is @object-ui/react-runtime, in objectui.
4 (new)the Tokens-in-filters blockquote on the canonical dashboard{current_user.id}{current_user_id}. current_user.id is the RLS expression root, not a filter token — spec/src/data/context-tokens.zod.ts:44,49 names this exact near-miss and :85 lists the real token. Found inside a span this flight was already rewriting, same defect class as 1–2, mechanically fixed against the spec; taken under the bounded-in-place rule.

Also deleted, never ported (card ruling): this package's claim that "unknown placeholders silently pass through as literal strings". It is false and the file contradicted itself 37 lines earlier. packages/core/src/utils/filter-tokens.ts:378 throws UnknownFilterTokenError, and the module header at :44 is titled "An unknown token throws".

Deliberate deviations from the routed plan

  1. UI-C-01 keeps its ## heading. The ruling says delete :1659-1768. Two in-file links (:1074, :1507) target #date-macros--filter-placeholders; deleting the heading breaks both, so the heading survives carrying the pointer. Also kept: two rules objectstack-query does not own — a filter token is presentation scope, not security; and AppContextSelector ids resolve in navigation recordId/params only, never in a filter. Both were their last mention in the package.
  2. UI-C-02 keeps ctx.session.positions in compact form. The routed anchor does not carry it (see follow-ups). Kept with the "not an authorization input" guard; the org-isolation half is deleted and pointed.
  3. UI-G-03 translates 1 of 3 CJK lines, not 3label: '打印总表(A3)''Print Summary Sheet (A3)'. The two at :755-756 are non-English user phrasings the router matches on; translating a phrase whose only job is to match untranslated input destroys it. Seat ruled A: they stay.
  4. The ratchet ceiling is not lowered — see the token table.

Not implemented (and why)

premise_false

None. git diff --stat a59f78d origin/main -- skills/objectstack-ui is empty, so every audit span was byte-identical at the branch point. Two PM mechanical assumptions were refined rather than confirmed — below.

PM mechanical assumptions — measured

  1. Confirmed.skills/objectstack-ui/** byte-identical between a59f78d and origin/main. (origin/main had already moved past the dispatch's d63c8a25 to 909a4417, which does not touch skills/; the branch is cut from 909a4417.)
  2. Refined — the predicted file is the wrong one.check:skill-docs does run in CI and the frontmatter edit does force a regeneration, but skills/README.md came back green on its own (✓ skills/README.md) — it does not embed the description. The out-of-date artifact was content/docs/ai/skills-reference.mdx. Regenerated with the one generator the card names; the diff is 2 lines, both the frontmatter's own text.
  3. Confirmed for tsc; the parse half not measured. Reverse-verified against a committed tree: re-injecting actionType/actionUrl on the widget turns check:skill-examplesred with two error TS2322: Type 'string' is not assignable to type 'undefined' — one per retired key, z.never() surfacing as undefined in the input type. Mutation proven on disk before measuring (injected-text grep count 1; blob 4a5d1e256b5d8296), restore proven the same way (git diff HEAD empty, blob back to 4a5d1e25, injected count 0) — neither leg read from an editor's exit code. This gate exercises tsc only, so the Zod parse failure is asserted from the schema source, not measured here.
  4. Confirmed, with one restructure. Marked count 259 → 263, "every marked block parsed, so tsc ran the SEMANTIC pass on all of them". Two needed more than a marker: the record-detail page carried UI-E-03's unresolvable relative import (replaced with an inlined 4-line defineAction), and the defineDataset block was a fragment — it now imports defineDataset + type DashboardWidget and binds the trailing widget literal to a typed const.
  5. Not exercised — no finding's premise was false.

follow-up for objectstack-query

rules/filters.md is the anchor and is strong: it already carries the fixed tokens, the parameterised form, both session tokens, both resolvers, the calendar-DAY *_end trap, and — decisively — "Unknown tokens are rejected, not ignored". These TRUE rows from the deleted objectstack-ui text are not in it and were not ported:

  1. Both {token} and ${token} spellings are acceptedspec/src/data/date-macros.zod.ts:200,207 and context-tokens.zod.ts:101. rules/filters.md shows only the bare form.
  2. Two more near-misses: {user_id} (a valid titleFormat field interpolation elsewhere) and {organization_id} (the real column name). Query names {current_user} and {this_quarter_start} only.
  3. A token embedded in a larger string is not substituted ('user-{current_user_id}'). Query states only the converse; filter-tokens.ts:44 states this half directly — "Values that merely CONTAIN braces are left untouched."
  4. isDateMacroToken(tok) from @objectstack/spec/data as the author-time type check.
  5. The build rule's name, filter-token-unknown, and why it exists: an unresolved token reaches SQL as a literal, matches nothing, and the widget renders 0 — indistinguishable from a genuine zero.

follow-up for objectstack-data

references/data-hooks.md carries the org-isolation half completely — UI-C-02's deletion is safely routed there. It does not document ctx.session.positions at all; :368 says only that ctx.session has "No role listsession.roles was retired in 17.0.0". So the ADR-0090 D3 spelling and the "not an authorization input" guard have no anchor to point at, and a compact form was kept here rather than deleted into a gap.

Gates — all 42 families, all at head 684415c3

⚠️Correcting a stale figure this PR body previously carried. It claimed 16 families. That derivation ran at 0f937dcc, when the changeset was SKILL.md alone; the next commit added content/docs/ai/skills-reference.mdx and scripts/skill-identifier-liveness-ledger.json, and I did not re-derive. Re-derived at the current head, node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack names 42 — the 26 extra are the docs family the .mdx pulls in. All 42 have now been run; every one of the 26 that had never been run passes. The earlier "16" was wrong and is retracted here rather than quietly overwritten.

41 of 42 exit 0. Each exit code captured by redirecting before any pipe. The full list, in the order the harvester prints it:

check-ci-filter-parity · check-cross-package-test-inputs · check-doc-frontmatter · check-doc-route-spelling · check-docs-section-name · check-section-landing-index · check-shard-attestation · check-skills-token-ratchet · doc-formula-expressions · doc-security-posture · check:docs · check:empty-state · check:liveness · check:skill-docs · check:skill-examples · check:strictness-ledger · check:variant-docs · check:yaml-examples · agent-test-spelling · bash32-floor · cli-command-ids · corpus-claim-drift · cross-package-test-inputs · doc-anchors · doc-authoring · docs-audit-scope · docs-redirects · docs-single-h1 · entry-guard · merge-driver · parse-guard · pm-governed-merges · pnpm-filter-targets · published-readme-links · react-page-adapter-contract · role-word · skill-compatibility · skill-frame-sync · skill-identifier-liveness · vendor-version-stamps · watch-hint-literal — all exit 0.

Named verdict lines for the two the review asked for:

  • node scripts/check-skills-token-ratchet.mjsexit 0, "skills/objectstack-ui/SKILL.md is 22856 tokens (ceiling 25445; headroom 2589)" · "38 authored bundle file(s) within their ceilings".
  • pnpm --filter @objectstack/spec check:skill-examplesexit 0, "✅ 263 prose examples type-check across 3 surface(s) — every marked block parsed, so tsc ran the SEMANTIC pass on all of them".

The 42nd, node scripts/check-test-completeness.mjs, exits 3 = NOT MEASURED by its own verdict text ("Nothing was measured… It is not a red, and there is nothing here to fix") — it needs a saved turbo run test log. Recorded as NOT MEASURED: not a pass, not a red.

Heavy runs went through scripts/pm/os-verify-lock.sh with OS_VERIFY_LOCK_SLOT=issue-14298. Prerequisite builds re-run at this head, not assumed: @objectstack/spec and the @objectstack/client-react / @objectstack/client dependency closure — without the latter check:skill-examples refuses to run rather than reporting green ("packages/client-react/dist holds no .d.ts declarations… a FALSE GREEN on exactly the change it exists to catch").

Repo-wide pnpm lint (eslint over the whole tree) was NOT run — it is CI's own step, in this derivation's unnarrowable "always runs" tail. A plain omission, not a measured narrowing; I claim none of the three evidence items a narrowing would need.

Two consequences outside SKILL.md

Both generator/tool output, neither hand-written, each the mechanical consequence of a funded edit:

  • content/docs/ai/skills-reference.mdxgen:skill-docs, forced by the frontmatter edit (assumption 2). Not content/docs/releases/.
  • scripts/skill-identifier-liveness-ledger.jsoncheck-skill-identifier-liveness.mjs --update, pruning dayStart and showMidnight. Both existed only to excuse the timeSegments block this flight deleted, and each ledger note independently records the implementation living in objectui plugin-gantt — the same measurement UI-D-02 rests on. --update never adds an exemption.

Changeset

skip-changeset applies and is on the PR. Checked against the repo's own rule: the exemption means "this PR declares no release of its own", and no package publishes skills/, content/docs/ or scripts/. The Check Changeset job reads labels live; the label cannot be applied before the PR exists, so it was applied immediately after creation and read back.


🤖 Generated with Claude Code

https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1

os-litantand others added 4 commits September 2, 2026 01:59
…e/drilldown trims, filterBindings + widget options funded
UI-C-01 delete the date-macro + context-token block; keep the heading (two
in-file anchors resolve to it) and point at objectstack-query
rules/filters.md. Two UI-owned rules stay: presentation-scope-not-
security, and AppContextSelector ids never resolving in a filter.
UI-C-02 drop the org-isolation narration; keep the blessed-name pointer at
objectstack-data's hooks reference. `ctx.session.positions` stays in
compact form -- the anchor does not carry it (see PR follow-up list).
UI-D-08 Cube Best Practices -> the two enforced facts.
UI-D-05 delete the renderer note that ends by telling the reader to ignore it.
UI-D-06 delete the v17 `compareTo` removal narration.
UI-B-03 move the dateGranularity bucket table out of `### Drilldown` and under
its own heading (reorder only).
UI-G-02 falsehood 2: the dataset dimension is the DEFAULT; options.dateGranularity
overrides it per widget (dashboard.zod.ts:217-225).
UI-E-02 falsehood 1: delete the retired `actionType`/`actionUrl` pair from the
canonical dashboard widget (dashboard.zod.ts:382-384, retiredKey =
z.never()).
falsehood 4 (found in span, same defect class): `{current_user.id}` ->
`{current_user_id}`; `current_user.id` is the RLS expression root, not
a filter token (spec/src/data/context-tokens.zod.ts:44,49,85).
UI-F-01/F-03 ADD the globalFilters/filterBindings construct (paid by D-05+D-06).
UI-F-02 ADD the five declared widget `options` keys (paid by D-08+D-03-to-come).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…etired, relationships/conditional-rules pointed at objectstack-data
UI-D-01 keep the two tables and the `userActions: { search: false }` example;
delete the two verbatim `os validate` diagnostics, the empty-array
essay (folded into the row that already existed) and the related-title
prose (reduced to its objectstack-data pointer).
UI-D-02 delete the `timeSegments` block -- self-declared NOT part of
GanttConfigSchema, zero implementation in this repo (every hit is in
objectui plugin-gantt), and 10 of the package's 13 CJK lines.
UI-C-04 the inlineEdit ladder and the modelled grid behaviours point at
objectstack-data rules/relationships.md, which carries them verbatim.
Kept the three UI-authored facts the anchor does NOT carry: the ghost
row, `autofill: false`, and the form's `taxRateField`.
UI-C-03 delete the visibleWhen/readonlyWhen/requiredWhen table; keep the
routing line, the row-by-row inline-grid note and the retired
`conditionalRequired` guard.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…our highest-traffic examples gated
UI-A-01 add `*.page.ts` / `*.report.ts` / `*.dataset.ts` to the trigger list --
`*.page.ts` is the corpus's most-authored kind (29 definitions) and had
no filename trigger at all.
UI-A-02 falsehood 3: drop "the React renderer implementation (lives in
packages/client-react)". That package is React hooks for the client SDK
(package.json description; src/index.tsx exports hooks + provider). The
renderer is @object-ui/react-runtime, in objectui.
UI-A-03 wizards: a stepped form over ONE object is this skill's `formViews`
`type: 'wizard'`; only step-branching flows route to automation.
UI-D-07 keep the requirement, drop the removal history.
UI-D-03 delete the "Why this model" justification.
UI-D-04 reduce the metadata-fence rationale to the two facts the table lacks
(live-not-a-screenshot; data-not-code).
UI-B-06 delete "When to Use This Skill" -- it restated the frontmatter.
UI-B-05 the Tailwind rule now states the rule once and points at ADR-0065.
UI-G-03 translate the CJK example label. The two remaining CJK lines are
non-English USER PHRASINGS the router matches on -- see the PR body.
UI-E-03 inline a minimal defineAction so the record-detail page block stands
alone (the relative import could never resolve in the gate build dir).
UI-E-01 mark four highest-traffic examples `os:check`: structured definePage,
the Dashboard literal, defineDataset, the react source tier.
Gate: pnpm --filter @objectstack/spec check:skill-examples -- 259 -> 263 marked
blocks, "every marked block parsed, so tsc ran the SEMANTIC pass on all of them".
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…nd the timeSegments deletion
Two mechanical consequences, neither hand-written:
- `content/docs/ai/skills-reference.mdx` — `pnpm --filter @objectstack/spec
gen:skill-docs`. The dispatch predicted `skills/README.md` would be the file
the drift gate demands; it is not. README came back green on its own (it does
not embed the description); the out-of-date artifact is the reference page.
Both are outputs of the one generator the card names.
- `scripts/skill-identifier-liveness-ledger.json` — `node
scripts/check-skill-identifier-liveness.mjs --update`, pruning the now-stale
`dayStart` / `showMidnight` exemptions. Both existed only to excuse the
`timeSegments` block this flight deleted, and each ledger note independently
records that the implementation lives in objectui plugin-gantt -- the same
measurement UI-D-02 rests on. `--update` never ADDS an exemption.
Gates: check:skill-docs 0 (both artifacts ✓); check:skill-identifier-liveness 0
("Leg 1: 498 citations over 48 published files ... 3 ledgered exemptions").
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
@github-actionsgithub-actionsBot added size/l documentation Improvements or additions to documentation labels Sep 2, 2026
@os-litantos-litant added skip-changeset PR has no user-facing published change; bypasses the changeset gate needs:contract-review and removed documentation Improvements or additions to documentation labels Sep 2, 2026 — with Claude
…ding
In-seat contract review is right: my UI-D-08 retitle asserted enforcement that
does not exist, which is the same defect class this flight exists to remove.
Re-verified against the source, and the evidence is stronger than the review
cited:
- `granularities: z.array(TimeUpdateInterval).optional()`
(packages/spec/src/data/analytics.zod.ts:147) — optional, and the file
contains ZERO `.refine(` / `superRefine` occurrences, so nothing requires it
on a `time` dimension.
- Cube `sql: z.string().describe('Base SQL statement or Table Name')` (:216).
The describe string itself admits raw SQL; nothing rejects it at parse time,
and no gate script under scripts/ or packages/*/scripts/ references
`cube.sql`.
So there is no gate or schema refinement to cite, and the word is dropped rather
than defended. The two body items are unchanged: they are prescriptions with a
stated mechanism (`cube.sql.trim()` read as the object name), not claims of
enforcement.
Gates at this head: node scripts/check-skills-token-ratchet.mjs exit 0 --
SKILL.md 22856 tokens (ceiling 25445, headroom 2589); pnpm --filter
@objectstack/spec check:skill-examples exit 0 -- "263 prose examples type-check
across 3 surface(s)".
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
@github-actionsgithub-actionsBot added the documentation Improvements or additions to documentation label Sep 2, 2026
@os-litantos-litant changed the title skills(ui): optimization flight — date macros/relationships pointed at their anchors, searchableFields and timeSegments cut, dashboards consolidated, retired widget keys removed (net −2,583 tokens)skills(ui): optimization flight — date macros/relationships pointed at their anchors, searchableFields and timeSegments cut, dashboards consolidated, retired widget keys removed (net −2,585 tokens)Sep 2, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review September 2, 2026 06:18
@os-zhuang
os-zhuang added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit 54a1125Sep 2, 2026
45 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-14298-skills-ui-optimization branch September 2, 2026 06:41
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/lskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@os-litant@os-zhuang
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

skills(ui): optimization flight — date macros/relationships pointed at their anchors, searchableFields and timeSegments cut, dashboards consolidated, retired widget keys removed (net −2,585 tokens) - #14338

Merged
os-zhuang merged 5 commits into
mainfrom
claude/issue-14298-skills-ui-optimization
Sep 2, 2026
Merged

Conversation

@os-litant

@os-litantos-litant commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Part of #14298

Governed surface (skills/**) ⇒ this PR stays draft; needs:contract-review is on both carriers because falsehoods 1–2 are contract-semantics corrections. Head sha for every gate figure below: 684415c3.

Review round 1 — one FAIL, fixed

In-seat contract review flagged the UI-D-08 retitle ### Cube Rules (enforced) as asserting enforcement that does not exist. Correct, and the evidence is stronger than the review cited — re-verified at source:

  • granularities: z.array(TimeUpdateInterval).optional() (packages/spec/src/data/analytics.zod.ts:147), and that file contains zero.refine( / superRefine occurrences, so nothing requires it on a time dimension.
  • Cube sql: z.string().describe('Base SQL statement or Table Name') (:216) — the describe string itself admits raw SQL; nothing rejects it at parse time, and no gate script under scripts/ or packages/*/scripts/ references cube.sql.

There is no gate or schema refinement to cite, so the word is dropped, not defended: the heading is now ### Cube Rules. The two body items are unchanged — they are prescriptions with a stated mechanism (cube.sql.trim() read as the object name), not claims of enforcement. Shipping an unbacked "(enforced)" would have been the same defect class this flight exists to remove.

Open questions ruled by the seat: Q1 → C (UI-E-04 deprecated objectName/viewType, filed by the seat as its own card — nothing done here); Q2 → A (the two CJK trigger phrases stay).

Per-file token delta (ratchet convention, ceil(utf8 bytes / 4))

filebeforeafterdeltaceiling
skills/objectstack-ui/SKILL.md25,44122,856−2,58525,445 (headroom 4 → 2,589)
package total36,54233,957−2,585
whole shipped bundle187,854185,269−2,585

Generated package members untouched and unchanged: contracts/react-blocks.contract.json 5,352 · references/react-blocks.md 3,153 · references/_index.md 1,205. evals/** untouched (1,102 + 289). The ceiling is left at 25,445: the ratchet header says a ceiling "may be LOWERED by any PR that shrinks its file … always legitimate and encouraged", but the card's flight constraint forbids touching the ratchet script, so the 2,589 tokens of new headroom are deliberately NOT claimed here — a follow-up may lower the row to the measurement.

Against the card's target. The card targets ≈ −9,170, of which −5,352 is UI-B-04's duplicated generated JSON — explicitly DEFERRED to #14296 item 3 and not mine. The in-file target was −4,199 prose against +385 of additions; landed −2,585. The gap is itemised below rather than smoothed over: the three funded additions cost +838 against the estimated +385 (the filterBindings and widget-options constructs are each roughly double their estimate), and UI-D-01 returned −387 against an estimated −900. Every number below is a measured byte delta.

Per-item: 落点 | before | after

Deletions and merges

id落点beforeafter
UI-C-01## Date Macros — Filter Placeholders (whole section + ## Context Tokens)1,288 tok265 tok (−1,023)
UI-D-02### Shift segmentation — timeSegments581 tok0 (−581)
UI-C-04master-detail inlineEdit ladder + line-item grid behaviours643 tok193 tok (−450)
UI-D-01### Toolbar Search (searchableFields)1,381 tok994 tok (−387)
UI-D-05the options.drillDown renderer note235 tok0 (−235)
UI-C-02action ctx org-isolation + positions narration371 tok154 tok (−217)
UI-B-06## When to Use This Skill136 tok0 (−136)
UI-D-06the "Removed in v17" compareTo blockquote106 tok0 (−106)
UI-D-08### Cube Best Practices (5 items)159 tok74 tok (−85), retitled ### Cube Rules — see Review round 1
UI-D-04the metadata fence rationale145 tok75 tok (−70)
UI-D-03"Why this model" (build-independent / collision-free / responsive-correct)79 tok22 tok (−57)
UI-C-03the visibleWhen/readonlyWhen/requiredWhen table149 tok103 tok (−46)
UI-D-07the removed-inline-query history86 tok68 tok (−18)
UI-B-05the 4th Tailwind className restatement67 tok52 tok (−15)
UI-B-03the dateGranularity bucket table under ### Drilldown273 tok273 tok (0 — moved under its own heading; reorder is free)

The three funded additions

idwhat landedcostnamed payersactual
UI-F-01 + UI-F-03### Dashboard filters — globalFilters + per-widget filterBindings: the broadcast rule, name (defaults to field; name it for the vocabulary, not the column), scope: 'widget' + targetWidgets, re-target, false opt-out, the absent-default incl. dateRange.field ?? 'created_at', plus a 2-widget example+371UI-D-05 (−235) + UI-D-06 (−106)−341, so +30 over
UI-F-02### Widget options — the five declared keys (dateGranularity / sortBy / sortOrder / limit / stageOrder), with the top-N spelling that had no documented form+357UI-D-08 (−85) + UI-D-03 (−57)−142, so +215 over
UI-E-01os:check marks on the four highest-traffic examples (+ UI-E-03's inlined action)+110UI-E-02 (−18)+92 over

The three additions cost +838 against −501 of named payers. They are nonetheless fully paid in the same file: the flight's total deletions are −3,423, so SKILL.md ends 2,585 tokens smaller and the ratchet is green with 2,589 tokens of headroom. Flagging the per-item overrun rather than re-cutting the payer list to fit, because the card's funding lines are its ruling and I would rather show them broken than silently re-derive them.

Falsehoods

#落点beforeafter
1canonical dashboard widgetactionType: 'url', actionUrl: '/objects/opportunity?filter=open'line deleted. dashboard.zod.ts:382-384 retires all three via retiredKey(...) = z.never(); prescription :309-320 "a dashboard widget has NO action button, and never had one".
2### Server-side date bucketing"Date bucketing lives on the dataset dimension, not the widget.""The dataset dimension carries the default; a widget's options.dateGranularity overrides it for that widget only." (dashboard.zod.ts:217-225)
3frontmatter"the React renderer implementation (lives in packages/client-react, not metadata)"clause deleted. packages/client-react is "React hooks for ObjectStack Client SDK"; the renderer is @object-ui/react-runtime, in objectui.
4 (new)the Tokens-in-filters blockquote on the canonical dashboard{current_user.id}{current_user_id}. current_user.id is the RLS expression root, not a filter token — spec/src/data/context-tokens.zod.ts:44,49 names this exact near-miss and :85 lists the real token. Found inside a span this flight was already rewriting, same defect class as 1–2, mechanically fixed against the spec; taken under the bounded-in-place rule.

Also deleted, never ported (card ruling): this package's claim that "unknown placeholders silently pass through as literal strings". It is false and the file contradicted itself 37 lines earlier. packages/core/src/utils/filter-tokens.ts:378 throws UnknownFilterTokenError, and the module header at :44 is titled "An unknown token throws".

Deliberate deviations from the routed plan

  1. UI-C-01 keeps its ## heading. The ruling says delete :1659-1768. Two in-file links (:1074, :1507) target #date-macros--filter-placeholders; deleting the heading breaks both, so the heading survives carrying the pointer. Also kept: two rules objectstack-query does not own — a filter token is presentation scope, not security; and AppContextSelector ids resolve in navigation recordId/params only, never in a filter. Both were their last mention in the package.
  2. UI-C-02 keeps ctx.session.positions in compact form. The routed anchor does not carry it (see follow-ups). Kept with the "not an authorization input" guard; the org-isolation half is deleted and pointed.
  3. UI-G-03 translates 1 of 3 CJK lines, not 3label: '打印总表(A3)''Print Summary Sheet (A3)'. The two at :755-756 are non-English user phrasings the router matches on; translating a phrase whose only job is to match untranslated input destroys it. Seat ruled A: they stay.
  4. The ratchet ceiling is not lowered — see the token table.

Not implemented (and why)

premise_false

None. git diff --stat a59f78d origin/main -- skills/objectstack-ui is empty, so every audit span was byte-identical at the branch point. Two PM mechanical assumptions were refined rather than confirmed — below.

PM mechanical assumptions — measured

  1. Confirmed.skills/objectstack-ui/** byte-identical between a59f78d and origin/main. (origin/main had already moved past the dispatch's d63c8a25 to 909a4417, which does not touch skills/; the branch is cut from 909a4417.)
  2. Refined — the predicted file is the wrong one.check:skill-docs does run in CI and the frontmatter edit does force a regeneration, but skills/README.md came back green on its own (✓ skills/README.md) — it does not embed the description. The out-of-date artifact was content/docs/ai/skills-reference.mdx. Regenerated with the one generator the card names; the diff is 2 lines, both the frontmatter's own text.
  3. Confirmed for tsc; the parse half not measured. Reverse-verified against a committed tree: re-injecting actionType/actionUrl on the widget turns check:skill-examplesred with two error TS2322: Type 'string' is not assignable to type 'undefined' — one per retired key, z.never() surfacing as undefined in the input type. Mutation proven on disk before measuring (injected-text grep count 1; blob 4a5d1e256b5d8296), restore proven the same way (git diff HEAD empty, blob back to 4a5d1e25, injected count 0) — neither leg read from an editor's exit code. This gate exercises tsc only, so the Zod parse failure is asserted from the schema source, not measured here.
  4. Confirmed, with one restructure. Marked count 259 → 263, "every marked block parsed, so tsc ran the SEMANTIC pass on all of them". Two needed more than a marker: the record-detail page carried UI-E-03's unresolvable relative import (replaced with an inlined 4-line defineAction), and the defineDataset block was a fragment — it now imports defineDataset + type DashboardWidget and binds the trailing widget literal to a typed const.
  5. Not exercised — no finding's premise was false.

follow-up for objectstack-query

rules/filters.md is the anchor and is strong: it already carries the fixed tokens, the parameterised form, both session tokens, both resolvers, the calendar-DAY *_end trap, and — decisively — "Unknown tokens are rejected, not ignored". These TRUE rows from the deleted objectstack-ui text are not in it and were not ported:

  1. Both {token} and ${token} spellings are acceptedspec/src/data/date-macros.zod.ts:200,207 and context-tokens.zod.ts:101. rules/filters.md shows only the bare form.
  2. Two more near-misses: {user_id} (a valid titleFormat field interpolation elsewhere) and {organization_id} (the real column name). Query names {current_user} and {this_quarter_start} only.
  3. A token embedded in a larger string is not substituted ('user-{current_user_id}'). Query states only the converse; filter-tokens.ts:44 states this half directly — "Values that merely CONTAIN braces are left untouched."
  4. isDateMacroToken(tok) from @objectstack/spec/data as the author-time type check.
  5. The build rule's name, filter-token-unknown, and why it exists: an unresolved token reaches SQL as a literal, matches nothing, and the widget renders 0 — indistinguishable from a genuine zero.

follow-up for objectstack-data

references/data-hooks.md carries the org-isolation half completely — UI-C-02's deletion is safely routed there. It does not document ctx.session.positions at all; :368 says only that ctx.session has "No role listsession.roles was retired in 17.0.0". So the ADR-0090 D3 spelling and the "not an authorization input" guard have no anchor to point at, and a compact form was kept here rather than deleted into a gap.

Gates — all 42 families, all at head 684415c3

⚠️Correcting a stale figure this PR body previously carried. It claimed 16 families. That derivation ran at 0f937dcc, when the changeset was SKILL.md alone; the next commit added content/docs/ai/skills-reference.mdx and scripts/skill-identifier-liveness-ledger.json, and I did not re-derive. Re-derived at the current head, node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack names 42 — the 26 extra are the docs family the .mdx pulls in. All 42 have now been run; every one of the 26 that had never been run passes. The earlier "16" was wrong and is retracted here rather than quietly overwritten.

41 of 42 exit 0. Each exit code captured by redirecting before any pipe. The full list, in the order the harvester prints it:

check-ci-filter-parity · check-cross-package-test-inputs · check-doc-frontmatter · check-doc-route-spelling · check-docs-section-name · check-section-landing-index · check-shard-attestation · check-skills-token-ratchet · doc-formula-expressions · doc-security-posture · check:docs · check:empty-state · check:liveness · check:skill-docs · check:skill-examples · check:strictness-ledger · check:variant-docs · check:yaml-examples · agent-test-spelling · bash32-floor · cli-command-ids · corpus-claim-drift · cross-package-test-inputs · doc-anchors · doc-authoring · docs-audit-scope · docs-redirects · docs-single-h1 · entry-guard · merge-driver · parse-guard · pm-governed-merges · pnpm-filter-targets · published-readme-links · react-page-adapter-contract · role-word · skill-compatibility · skill-frame-sync · skill-identifier-liveness · vendor-version-stamps · watch-hint-literal — all exit 0.

Named verdict lines for the two the review asked for:

  • node scripts/check-skills-token-ratchet.mjsexit 0, "skills/objectstack-ui/SKILL.md is 22856 tokens (ceiling 25445; headroom 2589)" · "38 authored bundle file(s) within their ceilings".
  • pnpm --filter @objectstack/spec check:skill-examplesexit 0, "✅ 263 prose examples type-check across 3 surface(s) — every marked block parsed, so tsc ran the SEMANTIC pass on all of them".

The 42nd, node scripts/check-test-completeness.mjs, exits 3 = NOT MEASURED by its own verdict text ("Nothing was measured… It is not a red, and there is nothing here to fix") — it needs a saved turbo run test log. Recorded as NOT MEASURED: not a pass, not a red.

Heavy runs went through scripts/pm/os-verify-lock.sh with OS_VERIFY_LOCK_SLOT=issue-14298. Prerequisite builds re-run at this head, not assumed: @objectstack/spec and the @objectstack/client-react / @objectstack/client dependency closure — without the latter check:skill-examples refuses to run rather than reporting green ("packages/client-react/dist holds no .d.ts declarations… a FALSE GREEN on exactly the change it exists to catch").

Repo-wide pnpm lint (eslint over the whole tree) was NOT run — it is CI's own step, in this derivation's unnarrowable "always runs" tail. A plain omission, not a measured narrowing; I claim none of the three evidence items a narrowing would need.

Two consequences outside SKILL.md

Both generator/tool output, neither hand-written, each the mechanical consequence of a funded edit:

  • content/docs/ai/skills-reference.mdxgen:skill-docs, forced by the frontmatter edit (assumption 2). Not content/docs/releases/.
  • scripts/skill-identifier-liveness-ledger.jsoncheck-skill-identifier-liveness.mjs --update, pruning dayStart and showMidnight. Both existed only to excuse the timeSegments block this flight deleted, and each ledger note independently records the implementation living in objectui plugin-gantt — the same measurement UI-D-02 rests on. --update never adds an exemption.

Changeset

skip-changeset applies and is on the PR. Checked against the repo's own rule: the exemption means "this PR declares no release of its own", and no package publishes skills/, content/docs/ or scripts/. The Check Changeset job reads labels live; the label cannot be applied before the PR exists, so it was applied immediately after creation and read back.


🤖 Generated with Claude Code

https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1

os-litantand others added 4 commits September 2, 2026 01:59
…e/drilldown trims, filterBindings + widget options funded
UI-C-01 delete the date-macro + context-token block; keep the heading (two
in-file anchors resolve to it) and point at objectstack-query
rules/filters.md. Two UI-owned rules stay: presentation-scope-not-
security, and AppContextSelector ids never resolving in a filter.
UI-C-02 drop the org-isolation narration; keep the blessed-name pointer at
objectstack-data's hooks reference. `ctx.session.positions` stays in
compact form -- the anchor does not carry it (see PR follow-up list).
UI-D-08 Cube Best Practices -> the two enforced facts.
UI-D-05 delete the renderer note that ends by telling the reader to ignore it.
UI-D-06 delete the v17 `compareTo` removal narration.
UI-B-03 move the dateGranularity bucket table out of `### Drilldown` and under
its own heading (reorder only).
UI-G-02 falsehood 2: the dataset dimension is the DEFAULT; options.dateGranularity
overrides it per widget (dashboard.zod.ts:217-225).
UI-E-02 falsehood 1: delete the retired `actionType`/`actionUrl` pair from the
canonical dashboard widget (dashboard.zod.ts:382-384, retiredKey =
z.never()).
falsehood 4 (found in span, same defect class): `{current_user.id}` ->
`{current_user_id}`; `current_user.id` is the RLS expression root, not
a filter token (spec/src/data/context-tokens.zod.ts:44,49,85).
UI-F-01/F-03 ADD the globalFilters/filterBindings construct (paid by D-05+D-06).
UI-F-02 ADD the five declared widget `options` keys (paid by D-08+D-03-to-come).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…etired, relationships/conditional-rules pointed at objectstack-data
UI-D-01 keep the two tables and the `userActions: { search: false }` example;
delete the two verbatim `os validate` diagnostics, the empty-array
essay (folded into the row that already existed) and the related-title
prose (reduced to its objectstack-data pointer).
UI-D-02 delete the `timeSegments` block -- self-declared NOT part of
GanttConfigSchema, zero implementation in this repo (every hit is in
objectui plugin-gantt), and 10 of the package's 13 CJK lines.
UI-C-04 the inlineEdit ladder and the modelled grid behaviours point at
objectstack-data rules/relationships.md, which carries them verbatim.
Kept the three UI-authored facts the anchor does NOT carry: the ghost
row, `autofill: false`, and the form's `taxRateField`.
UI-C-03 delete the visibleWhen/readonlyWhen/requiredWhen table; keep the
routing line, the row-by-row inline-grid note and the retired
`conditionalRequired` guard.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…our highest-traffic examples gated
UI-A-01 add `*.page.ts` / `*.report.ts` / `*.dataset.ts` to the trigger list --
`*.page.ts` is the corpus's most-authored kind (29 definitions) and had
no filename trigger at all.
UI-A-02 falsehood 3: drop "the React renderer implementation (lives in
packages/client-react)". That package is React hooks for the client SDK
(package.json description; src/index.tsx exports hooks + provider). The
renderer is @object-ui/react-runtime, in objectui.
UI-A-03 wizards: a stepped form over ONE object is this skill's `formViews`
`type: 'wizard'`; only step-branching flows route to automation.
UI-D-07 keep the requirement, drop the removal history.
UI-D-03 delete the "Why this model" justification.
UI-D-04 reduce the metadata-fence rationale to the two facts the table lacks
(live-not-a-screenshot; data-not-code).
UI-B-06 delete "When to Use This Skill" -- it restated the frontmatter.
UI-B-05 the Tailwind rule now states the rule once and points at ADR-0065.
UI-G-03 translate the CJK example label. The two remaining CJK lines are
non-English USER PHRASINGS the router matches on -- see the PR body.
UI-E-03 inline a minimal defineAction so the record-detail page block stands
alone (the relative import could never resolve in the gate build dir).
UI-E-01 mark four highest-traffic examples `os:check`: structured definePage,
the Dashboard literal, defineDataset, the react source tier.
Gate: pnpm --filter @objectstack/spec check:skill-examples -- 259 -> 263 marked
blocks, "every marked block parsed, so tsc ran the SEMANTIC pass on all of them".
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…nd the timeSegments deletion
Two mechanical consequences, neither hand-written:
- `content/docs/ai/skills-reference.mdx` — `pnpm --filter @objectstack/spec
gen:skill-docs`. The dispatch predicted `skills/README.md` would be the file
the drift gate demands; it is not. README came back green on its own (it does
not embed the description); the out-of-date artifact is the reference page.
Both are outputs of the one generator the card names.
- `scripts/skill-identifier-liveness-ledger.json` — `node
scripts/check-skill-identifier-liveness.mjs --update`, pruning the now-stale
`dayStart` / `showMidnight` exemptions. Both existed only to excuse the
`timeSegments` block this flight deleted, and each ledger note independently
records that the implementation lives in objectui plugin-gantt -- the same
measurement UI-D-02 rests on. `--update` never ADDS an exemption.
Gates: check:skill-docs 0 (both artifacts ✓); check:skill-identifier-liveness 0
("Leg 1: 498 citations over 48 published files ... 3 ledgered exemptions").
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
@github-actionsgithub-actionsBot added size/l documentation Improvements or additions to documentation labels Sep 2, 2026
@os-litantos-litant added skip-changeset PR has no user-facing published change; bypasses the changeset gate needs:contract-review and removed documentation Improvements or additions to documentation labels Sep 2, 2026 — with Claude
…ding
In-seat contract review is right: my UI-D-08 retitle asserted enforcement that
does not exist, which is the same defect class this flight exists to remove.
Re-verified against the source, and the evidence is stronger than the review
cited:
- `granularities: z.array(TimeUpdateInterval).optional()`
(packages/spec/src/data/analytics.zod.ts:147) — optional, and the file
contains ZERO `.refine(` / `superRefine` occurrences, so nothing requires it
on a `time` dimension.
- Cube `sql: z.string().describe('Base SQL statement or Table Name')` (:216).
The describe string itself admits raw SQL; nothing rejects it at parse time,
and no gate script under scripts/ or packages/*/scripts/ references
`cube.sql`.
So there is no gate or schema refinement to cite, and the word is dropped rather
than defended. The two body items are unchanged: they are prescriptions with a
stated mechanism (`cube.sql.trim()` read as the object name), not claims of
enforcement.
Gates at this head: node scripts/check-skills-token-ratchet.mjs exit 0 --
SKILL.md 22856 tokens (ceiling 25445, headroom 2589); pnpm --filter
@objectstack/spec check:skill-examples exit 0 -- "263 prose examples type-check
across 3 surface(s)".
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
@github-actionsgithub-actionsBot added the documentation Improvements or additions to documentation label Sep 2, 2026
@os-litantos-litant changed the title skills(ui): optimization flight — date macros/relationships pointed at their anchors, searchableFields and timeSegments cut, dashboards consolidated, retired widget keys removed (net −2,583 tokens)skills(ui): optimization flight — date macros/relationships pointed at their anchors, searchableFields and timeSegments cut, dashboards consolidated, retired widget keys removed (net −2,585 tokens)Sep 2, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review September 2, 2026 06:18
@os-zhuang
os-zhuang added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit 54a1125Sep 2, 2026
45 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-14298-skills-ui-optimization branch September 2, 2026 06:41
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/lskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@os-litant@os-zhuang
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

skills(ui): optimization flight — date macros/relationships pointed at their anchors, searchableFields and timeSegments cut, dashboards consolidated, retired widget keys removed (net −2,585 tokens) - #14338

Merged
os-zhuang merged 5 commits into
mainfrom
claude/issue-14298-skills-ui-optimization
Sep 2, 2026
Merged

Conversation

@os-litant

@os-litantos-litant commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Part of #14298

Governed surface (skills/**) ⇒ this PR stays draft; needs:contract-review is on both carriers because falsehoods 1–2 are contract-semantics corrections. Head sha for every gate figure below: 684415c3.

Review round 1 — one FAIL, fixed

In-seat contract review flagged the UI-D-08 retitle ### Cube Rules (enforced) as asserting enforcement that does not exist. Correct, and the evidence is stronger than the review cited — re-verified at source:

  • granularities: z.array(TimeUpdateInterval).optional() (packages/spec/src/data/analytics.zod.ts:147), and that file contains zero.refine( / superRefine occurrences, so nothing requires it on a time dimension.
  • Cube sql: z.string().describe('Base SQL statement or Table Name') (:216) — the describe string itself admits raw SQL; nothing rejects it at parse time, and no gate script under scripts/ or packages/*/scripts/ references cube.sql.

There is no gate or schema refinement to cite, so the word is dropped, not defended: the heading is now ### Cube Rules. The two body items are unchanged — they are prescriptions with a stated mechanism (cube.sql.trim() read as the object name), not claims of enforcement. Shipping an unbacked "(enforced)" would have been the same defect class this flight exists to remove.

Open questions ruled by the seat: Q1 → C (UI-E-04 deprecated objectName/viewType, filed by the seat as its own card — nothing done here); Q2 → A (the two CJK trigger phrases stay).

Per-file token delta (ratchet convention, ceil(utf8 bytes / 4))

filebeforeafterdeltaceiling
skills/objectstack-ui/SKILL.md25,44122,856−2,58525,445 (headroom 4 → 2,589)
package total36,54233,957−2,585
whole shipped bundle187,854185,269−2,585

Generated package members untouched and unchanged: contracts/react-blocks.contract.json 5,352 · references/react-blocks.md 3,153 · references/_index.md 1,205. evals/** untouched (1,102 + 289). The ceiling is left at 25,445: the ratchet header says a ceiling "may be LOWERED by any PR that shrinks its file … always legitimate and encouraged", but the card's flight constraint forbids touching the ratchet script, so the 2,589 tokens of new headroom are deliberately NOT claimed here — a follow-up may lower the row to the measurement.

Against the card's target. The card targets ≈ −9,170, of which −5,352 is UI-B-04's duplicated generated JSON — explicitly DEFERRED to #14296 item 3 and not mine. The in-file target was −4,199 prose against +385 of additions; landed −2,585. The gap is itemised below rather than smoothed over: the three funded additions cost +838 against the estimated +385 (the filterBindings and widget-options constructs are each roughly double their estimate), and UI-D-01 returned −387 against an estimated −900. Every number below is a measured byte delta.

Per-item: 落点 | before | after

Deletions and merges

id落点beforeafter
UI-C-01## Date Macros — Filter Placeholders (whole section + ## Context Tokens)1,288 tok265 tok (−1,023)
UI-D-02### Shift segmentation — timeSegments581 tok0 (−581)
UI-C-04master-detail inlineEdit ladder + line-item grid behaviours643 tok193 tok (−450)
UI-D-01### Toolbar Search (searchableFields)1,381 tok994 tok (−387)
UI-D-05the options.drillDown renderer note235 tok0 (−235)
UI-C-02action ctx org-isolation + positions narration371 tok154 tok (−217)
UI-B-06## When to Use This Skill136 tok0 (−136)
UI-D-06the "Removed in v17" compareTo blockquote106 tok0 (−106)
UI-D-08### Cube Best Practices (5 items)159 tok74 tok (−85), retitled ### Cube Rules — see Review round 1
UI-D-04the metadata fence rationale145 tok75 tok (−70)
UI-D-03"Why this model" (build-independent / collision-free / responsive-correct)79 tok22 tok (−57)
UI-C-03the visibleWhen/readonlyWhen/requiredWhen table149 tok103 tok (−46)
UI-D-07the removed-inline-query history86 tok68 tok (−18)
UI-B-05the 4th Tailwind className restatement67 tok52 tok (−15)
UI-B-03the dateGranularity bucket table under ### Drilldown273 tok273 tok (0 — moved under its own heading; reorder is free)

The three funded additions

idwhat landedcostnamed payersactual
UI-F-01 + UI-F-03### Dashboard filters — globalFilters + per-widget filterBindings: the broadcast rule, name (defaults to field; name it for the vocabulary, not the column), scope: 'widget' + targetWidgets, re-target, false opt-out, the absent-default incl. dateRange.field ?? 'created_at', plus a 2-widget example+371UI-D-05 (−235) + UI-D-06 (−106)−341, so +30 over
UI-F-02### Widget options — the five declared keys (dateGranularity / sortBy / sortOrder / limit / stageOrder), with the top-N spelling that had no documented form+357UI-D-08 (−85) + UI-D-03 (−57)−142, so +215 over
UI-E-01os:check marks on the four highest-traffic examples (+ UI-E-03's inlined action)+110UI-E-02 (−18)+92 over

The three additions cost +838 against −501 of named payers. They are nonetheless fully paid in the same file: the flight's total deletions are −3,423, so SKILL.md ends 2,585 tokens smaller and the ratchet is green with 2,589 tokens of headroom. Flagging the per-item overrun rather than re-cutting the payer list to fit, because the card's funding lines are its ruling and I would rather show them broken than silently re-derive them.

Falsehoods

#落点beforeafter
1canonical dashboard widgetactionType: 'url', actionUrl: '/objects/opportunity?filter=open'line deleted. dashboard.zod.ts:382-384 retires all three via retiredKey(...) = z.never(); prescription :309-320 "a dashboard widget has NO action button, and never had one".
2### Server-side date bucketing"Date bucketing lives on the dataset dimension, not the widget.""The dataset dimension carries the default; a widget's options.dateGranularity overrides it for that widget only." (dashboard.zod.ts:217-225)
3frontmatter"the React renderer implementation (lives in packages/client-react, not metadata)"clause deleted. packages/client-react is "React hooks for ObjectStack Client SDK"; the renderer is @object-ui/react-runtime, in objectui.
4 (new)the Tokens-in-filters blockquote on the canonical dashboard{current_user.id}{current_user_id}. current_user.id is the RLS expression root, not a filter token — spec/src/data/context-tokens.zod.ts:44,49 names this exact near-miss and :85 lists the real token. Found inside a span this flight was already rewriting, same defect class as 1–2, mechanically fixed against the spec; taken under the bounded-in-place rule.

Also deleted, never ported (card ruling): this package's claim that "unknown placeholders silently pass through as literal strings". It is false and the file contradicted itself 37 lines earlier. packages/core/src/utils/filter-tokens.ts:378 throws UnknownFilterTokenError, and the module header at :44 is titled "An unknown token throws".

Deliberate deviations from the routed plan

  1. UI-C-01 keeps its ## heading. The ruling says delete :1659-1768. Two in-file links (:1074, :1507) target #date-macros--filter-placeholders; deleting the heading breaks both, so the heading survives carrying the pointer. Also kept: two rules objectstack-query does not own — a filter token is presentation scope, not security; and AppContextSelector ids resolve in navigation recordId/params only, never in a filter. Both were their last mention in the package.
  2. UI-C-02 keeps ctx.session.positions in compact form. The routed anchor does not carry it (see follow-ups). Kept with the "not an authorization input" guard; the org-isolation half is deleted and pointed.
  3. UI-G-03 translates 1 of 3 CJK lines, not 3label: '打印总表(A3)''Print Summary Sheet (A3)'. The two at :755-756 are non-English user phrasings the router matches on; translating a phrase whose only job is to match untranslated input destroys it. Seat ruled A: they stay.
  4. The ratchet ceiling is not lowered — see the token table.

Not implemented (and why)

premise_false

None. git diff --stat a59f78d origin/main -- skills/objectstack-ui is empty, so every audit span was byte-identical at the branch point. Two PM mechanical assumptions were refined rather than confirmed — below.

PM mechanical assumptions — measured

  1. Confirmed.skills/objectstack-ui/** byte-identical between a59f78d and origin/main. (origin/main had already moved past the dispatch's d63c8a25 to 909a4417, which does not touch skills/; the branch is cut from 909a4417.)
  2. Refined — the predicted file is the wrong one.check:skill-docs does run in CI and the frontmatter edit does force a regeneration, but skills/README.md came back green on its own (✓ skills/README.md) — it does not embed the description. The out-of-date artifact was content/docs/ai/skills-reference.mdx. Regenerated with the one generator the card names; the diff is 2 lines, both the frontmatter's own text.
  3. Confirmed for tsc; the parse half not measured. Reverse-verified against a committed tree: re-injecting actionType/actionUrl on the widget turns check:skill-examplesred with two error TS2322: Type 'string' is not assignable to type 'undefined' — one per retired key, z.never() surfacing as undefined in the input type. Mutation proven on disk before measuring (injected-text grep count 1; blob 4a5d1e256b5d8296), restore proven the same way (git diff HEAD empty, blob back to 4a5d1e25, injected count 0) — neither leg read from an editor's exit code. This gate exercises tsc only, so the Zod parse failure is asserted from the schema source, not measured here.
  4. Confirmed, with one restructure. Marked count 259 → 263, "every marked block parsed, so tsc ran the SEMANTIC pass on all of them". Two needed more than a marker: the record-detail page carried UI-E-03's unresolvable relative import (replaced with an inlined 4-line defineAction), and the defineDataset block was a fragment — it now imports defineDataset + type DashboardWidget and binds the trailing widget literal to a typed const.
  5. Not exercised — no finding's premise was false.

follow-up for objectstack-query

rules/filters.md is the anchor and is strong: it already carries the fixed tokens, the parameterised form, both session tokens, both resolvers, the calendar-DAY *_end trap, and — decisively — "Unknown tokens are rejected, not ignored". These TRUE rows from the deleted objectstack-ui text are not in it and were not ported:

  1. Both {token} and ${token} spellings are acceptedspec/src/data/date-macros.zod.ts:200,207 and context-tokens.zod.ts:101. rules/filters.md shows only the bare form.
  2. Two more near-misses: {user_id} (a valid titleFormat field interpolation elsewhere) and {organization_id} (the real column name). Query names {current_user} and {this_quarter_start} only.
  3. A token embedded in a larger string is not substituted ('user-{current_user_id}'). Query states only the converse; filter-tokens.ts:44 states this half directly — "Values that merely CONTAIN braces are left untouched."
  4. isDateMacroToken(tok) from @objectstack/spec/data as the author-time type check.
  5. The build rule's name, filter-token-unknown, and why it exists: an unresolved token reaches SQL as a literal, matches nothing, and the widget renders 0 — indistinguishable from a genuine zero.

follow-up for objectstack-data

references/data-hooks.md carries the org-isolation half completely — UI-C-02's deletion is safely routed there. It does not document ctx.session.positions at all; :368 says only that ctx.session has "No role listsession.roles was retired in 17.0.0". So the ADR-0090 D3 spelling and the "not an authorization input" guard have no anchor to point at, and a compact form was kept here rather than deleted into a gap.

Gates — all 42 families, all at head 684415c3

⚠️Correcting a stale figure this PR body previously carried. It claimed 16 families. That derivation ran at 0f937dcc, when the changeset was SKILL.md alone; the next commit added content/docs/ai/skills-reference.mdx and scripts/skill-identifier-liveness-ledger.json, and I did not re-derive. Re-derived at the current head, node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack names 42 — the 26 extra are the docs family the .mdx pulls in. All 42 have now been run; every one of the 26 that had never been run passes. The earlier "16" was wrong and is retracted here rather than quietly overwritten.

41 of 42 exit 0. Each exit code captured by redirecting before any pipe. The full list, in the order the harvester prints it:

check-ci-filter-parity · check-cross-package-test-inputs · check-doc-frontmatter · check-doc-route-spelling · check-docs-section-name · check-section-landing-index · check-shard-attestation · check-skills-token-ratchet · doc-formula-expressions · doc-security-posture · check:docs · check:empty-state · check:liveness · check:skill-docs · check:skill-examples · check:strictness-ledger · check:variant-docs · check:yaml-examples · agent-test-spelling · bash32-floor · cli-command-ids · corpus-claim-drift · cross-package-test-inputs · doc-anchors · doc-authoring · docs-audit-scope · docs-redirects · docs-single-h1 · entry-guard · merge-driver · parse-guard · pm-governed-merges · pnpm-filter-targets · published-readme-links · react-page-adapter-contract · role-word · skill-compatibility · skill-frame-sync · skill-identifier-liveness · vendor-version-stamps · watch-hint-literal — all exit 0.

Named verdict lines for the two the review asked for:

  • node scripts/check-skills-token-ratchet.mjsexit 0, "skills/objectstack-ui/SKILL.md is 22856 tokens (ceiling 25445; headroom 2589)" · "38 authored bundle file(s) within their ceilings".
  • pnpm --filter @objectstack/spec check:skill-examplesexit 0, "✅ 263 prose examples type-check across 3 surface(s) — every marked block parsed, so tsc ran the SEMANTIC pass on all of them".

The 42nd, node scripts/check-test-completeness.mjs, exits 3 = NOT MEASURED by its own verdict text ("Nothing was measured… It is not a red, and there is nothing here to fix") — it needs a saved turbo run test log. Recorded as NOT MEASURED: not a pass, not a red.

Heavy runs went through scripts/pm/os-verify-lock.sh with OS_VERIFY_LOCK_SLOT=issue-14298. Prerequisite builds re-run at this head, not assumed: @objectstack/spec and the @objectstack/client-react / @objectstack/client dependency closure — without the latter check:skill-examples refuses to run rather than reporting green ("packages/client-react/dist holds no .d.ts declarations… a FALSE GREEN on exactly the change it exists to catch").

Repo-wide pnpm lint (eslint over the whole tree) was NOT run — it is CI's own step, in this derivation's unnarrowable "always runs" tail. A plain omission, not a measured narrowing; I claim none of the three evidence items a narrowing would need.

Two consequences outside SKILL.md

Both generator/tool output, neither hand-written, each the mechanical consequence of a funded edit:

  • content/docs/ai/skills-reference.mdxgen:skill-docs, forced by the frontmatter edit (assumption 2). Not content/docs/releases/.
  • scripts/skill-identifier-liveness-ledger.jsoncheck-skill-identifier-liveness.mjs --update, pruning dayStart and showMidnight. Both existed only to excuse the timeSegments block this flight deleted, and each ledger note independently records the implementation living in objectui plugin-gantt — the same measurement UI-D-02 rests on. --update never adds an exemption.

Changeset

skip-changeset applies and is on the PR. Checked against the repo's own rule: the exemption means "this PR declares no release of its own", and no package publishes skills/, content/docs/ or scripts/. The Check Changeset job reads labels live; the label cannot be applied before the PR exists, so it was applied immediately after creation and read back.


🤖 Generated with Claude Code

https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1

os-litantand others added 4 commits September 2, 2026 01:59
…e/drilldown trims, filterBindings + widget options funded
UI-C-01 delete the date-macro + context-token block; keep the heading (two
in-file anchors resolve to it) and point at objectstack-query
rules/filters.md. Two UI-owned rules stay: presentation-scope-not-
security, and AppContextSelector ids never resolving in a filter.
UI-C-02 drop the org-isolation narration; keep the blessed-name pointer at
objectstack-data's hooks reference. `ctx.session.positions` stays in
compact form -- the anchor does not carry it (see PR follow-up list).
UI-D-08 Cube Best Practices -> the two enforced facts.
UI-D-05 delete the renderer note that ends by telling the reader to ignore it.
UI-D-06 delete the v17 `compareTo` removal narration.
UI-B-03 move the dateGranularity bucket table out of `### Drilldown` and under
its own heading (reorder only).
UI-G-02 falsehood 2: the dataset dimension is the DEFAULT; options.dateGranularity
overrides it per widget (dashboard.zod.ts:217-225).
UI-E-02 falsehood 1: delete the retired `actionType`/`actionUrl` pair from the
canonical dashboard widget (dashboard.zod.ts:382-384, retiredKey =
z.never()).
falsehood 4 (found in span, same defect class): `{current_user.id}` ->
`{current_user_id}`; `current_user.id` is the RLS expression root, not
a filter token (spec/src/data/context-tokens.zod.ts:44,49,85).
UI-F-01/F-03 ADD the globalFilters/filterBindings construct (paid by D-05+D-06).
UI-F-02 ADD the five declared widget `options` keys (paid by D-08+D-03-to-come).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…etired, relationships/conditional-rules pointed at objectstack-data
UI-D-01 keep the two tables and the `userActions: { search: false }` example;
delete the two verbatim `os validate` diagnostics, the empty-array
essay (folded into the row that already existed) and the related-title
prose (reduced to its objectstack-data pointer).
UI-D-02 delete the `timeSegments` block -- self-declared NOT part of
GanttConfigSchema, zero implementation in this repo (every hit is in
objectui plugin-gantt), and 10 of the package's 13 CJK lines.
UI-C-04 the inlineEdit ladder and the modelled grid behaviours point at
objectstack-data rules/relationships.md, which carries them verbatim.
Kept the three UI-authored facts the anchor does NOT carry: the ghost
row, `autofill: false`, and the form's `taxRateField`.
UI-C-03 delete the visibleWhen/readonlyWhen/requiredWhen table; keep the
routing line, the row-by-row inline-grid note and the retired
`conditionalRequired` guard.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…our highest-traffic examples gated
UI-A-01 add `*.page.ts` / `*.report.ts` / `*.dataset.ts` to the trigger list --
`*.page.ts` is the corpus's most-authored kind (29 definitions) and had
no filename trigger at all.
UI-A-02 falsehood 3: drop "the React renderer implementation (lives in
packages/client-react)". That package is React hooks for the client SDK
(package.json description; src/index.tsx exports hooks + provider). The
renderer is @object-ui/react-runtime, in objectui.
UI-A-03 wizards: a stepped form over ONE object is this skill's `formViews`
`type: 'wizard'`; only step-branching flows route to automation.
UI-D-07 keep the requirement, drop the removal history.
UI-D-03 delete the "Why this model" justification.
UI-D-04 reduce the metadata-fence rationale to the two facts the table lacks
(live-not-a-screenshot; data-not-code).
UI-B-06 delete "When to Use This Skill" -- it restated the frontmatter.
UI-B-05 the Tailwind rule now states the rule once and points at ADR-0065.
UI-G-03 translate the CJK example label. The two remaining CJK lines are
non-English USER PHRASINGS the router matches on -- see the PR body.
UI-E-03 inline a minimal defineAction so the record-detail page block stands
alone (the relative import could never resolve in the gate build dir).
UI-E-01 mark four highest-traffic examples `os:check`: structured definePage,
the Dashboard literal, defineDataset, the react source tier.
Gate: pnpm --filter @objectstack/spec check:skill-examples -- 259 -> 263 marked
blocks, "every marked block parsed, so tsc ran the SEMANTIC pass on all of them".
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…nd the timeSegments deletion
Two mechanical consequences, neither hand-written:
- `content/docs/ai/skills-reference.mdx` — `pnpm --filter @objectstack/spec
gen:skill-docs`. The dispatch predicted `skills/README.md` would be the file
the drift gate demands; it is not. README came back green on its own (it does
not embed the description); the out-of-date artifact is the reference page.
Both are outputs of the one generator the card names.
- `scripts/skill-identifier-liveness-ledger.json` — `node
scripts/check-skill-identifier-liveness.mjs --update`, pruning the now-stale
`dayStart` / `showMidnight` exemptions. Both existed only to excuse the
`timeSegments` block this flight deleted, and each ledger note independently
records that the implementation lives in objectui plugin-gantt -- the same
measurement UI-D-02 rests on. `--update` never ADDS an exemption.
Gates: check:skill-docs 0 (both artifacts ✓); check:skill-identifier-liveness 0
("Leg 1: 498 citations over 48 published files ... 3 ledgered exemptions").
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
@github-actionsgithub-actionsBot added size/l documentation Improvements or additions to documentation labels Sep 2, 2026
@os-litantos-litant added skip-changeset PR has no user-facing published change; bypasses the changeset gate needs:contract-review and removed documentation Improvements or additions to documentation labels Sep 2, 2026 — with Claude
…ding
In-seat contract review is right: my UI-D-08 retitle asserted enforcement that
does not exist, which is the same defect class this flight exists to remove.
Re-verified against the source, and the evidence is stronger than the review
cited:
- `granularities: z.array(TimeUpdateInterval).optional()`
(packages/spec/src/data/analytics.zod.ts:147) — optional, and the file
contains ZERO `.refine(` / `superRefine` occurrences, so nothing requires it
on a `time` dimension.
- Cube `sql: z.string().describe('Base SQL statement or Table Name')` (:216).
The describe string itself admits raw SQL; nothing rejects it at parse time,
and no gate script under scripts/ or packages/*/scripts/ references
`cube.sql`.
So there is no gate or schema refinement to cite, and the word is dropped rather
than defended. The two body items are unchanged: they are prescriptions with a
stated mechanism (`cube.sql.trim()` read as the object name), not claims of
enforcement.
Gates at this head: node scripts/check-skills-token-ratchet.mjs exit 0 --
SKILL.md 22856 tokens (ceiling 25445, headroom 2589); pnpm --filter
@objectstack/spec check:skill-examples exit 0 -- "263 prose examples type-check
across 3 surface(s)".
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
@github-actionsgithub-actionsBot added the documentation Improvements or additions to documentation label Sep 2, 2026
@os-litantos-litant changed the title skills(ui): optimization flight — date macros/relationships pointed at their anchors, searchableFields and timeSegments cut, dashboards consolidated, retired widget keys removed (net −2,583 tokens)skills(ui): optimization flight — date macros/relationships pointed at their anchors, searchableFields and timeSegments cut, dashboards consolidated, retired widget keys removed (net −2,585 tokens)Sep 2, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review September 2, 2026 06:18
@os-zhuang
os-zhuang added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit 54a1125Sep 2, 2026
45 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-14298-skills-ui-optimization branch September 2, 2026 06:41
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/lskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@os-litant@os-zhuang
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

skills(ui): optimization flight — date macros/relationships pointed at their anchors, searchableFields and timeSegments cut, dashboards consolidated, retired widget keys removed (net −2,585 tokens) - #14338

Merged
os-zhuang merged 5 commits into
mainfrom
claude/issue-14298-skills-ui-optimization
Sep 2, 2026
Merged

Conversation

@os-litant

@os-litantos-litant commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Part of #14298

Governed surface (skills/**) ⇒ this PR stays draft; needs:contract-review is on both carriers because falsehoods 1–2 are contract-semantics corrections. Head sha for every gate figure below: 684415c3.

Review round 1 — one FAIL, fixed

In-seat contract review flagged the UI-D-08 retitle ### Cube Rules (enforced) as asserting enforcement that does not exist. Correct, and the evidence is stronger than the review cited — re-verified at source:

  • granularities: z.array(TimeUpdateInterval).optional() (packages/spec/src/data/analytics.zod.ts:147), and that file contains zero.refine( / superRefine occurrences, so nothing requires it on a time dimension.
  • Cube sql: z.string().describe('Base SQL statement or Table Name') (:216) — the describe string itself admits raw SQL; nothing rejects it at parse time, and no gate script under scripts/ or packages/*/scripts/ references cube.sql.

There is no gate or schema refinement to cite, so the word is dropped, not defended: the heading is now ### Cube Rules. The two body items are unchanged — they are prescriptions with a stated mechanism (cube.sql.trim() read as the object name), not claims of enforcement. Shipping an unbacked "(enforced)" would have been the same defect class this flight exists to remove.

Open questions ruled by the seat: Q1 → C (UI-E-04 deprecated objectName/viewType, filed by the seat as its own card — nothing done here); Q2 → A (the two CJK trigger phrases stay).

Per-file token delta (ratchet convention, ceil(utf8 bytes / 4))

filebeforeafterdeltaceiling
skills/objectstack-ui/SKILL.md25,44122,856−2,58525,445 (headroom 4 → 2,589)
package total36,54233,957−2,585
whole shipped bundle187,854185,269−2,585

Generated package members untouched and unchanged: contracts/react-blocks.contract.json 5,352 · references/react-blocks.md 3,153 · references/_index.md 1,205. evals/** untouched (1,102 + 289). The ceiling is left at 25,445: the ratchet header says a ceiling "may be LOWERED by any PR that shrinks its file … always legitimate and encouraged", but the card's flight constraint forbids touching the ratchet script, so the 2,589 tokens of new headroom are deliberately NOT claimed here — a follow-up may lower the row to the measurement.

Against the card's target. The card targets ≈ −9,170, of which −5,352 is UI-B-04's duplicated generated JSON — explicitly DEFERRED to #14296 item 3 and not mine. The in-file target was −4,199 prose against +385 of additions; landed −2,585. The gap is itemised below rather than smoothed over: the three funded additions cost +838 against the estimated +385 (the filterBindings and widget-options constructs are each roughly double their estimate), and UI-D-01 returned −387 against an estimated −900. Every number below is a measured byte delta.

Per-item: 落点 | before | after

Deletions and merges

id落点beforeafter
UI-C-01## Date Macros — Filter Placeholders (whole section + ## Context Tokens)1,288 tok265 tok (−1,023)
UI-D-02### Shift segmentation — timeSegments581 tok0 (−581)
UI-C-04master-detail inlineEdit ladder + line-item grid behaviours643 tok193 tok (−450)
UI-D-01### Toolbar Search (searchableFields)1,381 tok994 tok (−387)
UI-D-05the options.drillDown renderer note235 tok0 (−235)
UI-C-02action ctx org-isolation + positions narration371 tok154 tok (−217)
UI-B-06## When to Use This Skill136 tok0 (−136)
UI-D-06the "Removed in v17" compareTo blockquote106 tok0 (−106)
UI-D-08### Cube Best Practices (5 items)159 tok74 tok (−85), retitled ### Cube Rules — see Review round 1
UI-D-04the metadata fence rationale145 tok75 tok (−70)
UI-D-03"Why this model" (build-independent / collision-free / responsive-correct)79 tok22 tok (−57)
UI-C-03the visibleWhen/readonlyWhen/requiredWhen table149 tok103 tok (−46)
UI-D-07the removed-inline-query history86 tok68 tok (−18)
UI-B-05the 4th Tailwind className restatement67 tok52 tok (−15)
UI-B-03the dateGranularity bucket table under ### Drilldown273 tok273 tok (0 — moved under its own heading; reorder is free)

The three funded additions

idwhat landedcostnamed payersactual
UI-F-01 + UI-F-03### Dashboard filters — globalFilters + per-widget filterBindings: the broadcast rule, name (defaults to field; name it for the vocabulary, not the column), scope: 'widget' + targetWidgets, re-target, false opt-out, the absent-default incl. dateRange.field ?? 'created_at', plus a 2-widget example+371UI-D-05 (−235) + UI-D-06 (−106)−341, so +30 over
UI-F-02### Widget options — the five declared keys (dateGranularity / sortBy / sortOrder / limit / stageOrder), with the top-N spelling that had no documented form+357UI-D-08 (−85) + UI-D-03 (−57)−142, so +215 over
UI-E-01os:check marks on the four highest-traffic examples (+ UI-E-03's inlined action)+110UI-E-02 (−18)+92 over

The three additions cost +838 against −501 of named payers. They are nonetheless fully paid in the same file: the flight's total deletions are −3,423, so SKILL.md ends 2,585 tokens smaller and the ratchet is green with 2,589 tokens of headroom. Flagging the per-item overrun rather than re-cutting the payer list to fit, because the card's funding lines are its ruling and I would rather show them broken than silently re-derive them.

Falsehoods

#落点beforeafter
1canonical dashboard widgetactionType: 'url', actionUrl: '/objects/opportunity?filter=open'line deleted. dashboard.zod.ts:382-384 retires all three via retiredKey(...) = z.never(); prescription :309-320 "a dashboard widget has NO action button, and never had one".
2### Server-side date bucketing"Date bucketing lives on the dataset dimension, not the widget.""The dataset dimension carries the default; a widget's options.dateGranularity overrides it for that widget only." (dashboard.zod.ts:217-225)
3frontmatter"the React renderer implementation (lives in packages/client-react, not metadata)"clause deleted. packages/client-react is "React hooks for ObjectStack Client SDK"; the renderer is @object-ui/react-runtime, in objectui.
4 (new)the Tokens-in-filters blockquote on the canonical dashboard{current_user.id}{current_user_id}. current_user.id is the RLS expression root, not a filter token — spec/src/data/context-tokens.zod.ts:44,49 names this exact near-miss and :85 lists the real token. Found inside a span this flight was already rewriting, same defect class as 1–2, mechanically fixed against the spec; taken under the bounded-in-place rule.

Also deleted, never ported (card ruling): this package's claim that "unknown placeholders silently pass through as literal strings". It is false and the file contradicted itself 37 lines earlier. packages/core/src/utils/filter-tokens.ts:378 throws UnknownFilterTokenError, and the module header at :44 is titled "An unknown token throws".

Deliberate deviations from the routed plan

  1. UI-C-01 keeps its ## heading. The ruling says delete :1659-1768. Two in-file links (:1074, :1507) target #date-macros--filter-placeholders; deleting the heading breaks both, so the heading survives carrying the pointer. Also kept: two rules objectstack-query does not own — a filter token is presentation scope, not security; and AppContextSelector ids resolve in navigation recordId/params only, never in a filter. Both were their last mention in the package.
  2. UI-C-02 keeps ctx.session.positions in compact form. The routed anchor does not carry it (see follow-ups). Kept with the "not an authorization input" guard; the org-isolation half is deleted and pointed.
  3. UI-G-03 translates 1 of 3 CJK lines, not 3label: '打印总表(A3)''Print Summary Sheet (A3)'. The two at :755-756 are non-English user phrasings the router matches on; translating a phrase whose only job is to match untranslated input destroys it. Seat ruled A: they stay.
  4. The ratchet ceiling is not lowered — see the token table.

Not implemented (and why)

premise_false

None. git diff --stat a59f78d origin/main -- skills/objectstack-ui is empty, so every audit span was byte-identical at the branch point. Two PM mechanical assumptions were refined rather than confirmed — below.

PM mechanical assumptions — measured

  1. Confirmed.skills/objectstack-ui/** byte-identical between a59f78d and origin/main. (origin/main had already moved past the dispatch's d63c8a25 to 909a4417, which does not touch skills/; the branch is cut from 909a4417.)
  2. Refined — the predicted file is the wrong one.check:skill-docs does run in CI and the frontmatter edit does force a regeneration, but skills/README.md came back green on its own (✓ skills/README.md) — it does not embed the description. The out-of-date artifact was content/docs/ai/skills-reference.mdx. Regenerated with the one generator the card names; the diff is 2 lines, both the frontmatter's own text.
  3. Confirmed for tsc; the parse half not measured. Reverse-verified against a committed tree: re-injecting actionType/actionUrl on the widget turns check:skill-examplesred with two error TS2322: Type 'string' is not assignable to type 'undefined' — one per retired key, z.never() surfacing as undefined in the input type. Mutation proven on disk before measuring (injected-text grep count 1; blob 4a5d1e256b5d8296), restore proven the same way (git diff HEAD empty, blob back to 4a5d1e25, injected count 0) — neither leg read from an editor's exit code. This gate exercises tsc only, so the Zod parse failure is asserted from the schema source, not measured here.
  4. Confirmed, with one restructure. Marked count 259 → 263, "every marked block parsed, so tsc ran the SEMANTIC pass on all of them". Two needed more than a marker: the record-detail page carried UI-E-03's unresolvable relative import (replaced with an inlined 4-line defineAction), and the defineDataset block was a fragment — it now imports defineDataset + type DashboardWidget and binds the trailing widget literal to a typed const.
  5. Not exercised — no finding's premise was false.

follow-up for objectstack-query

rules/filters.md is the anchor and is strong: it already carries the fixed tokens, the parameterised form, both session tokens, both resolvers, the calendar-DAY *_end trap, and — decisively — "Unknown tokens are rejected, not ignored". These TRUE rows from the deleted objectstack-ui text are not in it and were not ported:

  1. Both {token} and ${token} spellings are acceptedspec/src/data/date-macros.zod.ts:200,207 and context-tokens.zod.ts:101. rules/filters.md shows only the bare form.
  2. Two more near-misses: {user_id} (a valid titleFormat field interpolation elsewhere) and {organization_id} (the real column name). Query names {current_user} and {this_quarter_start} only.
  3. A token embedded in a larger string is not substituted ('user-{current_user_id}'). Query states only the converse; filter-tokens.ts:44 states this half directly — "Values that merely CONTAIN braces are left untouched."
  4. isDateMacroToken(tok) from @objectstack/spec/data as the author-time type check.
  5. The build rule's name, filter-token-unknown, and why it exists: an unresolved token reaches SQL as a literal, matches nothing, and the widget renders 0 — indistinguishable from a genuine zero.

follow-up for objectstack-data

references/data-hooks.md carries the org-isolation half completely — UI-C-02's deletion is safely routed there. It does not document ctx.session.positions at all; :368 says only that ctx.session has "No role listsession.roles was retired in 17.0.0". So the ADR-0090 D3 spelling and the "not an authorization input" guard have no anchor to point at, and a compact form was kept here rather than deleted into a gap.

Gates — all 42 families, all at head 684415c3

⚠️Correcting a stale figure this PR body previously carried. It claimed 16 families. That derivation ran at 0f937dcc, when the changeset was SKILL.md alone; the next commit added content/docs/ai/skills-reference.mdx and scripts/skill-identifier-liveness-ledger.json, and I did not re-derive. Re-derived at the current head, node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack names 42 — the 26 extra are the docs family the .mdx pulls in. All 42 have now been run; every one of the 26 that had never been run passes. The earlier "16" was wrong and is retracted here rather than quietly overwritten.

41 of 42 exit 0. Each exit code captured by redirecting before any pipe. The full list, in the order the harvester prints it:

check-ci-filter-parity · check-cross-package-test-inputs · check-doc-frontmatter · check-doc-route-spelling · check-docs-section-name · check-section-landing-index · check-shard-attestation · check-skills-token-ratchet · doc-formula-expressions · doc-security-posture · check:docs · check:empty-state · check:liveness · check:skill-docs · check:skill-examples · check:strictness-ledger · check:variant-docs · check:yaml-examples · agent-test-spelling · bash32-floor · cli-command-ids · corpus-claim-drift · cross-package-test-inputs · doc-anchors · doc-authoring · docs-audit-scope · docs-redirects · docs-single-h1 · entry-guard · merge-driver · parse-guard · pm-governed-merges · pnpm-filter-targets · published-readme-links · react-page-adapter-contract · role-word · skill-compatibility · skill-frame-sync · skill-identifier-liveness · vendor-version-stamps · watch-hint-literal — all exit 0.

Named verdict lines for the two the review asked for:

  • node scripts/check-skills-token-ratchet.mjsexit 0, "skills/objectstack-ui/SKILL.md is 22856 tokens (ceiling 25445; headroom 2589)" · "38 authored bundle file(s) within their ceilings".
  • pnpm --filter @objectstack/spec check:skill-examplesexit 0, "✅ 263 prose examples type-check across 3 surface(s) — every marked block parsed, so tsc ran the SEMANTIC pass on all of them".

The 42nd, node scripts/check-test-completeness.mjs, exits 3 = NOT MEASURED by its own verdict text ("Nothing was measured… It is not a red, and there is nothing here to fix") — it needs a saved turbo run test log. Recorded as NOT MEASURED: not a pass, not a red.

Heavy runs went through scripts/pm/os-verify-lock.sh with OS_VERIFY_LOCK_SLOT=issue-14298. Prerequisite builds re-run at this head, not assumed: @objectstack/spec and the @objectstack/client-react / @objectstack/client dependency closure — without the latter check:skill-examples refuses to run rather than reporting green ("packages/client-react/dist holds no .d.ts declarations… a FALSE GREEN on exactly the change it exists to catch").

Repo-wide pnpm lint (eslint over the whole tree) was NOT run — it is CI's own step, in this derivation's unnarrowable "always runs" tail. A plain omission, not a measured narrowing; I claim none of the three evidence items a narrowing would need.

Two consequences outside SKILL.md

Both generator/tool output, neither hand-written, each the mechanical consequence of a funded edit:

  • content/docs/ai/skills-reference.mdxgen:skill-docs, forced by the frontmatter edit (assumption 2). Not content/docs/releases/.
  • scripts/skill-identifier-liveness-ledger.jsoncheck-skill-identifier-liveness.mjs --update, pruning dayStart and showMidnight. Both existed only to excuse the timeSegments block this flight deleted, and each ledger note independently records the implementation living in objectui plugin-gantt — the same measurement UI-D-02 rests on. --update never adds an exemption.

Changeset

skip-changeset applies and is on the PR. Checked against the repo's own rule: the exemption means "this PR declares no release of its own", and no package publishes skills/, content/docs/ or scripts/. The Check Changeset job reads labels live; the label cannot be applied before the PR exists, so it was applied immediately after creation and read back.


🤖 Generated with Claude Code

https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1

os-litantand others added 4 commits September 2, 2026 01:59
…e/drilldown trims, filterBindings + widget options funded
UI-C-01 delete the date-macro + context-token block; keep the heading (two
in-file anchors resolve to it) and point at objectstack-query
rules/filters.md. Two UI-owned rules stay: presentation-scope-not-
security, and AppContextSelector ids never resolving in a filter.
UI-C-02 drop the org-isolation narration; keep the blessed-name pointer at
objectstack-data's hooks reference. `ctx.session.positions` stays in
compact form -- the anchor does not carry it (see PR follow-up list).
UI-D-08 Cube Best Practices -> the two enforced facts.
UI-D-05 delete the renderer note that ends by telling the reader to ignore it.
UI-D-06 delete the v17 `compareTo` removal narration.
UI-B-03 move the dateGranularity bucket table out of `### Drilldown` and under
its own heading (reorder only).
UI-G-02 falsehood 2: the dataset dimension is the DEFAULT; options.dateGranularity
overrides it per widget (dashboard.zod.ts:217-225).
UI-E-02 falsehood 1: delete the retired `actionType`/`actionUrl` pair from the
canonical dashboard widget (dashboard.zod.ts:382-384, retiredKey =
z.never()).
falsehood 4 (found in span, same defect class): `{current_user.id}` ->
`{current_user_id}`; `current_user.id` is the RLS expression root, not
a filter token (spec/src/data/context-tokens.zod.ts:44,49,85).
UI-F-01/F-03 ADD the globalFilters/filterBindings construct (paid by D-05+D-06).
UI-F-02 ADD the five declared widget `options` keys (paid by D-08+D-03-to-come).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…etired, relationships/conditional-rules pointed at objectstack-data
UI-D-01 keep the two tables and the `userActions: { search: false }` example;
delete the two verbatim `os validate` diagnostics, the empty-array
essay (folded into the row that already existed) and the related-title
prose (reduced to its objectstack-data pointer).
UI-D-02 delete the `timeSegments` block -- self-declared NOT part of
GanttConfigSchema, zero implementation in this repo (every hit is in
objectui plugin-gantt), and 10 of the package's 13 CJK lines.
UI-C-04 the inlineEdit ladder and the modelled grid behaviours point at
objectstack-data rules/relationships.md, which carries them verbatim.
Kept the three UI-authored facts the anchor does NOT carry: the ghost
row, `autofill: false`, and the form's `taxRateField`.
UI-C-03 delete the visibleWhen/readonlyWhen/requiredWhen table; keep the
routing line, the row-by-row inline-grid note and the retired
`conditionalRequired` guard.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…our highest-traffic examples gated
UI-A-01 add `*.page.ts` / `*.report.ts` / `*.dataset.ts` to the trigger list --
`*.page.ts` is the corpus's most-authored kind (29 definitions) and had
no filename trigger at all.
UI-A-02 falsehood 3: drop "the React renderer implementation (lives in
packages/client-react)". That package is React hooks for the client SDK
(package.json description; src/index.tsx exports hooks + provider). The
renderer is @object-ui/react-runtime, in objectui.
UI-A-03 wizards: a stepped form over ONE object is this skill's `formViews`
`type: 'wizard'`; only step-branching flows route to automation.
UI-D-07 keep the requirement, drop the removal history.
UI-D-03 delete the "Why this model" justification.
UI-D-04 reduce the metadata-fence rationale to the two facts the table lacks
(live-not-a-screenshot; data-not-code).
UI-B-06 delete "When to Use This Skill" -- it restated the frontmatter.
UI-B-05 the Tailwind rule now states the rule once and points at ADR-0065.
UI-G-03 translate the CJK example label. The two remaining CJK lines are
non-English USER PHRASINGS the router matches on -- see the PR body.
UI-E-03 inline a minimal defineAction so the record-detail page block stands
alone (the relative import could never resolve in the gate build dir).
UI-E-01 mark four highest-traffic examples `os:check`: structured definePage,
the Dashboard literal, defineDataset, the react source tier.
Gate: pnpm --filter @objectstack/spec check:skill-examples -- 259 -> 263 marked
blocks, "every marked block parsed, so tsc ran the SEMANTIC pass on all of them".
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…nd the timeSegments deletion
Two mechanical consequences, neither hand-written:
- `content/docs/ai/skills-reference.mdx` — `pnpm --filter @objectstack/spec
gen:skill-docs`. The dispatch predicted `skills/README.md` would be the file
the drift gate demands; it is not. README came back green on its own (it does
not embed the description); the out-of-date artifact is the reference page.
Both are outputs of the one generator the card names.
- `scripts/skill-identifier-liveness-ledger.json` — `node
scripts/check-skill-identifier-liveness.mjs --update`, pruning the now-stale
`dayStart` / `showMidnight` exemptions. Both existed only to excuse the
`timeSegments` block this flight deleted, and each ledger note independently
records that the implementation lives in objectui plugin-gantt -- the same
measurement UI-D-02 rests on. `--update` never ADDS an exemption.
Gates: check:skill-docs 0 (both artifacts ✓); check:skill-identifier-liveness 0
("Leg 1: 498 citations over 48 published files ... 3 ledgered exemptions").
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
@github-actionsgithub-actionsBot added size/l documentation Improvements or additions to documentation labels Sep 2, 2026
@os-litantos-litant added skip-changeset PR has no user-facing published change; bypasses the changeset gate needs:contract-review and removed documentation Improvements or additions to documentation labels Sep 2, 2026 — with Claude
…ding
In-seat contract review is right: my UI-D-08 retitle asserted enforcement that
does not exist, which is the same defect class this flight exists to remove.
Re-verified against the source, and the evidence is stronger than the review
cited:
- `granularities: z.array(TimeUpdateInterval).optional()`
(packages/spec/src/data/analytics.zod.ts:147) — optional, and the file
contains ZERO `.refine(` / `superRefine` occurrences, so nothing requires it
on a `time` dimension.
- Cube `sql: z.string().describe('Base SQL statement or Table Name')` (:216).
The describe string itself admits raw SQL; nothing rejects it at parse time,
and no gate script under scripts/ or packages/*/scripts/ references
`cube.sql`.
So there is no gate or schema refinement to cite, and the word is dropped rather
than defended. The two body items are unchanged: they are prescriptions with a
stated mechanism (`cube.sql.trim()` read as the object name), not claims of
enforcement.
Gates at this head: node scripts/check-skills-token-ratchet.mjs exit 0 --
SKILL.md 22856 tokens (ceiling 25445, headroom 2589); pnpm --filter
@objectstack/spec check:skill-examples exit 0 -- "263 prose examples type-check
across 3 surface(s)".
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
@github-actionsgithub-actionsBot added the documentation Improvements or additions to documentation label Sep 2, 2026
@os-litantos-litant changed the title skills(ui): optimization flight — date macros/relationships pointed at their anchors, searchableFields and timeSegments cut, dashboards consolidated, retired widget keys removed (net −2,583 tokens)skills(ui): optimization flight — date macros/relationships pointed at their anchors, searchableFields and timeSegments cut, dashboards consolidated, retired widget keys removed (net −2,585 tokens)Sep 2, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review September 2, 2026 06:18
@os-zhuang
os-zhuang added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit 54a1125Sep 2, 2026
45 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-14298-skills-ui-optimization branch September 2, 2026 06:41
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/lskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@os-litant@os-zhuang
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

skills(ui): optimization flight — date macros/relationships pointed at their anchors, searchableFields and timeSegments cut, dashboards consolidated, retired widget keys removed (net −2,585 tokens) - #14338

Merged
os-zhuang merged 5 commits into
mainfrom
claude/issue-14298-skills-ui-optimization
Sep 2, 2026
Merged

Conversation

@os-litant

@os-litantos-litant commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Part of #14298

Governed surface (skills/**) ⇒ this PR stays draft; needs:contract-review is on both carriers because falsehoods 1–2 are contract-semantics corrections. Head sha for every gate figure below: 684415c3.

Review round 1 — one FAIL, fixed

In-seat contract review flagged the UI-D-08 retitle ### Cube Rules (enforced) as asserting enforcement that does not exist. Correct, and the evidence is stronger than the review cited — re-verified at source:

  • granularities: z.array(TimeUpdateInterval).optional() (packages/spec/src/data/analytics.zod.ts:147), and that file contains zero.refine( / superRefine occurrences, so nothing requires it on a time dimension.
  • Cube sql: z.string().describe('Base SQL statement or Table Name') (:216) — the describe string itself admits raw SQL; nothing rejects it at parse time, and no gate script under scripts/ or packages/*/scripts/ references cube.sql.

There is no gate or schema refinement to cite, so the word is dropped, not defended: the heading is now ### Cube Rules. The two body items are unchanged — they are prescriptions with a stated mechanism (cube.sql.trim() read as the object name), not claims of enforcement. Shipping an unbacked "(enforced)" would have been the same defect class this flight exists to remove.

Open questions ruled by the seat: Q1 → C (UI-E-04 deprecated objectName/viewType, filed by the seat as its own card — nothing done here); Q2 → A (the two CJK trigger phrases stay).

Per-file token delta (ratchet convention, ceil(utf8 bytes / 4))

filebeforeafterdeltaceiling
skills/objectstack-ui/SKILL.md25,44122,856−2,58525,445 (headroom 4 → 2,589)
package total36,54233,957−2,585
whole shipped bundle187,854185,269−2,585

Generated package members untouched and unchanged: contracts/react-blocks.contract.json 5,352 · references/react-blocks.md 3,153 · references/_index.md 1,205. evals/** untouched (1,102 + 289). The ceiling is left at 25,445: the ratchet header says a ceiling "may be LOWERED by any PR that shrinks its file … always legitimate and encouraged", but the card's flight constraint forbids touching the ratchet script, so the 2,589 tokens of new headroom are deliberately NOT claimed here — a follow-up may lower the row to the measurement.

Against the card's target. The card targets ≈ −9,170, of which −5,352 is UI-B-04's duplicated generated JSON — explicitly DEFERRED to #14296 item 3 and not mine. The in-file target was −4,199 prose against +385 of additions; landed −2,585. The gap is itemised below rather than smoothed over: the three funded additions cost +838 against the estimated +385 (the filterBindings and widget-options constructs are each roughly double their estimate), and UI-D-01 returned −387 against an estimated −900. Every number below is a measured byte delta.

Per-item: 落点 | before | after

Deletions and merges

id落点beforeafter
UI-C-01## Date Macros — Filter Placeholders (whole section + ## Context Tokens)1,288 tok265 tok (−1,023)
UI-D-02### Shift segmentation — timeSegments581 tok0 (−581)
UI-C-04master-detail inlineEdit ladder + line-item grid behaviours643 tok193 tok (−450)
UI-D-01### Toolbar Search (searchableFields)1,381 tok994 tok (−387)
UI-D-05the options.drillDown renderer note235 tok0 (−235)
UI-C-02action ctx org-isolation + positions narration371 tok154 tok (−217)
UI-B-06## When to Use This Skill136 tok0 (−136)
UI-D-06the "Removed in v17" compareTo blockquote106 tok0 (−106)
UI-D-08### Cube Best Practices (5 items)159 tok74 tok (−85), retitled ### Cube Rules — see Review round 1
UI-D-04the metadata fence rationale145 tok75 tok (−70)
UI-D-03"Why this model" (build-independent / collision-free / responsive-correct)79 tok22 tok (−57)
UI-C-03the visibleWhen/readonlyWhen/requiredWhen table149 tok103 tok (−46)
UI-D-07the removed-inline-query history86 tok68 tok (−18)
UI-B-05the 4th Tailwind className restatement67 tok52 tok (−15)
UI-B-03the dateGranularity bucket table under ### Drilldown273 tok273 tok (0 — moved under its own heading; reorder is free)

The three funded additions

idwhat landedcostnamed payersactual
UI-F-01 + UI-F-03### Dashboard filters — globalFilters + per-widget filterBindings: the broadcast rule, name (defaults to field; name it for the vocabulary, not the column), scope: 'widget' + targetWidgets, re-target, false opt-out, the absent-default incl. dateRange.field ?? 'created_at', plus a 2-widget example+371UI-D-05 (−235) + UI-D-06 (−106)−341, so +30 over
UI-F-02### Widget options — the five declared keys (dateGranularity / sortBy / sortOrder / limit / stageOrder), with the top-N spelling that had no documented form+357UI-D-08 (−85) + UI-D-03 (−57)−142, so +215 over
UI-E-01os:check marks on the four highest-traffic examples (+ UI-E-03's inlined action)+110UI-E-02 (−18)+92 over

The three additions cost +838 against −501 of named payers. They are nonetheless fully paid in the same file: the flight's total deletions are −3,423, so SKILL.md ends 2,585 tokens smaller and the ratchet is green with 2,589 tokens of headroom. Flagging the per-item overrun rather than re-cutting the payer list to fit, because the card's funding lines are its ruling and I would rather show them broken than silently re-derive them.

Falsehoods

#落点beforeafter
1canonical dashboard widgetactionType: 'url', actionUrl: '/objects/opportunity?filter=open'line deleted. dashboard.zod.ts:382-384 retires all three via retiredKey(...) = z.never(); prescription :309-320 "a dashboard widget has NO action button, and never had one".
2### Server-side date bucketing"Date bucketing lives on the dataset dimension, not the widget.""The dataset dimension carries the default; a widget's options.dateGranularity overrides it for that widget only." (dashboard.zod.ts:217-225)
3frontmatter"the React renderer implementation (lives in packages/client-react, not metadata)"clause deleted. packages/client-react is "React hooks for ObjectStack Client SDK"; the renderer is @object-ui/react-runtime, in objectui.
4 (new)the Tokens-in-filters blockquote on the canonical dashboard{current_user.id}{current_user_id}. current_user.id is the RLS expression root, not a filter token — spec/src/data/context-tokens.zod.ts:44,49 names this exact near-miss and :85 lists the real token. Found inside a span this flight was already rewriting, same defect class as 1–2, mechanically fixed against the spec; taken under the bounded-in-place rule.

Also deleted, never ported (card ruling): this package's claim that "unknown placeholders silently pass through as literal strings". It is false and the file contradicted itself 37 lines earlier. packages/core/src/utils/filter-tokens.ts:378 throws UnknownFilterTokenError, and the module header at :44 is titled "An unknown token throws".

Deliberate deviations from the routed plan

  1. UI-C-01 keeps its ## heading. The ruling says delete :1659-1768. Two in-file links (:1074, :1507) target #date-macros--filter-placeholders; deleting the heading breaks both, so the heading survives carrying the pointer. Also kept: two rules objectstack-query does not own — a filter token is presentation scope, not security; and AppContextSelector ids resolve in navigation recordId/params only, never in a filter. Both were their last mention in the package.
  2. UI-C-02 keeps ctx.session.positions in compact form. The routed anchor does not carry it (see follow-ups). Kept with the "not an authorization input" guard; the org-isolation half is deleted and pointed.
  3. UI-G-03 translates 1 of 3 CJK lines, not 3label: '打印总表(A3)''Print Summary Sheet (A3)'. The two at :755-756 are non-English user phrasings the router matches on; translating a phrase whose only job is to match untranslated input destroys it. Seat ruled A: they stay.
  4. The ratchet ceiling is not lowered — see the token table.

Not implemented (and why)

premise_false

None. git diff --stat a59f78d origin/main -- skills/objectstack-ui is empty, so every audit span was byte-identical at the branch point. Two PM mechanical assumptions were refined rather than confirmed — below.

PM mechanical assumptions — measured

  1. Confirmed.skills/objectstack-ui/** byte-identical between a59f78d and origin/main. (origin/main had already moved past the dispatch's d63c8a25 to 909a4417, which does not touch skills/; the branch is cut from 909a4417.)
  2. Refined — the predicted file is the wrong one.check:skill-docs does run in CI and the frontmatter edit does force a regeneration, but skills/README.md came back green on its own (✓ skills/README.md) — it does not embed the description. The out-of-date artifact was content/docs/ai/skills-reference.mdx. Regenerated with the one generator the card names; the diff is 2 lines, both the frontmatter's own text.
  3. Confirmed for tsc; the parse half not measured. Reverse-verified against a committed tree: re-injecting actionType/actionUrl on the widget turns check:skill-examplesred with two error TS2322: Type 'string' is not assignable to type 'undefined' — one per retired key, z.never() surfacing as undefined in the input type. Mutation proven on disk before measuring (injected-text grep count 1; blob 4a5d1e256b5d8296), restore proven the same way (git diff HEAD empty, blob back to 4a5d1e25, injected count 0) — neither leg read from an editor's exit code. This gate exercises tsc only, so the Zod parse failure is asserted from the schema source, not measured here.
  4. Confirmed, with one restructure. Marked count 259 → 263, "every marked block parsed, so tsc ran the SEMANTIC pass on all of them". Two needed more than a marker: the record-detail page carried UI-E-03's unresolvable relative import (replaced with an inlined 4-line defineAction), and the defineDataset block was a fragment — it now imports defineDataset + type DashboardWidget and binds the trailing widget literal to a typed const.
  5. Not exercised — no finding's premise was false.

follow-up for objectstack-query

rules/filters.md is the anchor and is strong: it already carries the fixed tokens, the parameterised form, both session tokens, both resolvers, the calendar-DAY *_end trap, and — decisively — "Unknown tokens are rejected, not ignored". These TRUE rows from the deleted objectstack-ui text are not in it and were not ported:

  1. Both {token} and ${token} spellings are acceptedspec/src/data/date-macros.zod.ts:200,207 and context-tokens.zod.ts:101. rules/filters.md shows only the bare form.
  2. Two more near-misses: {user_id} (a valid titleFormat field interpolation elsewhere) and {organization_id} (the real column name). Query names {current_user} and {this_quarter_start} only.
  3. A token embedded in a larger string is not substituted ('user-{current_user_id}'). Query states only the converse; filter-tokens.ts:44 states this half directly — "Values that merely CONTAIN braces are left untouched."
  4. isDateMacroToken(tok) from @objectstack/spec/data as the author-time type check.
  5. The build rule's name, filter-token-unknown, and why it exists: an unresolved token reaches SQL as a literal, matches nothing, and the widget renders 0 — indistinguishable from a genuine zero.

follow-up for objectstack-data

references/data-hooks.md carries the org-isolation half completely — UI-C-02's deletion is safely routed there. It does not document ctx.session.positions at all; :368 says only that ctx.session has "No role listsession.roles was retired in 17.0.0". So the ADR-0090 D3 spelling and the "not an authorization input" guard have no anchor to point at, and a compact form was kept here rather than deleted into a gap.

Gates — all 42 families, all at head 684415c3

⚠️Correcting a stale figure this PR body previously carried. It claimed 16 families. That derivation ran at 0f937dcc, when the changeset was SKILL.md alone; the next commit added content/docs/ai/skills-reference.mdx and scripts/skill-identifier-liveness-ledger.json, and I did not re-derive. Re-derived at the current head, node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack names 42 — the 26 extra are the docs family the .mdx pulls in. All 42 have now been run; every one of the 26 that had never been run passes. The earlier "16" was wrong and is retracted here rather than quietly overwritten.

41 of 42 exit 0. Each exit code captured by redirecting before any pipe. The full list, in the order the harvester prints it:

check-ci-filter-parity · check-cross-package-test-inputs · check-doc-frontmatter · check-doc-route-spelling · check-docs-section-name · check-section-landing-index · check-shard-attestation · check-skills-token-ratchet · doc-formula-expressions · doc-security-posture · check:docs · check:empty-state · check:liveness · check:skill-docs · check:skill-examples · check:strictness-ledger · check:variant-docs · check:yaml-examples · agent-test-spelling · bash32-floor · cli-command-ids · corpus-claim-drift · cross-package-test-inputs · doc-anchors · doc-authoring · docs-audit-scope · docs-redirects · docs-single-h1 · entry-guard · merge-driver · parse-guard · pm-governed-merges · pnpm-filter-targets · published-readme-links · react-page-adapter-contract · role-word · skill-compatibility · skill-frame-sync · skill-identifier-liveness · vendor-version-stamps · watch-hint-literal — all exit 0.

Named verdict lines for the two the review asked for:

  • node scripts/check-skills-token-ratchet.mjsexit 0, "skills/objectstack-ui/SKILL.md is 22856 tokens (ceiling 25445; headroom 2589)" · "38 authored bundle file(s) within their ceilings".
  • pnpm --filter @objectstack/spec check:skill-examplesexit 0, "✅ 263 prose examples type-check across 3 surface(s) — every marked block parsed, so tsc ran the SEMANTIC pass on all of them".

The 42nd, node scripts/check-test-completeness.mjs, exits 3 = NOT MEASURED by its own verdict text ("Nothing was measured… It is not a red, and there is nothing here to fix") — it needs a saved turbo run test log. Recorded as NOT MEASURED: not a pass, not a red.

Heavy runs went through scripts/pm/os-verify-lock.sh with OS_VERIFY_LOCK_SLOT=issue-14298. Prerequisite builds re-run at this head, not assumed: @objectstack/spec and the @objectstack/client-react / @objectstack/client dependency closure — without the latter check:skill-examples refuses to run rather than reporting green ("packages/client-react/dist holds no .d.ts declarations… a FALSE GREEN on exactly the change it exists to catch").

Repo-wide pnpm lint (eslint over the whole tree) was NOT run — it is CI's own step, in this derivation's unnarrowable "always runs" tail. A plain omission, not a measured narrowing; I claim none of the three evidence items a narrowing would need.

Two consequences outside SKILL.md

Both generator/tool output, neither hand-written, each the mechanical consequence of a funded edit:

  • content/docs/ai/skills-reference.mdxgen:skill-docs, forced by the frontmatter edit (assumption 2). Not content/docs/releases/.
  • scripts/skill-identifier-liveness-ledger.jsoncheck-skill-identifier-liveness.mjs --update, pruning dayStart and showMidnight. Both existed only to excuse the timeSegments block this flight deleted, and each ledger note independently records the implementation living in objectui plugin-gantt — the same measurement UI-D-02 rests on. --update never adds an exemption.

Changeset

skip-changeset applies and is on the PR. Checked against the repo's own rule: the exemption means "this PR declares no release of its own", and no package publishes skills/, content/docs/ or scripts/. The Check Changeset job reads labels live; the label cannot be applied before the PR exists, so it was applied immediately after creation and read back.


🤖 Generated with Claude Code

https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1

os-litantand others added 4 commits September 2, 2026 01:59
…e/drilldown trims, filterBindings + widget options funded
UI-C-01 delete the date-macro + context-token block; keep the heading (two
in-file anchors resolve to it) and point at objectstack-query
rules/filters.md. Two UI-owned rules stay: presentation-scope-not-
security, and AppContextSelector ids never resolving in a filter.
UI-C-02 drop the org-isolation narration; keep the blessed-name pointer at
objectstack-data's hooks reference. `ctx.session.positions` stays in
compact form -- the anchor does not carry it (see PR follow-up list).
UI-D-08 Cube Best Practices -> the two enforced facts.
UI-D-05 delete the renderer note that ends by telling the reader to ignore it.
UI-D-06 delete the v17 `compareTo` removal narration.
UI-B-03 move the dateGranularity bucket table out of `### Drilldown` and under
its own heading (reorder only).
UI-G-02 falsehood 2: the dataset dimension is the DEFAULT; options.dateGranularity
overrides it per widget (dashboard.zod.ts:217-225).
UI-E-02 falsehood 1: delete the retired `actionType`/`actionUrl` pair from the
canonical dashboard widget (dashboard.zod.ts:382-384, retiredKey =
z.never()).
falsehood 4 (found in span, same defect class): `{current_user.id}` ->
`{current_user_id}`; `current_user.id` is the RLS expression root, not
a filter token (spec/src/data/context-tokens.zod.ts:44,49,85).
UI-F-01/F-03 ADD the globalFilters/filterBindings construct (paid by D-05+D-06).
UI-F-02 ADD the five declared widget `options` keys (paid by D-08+D-03-to-come).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…etired, relationships/conditional-rules pointed at objectstack-data
UI-D-01 keep the two tables and the `userActions: { search: false }` example;
delete the two verbatim `os validate` diagnostics, the empty-array
essay (folded into the row that already existed) and the related-title
prose (reduced to its objectstack-data pointer).
UI-D-02 delete the `timeSegments` block -- self-declared NOT part of
GanttConfigSchema, zero implementation in this repo (every hit is in
objectui plugin-gantt), and 10 of the package's 13 CJK lines.
UI-C-04 the inlineEdit ladder and the modelled grid behaviours point at
objectstack-data rules/relationships.md, which carries them verbatim.
Kept the three UI-authored facts the anchor does NOT carry: the ghost
row, `autofill: false`, and the form's `taxRateField`.
UI-C-03 delete the visibleWhen/readonlyWhen/requiredWhen table; keep the
routing line, the row-by-row inline-grid note and the retired
`conditionalRequired` guard.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…our highest-traffic examples gated
UI-A-01 add `*.page.ts` / `*.report.ts` / `*.dataset.ts` to the trigger list --
`*.page.ts` is the corpus's most-authored kind (29 definitions) and had
no filename trigger at all.
UI-A-02 falsehood 3: drop "the React renderer implementation (lives in
packages/client-react)". That package is React hooks for the client SDK
(package.json description; src/index.tsx exports hooks + provider). The
renderer is @object-ui/react-runtime, in objectui.
UI-A-03 wizards: a stepped form over ONE object is this skill's `formViews`
`type: 'wizard'`; only step-branching flows route to automation.
UI-D-07 keep the requirement, drop the removal history.
UI-D-03 delete the "Why this model" justification.
UI-D-04 reduce the metadata-fence rationale to the two facts the table lacks
(live-not-a-screenshot; data-not-code).
UI-B-06 delete "When to Use This Skill" -- it restated the frontmatter.
UI-B-05 the Tailwind rule now states the rule once and points at ADR-0065.
UI-G-03 translate the CJK example label. The two remaining CJK lines are
non-English USER PHRASINGS the router matches on -- see the PR body.
UI-E-03 inline a minimal defineAction so the record-detail page block stands
alone (the relative import could never resolve in the gate build dir).
UI-E-01 mark four highest-traffic examples `os:check`: structured definePage,
the Dashboard literal, defineDataset, the react source tier.
Gate: pnpm --filter @objectstack/spec check:skill-examples -- 259 -> 263 marked
blocks, "every marked block parsed, so tsc ran the SEMANTIC pass on all of them".
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…nd the timeSegments deletion
Two mechanical consequences, neither hand-written:
- `content/docs/ai/skills-reference.mdx` — `pnpm --filter @objectstack/spec
gen:skill-docs`. The dispatch predicted `skills/README.md` would be the file
the drift gate demands; it is not. README came back green on its own (it does
not embed the description); the out-of-date artifact is the reference page.
Both are outputs of the one generator the card names.
- `scripts/skill-identifier-liveness-ledger.json` — `node
scripts/check-skill-identifier-liveness.mjs --update`, pruning the now-stale
`dayStart` / `showMidnight` exemptions. Both existed only to excuse the
`timeSegments` block this flight deleted, and each ledger note independently
records that the implementation lives in objectui plugin-gantt -- the same
measurement UI-D-02 rests on. `--update` never ADDS an exemption.
Gates: check:skill-docs 0 (both artifacts ✓); check:skill-identifier-liveness 0
("Leg 1: 498 citations over 48 published files ... 3 ledgered exemptions").
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
@github-actionsgithub-actionsBot added size/l documentation Improvements or additions to documentation labels Sep 2, 2026
@os-litantos-litant added skip-changeset PR has no user-facing published change; bypasses the changeset gate needs:contract-review and removed documentation Improvements or additions to documentation labels Sep 2, 2026 — with Claude
…ding
In-seat contract review is right: my UI-D-08 retitle asserted enforcement that
does not exist, which is the same defect class this flight exists to remove.
Re-verified against the source, and the evidence is stronger than the review
cited:
- `granularities: z.array(TimeUpdateInterval).optional()`
(packages/spec/src/data/analytics.zod.ts:147) — optional, and the file
contains ZERO `.refine(` / `superRefine` occurrences, so nothing requires it
on a `time` dimension.
- Cube `sql: z.string().describe('Base SQL statement or Table Name')` (:216).
The describe string itself admits raw SQL; nothing rejects it at parse time,
and no gate script under scripts/ or packages/*/scripts/ references
`cube.sql`.
So there is no gate or schema refinement to cite, and the word is dropped rather
than defended. The two body items are unchanged: they are prescriptions with a
stated mechanism (`cube.sql.trim()` read as the object name), not claims of
enforcement.
Gates at this head: node scripts/check-skills-token-ratchet.mjs exit 0 --
SKILL.md 22856 tokens (ceiling 25445, headroom 2589); pnpm --filter
@objectstack/spec check:skill-examples exit 0 -- "263 prose examples type-check
across 3 surface(s)".
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
@github-actionsgithub-actionsBot added the documentation Improvements or additions to documentation label Sep 2, 2026
@os-litantos-litant changed the title skills(ui): optimization flight — date macros/relationships pointed at their anchors, searchableFields and timeSegments cut, dashboards consolidated, retired widget keys removed (net −2,583 tokens)skills(ui): optimization flight — date macros/relationships pointed at their anchors, searchableFields and timeSegments cut, dashboards consolidated, retired widget keys removed (net −2,585 tokens)Sep 2, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review September 2, 2026 06:18
@os-zhuang
os-zhuang added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit 54a1125Sep 2, 2026
45 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-14298-skills-ui-optimization branch September 2, 2026 06:41
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/lskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@os-litant@os-zhuang