skills(ui): split the entry into SKILL.md + rules/ under #14296 item 1 (package net −58 tokens, −0.17%) - #14658

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

skills(ui): split the entry into SKILL.md + rules/ under #14296 item 1 (package net −58 tokens, −0.17%)#14658
os-zhuang merged 3 commits into
mainfrom
claude/issue-14298-skills-ui-split

Conversation

@os-litant

Copy link
Copy Markdown
Collaborator

Part of #14298

Ruling: "#14296 item 1 = A, comment 5507419465". Condition (a) was read at programme level by "#14568 = A, comment 5511939006" (director seat, verbatim reply 「同意」): the split PR itself must land token-neutral or negative, and the package arithmetic is carried by the programme.

The three conditions, with numbers

(a) Token-neutral or negative — measured -58.node scripts/check-skills-token-ratchet.mjs before and after, at head d72e3dcc:

beforeafter
SKILL.md22,8563,815
rules/*.md (5 new files)18,983
generated (contracts/react-blocks.contract.json, references/react-blocks.md, references/_index.md)9,7109,710
evals/1,3911,391
package33,95733,899

Net -58 (-0.17%). Gross deletions -248, additions +190 (five file titles, one ## Detailed Rules heading, five one-line pointers). Nothing in this PR is positive.

Programme account for the package: round 1 #14338-2,585 + this split -58 + seam card #14559-5,352 = -7,995 against the pre-programme 36,542 = -21.9%.

(b) Ceilings. Five rows added, each pinned AT its landed count so every new file starts with exactly zero headroom; the entry row re-locked to its landed count. No other row changed.

rowceiling
skills/objectstack-ui/SKILL.md25,445 → 3,815 (re-lock)
skills/objectstack-ui/rules/actions.md2,108 (new)
skills/objectstack-ui/rules/dashboards.md6,090 (new)
skills/objectstack-ui/rules/list-views.md3,011 (new)
skills/objectstack-ui/rules/navigation.md2,273 (new)
skills/objectstack-ui/rules/pages.md5,501 (new)

(c) Not a channel for added prose — proved line by line, not asserted. Comparing the multiset of non-blank lines before (1,591) and after (1,586): 28 lines in the new tree are not lines of the old SKILL.md, and not one of them is a new sentence — 5 file titles, 1## Detailed Rules heading, 5 one-line pointers, 10 headings whose only change is a level shift or a deletion inside the heading text, and 7 lines whose only change is a rewritten relative link or a deleted dead clause. That is the entire set of text this PR authored. The check is reproducible from the diff.

File map

old section (spans at the merge base)new hometokens
## Configuring a List View · ## Configuring Kanban Views · ## Configuring Gantt Viewsrules/list-views.md3,011
## App Navigation (the App.create example) · ## Three Run Modes · ## Record Presentationrules/navigation.md2,273
## Dashboards · ## Dashboards (cont.) · ### Report Configuration · ## Analytics Cubesrules/dashboards.md6,090
## Pages — Lightning-Style Page Layouts · ## Docs — Package Documentationrules/pages.md5,501
## Actions (body below ### Action Types)rules/actions.md2,108
frontmatter · ## View Types · ## Detailed Rules · ## App Navigation head · ## Report Types · ## CRM UI Blueprint · ## Date Macros · ## Actions head · ## Common Pitfalls · ## Verify your work · ## Referencesstays in SKILL.md3,815

Five files, not the audit's suggested nine — the brief says fewer is better, and two of the nine were folded deliberately: rules/filter-tokens.md was not created because ## Date Macros is cross-cutting (list views, dashboards, reports, pages) and is the target of the package's only in-file anchors, so it stays in the entry; rules/master-detail.md was not created because ### Master-Detail Forms is a routing ladder ("you almost never need a custom page or form config — prefer, in order"), which is exactly the kind of construct the entry keeps.

Dashboards now have one home. The two sections that sat 780 lines apart are adjacent in rules/dashboards.md, the second demoted to ### KPI Widgets, Filters, Drilldown under the first — which is what makes the three UI-B-02 deletions below dead text rather than a judgement call.

Deletions, per finding

finding落点beforeafter
UI-B-02SKILL.md:554-558"See the Production Pattern section below for the full Dashboard shape with refreshInterval, header actions, date range, global filters, widget options, and the period-over-period (compareTo) modifier; date bucketing comes from the bound dataset dimension's dateGranularity (ADR-0021)."deleted — a forward reference to a section that is now the next thing on the page (-75)
UI-B-02SKILL.md:1316-1317"Dashboards (Dashboard) are first-class metadata. Beyond the basic widget layout shown above, the production-grade pattern uses:"deleted — a second introduction to a section that no longer restarts (-33)
UI-B-02SKILL.md:1381-1384the "Tokens in filters" blockquote, pointing at Date Macros for the second time in the same filedeleted — the merged file carries that pointer once (-69)
UI-B-05 residueSKILL.md:1029-1032"Real component props/callbacks flow through — e.g. ObjectForm honors objectName / mode / recordId / formType / onSuccess / onCancel; ListView honors objectName / fields / onRowClick / navigation."deleted — the very next blockquote says "Do not guess props — read the contract … author against it, not from memory", and this sentence is a from-memory copy of that generated contract (-57 with its trailing clause)
UI-B-02 (split-exposed)SKILL.md## Report Types"a report visualizes via its embedded chart: config (see the example below)"the parenthetical deleted — the report example is now in rules/dashboards.md (-6)
UI-B-02 (split-exposed)rules/navigation.md Record Presentation"for bespoke layout, assign a record Page (below)"the parenthetical deleted — Pages is now rules/pages.md (-2)
UI-B-02 (split-exposed)rules/pages.md page type list"configured via interfaceConfig (see the iron rule above)"the parenthetical deleted — the iron rule is now in rules/navigation.md (-6)

Gross -248. No decision-changing construct was deleted, and nothing was deleted to reach a number — condition (a) is satisfied by the split being byte-conserving, not by these.

Every "above" / "below" in the new tree was swept for a target that left its file; those three were the only ones, and each is deleted rather than rewritten — a dead pointer is removed text, not an occasion for new prose.

The one-topic-two-files cost, declared

check:skill-identifier-liveness Leg 2 binds three sections to skills/objectstack-ui/SKILL.mdby path (report-types, action-types, navigation-item-types); a bound heading that leaves its file yields [stale-binding] … A renamed heading unbinds the assertion, so it fails here rather than quietly checking nothing, pinned by that script's own self-test. Nothing in the script was changed. So three topics are split across two files:

  • ## Report Types keeps its exhaustive table in the entry; ### Report Configuration moved to rules/dashboards.md (promoted to ##).
  • ### Action Types keeps its table in the entry; the rest of Actions moved to rules/actions.md (headings shifted up one level).
  • ### Navigation Item Types keeps its table in the entry; the App.create example moved to rules/navigation.md.

That is a real legibility cost of the split as constrained, and it is the reason those three entry sections look thin.

Link rewrites

Three links crossed a directory boundary and were rewritten, following the skills/objectstack-platform/rules/ precedent: #date-macros--filter-placeholders became ../SKILL.md#date-macros--filter-placeholders, and ./references/react-blocks.md / ./contracts/react-blocks.contract.json became ../references/… / ../contracts/….

Not in this PR

premise_false: none — no audit finding was skipped this round for a false premise.

Gates

Head d72e3dcc. Family re-derived on the final commit with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands (25 commands, from the script's own merge-base changeset — not a hand-written path list), and the whole union re-run on that head under scripts/pm/os-verify-lock.sh with OS_VERIFY_LOCK_SLOT=issue-14298-r2. Every exit code captured before any pipe. 31 ran, 30 exit 0.

The six beyond the derivation, each owed for a named reason: check-skills-token-ratchet.mjs --self-test (this PR edits that gate, so its own self-test is owed on top of the derived family — 64 cases pass), check:skill-examples and check:skill-refs (the dispatch named them; skills/** changed), check:doc-anchors and check:published-readme-links (links crossed a directory), check:nul-bytes (any edit).

The verdicts that answer this PR's specific risks, quoted from the gates themselves:

  • check:skill-examples — "256 prose examples type-check across 3 surface(s) — every marked block parsed, so tsc ran the SEMANTIC pass on all of them". All 15 os:check markers travelled with their fences (0 in the entry, 15 across the five rules files; 15 before, 15 after) and the marked blocks still compile from their new files.
  • check:skill-identifier-liveness — "Leg 1: 465 citation(s) over 46 published file(s) … Leg 2: 8 registered exhaustive section(s), 0 ledgered gap(s)". The three path-keyed ui bindings still resolve inside SKILL.md.
  • check:published-readme-links — "176 outbound link(s) across 60 published markdown file(s) … 1 anchor(s) verified, 103/103 relative target(s) found". The new ../SKILL.md#date-macros--filter-placeholders and ../references/… links resolve.
  • check:doc-anchors — "295 internal #fragment link(s) across 409 source file(s) all resolve to a real heading".
  • check:skill-docs / check:skill-refs — both in sync; no generated file needed regenerating, and none was touched.
  • check:role-word — green after the baseline re-point (its own commit; see below).
  • node scripts/check-skills-token-ratchet.mjs — "36 authored bundle file(s) within their ceilings", every objectstack-ui row at exactly zero headroom.

check:test-completeness exited 3, which is NOT MEASURED, not a failure — the gate says so itself: "Nothing was measured: this gate exited before parsing a single summary line … ⛔ It is NOT a finding". Recorded as such rather than counted green.

check:role-word needed the baseline re-pointed, and that is a pure relocation. The baseline is keyed by PATH; the two occurrences it already carried for SKILL.md ("the tab-bar role", "semantic roles") moved into rules/list-views.md and rules/navigation.md as byte-identical lines. --update therefore produced a three-line diff — one row removed, two added, total unchanged at 2 — and re-baselined no other file. It is in its own commit. The count did not move, which is what the brief asked to be shown.

Repo-wide pnpm lint was not run; the narrowing is measured, not assumed. (1) The population comes from eslint's own config, not a guess: every files glob in eslint.config.mjs is {ts,tsx,mts,cts,js,jsx,mjs,cjs}, no markdown plugin is configured, and .md appears in no glob — so the six markdown files in this diff are outside eslint's population entirely. (2) Counted from --format json: of the eight changed files eslint claims exactly one, scripts/check-skills-token-ratchet.mjs, at 0 errors / 0 warnings; role-word-baseline.json reports "File ignored because no matching configuration was supplied". (3) Invariance for untouched files: the config configures no projectService and no project, so type-aware linting is off and nothing in this diff can move the verdict of a file it does not contain. CI's Lint job runs the full sweep regardless.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1


Generated by Claude Code

…okens)
The 22,856-token entry file becomes a 3,821-token entry plus five `rules/*.md`
files, converging objectstack-ui on the catalog's declared anatomy
(`skills/README.md`, Skill anatomy) that data, platform and query already use.
Text MOVES; it is not rewritten. The only text that is not a moved line is five
file titles and five one-line pointers. Deleted, all of it restatement the
reassembly exposes:
UI-B-02 the forward reference from `## Dashboards` to "the Production Pattern
section below" (-75), the re-introduction paragraph under the second
dashboards heading (-33), and the duplicated Date Macros pointer
blockquote (-69) -- the two dashboard sections, previously 780 lines
apart, now share one home in `rules/dashboards.md`.
UI-B-05 the prose prop list for the two react blocks (-53 -57 with its trailing
clause), which restated the generated contract that the very next
blockquote makes authoritative.
`check:skill-identifier-liveness` Leg 2 binds three sections to this file BY
PATH, so `## Report Types`, `### Action Types` and `### Navigation Item Types`
keep their exhaustive tables in the entry while their bodies move -- one topic
across two files, in three places. Nothing in that script changed.
Ratchet: one row per new file, pinned at its landed count; the entry row
re-locked 25445 -> 3821. No other row moves.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
Sweeping every "above" / "below" in the new tree for a target that is no longer
in the same file found three, all dead on arrival and all deleted rather than
rewritten -- a dead pointer is removed text, not an occasion for new prose:
SKILL.md "There is no `chart` report type ... (see the example
below)" -- the report example moved to rules/dashboards.md.
rules/navigation "assign a record `Page` (below)" -- Pages moved to
rules/pages.md.
rules/pages page type `list` "(see the iron rule above)" -- the iron
rule moved to rules/navigation.md.
-14 tokens. The three ratchet rows are re-pinned at the new landed counts so
every objectstack-ui row keeps exactly zero headroom; package 33,957 -> 33,899,
net -58.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
Pure relocation, not an admission. The baseline is keyed by PATH, and the two
occurrences it already carried for `skills/objectstack-ui/SKILL.md` moved into
`rules/list-views.md` ("the tab-bar role") and `rules/navigation.md` ("semantic
roles") -- byte-identical lines, so `--update` reads the same two occurrences
at two new paths and drops the old row:
- "skills/objectstack-ui/SKILL.md": 2
+ "skills/objectstack-ui/rules/list-views.md": 1
+ "skills/objectstack-ui/rules/navigation.md": 1
The whole baseline diff is those three lines: no other file was re-baselined,
and the total is unchanged at 2, so the shrink-only ratchet is not weakened.
This is the case the gate's ratchet-DOWN remedy names, kept in its own commit.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@os-litant@os-zhuang@claude
, '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): split the entry into SKILL.md + rules/ under #14296 item 1 (package net −58 tokens, −0.17%) - #14658

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

skills(ui): split the entry into SKILL.md + rules/ under #14296 item 1 (package net −58 tokens, −0.17%)#14658
os-zhuang merged 3 commits into
mainfrom
claude/issue-14298-skills-ui-split

Conversation

@os-litant

Copy link
Copy Markdown
Collaborator

Part of #14298

Ruling: "#14296 item 1 = A, comment 5507419465". Condition (a) was read at programme level by "#14568 = A, comment 5511939006" (director seat, verbatim reply 「同意」): the split PR itself must land token-neutral or negative, and the package arithmetic is carried by the programme.

The three conditions, with numbers

(a) Token-neutral or negative — measured -58.node scripts/check-skills-token-ratchet.mjs before and after, at head d72e3dcc:

beforeafter
SKILL.md22,8563,815
rules/*.md (5 new files)18,983
generated (contracts/react-blocks.contract.json, references/react-blocks.md, references/_index.md)9,7109,710
evals/1,3911,391
package33,95733,899

Net -58 (-0.17%). Gross deletions -248, additions +190 (five file titles, one ## Detailed Rules heading, five one-line pointers). Nothing in this PR is positive.

Programme account for the package: round 1 #14338-2,585 + this split -58 + seam card #14559-5,352 = -7,995 against the pre-programme 36,542 = -21.9%.

(b) Ceilings. Five rows added, each pinned AT its landed count so every new file starts with exactly zero headroom; the entry row re-locked to its landed count. No other row changed.

rowceiling
skills/objectstack-ui/SKILL.md25,445 → 3,815 (re-lock)
skills/objectstack-ui/rules/actions.md2,108 (new)
skills/objectstack-ui/rules/dashboards.md6,090 (new)
skills/objectstack-ui/rules/list-views.md3,011 (new)
skills/objectstack-ui/rules/navigation.md2,273 (new)
skills/objectstack-ui/rules/pages.md5,501 (new)

(c) Not a channel for added prose — proved line by line, not asserted. Comparing the multiset of non-blank lines before (1,591) and after (1,586): 28 lines in the new tree are not lines of the old SKILL.md, and not one of them is a new sentence — 5 file titles, 1## Detailed Rules heading, 5 one-line pointers, 10 headings whose only change is a level shift or a deletion inside the heading text, and 7 lines whose only change is a rewritten relative link or a deleted dead clause. That is the entire set of text this PR authored. The check is reproducible from the diff.

File map

old section (spans at the merge base)new hometokens
## Configuring a List View · ## Configuring Kanban Views · ## Configuring Gantt Viewsrules/list-views.md3,011
## App Navigation (the App.create example) · ## Three Run Modes · ## Record Presentationrules/navigation.md2,273
## Dashboards · ## Dashboards (cont.) · ### Report Configuration · ## Analytics Cubesrules/dashboards.md6,090
## Pages — Lightning-Style Page Layouts · ## Docs — Package Documentationrules/pages.md5,501
## Actions (body below ### Action Types)rules/actions.md2,108
frontmatter · ## View Types · ## Detailed Rules · ## App Navigation head · ## Report Types · ## CRM UI Blueprint · ## Date Macros · ## Actions head · ## Common Pitfalls · ## Verify your work · ## Referencesstays in SKILL.md3,815

Five files, not the audit's suggested nine — the brief says fewer is better, and two of the nine were folded deliberately: rules/filter-tokens.md was not created because ## Date Macros is cross-cutting (list views, dashboards, reports, pages) and is the target of the package's only in-file anchors, so it stays in the entry; rules/master-detail.md was not created because ### Master-Detail Forms is a routing ladder ("you almost never need a custom page or form config — prefer, in order"), which is exactly the kind of construct the entry keeps.

Dashboards now have one home. The two sections that sat 780 lines apart are adjacent in rules/dashboards.md, the second demoted to ### KPI Widgets, Filters, Drilldown under the first — which is what makes the three UI-B-02 deletions below dead text rather than a judgement call.

Deletions, per finding

finding落点beforeafter
UI-B-02SKILL.md:554-558"See the Production Pattern section below for the full Dashboard shape with refreshInterval, header actions, date range, global filters, widget options, and the period-over-period (compareTo) modifier; date bucketing comes from the bound dataset dimension's dateGranularity (ADR-0021)."deleted — a forward reference to a section that is now the next thing on the page (-75)
UI-B-02SKILL.md:1316-1317"Dashboards (Dashboard) are first-class metadata. Beyond the basic widget layout shown above, the production-grade pattern uses:"deleted — a second introduction to a section that no longer restarts (-33)
UI-B-02SKILL.md:1381-1384the "Tokens in filters" blockquote, pointing at Date Macros for the second time in the same filedeleted — the merged file carries that pointer once (-69)
UI-B-05 residueSKILL.md:1029-1032"Real component props/callbacks flow through — e.g. ObjectForm honors objectName / mode / recordId / formType / onSuccess / onCancel; ListView honors objectName / fields / onRowClick / navigation."deleted — the very next blockquote says "Do not guess props — read the contract … author against it, not from memory", and this sentence is a from-memory copy of that generated contract (-57 with its trailing clause)
UI-B-02 (split-exposed)SKILL.md## Report Types"a report visualizes via its embedded chart: config (see the example below)"the parenthetical deleted — the report example is now in rules/dashboards.md (-6)
UI-B-02 (split-exposed)rules/navigation.md Record Presentation"for bespoke layout, assign a record Page (below)"the parenthetical deleted — Pages is now rules/pages.md (-2)
UI-B-02 (split-exposed)rules/pages.md page type list"configured via interfaceConfig (see the iron rule above)"the parenthetical deleted — the iron rule is now in rules/navigation.md (-6)

Gross -248. No decision-changing construct was deleted, and nothing was deleted to reach a number — condition (a) is satisfied by the split being byte-conserving, not by these.

Every "above" / "below" in the new tree was swept for a target that left its file; those three were the only ones, and each is deleted rather than rewritten — a dead pointer is removed text, not an occasion for new prose.

The one-topic-two-files cost, declared

check:skill-identifier-liveness Leg 2 binds three sections to skills/objectstack-ui/SKILL.mdby path (report-types, action-types, navigation-item-types); a bound heading that leaves its file yields [stale-binding] … A renamed heading unbinds the assertion, so it fails here rather than quietly checking nothing, pinned by that script's own self-test. Nothing in the script was changed. So three topics are split across two files:

  • ## Report Types keeps its exhaustive table in the entry; ### Report Configuration moved to rules/dashboards.md (promoted to ##).
  • ### Action Types keeps its table in the entry; the rest of Actions moved to rules/actions.md (headings shifted up one level).
  • ### Navigation Item Types keeps its table in the entry; the App.create example moved to rules/navigation.md.

That is a real legibility cost of the split as constrained, and it is the reason those three entry sections look thin.

Link rewrites

Three links crossed a directory boundary and were rewritten, following the skills/objectstack-platform/rules/ precedent: #date-macros--filter-placeholders became ../SKILL.md#date-macros--filter-placeholders, and ./references/react-blocks.md / ./contracts/react-blocks.contract.json became ../references/… / ../contracts/….

Not in this PR

premise_false: none — no audit finding was skipped this round for a false premise.

Gates

Head d72e3dcc. Family re-derived on the final commit with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands (25 commands, from the script's own merge-base changeset — not a hand-written path list), and the whole union re-run on that head under scripts/pm/os-verify-lock.sh with OS_VERIFY_LOCK_SLOT=issue-14298-r2. Every exit code captured before any pipe. 31 ran, 30 exit 0.

The six beyond the derivation, each owed for a named reason: check-skills-token-ratchet.mjs --self-test (this PR edits that gate, so its own self-test is owed on top of the derived family — 64 cases pass), check:skill-examples and check:skill-refs (the dispatch named them; skills/** changed), check:doc-anchors and check:published-readme-links (links crossed a directory), check:nul-bytes (any edit).

The verdicts that answer this PR's specific risks, quoted from the gates themselves:

  • check:skill-examples — "256 prose examples type-check across 3 surface(s) — every marked block parsed, so tsc ran the SEMANTIC pass on all of them". All 15 os:check markers travelled with their fences (0 in the entry, 15 across the five rules files; 15 before, 15 after) and the marked blocks still compile from their new files.
  • check:skill-identifier-liveness — "Leg 1: 465 citation(s) over 46 published file(s) … Leg 2: 8 registered exhaustive section(s), 0 ledgered gap(s)". The three path-keyed ui bindings still resolve inside SKILL.md.
  • check:published-readme-links — "176 outbound link(s) across 60 published markdown file(s) … 1 anchor(s) verified, 103/103 relative target(s) found". The new ../SKILL.md#date-macros--filter-placeholders and ../references/… links resolve.
  • check:doc-anchors — "295 internal #fragment link(s) across 409 source file(s) all resolve to a real heading".
  • check:skill-docs / check:skill-refs — both in sync; no generated file needed regenerating, and none was touched.
  • check:role-word — green after the baseline re-point (its own commit; see below).
  • node scripts/check-skills-token-ratchet.mjs — "36 authored bundle file(s) within their ceilings", every objectstack-ui row at exactly zero headroom.

check:test-completeness exited 3, which is NOT MEASURED, not a failure — the gate says so itself: "Nothing was measured: this gate exited before parsing a single summary line … ⛔ It is NOT a finding". Recorded as such rather than counted green.

check:role-word needed the baseline re-pointed, and that is a pure relocation. The baseline is keyed by PATH; the two occurrences it already carried for SKILL.md ("the tab-bar role", "semantic roles") moved into rules/list-views.md and rules/navigation.md as byte-identical lines. --update therefore produced a three-line diff — one row removed, two added, total unchanged at 2 — and re-baselined no other file. It is in its own commit. The count did not move, which is what the brief asked to be shown.

Repo-wide pnpm lint was not run; the narrowing is measured, not assumed. (1) The population comes from eslint's own config, not a guess: every files glob in eslint.config.mjs is {ts,tsx,mts,cts,js,jsx,mjs,cjs}, no markdown plugin is configured, and .md appears in no glob — so the six markdown files in this diff are outside eslint's population entirely. (2) Counted from --format json: of the eight changed files eslint claims exactly one, scripts/check-skills-token-ratchet.mjs, at 0 errors / 0 warnings; role-word-baseline.json reports "File ignored because no matching configuration was supplied". (3) Invariance for untouched files: the config configures no projectService and no project, so type-aware linting is off and nothing in this diff can move the verdict of a file it does not contain. CI's Lint job runs the full sweep regardless.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1


Generated by Claude Code

…okens)
The 22,856-token entry file becomes a 3,821-token entry plus five `rules/*.md`
files, converging objectstack-ui on the catalog's declared anatomy
(`skills/README.md`, Skill anatomy) that data, platform and query already use.
Text MOVES; it is not rewritten. The only text that is not a moved line is five
file titles and five one-line pointers. Deleted, all of it restatement the
reassembly exposes:
UI-B-02 the forward reference from `## Dashboards` to "the Production Pattern
section below" (-75), the re-introduction paragraph under the second
dashboards heading (-33), and the duplicated Date Macros pointer
blockquote (-69) -- the two dashboard sections, previously 780 lines
apart, now share one home in `rules/dashboards.md`.
UI-B-05 the prose prop list for the two react blocks (-53 -57 with its trailing
clause), which restated the generated contract that the very next
blockquote makes authoritative.
`check:skill-identifier-liveness` Leg 2 binds three sections to this file BY
PATH, so `## Report Types`, `### Action Types` and `### Navigation Item Types`
keep their exhaustive tables in the entry while their bodies move -- one topic
across two files, in three places. Nothing in that script changed.
Ratchet: one row per new file, pinned at its landed count; the entry row
re-locked 25445 -> 3821. No other row moves.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
Sweeping every "above" / "below" in the new tree for a target that is no longer
in the same file found three, all dead on arrival and all deleted rather than
rewritten -- a dead pointer is removed text, not an occasion for new prose:
SKILL.md "There is no `chart` report type ... (see the example
below)" -- the report example moved to rules/dashboards.md.
rules/navigation "assign a record `Page` (below)" -- Pages moved to
rules/pages.md.
rules/pages page type `list` "(see the iron rule above)" -- the iron
rule moved to rules/navigation.md.
-14 tokens. The three ratchet rows are re-pinned at the new landed counts so
every objectstack-ui row keeps exactly zero headroom; package 33,957 -> 33,899,
net -58.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
Pure relocation, not an admission. The baseline is keyed by PATH, and the two
occurrences it already carried for `skills/objectstack-ui/SKILL.md` moved into
`rules/list-views.md` ("the tab-bar role") and `rules/navigation.md` ("semantic
roles") -- byte-identical lines, so `--update` reads the same two occurrences
at two new paths and drops the old row:
- "skills/objectstack-ui/SKILL.md": 2
+ "skills/objectstack-ui/rules/list-views.md": 1
+ "skills/objectstack-ui/rules/navigation.md": 1
The whole baseline diff is those three lines: no other file was re-baselined,
and the total is unchanged at 2, so the shrink-only ratchet is not weakened.
This is the case the gate's ratchet-DOWN remedy names, kept in its own commit.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@os-litant@os-zhuang@claude
, '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): split the entry into SKILL.md + rules/ under #14296 item 1 (package net −58 tokens, −0.17%) - #14658

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

skills(ui): split the entry into SKILL.md + rules/ under #14296 item 1 (package net −58 tokens, −0.17%)#14658
os-zhuang merged 3 commits into
mainfrom
claude/issue-14298-skills-ui-split

Conversation

@os-litant

Copy link
Copy Markdown
Collaborator

Part of #14298

Ruling: "#14296 item 1 = A, comment 5507419465". Condition (a) was read at programme level by "#14568 = A, comment 5511939006" (director seat, verbatim reply 「同意」): the split PR itself must land token-neutral or negative, and the package arithmetic is carried by the programme.

The three conditions, with numbers

(a) Token-neutral or negative — measured -58.node scripts/check-skills-token-ratchet.mjs before and after, at head d72e3dcc:

beforeafter
SKILL.md22,8563,815
rules/*.md (5 new files)18,983
generated (contracts/react-blocks.contract.json, references/react-blocks.md, references/_index.md)9,7109,710
evals/1,3911,391
package33,95733,899

Net -58 (-0.17%). Gross deletions -248, additions +190 (five file titles, one ## Detailed Rules heading, five one-line pointers). Nothing in this PR is positive.

Programme account for the package: round 1 #14338-2,585 + this split -58 + seam card #14559-5,352 = -7,995 against the pre-programme 36,542 = -21.9%.

(b) Ceilings. Five rows added, each pinned AT its landed count so every new file starts with exactly zero headroom; the entry row re-locked to its landed count. No other row changed.

rowceiling
skills/objectstack-ui/SKILL.md25,445 → 3,815 (re-lock)
skills/objectstack-ui/rules/actions.md2,108 (new)
skills/objectstack-ui/rules/dashboards.md6,090 (new)
skills/objectstack-ui/rules/list-views.md3,011 (new)
skills/objectstack-ui/rules/navigation.md2,273 (new)
skills/objectstack-ui/rules/pages.md5,501 (new)

(c) Not a channel for added prose — proved line by line, not asserted. Comparing the multiset of non-blank lines before (1,591) and after (1,586): 28 lines in the new tree are not lines of the old SKILL.md, and not one of them is a new sentence — 5 file titles, 1## Detailed Rules heading, 5 one-line pointers, 10 headings whose only change is a level shift or a deletion inside the heading text, and 7 lines whose only change is a rewritten relative link or a deleted dead clause. That is the entire set of text this PR authored. The check is reproducible from the diff.

File map

old section (spans at the merge base)new hometokens
## Configuring a List View · ## Configuring Kanban Views · ## Configuring Gantt Viewsrules/list-views.md3,011
## App Navigation (the App.create example) · ## Three Run Modes · ## Record Presentationrules/navigation.md2,273
## Dashboards · ## Dashboards (cont.) · ### Report Configuration · ## Analytics Cubesrules/dashboards.md6,090
## Pages — Lightning-Style Page Layouts · ## Docs — Package Documentationrules/pages.md5,501
## Actions (body below ### Action Types)rules/actions.md2,108
frontmatter · ## View Types · ## Detailed Rules · ## App Navigation head · ## Report Types · ## CRM UI Blueprint · ## Date Macros · ## Actions head · ## Common Pitfalls · ## Verify your work · ## Referencesstays in SKILL.md3,815

Five files, not the audit's suggested nine — the brief says fewer is better, and two of the nine were folded deliberately: rules/filter-tokens.md was not created because ## Date Macros is cross-cutting (list views, dashboards, reports, pages) and is the target of the package's only in-file anchors, so it stays in the entry; rules/master-detail.md was not created because ### Master-Detail Forms is a routing ladder ("you almost never need a custom page or form config — prefer, in order"), which is exactly the kind of construct the entry keeps.

Dashboards now have one home. The two sections that sat 780 lines apart are adjacent in rules/dashboards.md, the second demoted to ### KPI Widgets, Filters, Drilldown under the first — which is what makes the three UI-B-02 deletions below dead text rather than a judgement call.

Deletions, per finding

finding落点beforeafter
UI-B-02SKILL.md:554-558"See the Production Pattern section below for the full Dashboard shape with refreshInterval, header actions, date range, global filters, widget options, and the period-over-period (compareTo) modifier; date bucketing comes from the bound dataset dimension's dateGranularity (ADR-0021)."deleted — a forward reference to a section that is now the next thing on the page (-75)
UI-B-02SKILL.md:1316-1317"Dashboards (Dashboard) are first-class metadata. Beyond the basic widget layout shown above, the production-grade pattern uses:"deleted — a second introduction to a section that no longer restarts (-33)
UI-B-02SKILL.md:1381-1384the "Tokens in filters" blockquote, pointing at Date Macros for the second time in the same filedeleted — the merged file carries that pointer once (-69)
UI-B-05 residueSKILL.md:1029-1032"Real component props/callbacks flow through — e.g. ObjectForm honors objectName / mode / recordId / formType / onSuccess / onCancel; ListView honors objectName / fields / onRowClick / navigation."deleted — the very next blockquote says "Do not guess props — read the contract … author against it, not from memory", and this sentence is a from-memory copy of that generated contract (-57 with its trailing clause)
UI-B-02 (split-exposed)SKILL.md## Report Types"a report visualizes via its embedded chart: config (see the example below)"the parenthetical deleted — the report example is now in rules/dashboards.md (-6)
UI-B-02 (split-exposed)rules/navigation.md Record Presentation"for bespoke layout, assign a record Page (below)"the parenthetical deleted — Pages is now rules/pages.md (-2)
UI-B-02 (split-exposed)rules/pages.md page type list"configured via interfaceConfig (see the iron rule above)"the parenthetical deleted — the iron rule is now in rules/navigation.md (-6)

Gross -248. No decision-changing construct was deleted, and nothing was deleted to reach a number — condition (a) is satisfied by the split being byte-conserving, not by these.

Every "above" / "below" in the new tree was swept for a target that left its file; those three were the only ones, and each is deleted rather than rewritten — a dead pointer is removed text, not an occasion for new prose.

The one-topic-two-files cost, declared

check:skill-identifier-liveness Leg 2 binds three sections to skills/objectstack-ui/SKILL.mdby path (report-types, action-types, navigation-item-types); a bound heading that leaves its file yields [stale-binding] … A renamed heading unbinds the assertion, so it fails here rather than quietly checking nothing, pinned by that script's own self-test. Nothing in the script was changed. So three topics are split across two files:

  • ## Report Types keeps its exhaustive table in the entry; ### Report Configuration moved to rules/dashboards.md (promoted to ##).
  • ### Action Types keeps its table in the entry; the rest of Actions moved to rules/actions.md (headings shifted up one level).
  • ### Navigation Item Types keeps its table in the entry; the App.create example moved to rules/navigation.md.

That is a real legibility cost of the split as constrained, and it is the reason those three entry sections look thin.

Link rewrites

Three links crossed a directory boundary and were rewritten, following the skills/objectstack-platform/rules/ precedent: #date-macros--filter-placeholders became ../SKILL.md#date-macros--filter-placeholders, and ./references/react-blocks.md / ./contracts/react-blocks.contract.json became ../references/… / ../contracts/….

Not in this PR

premise_false: none — no audit finding was skipped this round for a false premise.

Gates

Head d72e3dcc. Family re-derived on the final commit with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands (25 commands, from the script's own merge-base changeset — not a hand-written path list), and the whole union re-run on that head under scripts/pm/os-verify-lock.sh with OS_VERIFY_LOCK_SLOT=issue-14298-r2. Every exit code captured before any pipe. 31 ran, 30 exit 0.

The six beyond the derivation, each owed for a named reason: check-skills-token-ratchet.mjs --self-test (this PR edits that gate, so its own self-test is owed on top of the derived family — 64 cases pass), check:skill-examples and check:skill-refs (the dispatch named them; skills/** changed), check:doc-anchors and check:published-readme-links (links crossed a directory), check:nul-bytes (any edit).

The verdicts that answer this PR's specific risks, quoted from the gates themselves:

  • check:skill-examples — "256 prose examples type-check across 3 surface(s) — every marked block parsed, so tsc ran the SEMANTIC pass on all of them". All 15 os:check markers travelled with their fences (0 in the entry, 15 across the five rules files; 15 before, 15 after) and the marked blocks still compile from their new files.
  • check:skill-identifier-liveness — "Leg 1: 465 citation(s) over 46 published file(s) … Leg 2: 8 registered exhaustive section(s), 0 ledgered gap(s)". The three path-keyed ui bindings still resolve inside SKILL.md.
  • check:published-readme-links — "176 outbound link(s) across 60 published markdown file(s) … 1 anchor(s) verified, 103/103 relative target(s) found". The new ../SKILL.md#date-macros--filter-placeholders and ../references/… links resolve.
  • check:doc-anchors — "295 internal #fragment link(s) across 409 source file(s) all resolve to a real heading".
  • check:skill-docs / check:skill-refs — both in sync; no generated file needed regenerating, and none was touched.
  • check:role-word — green after the baseline re-point (its own commit; see below).
  • node scripts/check-skills-token-ratchet.mjs — "36 authored bundle file(s) within their ceilings", every objectstack-ui row at exactly zero headroom.

check:test-completeness exited 3, which is NOT MEASURED, not a failure — the gate says so itself: "Nothing was measured: this gate exited before parsing a single summary line … ⛔ It is NOT a finding". Recorded as such rather than counted green.

check:role-word needed the baseline re-pointed, and that is a pure relocation. The baseline is keyed by PATH; the two occurrences it already carried for SKILL.md ("the tab-bar role", "semantic roles") moved into rules/list-views.md and rules/navigation.md as byte-identical lines. --update therefore produced a three-line diff — one row removed, two added, total unchanged at 2 — and re-baselined no other file. It is in its own commit. The count did not move, which is what the brief asked to be shown.

Repo-wide pnpm lint was not run; the narrowing is measured, not assumed. (1) The population comes from eslint's own config, not a guess: every files glob in eslint.config.mjs is {ts,tsx,mts,cts,js,jsx,mjs,cjs}, no markdown plugin is configured, and .md appears in no glob — so the six markdown files in this diff are outside eslint's population entirely. (2) Counted from --format json: of the eight changed files eslint claims exactly one, scripts/check-skills-token-ratchet.mjs, at 0 errors / 0 warnings; role-word-baseline.json reports "File ignored because no matching configuration was supplied". (3) Invariance for untouched files: the config configures no projectService and no project, so type-aware linting is off and nothing in this diff can move the verdict of a file it does not contain. CI's Lint job runs the full sweep regardless.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1


Generated by Claude Code

…okens)
The 22,856-token entry file becomes a 3,821-token entry plus five `rules/*.md`
files, converging objectstack-ui on the catalog's declared anatomy
(`skills/README.md`, Skill anatomy) that data, platform and query already use.
Text MOVES; it is not rewritten. The only text that is not a moved line is five
file titles and five one-line pointers. Deleted, all of it restatement the
reassembly exposes:
UI-B-02 the forward reference from `## Dashboards` to "the Production Pattern
section below" (-75), the re-introduction paragraph under the second
dashboards heading (-33), and the duplicated Date Macros pointer
blockquote (-69) -- the two dashboard sections, previously 780 lines
apart, now share one home in `rules/dashboards.md`.
UI-B-05 the prose prop list for the two react blocks (-53 -57 with its trailing
clause), which restated the generated contract that the very next
blockquote makes authoritative.
`check:skill-identifier-liveness` Leg 2 binds three sections to this file BY
PATH, so `## Report Types`, `### Action Types` and `### Navigation Item Types`
keep their exhaustive tables in the entry while their bodies move -- one topic
across two files, in three places. Nothing in that script changed.
Ratchet: one row per new file, pinned at its landed count; the entry row
re-locked 25445 -> 3821. No other row moves.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
Sweeping every "above" / "below" in the new tree for a target that is no longer
in the same file found three, all dead on arrival and all deleted rather than
rewritten -- a dead pointer is removed text, not an occasion for new prose:
SKILL.md "There is no `chart` report type ... (see the example
below)" -- the report example moved to rules/dashboards.md.
rules/navigation "assign a record `Page` (below)" -- Pages moved to
rules/pages.md.
rules/pages page type `list` "(see the iron rule above)" -- the iron
rule moved to rules/navigation.md.
-14 tokens. The three ratchet rows are re-pinned at the new landed counts so
every objectstack-ui row keeps exactly zero headroom; package 33,957 -> 33,899,
net -58.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
Pure relocation, not an admission. The baseline is keyed by PATH, and the two
occurrences it already carried for `skills/objectstack-ui/SKILL.md` moved into
`rules/list-views.md` ("the tab-bar role") and `rules/navigation.md` ("semantic
roles") -- byte-identical lines, so `--update` reads the same two occurrences
at two new paths and drops the old row:
- "skills/objectstack-ui/SKILL.md": 2
+ "skills/objectstack-ui/rules/list-views.md": 1
+ "skills/objectstack-ui/rules/navigation.md": 1
The whole baseline diff is those three lines: no other file was re-baselined,
and the total is unchanged at 2, so the shrink-only ratchet is not weakened.
This is the case the gate's ratchet-DOWN remedy names, kept in its own commit.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@os-litant@os-zhuang@claude
, '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): split the entry into SKILL.md + rules/ under #14296 item 1 (package net −58 tokens, −0.17%) - #14658

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

skills(ui): split the entry into SKILL.md + rules/ under #14296 item 1 (package net −58 tokens, −0.17%)#14658
os-zhuang merged 3 commits into
mainfrom
claude/issue-14298-skills-ui-split

Conversation

@os-litant

Copy link
Copy Markdown
Collaborator

Part of #14298

Ruling: "#14296 item 1 = A, comment 5507419465". Condition (a) was read at programme level by "#14568 = A, comment 5511939006" (director seat, verbatim reply 「同意」): the split PR itself must land token-neutral or negative, and the package arithmetic is carried by the programme.

The three conditions, with numbers

(a) Token-neutral or negative — measured -58.node scripts/check-skills-token-ratchet.mjs before and after, at head d72e3dcc:

beforeafter
SKILL.md22,8563,815
rules/*.md (5 new files)18,983
generated (contracts/react-blocks.contract.json, references/react-blocks.md, references/_index.md)9,7109,710
evals/1,3911,391
package33,95733,899

Net -58 (-0.17%). Gross deletions -248, additions +190 (five file titles, one ## Detailed Rules heading, five one-line pointers). Nothing in this PR is positive.

Programme account for the package: round 1 #14338-2,585 + this split -58 + seam card #14559-5,352 = -7,995 against the pre-programme 36,542 = -21.9%.

(b) Ceilings. Five rows added, each pinned AT its landed count so every new file starts with exactly zero headroom; the entry row re-locked to its landed count. No other row changed.

rowceiling
skills/objectstack-ui/SKILL.md25,445 → 3,815 (re-lock)
skills/objectstack-ui/rules/actions.md2,108 (new)
skills/objectstack-ui/rules/dashboards.md6,090 (new)
skills/objectstack-ui/rules/list-views.md3,011 (new)
skills/objectstack-ui/rules/navigation.md2,273 (new)
skills/objectstack-ui/rules/pages.md5,501 (new)

(c) Not a channel for added prose — proved line by line, not asserted. Comparing the multiset of non-blank lines before (1,591) and after (1,586): 28 lines in the new tree are not lines of the old SKILL.md, and not one of them is a new sentence — 5 file titles, 1## Detailed Rules heading, 5 one-line pointers, 10 headings whose only change is a level shift or a deletion inside the heading text, and 7 lines whose only change is a rewritten relative link or a deleted dead clause. That is the entire set of text this PR authored. The check is reproducible from the diff.

File map

old section (spans at the merge base)new hometokens
## Configuring a List View · ## Configuring Kanban Views · ## Configuring Gantt Viewsrules/list-views.md3,011
## App Navigation (the App.create example) · ## Three Run Modes · ## Record Presentationrules/navigation.md2,273
## Dashboards · ## Dashboards (cont.) · ### Report Configuration · ## Analytics Cubesrules/dashboards.md6,090
## Pages — Lightning-Style Page Layouts · ## Docs — Package Documentationrules/pages.md5,501
## Actions (body below ### Action Types)rules/actions.md2,108
frontmatter · ## View Types · ## Detailed Rules · ## App Navigation head · ## Report Types · ## CRM UI Blueprint · ## Date Macros · ## Actions head · ## Common Pitfalls · ## Verify your work · ## Referencesstays in SKILL.md3,815

Five files, not the audit's suggested nine — the brief says fewer is better, and two of the nine were folded deliberately: rules/filter-tokens.md was not created because ## Date Macros is cross-cutting (list views, dashboards, reports, pages) and is the target of the package's only in-file anchors, so it stays in the entry; rules/master-detail.md was not created because ### Master-Detail Forms is a routing ladder ("you almost never need a custom page or form config — prefer, in order"), which is exactly the kind of construct the entry keeps.

Dashboards now have one home. The two sections that sat 780 lines apart are adjacent in rules/dashboards.md, the second demoted to ### KPI Widgets, Filters, Drilldown under the first — which is what makes the three UI-B-02 deletions below dead text rather than a judgement call.

Deletions, per finding

finding落点beforeafter
UI-B-02SKILL.md:554-558"See the Production Pattern section below for the full Dashboard shape with refreshInterval, header actions, date range, global filters, widget options, and the period-over-period (compareTo) modifier; date bucketing comes from the bound dataset dimension's dateGranularity (ADR-0021)."deleted — a forward reference to a section that is now the next thing on the page (-75)
UI-B-02SKILL.md:1316-1317"Dashboards (Dashboard) are first-class metadata. Beyond the basic widget layout shown above, the production-grade pattern uses:"deleted — a second introduction to a section that no longer restarts (-33)
UI-B-02SKILL.md:1381-1384the "Tokens in filters" blockquote, pointing at Date Macros for the second time in the same filedeleted — the merged file carries that pointer once (-69)
UI-B-05 residueSKILL.md:1029-1032"Real component props/callbacks flow through — e.g. ObjectForm honors objectName / mode / recordId / formType / onSuccess / onCancel; ListView honors objectName / fields / onRowClick / navigation."deleted — the very next blockquote says "Do not guess props — read the contract … author against it, not from memory", and this sentence is a from-memory copy of that generated contract (-57 with its trailing clause)
UI-B-02 (split-exposed)SKILL.md## Report Types"a report visualizes via its embedded chart: config (see the example below)"the parenthetical deleted — the report example is now in rules/dashboards.md (-6)
UI-B-02 (split-exposed)rules/navigation.md Record Presentation"for bespoke layout, assign a record Page (below)"the parenthetical deleted — Pages is now rules/pages.md (-2)
UI-B-02 (split-exposed)rules/pages.md page type list"configured via interfaceConfig (see the iron rule above)"the parenthetical deleted — the iron rule is now in rules/navigation.md (-6)

Gross -248. No decision-changing construct was deleted, and nothing was deleted to reach a number — condition (a) is satisfied by the split being byte-conserving, not by these.

Every "above" / "below" in the new tree was swept for a target that left its file; those three were the only ones, and each is deleted rather than rewritten — a dead pointer is removed text, not an occasion for new prose.

The one-topic-two-files cost, declared

check:skill-identifier-liveness Leg 2 binds three sections to skills/objectstack-ui/SKILL.mdby path (report-types, action-types, navigation-item-types); a bound heading that leaves its file yields [stale-binding] … A renamed heading unbinds the assertion, so it fails here rather than quietly checking nothing, pinned by that script's own self-test. Nothing in the script was changed. So three topics are split across two files:

  • ## Report Types keeps its exhaustive table in the entry; ### Report Configuration moved to rules/dashboards.md (promoted to ##).
  • ### Action Types keeps its table in the entry; the rest of Actions moved to rules/actions.md (headings shifted up one level).
  • ### Navigation Item Types keeps its table in the entry; the App.create example moved to rules/navigation.md.

That is a real legibility cost of the split as constrained, and it is the reason those three entry sections look thin.

Link rewrites

Three links crossed a directory boundary and were rewritten, following the skills/objectstack-platform/rules/ precedent: #date-macros--filter-placeholders became ../SKILL.md#date-macros--filter-placeholders, and ./references/react-blocks.md / ./contracts/react-blocks.contract.json became ../references/… / ../contracts/….

Not in this PR

premise_false: none — no audit finding was skipped this round for a false premise.

Gates

Head d72e3dcc. Family re-derived on the final commit with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands (25 commands, from the script's own merge-base changeset — not a hand-written path list), and the whole union re-run on that head under scripts/pm/os-verify-lock.sh with OS_VERIFY_LOCK_SLOT=issue-14298-r2. Every exit code captured before any pipe. 31 ran, 30 exit 0.

The six beyond the derivation, each owed for a named reason: check-skills-token-ratchet.mjs --self-test (this PR edits that gate, so its own self-test is owed on top of the derived family — 64 cases pass), check:skill-examples and check:skill-refs (the dispatch named them; skills/** changed), check:doc-anchors and check:published-readme-links (links crossed a directory), check:nul-bytes (any edit).

The verdicts that answer this PR's specific risks, quoted from the gates themselves:

  • check:skill-examples — "256 prose examples type-check across 3 surface(s) — every marked block parsed, so tsc ran the SEMANTIC pass on all of them". All 15 os:check markers travelled with their fences (0 in the entry, 15 across the five rules files; 15 before, 15 after) and the marked blocks still compile from their new files.
  • check:skill-identifier-liveness — "Leg 1: 465 citation(s) over 46 published file(s) … Leg 2: 8 registered exhaustive section(s), 0 ledgered gap(s)". The three path-keyed ui bindings still resolve inside SKILL.md.
  • check:published-readme-links — "176 outbound link(s) across 60 published markdown file(s) … 1 anchor(s) verified, 103/103 relative target(s) found". The new ../SKILL.md#date-macros--filter-placeholders and ../references/… links resolve.
  • check:doc-anchors — "295 internal #fragment link(s) across 409 source file(s) all resolve to a real heading".
  • check:skill-docs / check:skill-refs — both in sync; no generated file needed regenerating, and none was touched.
  • check:role-word — green after the baseline re-point (its own commit; see below).
  • node scripts/check-skills-token-ratchet.mjs — "36 authored bundle file(s) within their ceilings", every objectstack-ui row at exactly zero headroom.

check:test-completeness exited 3, which is NOT MEASURED, not a failure — the gate says so itself: "Nothing was measured: this gate exited before parsing a single summary line … ⛔ It is NOT a finding". Recorded as such rather than counted green.

check:role-word needed the baseline re-pointed, and that is a pure relocation. The baseline is keyed by PATH; the two occurrences it already carried for SKILL.md ("the tab-bar role", "semantic roles") moved into rules/list-views.md and rules/navigation.md as byte-identical lines. --update therefore produced a three-line diff — one row removed, two added, total unchanged at 2 — and re-baselined no other file. It is in its own commit. The count did not move, which is what the brief asked to be shown.

Repo-wide pnpm lint was not run; the narrowing is measured, not assumed. (1) The population comes from eslint's own config, not a guess: every files glob in eslint.config.mjs is {ts,tsx,mts,cts,js,jsx,mjs,cjs}, no markdown plugin is configured, and .md appears in no glob — so the six markdown files in this diff are outside eslint's population entirely. (2) Counted from --format json: of the eight changed files eslint claims exactly one, scripts/check-skills-token-ratchet.mjs, at 0 errors / 0 warnings; role-word-baseline.json reports "File ignored because no matching configuration was supplied". (3) Invariance for untouched files: the config configures no projectService and no project, so type-aware linting is off and nothing in this diff can move the verdict of a file it does not contain. CI's Lint job runs the full sweep regardless.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1


Generated by Claude Code

…okens)
The 22,856-token entry file becomes a 3,821-token entry plus five `rules/*.md`
files, converging objectstack-ui on the catalog's declared anatomy
(`skills/README.md`, Skill anatomy) that data, platform and query already use.
Text MOVES; it is not rewritten. The only text that is not a moved line is five
file titles and five one-line pointers. Deleted, all of it restatement the
reassembly exposes:
UI-B-02 the forward reference from `## Dashboards` to "the Production Pattern
section below" (-75), the re-introduction paragraph under the second
dashboards heading (-33), and the duplicated Date Macros pointer
blockquote (-69) -- the two dashboard sections, previously 780 lines
apart, now share one home in `rules/dashboards.md`.
UI-B-05 the prose prop list for the two react blocks (-53 -57 with its trailing
clause), which restated the generated contract that the very next
blockquote makes authoritative.
`check:skill-identifier-liveness` Leg 2 binds three sections to this file BY
PATH, so `## Report Types`, `### Action Types` and `### Navigation Item Types`
keep their exhaustive tables in the entry while their bodies move -- one topic
across two files, in three places. Nothing in that script changed.
Ratchet: one row per new file, pinned at its landed count; the entry row
re-locked 25445 -> 3821. No other row moves.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
Sweeping every "above" / "below" in the new tree for a target that is no longer
in the same file found three, all dead on arrival and all deleted rather than
rewritten -- a dead pointer is removed text, not an occasion for new prose:
SKILL.md "There is no `chart` report type ... (see the example
below)" -- the report example moved to rules/dashboards.md.
rules/navigation "assign a record `Page` (below)" -- Pages moved to
rules/pages.md.
rules/pages page type `list` "(see the iron rule above)" -- the iron
rule moved to rules/navigation.md.
-14 tokens. The three ratchet rows are re-pinned at the new landed counts so
every objectstack-ui row keeps exactly zero headroom; package 33,957 -> 33,899,
net -58.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
Pure relocation, not an admission. The baseline is keyed by PATH, and the two
occurrences it already carried for `skills/objectstack-ui/SKILL.md` moved into
`rules/list-views.md` ("the tab-bar role") and `rules/navigation.md` ("semantic
roles") -- byte-identical lines, so `--update` reads the same two occurrences
at two new paths and drops the old row:
- "skills/objectstack-ui/SKILL.md": 2
+ "skills/objectstack-ui/rules/list-views.md": 1
+ "skills/objectstack-ui/rules/navigation.md": 1
The whole baseline diff is those three lines: no other file was re-baselined,
and the total is unchanged at 2, so the shrink-only ratchet is not weakened.
This is the case the gate's ratchet-DOWN remedy names, kept in its own commit.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@os-litant@os-zhuang@claude
, '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): split the entry into SKILL.md + rules/ under #14296 item 1 (package net −58 tokens, −0.17%) - #14658

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

skills(ui): split the entry into SKILL.md + rules/ under #14296 item 1 (package net −58 tokens, −0.17%)#14658
os-zhuang merged 3 commits into
mainfrom
claude/issue-14298-skills-ui-split

Conversation

@os-litant

Copy link
Copy Markdown
Collaborator

Part of #14298

Ruling: "#14296 item 1 = A, comment 5507419465". Condition (a) was read at programme level by "#14568 = A, comment 5511939006" (director seat, verbatim reply 「同意」): the split PR itself must land token-neutral or negative, and the package arithmetic is carried by the programme.

The three conditions, with numbers

(a) Token-neutral or negative — measured -58.node scripts/check-skills-token-ratchet.mjs before and after, at head d72e3dcc:

beforeafter
SKILL.md22,8563,815
rules/*.md (5 new files)18,983
generated (contracts/react-blocks.contract.json, references/react-blocks.md, references/_index.md)9,7109,710
evals/1,3911,391
package33,95733,899

Net -58 (-0.17%). Gross deletions -248, additions +190 (five file titles, one ## Detailed Rules heading, five one-line pointers). Nothing in this PR is positive.

Programme account for the package: round 1 #14338-2,585 + this split -58 + seam card #14559-5,352 = -7,995 against the pre-programme 36,542 = -21.9%.

(b) Ceilings. Five rows added, each pinned AT its landed count so every new file starts with exactly zero headroom; the entry row re-locked to its landed count. No other row changed.

rowceiling
skills/objectstack-ui/SKILL.md25,445 → 3,815 (re-lock)
skills/objectstack-ui/rules/actions.md2,108 (new)
skills/objectstack-ui/rules/dashboards.md6,090 (new)
skills/objectstack-ui/rules/list-views.md3,011 (new)
skills/objectstack-ui/rules/navigation.md2,273 (new)
skills/objectstack-ui/rules/pages.md5,501 (new)

(c) Not a channel for added prose — proved line by line, not asserted. Comparing the multiset of non-blank lines before (1,591) and after (1,586): 28 lines in the new tree are not lines of the old SKILL.md, and not one of them is a new sentence — 5 file titles, 1## Detailed Rules heading, 5 one-line pointers, 10 headings whose only change is a level shift or a deletion inside the heading text, and 7 lines whose only change is a rewritten relative link or a deleted dead clause. That is the entire set of text this PR authored. The check is reproducible from the diff.

File map

old section (spans at the merge base)new hometokens
## Configuring a List View · ## Configuring Kanban Views · ## Configuring Gantt Viewsrules/list-views.md3,011
## App Navigation (the App.create example) · ## Three Run Modes · ## Record Presentationrules/navigation.md2,273
## Dashboards · ## Dashboards (cont.) · ### Report Configuration · ## Analytics Cubesrules/dashboards.md6,090
## Pages — Lightning-Style Page Layouts · ## Docs — Package Documentationrules/pages.md5,501
## Actions (body below ### Action Types)rules/actions.md2,108
frontmatter · ## View Types · ## Detailed Rules · ## App Navigation head · ## Report Types · ## CRM UI Blueprint · ## Date Macros · ## Actions head · ## Common Pitfalls · ## Verify your work · ## Referencesstays in SKILL.md3,815

Five files, not the audit's suggested nine — the brief says fewer is better, and two of the nine were folded deliberately: rules/filter-tokens.md was not created because ## Date Macros is cross-cutting (list views, dashboards, reports, pages) and is the target of the package's only in-file anchors, so it stays in the entry; rules/master-detail.md was not created because ### Master-Detail Forms is a routing ladder ("you almost never need a custom page or form config — prefer, in order"), which is exactly the kind of construct the entry keeps.

Dashboards now have one home. The two sections that sat 780 lines apart are adjacent in rules/dashboards.md, the second demoted to ### KPI Widgets, Filters, Drilldown under the first — which is what makes the three UI-B-02 deletions below dead text rather than a judgement call.

Deletions, per finding

finding落点beforeafter
UI-B-02SKILL.md:554-558"See the Production Pattern section below for the full Dashboard shape with refreshInterval, header actions, date range, global filters, widget options, and the period-over-period (compareTo) modifier; date bucketing comes from the bound dataset dimension's dateGranularity (ADR-0021)."deleted — a forward reference to a section that is now the next thing on the page (-75)
UI-B-02SKILL.md:1316-1317"Dashboards (Dashboard) are first-class metadata. Beyond the basic widget layout shown above, the production-grade pattern uses:"deleted — a second introduction to a section that no longer restarts (-33)
UI-B-02SKILL.md:1381-1384the "Tokens in filters" blockquote, pointing at Date Macros for the second time in the same filedeleted — the merged file carries that pointer once (-69)
UI-B-05 residueSKILL.md:1029-1032"Real component props/callbacks flow through — e.g. ObjectForm honors objectName / mode / recordId / formType / onSuccess / onCancel; ListView honors objectName / fields / onRowClick / navigation."deleted — the very next blockquote says "Do not guess props — read the contract … author against it, not from memory", and this sentence is a from-memory copy of that generated contract (-57 with its trailing clause)
UI-B-02 (split-exposed)SKILL.md## Report Types"a report visualizes via its embedded chart: config (see the example below)"the parenthetical deleted — the report example is now in rules/dashboards.md (-6)
UI-B-02 (split-exposed)rules/navigation.md Record Presentation"for bespoke layout, assign a record Page (below)"the parenthetical deleted — Pages is now rules/pages.md (-2)
UI-B-02 (split-exposed)rules/pages.md page type list"configured via interfaceConfig (see the iron rule above)"the parenthetical deleted — the iron rule is now in rules/navigation.md (-6)

Gross -248. No decision-changing construct was deleted, and nothing was deleted to reach a number — condition (a) is satisfied by the split being byte-conserving, not by these.

Every "above" / "below" in the new tree was swept for a target that left its file; those three were the only ones, and each is deleted rather than rewritten — a dead pointer is removed text, not an occasion for new prose.

The one-topic-two-files cost, declared

check:skill-identifier-liveness Leg 2 binds three sections to skills/objectstack-ui/SKILL.mdby path (report-types, action-types, navigation-item-types); a bound heading that leaves its file yields [stale-binding] … A renamed heading unbinds the assertion, so it fails here rather than quietly checking nothing, pinned by that script's own self-test. Nothing in the script was changed. So three topics are split across two files:

  • ## Report Types keeps its exhaustive table in the entry; ### Report Configuration moved to rules/dashboards.md (promoted to ##).
  • ### Action Types keeps its table in the entry; the rest of Actions moved to rules/actions.md (headings shifted up one level).
  • ### Navigation Item Types keeps its table in the entry; the App.create example moved to rules/navigation.md.

That is a real legibility cost of the split as constrained, and it is the reason those three entry sections look thin.

Link rewrites

Three links crossed a directory boundary and were rewritten, following the skills/objectstack-platform/rules/ precedent: #date-macros--filter-placeholders became ../SKILL.md#date-macros--filter-placeholders, and ./references/react-blocks.md / ./contracts/react-blocks.contract.json became ../references/… / ../contracts/….

Not in this PR

premise_false: none — no audit finding was skipped this round for a false premise.

Gates

Head d72e3dcc. Family re-derived on the final commit with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands (25 commands, from the script's own merge-base changeset — not a hand-written path list), and the whole union re-run on that head under scripts/pm/os-verify-lock.sh with OS_VERIFY_LOCK_SLOT=issue-14298-r2. Every exit code captured before any pipe. 31 ran, 30 exit 0.

The six beyond the derivation, each owed for a named reason: check-skills-token-ratchet.mjs --self-test (this PR edits that gate, so its own self-test is owed on top of the derived family — 64 cases pass), check:skill-examples and check:skill-refs (the dispatch named them; skills/** changed), check:doc-anchors and check:published-readme-links (links crossed a directory), check:nul-bytes (any edit).

The verdicts that answer this PR's specific risks, quoted from the gates themselves:

  • check:skill-examples — "256 prose examples type-check across 3 surface(s) — every marked block parsed, so tsc ran the SEMANTIC pass on all of them". All 15 os:check markers travelled with their fences (0 in the entry, 15 across the five rules files; 15 before, 15 after) and the marked blocks still compile from their new files.
  • check:skill-identifier-liveness — "Leg 1: 465 citation(s) over 46 published file(s) … Leg 2: 8 registered exhaustive section(s), 0 ledgered gap(s)". The three path-keyed ui bindings still resolve inside SKILL.md.
  • check:published-readme-links — "176 outbound link(s) across 60 published markdown file(s) … 1 anchor(s) verified, 103/103 relative target(s) found". The new ../SKILL.md#date-macros--filter-placeholders and ../references/… links resolve.
  • check:doc-anchors — "295 internal #fragment link(s) across 409 source file(s) all resolve to a real heading".
  • check:skill-docs / check:skill-refs — both in sync; no generated file needed regenerating, and none was touched.
  • check:role-word — green after the baseline re-point (its own commit; see below).
  • node scripts/check-skills-token-ratchet.mjs — "36 authored bundle file(s) within their ceilings", every objectstack-ui row at exactly zero headroom.

check:test-completeness exited 3, which is NOT MEASURED, not a failure — the gate says so itself: "Nothing was measured: this gate exited before parsing a single summary line … ⛔ It is NOT a finding". Recorded as such rather than counted green.

check:role-word needed the baseline re-pointed, and that is a pure relocation. The baseline is keyed by PATH; the two occurrences it already carried for SKILL.md ("the tab-bar role", "semantic roles") moved into rules/list-views.md and rules/navigation.md as byte-identical lines. --update therefore produced a three-line diff — one row removed, two added, total unchanged at 2 — and re-baselined no other file. It is in its own commit. The count did not move, which is what the brief asked to be shown.

Repo-wide pnpm lint was not run; the narrowing is measured, not assumed. (1) The population comes from eslint's own config, not a guess: every files glob in eslint.config.mjs is {ts,tsx,mts,cts,js,jsx,mjs,cjs}, no markdown plugin is configured, and .md appears in no glob — so the six markdown files in this diff are outside eslint's population entirely. (2) Counted from --format json: of the eight changed files eslint claims exactly one, scripts/check-skills-token-ratchet.mjs, at 0 errors / 0 warnings; role-word-baseline.json reports "File ignored because no matching configuration was supplied". (3) Invariance for untouched files: the config configures no projectService and no project, so type-aware linting is off and nothing in this diff can move the verdict of a file it does not contain. CI's Lint job runs the full sweep regardless.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1


Generated by Claude Code

…okens)
The 22,856-token entry file becomes a 3,821-token entry plus five `rules/*.md`
files, converging objectstack-ui on the catalog's declared anatomy
(`skills/README.md`, Skill anatomy) that data, platform and query already use.
Text MOVES; it is not rewritten. The only text that is not a moved line is five
file titles and five one-line pointers. Deleted, all of it restatement the
reassembly exposes:
UI-B-02 the forward reference from `## Dashboards` to "the Production Pattern
section below" (-75), the re-introduction paragraph under the second
dashboards heading (-33), and the duplicated Date Macros pointer
blockquote (-69) -- the two dashboard sections, previously 780 lines
apart, now share one home in `rules/dashboards.md`.
UI-B-05 the prose prop list for the two react blocks (-53 -57 with its trailing
clause), which restated the generated contract that the very next
blockquote makes authoritative.
`check:skill-identifier-liveness` Leg 2 binds three sections to this file BY
PATH, so `## Report Types`, `### Action Types` and `### Navigation Item Types`
keep their exhaustive tables in the entry while their bodies move -- one topic
across two files, in three places. Nothing in that script changed.
Ratchet: one row per new file, pinned at its landed count; the entry row
re-locked 25445 -> 3821. No other row moves.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
Sweeping every "above" / "below" in the new tree for a target that is no longer
in the same file found three, all dead on arrival and all deleted rather than
rewritten -- a dead pointer is removed text, not an occasion for new prose:
SKILL.md "There is no `chart` report type ... (see the example
below)" -- the report example moved to rules/dashboards.md.
rules/navigation "assign a record `Page` (below)" -- Pages moved to
rules/pages.md.
rules/pages page type `list` "(see the iron rule above)" -- the iron
rule moved to rules/navigation.md.
-14 tokens. The three ratchet rows are re-pinned at the new landed counts so
every objectstack-ui row keeps exactly zero headroom; package 33,957 -> 33,899,
net -58.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
Pure relocation, not an admission. The baseline is keyed by PATH, and the two
occurrences it already carried for `skills/objectstack-ui/SKILL.md` moved into
`rules/list-views.md` ("the tab-bar role") and `rules/navigation.md` ("semantic
roles") -- byte-identical lines, so `--update` reads the same two occurrences
at two new paths and drops the old row:
- "skills/objectstack-ui/SKILL.md": 2
+ "skills/objectstack-ui/rules/list-views.md": 1
+ "skills/objectstack-ui/rules/navigation.md": 1
The whole baseline diff is those three lines: no other file was re-baselined,
and the total is unchanged at 2, so the shrink-only ratchet is not weakened.
This is the case the gate's ratchet-DOWN remedy names, kept in its own commit.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@os-litant@os-zhuang@claude
, '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): split the entry into SKILL.md + rules/ under #14296 item 1 (package net −58 tokens, −0.17%) - #14658

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

skills(ui): split the entry into SKILL.md + rules/ under #14296 item 1 (package net −58 tokens, −0.17%)#14658
os-zhuang merged 3 commits into
mainfrom
claude/issue-14298-skills-ui-split

Conversation

@os-litant

Copy link
Copy Markdown
Collaborator

Part of #14298

Ruling: "#14296 item 1 = A, comment 5507419465". Condition (a) was read at programme level by "#14568 = A, comment 5511939006" (director seat, verbatim reply 「同意」): the split PR itself must land token-neutral or negative, and the package arithmetic is carried by the programme.

The three conditions, with numbers

(a) Token-neutral or negative — measured -58.node scripts/check-skills-token-ratchet.mjs before and after, at head d72e3dcc:

beforeafter
SKILL.md22,8563,815
rules/*.md (5 new files)18,983
generated (contracts/react-blocks.contract.json, references/react-blocks.md, references/_index.md)9,7109,710
evals/1,3911,391
package33,95733,899

Net -58 (-0.17%). Gross deletions -248, additions +190 (five file titles, one ## Detailed Rules heading, five one-line pointers). Nothing in this PR is positive.

Programme account for the package: round 1 #14338-2,585 + this split -58 + seam card #14559-5,352 = -7,995 against the pre-programme 36,542 = -21.9%.

(b) Ceilings. Five rows added, each pinned AT its landed count so every new file starts with exactly zero headroom; the entry row re-locked to its landed count. No other row changed.

rowceiling
skills/objectstack-ui/SKILL.md25,445 → 3,815 (re-lock)
skills/objectstack-ui/rules/actions.md2,108 (new)
skills/objectstack-ui/rules/dashboards.md6,090 (new)
skills/objectstack-ui/rules/list-views.md3,011 (new)
skills/objectstack-ui/rules/navigation.md2,273 (new)
skills/objectstack-ui/rules/pages.md5,501 (new)

(c) Not a channel for added prose — proved line by line, not asserted. Comparing the multiset of non-blank lines before (1,591) and after (1,586): 28 lines in the new tree are not lines of the old SKILL.md, and not one of them is a new sentence — 5 file titles, 1## Detailed Rules heading, 5 one-line pointers, 10 headings whose only change is a level shift or a deletion inside the heading text, and 7 lines whose only change is a rewritten relative link or a deleted dead clause. That is the entire set of text this PR authored. The check is reproducible from the diff.

File map

old section (spans at the merge base)new hometokens
## Configuring a List View · ## Configuring Kanban Views · ## Configuring Gantt Viewsrules/list-views.md3,011
## App Navigation (the App.create example) · ## Three Run Modes · ## Record Presentationrules/navigation.md2,273
## Dashboards · ## Dashboards (cont.) · ### Report Configuration · ## Analytics Cubesrules/dashboards.md6,090
## Pages — Lightning-Style Page Layouts · ## Docs — Package Documentationrules/pages.md5,501
## Actions (body below ### Action Types)rules/actions.md2,108
frontmatter · ## View Types · ## Detailed Rules · ## App Navigation head · ## Report Types · ## CRM UI Blueprint · ## Date Macros · ## Actions head · ## Common Pitfalls · ## Verify your work · ## Referencesstays in SKILL.md3,815

Five files, not the audit's suggested nine — the brief says fewer is better, and two of the nine were folded deliberately: rules/filter-tokens.md was not created because ## Date Macros is cross-cutting (list views, dashboards, reports, pages) and is the target of the package's only in-file anchors, so it stays in the entry; rules/master-detail.md was not created because ### Master-Detail Forms is a routing ladder ("you almost never need a custom page or form config — prefer, in order"), which is exactly the kind of construct the entry keeps.

Dashboards now have one home. The two sections that sat 780 lines apart are adjacent in rules/dashboards.md, the second demoted to ### KPI Widgets, Filters, Drilldown under the first — which is what makes the three UI-B-02 deletions below dead text rather than a judgement call.

Deletions, per finding

finding落点beforeafter
UI-B-02SKILL.md:554-558"See the Production Pattern section below for the full Dashboard shape with refreshInterval, header actions, date range, global filters, widget options, and the period-over-period (compareTo) modifier; date bucketing comes from the bound dataset dimension's dateGranularity (ADR-0021)."deleted — a forward reference to a section that is now the next thing on the page (-75)
UI-B-02SKILL.md:1316-1317"Dashboards (Dashboard) are first-class metadata. Beyond the basic widget layout shown above, the production-grade pattern uses:"deleted — a second introduction to a section that no longer restarts (-33)
UI-B-02SKILL.md:1381-1384the "Tokens in filters" blockquote, pointing at Date Macros for the second time in the same filedeleted — the merged file carries that pointer once (-69)
UI-B-05 residueSKILL.md:1029-1032"Real component props/callbacks flow through — e.g. ObjectForm honors objectName / mode / recordId / formType / onSuccess / onCancel; ListView honors objectName / fields / onRowClick / navigation."deleted — the very next blockquote says "Do not guess props — read the contract … author against it, not from memory", and this sentence is a from-memory copy of that generated contract (-57 with its trailing clause)
UI-B-02 (split-exposed)SKILL.md## Report Types"a report visualizes via its embedded chart: config (see the example below)"the parenthetical deleted — the report example is now in rules/dashboards.md (-6)
UI-B-02 (split-exposed)rules/navigation.md Record Presentation"for bespoke layout, assign a record Page (below)"the parenthetical deleted — Pages is now rules/pages.md (-2)
UI-B-02 (split-exposed)rules/pages.md page type list"configured via interfaceConfig (see the iron rule above)"the parenthetical deleted — the iron rule is now in rules/navigation.md (-6)

Gross -248. No decision-changing construct was deleted, and nothing was deleted to reach a number — condition (a) is satisfied by the split being byte-conserving, not by these.

Every "above" / "below" in the new tree was swept for a target that left its file; those three were the only ones, and each is deleted rather than rewritten — a dead pointer is removed text, not an occasion for new prose.

The one-topic-two-files cost, declared

check:skill-identifier-liveness Leg 2 binds three sections to skills/objectstack-ui/SKILL.mdby path (report-types, action-types, navigation-item-types); a bound heading that leaves its file yields [stale-binding] … A renamed heading unbinds the assertion, so it fails here rather than quietly checking nothing, pinned by that script's own self-test. Nothing in the script was changed. So three topics are split across two files:

  • ## Report Types keeps its exhaustive table in the entry; ### Report Configuration moved to rules/dashboards.md (promoted to ##).
  • ### Action Types keeps its table in the entry; the rest of Actions moved to rules/actions.md (headings shifted up one level).
  • ### Navigation Item Types keeps its table in the entry; the App.create example moved to rules/navigation.md.

That is a real legibility cost of the split as constrained, and it is the reason those three entry sections look thin.

Link rewrites

Three links crossed a directory boundary and were rewritten, following the skills/objectstack-platform/rules/ precedent: #date-macros--filter-placeholders became ../SKILL.md#date-macros--filter-placeholders, and ./references/react-blocks.md / ./contracts/react-blocks.contract.json became ../references/… / ../contracts/….

Not in this PR

premise_false: none — no audit finding was skipped this round for a false premise.

Gates

Head d72e3dcc. Family re-derived on the final commit with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands (25 commands, from the script's own merge-base changeset — not a hand-written path list), and the whole union re-run on that head under scripts/pm/os-verify-lock.sh with OS_VERIFY_LOCK_SLOT=issue-14298-r2. Every exit code captured before any pipe. 31 ran, 30 exit 0.

The six beyond the derivation, each owed for a named reason: check-skills-token-ratchet.mjs --self-test (this PR edits that gate, so its own self-test is owed on top of the derived family — 64 cases pass), check:skill-examples and check:skill-refs (the dispatch named them; skills/** changed), check:doc-anchors and check:published-readme-links (links crossed a directory), check:nul-bytes (any edit).

The verdicts that answer this PR's specific risks, quoted from the gates themselves:

  • check:skill-examples — "256 prose examples type-check across 3 surface(s) — every marked block parsed, so tsc ran the SEMANTIC pass on all of them". All 15 os:check markers travelled with their fences (0 in the entry, 15 across the five rules files; 15 before, 15 after) and the marked blocks still compile from their new files.
  • check:skill-identifier-liveness — "Leg 1: 465 citation(s) over 46 published file(s) … Leg 2: 8 registered exhaustive section(s), 0 ledgered gap(s)". The three path-keyed ui bindings still resolve inside SKILL.md.
  • check:published-readme-links — "176 outbound link(s) across 60 published markdown file(s) … 1 anchor(s) verified, 103/103 relative target(s) found". The new ../SKILL.md#date-macros--filter-placeholders and ../references/… links resolve.
  • check:doc-anchors — "295 internal #fragment link(s) across 409 source file(s) all resolve to a real heading".
  • check:skill-docs / check:skill-refs — both in sync; no generated file needed regenerating, and none was touched.
  • check:role-word — green after the baseline re-point (its own commit; see below).
  • node scripts/check-skills-token-ratchet.mjs — "36 authored bundle file(s) within their ceilings", every objectstack-ui row at exactly zero headroom.

check:test-completeness exited 3, which is NOT MEASURED, not a failure — the gate says so itself: "Nothing was measured: this gate exited before parsing a single summary line … ⛔ It is NOT a finding". Recorded as such rather than counted green.

check:role-word needed the baseline re-pointed, and that is a pure relocation. The baseline is keyed by PATH; the two occurrences it already carried for SKILL.md ("the tab-bar role", "semantic roles") moved into rules/list-views.md and rules/navigation.md as byte-identical lines. --update therefore produced a three-line diff — one row removed, two added, total unchanged at 2 — and re-baselined no other file. It is in its own commit. The count did not move, which is what the brief asked to be shown.

Repo-wide pnpm lint was not run; the narrowing is measured, not assumed. (1) The population comes from eslint's own config, not a guess: every files glob in eslint.config.mjs is {ts,tsx,mts,cts,js,jsx,mjs,cjs}, no markdown plugin is configured, and .md appears in no glob — so the six markdown files in this diff are outside eslint's population entirely. (2) Counted from --format json: of the eight changed files eslint claims exactly one, scripts/check-skills-token-ratchet.mjs, at 0 errors / 0 warnings; role-word-baseline.json reports "File ignored because no matching configuration was supplied". (3) Invariance for untouched files: the config configures no projectService and no project, so type-aware linting is off and nothing in this diff can move the verdict of a file it does not contain. CI's Lint job runs the full sweep regardless.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1


Generated by Claude Code

…okens)
The 22,856-token entry file becomes a 3,821-token entry plus five `rules/*.md`
files, converging objectstack-ui on the catalog's declared anatomy
(`skills/README.md`, Skill anatomy) that data, platform and query already use.
Text MOVES; it is not rewritten. The only text that is not a moved line is five
file titles and five one-line pointers. Deleted, all of it restatement the
reassembly exposes:
UI-B-02 the forward reference from `## Dashboards` to "the Production Pattern
section below" (-75), the re-introduction paragraph under the second
dashboards heading (-33), and the duplicated Date Macros pointer
blockquote (-69) -- the two dashboard sections, previously 780 lines
apart, now share one home in `rules/dashboards.md`.
UI-B-05 the prose prop list for the two react blocks (-53 -57 with its trailing
clause), which restated the generated contract that the very next
blockquote makes authoritative.
`check:skill-identifier-liveness` Leg 2 binds three sections to this file BY
PATH, so `## Report Types`, `### Action Types` and `### Navigation Item Types`
keep their exhaustive tables in the entry while their bodies move -- one topic
across two files, in three places. Nothing in that script changed.
Ratchet: one row per new file, pinned at its landed count; the entry row
re-locked 25445 -> 3821. No other row moves.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
Sweeping every "above" / "below" in the new tree for a target that is no longer
in the same file found three, all dead on arrival and all deleted rather than
rewritten -- a dead pointer is removed text, not an occasion for new prose:
SKILL.md "There is no `chart` report type ... (see the example
below)" -- the report example moved to rules/dashboards.md.
rules/navigation "assign a record `Page` (below)" -- Pages moved to
rules/pages.md.
rules/pages page type `list` "(see the iron rule above)" -- the iron
rule moved to rules/navigation.md.
-14 tokens. The three ratchet rows are re-pinned at the new landed counts so
every objectstack-ui row keeps exactly zero headroom; package 33,957 -> 33,899,
net -58.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
Pure relocation, not an admission. The baseline is keyed by PATH, and the two
occurrences it already carried for `skills/objectstack-ui/SKILL.md` moved into
`rules/list-views.md` ("the tab-bar role") and `rules/navigation.md` ("semantic
roles") -- byte-identical lines, so `--update` reads the same two occurrences
at two new paths and drops the old row:
- "skills/objectstack-ui/SKILL.md": 2
+ "skills/objectstack-ui/rules/list-views.md": 1
+ "skills/objectstack-ui/rules/navigation.md": 1
The whole baseline diff is those three lines: no other file was re-baselined,
and the total is unchanged at 2, so the shrink-only ratchet is not weakened.
This is the case the gate's ratchet-DOWN remedy names, kept in its own commit.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@os-litant@os-zhuang@claude
, '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): split the entry into SKILL.md + rules/ under #14296 item 1 (package net −58 tokens, −0.17%) - #14658

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

skills(ui): split the entry into SKILL.md + rules/ under #14296 item 1 (package net −58 tokens, −0.17%)#14658
os-zhuang merged 3 commits into
mainfrom
claude/issue-14298-skills-ui-split

Conversation

@os-litant

Copy link
Copy Markdown
Collaborator

Part of #14298

Ruling: "#14296 item 1 = A, comment 5507419465". Condition (a) was read at programme level by "#14568 = A, comment 5511939006" (director seat, verbatim reply 「同意」): the split PR itself must land token-neutral or negative, and the package arithmetic is carried by the programme.

The three conditions, with numbers

(a) Token-neutral or negative — measured -58.node scripts/check-skills-token-ratchet.mjs before and after, at head d72e3dcc:

beforeafter
SKILL.md22,8563,815
rules/*.md (5 new files)18,983
generated (contracts/react-blocks.contract.json, references/react-blocks.md, references/_index.md)9,7109,710
evals/1,3911,391
package33,95733,899

Net -58 (-0.17%). Gross deletions -248, additions +190 (five file titles, one ## Detailed Rules heading, five one-line pointers). Nothing in this PR is positive.

Programme account for the package: round 1 #14338-2,585 + this split -58 + seam card #14559-5,352 = -7,995 against the pre-programme 36,542 = -21.9%.

(b) Ceilings. Five rows added, each pinned AT its landed count so every new file starts with exactly zero headroom; the entry row re-locked to its landed count. No other row changed.

rowceiling
skills/objectstack-ui/SKILL.md25,445 → 3,815 (re-lock)
skills/objectstack-ui/rules/actions.md2,108 (new)
skills/objectstack-ui/rules/dashboards.md6,090 (new)
skills/objectstack-ui/rules/list-views.md3,011 (new)
skills/objectstack-ui/rules/navigation.md2,273 (new)
skills/objectstack-ui/rules/pages.md5,501 (new)

(c) Not a channel for added prose — proved line by line, not asserted. Comparing the multiset of non-blank lines before (1,591) and after (1,586): 28 lines in the new tree are not lines of the old SKILL.md, and not one of them is a new sentence — 5 file titles, 1## Detailed Rules heading, 5 one-line pointers, 10 headings whose only change is a level shift or a deletion inside the heading text, and 7 lines whose only change is a rewritten relative link or a deleted dead clause. That is the entire set of text this PR authored. The check is reproducible from the diff.

File map

old section (spans at the merge base)new hometokens
## Configuring a List View · ## Configuring Kanban Views · ## Configuring Gantt Viewsrules/list-views.md3,011
## App Navigation (the App.create example) · ## Three Run Modes · ## Record Presentationrules/navigation.md2,273
## Dashboards · ## Dashboards (cont.) · ### Report Configuration · ## Analytics Cubesrules/dashboards.md6,090
## Pages — Lightning-Style Page Layouts · ## Docs — Package Documentationrules/pages.md5,501
## Actions (body below ### Action Types)rules/actions.md2,108
frontmatter · ## View Types · ## Detailed Rules · ## App Navigation head · ## Report Types · ## CRM UI Blueprint · ## Date Macros · ## Actions head · ## Common Pitfalls · ## Verify your work · ## Referencesstays in SKILL.md3,815

Five files, not the audit's suggested nine — the brief says fewer is better, and two of the nine were folded deliberately: rules/filter-tokens.md was not created because ## Date Macros is cross-cutting (list views, dashboards, reports, pages) and is the target of the package's only in-file anchors, so it stays in the entry; rules/master-detail.md was not created because ### Master-Detail Forms is a routing ladder ("you almost never need a custom page or form config — prefer, in order"), which is exactly the kind of construct the entry keeps.

Dashboards now have one home. The two sections that sat 780 lines apart are adjacent in rules/dashboards.md, the second demoted to ### KPI Widgets, Filters, Drilldown under the first — which is what makes the three UI-B-02 deletions below dead text rather than a judgement call.

Deletions, per finding

finding落点beforeafter
UI-B-02SKILL.md:554-558"See the Production Pattern section below for the full Dashboard shape with refreshInterval, header actions, date range, global filters, widget options, and the period-over-period (compareTo) modifier; date bucketing comes from the bound dataset dimension's dateGranularity (ADR-0021)."deleted — a forward reference to a section that is now the next thing on the page (-75)
UI-B-02SKILL.md:1316-1317"Dashboards (Dashboard) are first-class metadata. Beyond the basic widget layout shown above, the production-grade pattern uses:"deleted — a second introduction to a section that no longer restarts (-33)
UI-B-02SKILL.md:1381-1384the "Tokens in filters" blockquote, pointing at Date Macros for the second time in the same filedeleted — the merged file carries that pointer once (-69)
UI-B-05 residueSKILL.md:1029-1032"Real component props/callbacks flow through — e.g. ObjectForm honors objectName / mode / recordId / formType / onSuccess / onCancel; ListView honors objectName / fields / onRowClick / navigation."deleted — the very next blockquote says "Do not guess props — read the contract … author against it, not from memory", and this sentence is a from-memory copy of that generated contract (-57 with its trailing clause)
UI-B-02 (split-exposed)SKILL.md## Report Types"a report visualizes via its embedded chart: config (see the example below)"the parenthetical deleted — the report example is now in rules/dashboards.md (-6)
UI-B-02 (split-exposed)rules/navigation.md Record Presentation"for bespoke layout, assign a record Page (below)"the parenthetical deleted — Pages is now rules/pages.md (-2)
UI-B-02 (split-exposed)rules/pages.md page type list"configured via interfaceConfig (see the iron rule above)"the parenthetical deleted — the iron rule is now in rules/navigation.md (-6)

Gross -248. No decision-changing construct was deleted, and nothing was deleted to reach a number — condition (a) is satisfied by the split being byte-conserving, not by these.

Every "above" / "below" in the new tree was swept for a target that left its file; those three were the only ones, and each is deleted rather than rewritten — a dead pointer is removed text, not an occasion for new prose.

The one-topic-two-files cost, declared

check:skill-identifier-liveness Leg 2 binds three sections to skills/objectstack-ui/SKILL.mdby path (report-types, action-types, navigation-item-types); a bound heading that leaves its file yields [stale-binding] … A renamed heading unbinds the assertion, so it fails here rather than quietly checking nothing, pinned by that script's own self-test. Nothing in the script was changed. So three topics are split across two files:

  • ## Report Types keeps its exhaustive table in the entry; ### Report Configuration moved to rules/dashboards.md (promoted to ##).
  • ### Action Types keeps its table in the entry; the rest of Actions moved to rules/actions.md (headings shifted up one level).
  • ### Navigation Item Types keeps its table in the entry; the App.create example moved to rules/navigation.md.

That is a real legibility cost of the split as constrained, and it is the reason those three entry sections look thin.

Link rewrites

Three links crossed a directory boundary and were rewritten, following the skills/objectstack-platform/rules/ precedent: #date-macros--filter-placeholders became ../SKILL.md#date-macros--filter-placeholders, and ./references/react-blocks.md / ./contracts/react-blocks.contract.json became ../references/… / ../contracts/….

Not in this PR

premise_false: none — no audit finding was skipped this round for a false premise.

Gates

Head d72e3dcc. Family re-derived on the final commit with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands (25 commands, from the script's own merge-base changeset — not a hand-written path list), and the whole union re-run on that head under scripts/pm/os-verify-lock.sh with OS_VERIFY_LOCK_SLOT=issue-14298-r2. Every exit code captured before any pipe. 31 ran, 30 exit 0.

The six beyond the derivation, each owed for a named reason: check-skills-token-ratchet.mjs --self-test (this PR edits that gate, so its own self-test is owed on top of the derived family — 64 cases pass), check:skill-examples and check:skill-refs (the dispatch named them; skills/** changed), check:doc-anchors and check:published-readme-links (links crossed a directory), check:nul-bytes (any edit).

The verdicts that answer this PR's specific risks, quoted from the gates themselves:

  • check:skill-examples — "256 prose examples type-check across 3 surface(s) — every marked block parsed, so tsc ran the SEMANTIC pass on all of them". All 15 os:check markers travelled with their fences (0 in the entry, 15 across the five rules files; 15 before, 15 after) and the marked blocks still compile from their new files.
  • check:skill-identifier-liveness — "Leg 1: 465 citation(s) over 46 published file(s) … Leg 2: 8 registered exhaustive section(s), 0 ledgered gap(s)". The three path-keyed ui bindings still resolve inside SKILL.md.
  • check:published-readme-links — "176 outbound link(s) across 60 published markdown file(s) … 1 anchor(s) verified, 103/103 relative target(s) found". The new ../SKILL.md#date-macros--filter-placeholders and ../references/… links resolve.
  • check:doc-anchors — "295 internal #fragment link(s) across 409 source file(s) all resolve to a real heading".
  • check:skill-docs / check:skill-refs — both in sync; no generated file needed regenerating, and none was touched.
  • check:role-word — green after the baseline re-point (its own commit; see below).
  • node scripts/check-skills-token-ratchet.mjs — "36 authored bundle file(s) within their ceilings", every objectstack-ui row at exactly zero headroom.

check:test-completeness exited 3, which is NOT MEASURED, not a failure — the gate says so itself: "Nothing was measured: this gate exited before parsing a single summary line … ⛔ It is NOT a finding". Recorded as such rather than counted green.

check:role-word needed the baseline re-pointed, and that is a pure relocation. The baseline is keyed by PATH; the two occurrences it already carried for SKILL.md ("the tab-bar role", "semantic roles") moved into rules/list-views.md and rules/navigation.md as byte-identical lines. --update therefore produced a three-line diff — one row removed, two added, total unchanged at 2 — and re-baselined no other file. It is in its own commit. The count did not move, which is what the brief asked to be shown.

Repo-wide pnpm lint was not run; the narrowing is measured, not assumed. (1) The population comes from eslint's own config, not a guess: every files glob in eslint.config.mjs is {ts,tsx,mts,cts,js,jsx,mjs,cjs}, no markdown plugin is configured, and .md appears in no glob — so the six markdown files in this diff are outside eslint's population entirely. (2) Counted from --format json: of the eight changed files eslint claims exactly one, scripts/check-skills-token-ratchet.mjs, at 0 errors / 0 warnings; role-word-baseline.json reports "File ignored because no matching configuration was supplied". (3) Invariance for untouched files: the config configures no projectService and no project, so type-aware linting is off and nothing in this diff can move the verdict of a file it does not contain. CI's Lint job runs the full sweep regardless.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1


Generated by Claude Code

…okens)
The 22,856-token entry file becomes a 3,821-token entry plus five `rules/*.md`
files, converging objectstack-ui on the catalog's declared anatomy
(`skills/README.md`, Skill anatomy) that data, platform and query already use.
Text MOVES; it is not rewritten. The only text that is not a moved line is five
file titles and five one-line pointers. Deleted, all of it restatement the
reassembly exposes:
UI-B-02 the forward reference from `## Dashboards` to "the Production Pattern
section below" (-75), the re-introduction paragraph under the second
dashboards heading (-33), and the duplicated Date Macros pointer
blockquote (-69) -- the two dashboard sections, previously 780 lines
apart, now share one home in `rules/dashboards.md`.
UI-B-05 the prose prop list for the two react blocks (-53 -57 with its trailing
clause), which restated the generated contract that the very next
blockquote makes authoritative.
`check:skill-identifier-liveness` Leg 2 binds three sections to this file BY
PATH, so `## Report Types`, `### Action Types` and `### Navigation Item Types`
keep their exhaustive tables in the entry while their bodies move -- one topic
across two files, in three places. Nothing in that script changed.
Ratchet: one row per new file, pinned at its landed count; the entry row
re-locked 25445 -> 3821. No other row moves.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
Sweeping every "above" / "below" in the new tree for a target that is no longer
in the same file found three, all dead on arrival and all deleted rather than
rewritten -- a dead pointer is removed text, not an occasion for new prose:
SKILL.md "There is no `chart` report type ... (see the example
below)" -- the report example moved to rules/dashboards.md.
rules/navigation "assign a record `Page` (below)" -- Pages moved to
rules/pages.md.
rules/pages page type `list` "(see the iron rule above)" -- the iron
rule moved to rules/navigation.md.
-14 tokens. The three ratchet rows are re-pinned at the new landed counts so
every objectstack-ui row keeps exactly zero headroom; package 33,957 -> 33,899,
net -58.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
Pure relocation, not an admission. The baseline is keyed by PATH, and the two
occurrences it already carried for `skills/objectstack-ui/SKILL.md` moved into
`rules/list-views.md` ("the tab-bar role") and `rules/navigation.md` ("semantic
roles") -- byte-identical lines, so `--update` reads the same two occurrences
at two new paths and drops the old row:
- "skills/objectstack-ui/SKILL.md": 2
+ "skills/objectstack-ui/rules/list-views.md": 1
+ "skills/objectstack-ui/rules/navigation.md": 1
The whole baseline diff is those three lines: no other file was re-baselined,
and the total is unchanged at 2, so the shrink-only ratchet is not weakened.
This is the case the gate's ratchet-DOWN remedy names, kept in its own commit.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@os-litant@os-zhuang@claude
, '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): split the entry into SKILL.md + rules/ under #14296 item 1 (package net −58 tokens, −0.17%) - #14658

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

skills(ui): split the entry into SKILL.md + rules/ under #14296 item 1 (package net −58 tokens, −0.17%)#14658
os-zhuang merged 3 commits into
mainfrom
claude/issue-14298-skills-ui-split

Conversation

@os-litant

Copy link
Copy Markdown
Collaborator

Part of #14298

Ruling: "#14296 item 1 = A, comment 5507419465". Condition (a) was read at programme level by "#14568 = A, comment 5511939006" (director seat, verbatim reply 「同意」): the split PR itself must land token-neutral or negative, and the package arithmetic is carried by the programme.

The three conditions, with numbers

(a) Token-neutral or negative — measured -58.node scripts/check-skills-token-ratchet.mjs before and after, at head d72e3dcc:

beforeafter
SKILL.md22,8563,815
rules/*.md (5 new files)18,983
generated (contracts/react-blocks.contract.json, references/react-blocks.md, references/_index.md)9,7109,710
evals/1,3911,391
package33,95733,899

Net -58 (-0.17%). Gross deletions -248, additions +190 (five file titles, one ## Detailed Rules heading, five one-line pointers). Nothing in this PR is positive.

Programme account for the package: round 1 #14338-2,585 + this split -58 + seam card #14559-5,352 = -7,995 against the pre-programme 36,542 = -21.9%.

(b) Ceilings. Five rows added, each pinned AT its landed count so every new file starts with exactly zero headroom; the entry row re-locked to its landed count. No other row changed.

rowceiling
skills/objectstack-ui/SKILL.md25,445 → 3,815 (re-lock)
skills/objectstack-ui/rules/actions.md2,108 (new)
skills/objectstack-ui/rules/dashboards.md6,090 (new)
skills/objectstack-ui/rules/list-views.md3,011 (new)
skills/objectstack-ui/rules/navigation.md2,273 (new)
skills/objectstack-ui/rules/pages.md5,501 (new)

(c) Not a channel for added prose — proved line by line, not asserted. Comparing the multiset of non-blank lines before (1,591) and after (1,586): 28 lines in the new tree are not lines of the old SKILL.md, and not one of them is a new sentence — 5 file titles, 1## Detailed Rules heading, 5 one-line pointers, 10 headings whose only change is a level shift or a deletion inside the heading text, and 7 lines whose only change is a rewritten relative link or a deleted dead clause. That is the entire set of text this PR authored. The check is reproducible from the diff.

File map

old section (spans at the merge base)new hometokens
## Configuring a List View · ## Configuring Kanban Views · ## Configuring Gantt Viewsrules/list-views.md3,011
## App Navigation (the App.create example) · ## Three Run Modes · ## Record Presentationrules/navigation.md2,273
## Dashboards · ## Dashboards (cont.) · ### Report Configuration · ## Analytics Cubesrules/dashboards.md6,090
## Pages — Lightning-Style Page Layouts · ## Docs — Package Documentationrules/pages.md5,501
## Actions (body below ### Action Types)rules/actions.md2,108
frontmatter · ## View Types · ## Detailed Rules · ## App Navigation head · ## Report Types · ## CRM UI Blueprint · ## Date Macros · ## Actions head · ## Common Pitfalls · ## Verify your work · ## Referencesstays in SKILL.md3,815

Five files, not the audit's suggested nine — the brief says fewer is better, and two of the nine were folded deliberately: rules/filter-tokens.md was not created because ## Date Macros is cross-cutting (list views, dashboards, reports, pages) and is the target of the package's only in-file anchors, so it stays in the entry; rules/master-detail.md was not created because ### Master-Detail Forms is a routing ladder ("you almost never need a custom page or form config — prefer, in order"), which is exactly the kind of construct the entry keeps.

Dashboards now have one home. The two sections that sat 780 lines apart are adjacent in rules/dashboards.md, the second demoted to ### KPI Widgets, Filters, Drilldown under the first — which is what makes the three UI-B-02 deletions below dead text rather than a judgement call.

Deletions, per finding

finding落点beforeafter
UI-B-02SKILL.md:554-558"See the Production Pattern section below for the full Dashboard shape with refreshInterval, header actions, date range, global filters, widget options, and the period-over-period (compareTo) modifier; date bucketing comes from the bound dataset dimension's dateGranularity (ADR-0021)."deleted — a forward reference to a section that is now the next thing on the page (-75)
UI-B-02SKILL.md:1316-1317"Dashboards (Dashboard) are first-class metadata. Beyond the basic widget layout shown above, the production-grade pattern uses:"deleted — a second introduction to a section that no longer restarts (-33)
UI-B-02SKILL.md:1381-1384the "Tokens in filters" blockquote, pointing at Date Macros for the second time in the same filedeleted — the merged file carries that pointer once (-69)
UI-B-05 residueSKILL.md:1029-1032"Real component props/callbacks flow through — e.g. ObjectForm honors objectName / mode / recordId / formType / onSuccess / onCancel; ListView honors objectName / fields / onRowClick / navigation."deleted — the very next blockquote says "Do not guess props — read the contract … author against it, not from memory", and this sentence is a from-memory copy of that generated contract (-57 with its trailing clause)
UI-B-02 (split-exposed)SKILL.md## Report Types"a report visualizes via its embedded chart: config (see the example below)"the parenthetical deleted — the report example is now in rules/dashboards.md (-6)
UI-B-02 (split-exposed)rules/navigation.md Record Presentation"for bespoke layout, assign a record Page (below)"the parenthetical deleted — Pages is now rules/pages.md (-2)
UI-B-02 (split-exposed)rules/pages.md page type list"configured via interfaceConfig (see the iron rule above)"the parenthetical deleted — the iron rule is now in rules/navigation.md (-6)

Gross -248. No decision-changing construct was deleted, and nothing was deleted to reach a number — condition (a) is satisfied by the split being byte-conserving, not by these.

Every "above" / "below" in the new tree was swept for a target that left its file; those three were the only ones, and each is deleted rather than rewritten — a dead pointer is removed text, not an occasion for new prose.

The one-topic-two-files cost, declared

check:skill-identifier-liveness Leg 2 binds three sections to skills/objectstack-ui/SKILL.mdby path (report-types, action-types, navigation-item-types); a bound heading that leaves its file yields [stale-binding] … A renamed heading unbinds the assertion, so it fails here rather than quietly checking nothing, pinned by that script's own self-test. Nothing in the script was changed. So three topics are split across two files:

  • ## Report Types keeps its exhaustive table in the entry; ### Report Configuration moved to rules/dashboards.md (promoted to ##).
  • ### Action Types keeps its table in the entry; the rest of Actions moved to rules/actions.md (headings shifted up one level).
  • ### Navigation Item Types keeps its table in the entry; the App.create example moved to rules/navigation.md.

That is a real legibility cost of the split as constrained, and it is the reason those three entry sections look thin.

Link rewrites

Three links crossed a directory boundary and were rewritten, following the skills/objectstack-platform/rules/ precedent: #date-macros--filter-placeholders became ../SKILL.md#date-macros--filter-placeholders, and ./references/react-blocks.md / ./contracts/react-blocks.contract.json became ../references/… / ../contracts/….

Not in this PR

premise_false: none — no audit finding was skipped this round for a false premise.

Gates

Head d72e3dcc. Family re-derived on the final commit with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands (25 commands, from the script's own merge-base changeset — not a hand-written path list), and the whole union re-run on that head under scripts/pm/os-verify-lock.sh with OS_VERIFY_LOCK_SLOT=issue-14298-r2. Every exit code captured before any pipe. 31 ran, 30 exit 0.

The six beyond the derivation, each owed for a named reason: check-skills-token-ratchet.mjs --self-test (this PR edits that gate, so its own self-test is owed on top of the derived family — 64 cases pass), check:skill-examples and check:skill-refs (the dispatch named them; skills/** changed), check:doc-anchors and check:published-readme-links (links crossed a directory), check:nul-bytes (any edit).

The verdicts that answer this PR's specific risks, quoted from the gates themselves:

  • check:skill-examples — "256 prose examples type-check across 3 surface(s) — every marked block parsed, so tsc ran the SEMANTIC pass on all of them". All 15 os:check markers travelled with their fences (0 in the entry, 15 across the five rules files; 15 before, 15 after) and the marked blocks still compile from their new files.
  • check:skill-identifier-liveness — "Leg 1: 465 citation(s) over 46 published file(s) … Leg 2: 8 registered exhaustive section(s), 0 ledgered gap(s)". The three path-keyed ui bindings still resolve inside SKILL.md.
  • check:published-readme-links — "176 outbound link(s) across 60 published markdown file(s) … 1 anchor(s) verified, 103/103 relative target(s) found". The new ../SKILL.md#date-macros--filter-placeholders and ../references/… links resolve.
  • check:doc-anchors — "295 internal #fragment link(s) across 409 source file(s) all resolve to a real heading".
  • check:skill-docs / check:skill-refs — both in sync; no generated file needed regenerating, and none was touched.
  • check:role-word — green after the baseline re-point (its own commit; see below).
  • node scripts/check-skills-token-ratchet.mjs — "36 authored bundle file(s) within their ceilings", every objectstack-ui row at exactly zero headroom.

check:test-completeness exited 3, which is NOT MEASURED, not a failure — the gate says so itself: "Nothing was measured: this gate exited before parsing a single summary line … ⛔ It is NOT a finding". Recorded as such rather than counted green.

check:role-word needed the baseline re-pointed, and that is a pure relocation. The baseline is keyed by PATH; the two occurrences it already carried for SKILL.md ("the tab-bar role", "semantic roles") moved into rules/list-views.md and rules/navigation.md as byte-identical lines. --update therefore produced a three-line diff — one row removed, two added, total unchanged at 2 — and re-baselined no other file. It is in its own commit. The count did not move, which is what the brief asked to be shown.

Repo-wide pnpm lint was not run; the narrowing is measured, not assumed. (1) The population comes from eslint's own config, not a guess: every files glob in eslint.config.mjs is {ts,tsx,mts,cts,js,jsx,mjs,cjs}, no markdown plugin is configured, and .md appears in no glob — so the six markdown files in this diff are outside eslint's population entirely. (2) Counted from --format json: of the eight changed files eslint claims exactly one, scripts/check-skills-token-ratchet.mjs, at 0 errors / 0 warnings; role-word-baseline.json reports "File ignored because no matching configuration was supplied". (3) Invariance for untouched files: the config configures no projectService and no project, so type-aware linting is off and nothing in this diff can move the verdict of a file it does not contain. CI's Lint job runs the full sweep regardless.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1


Generated by Claude Code

…okens)
The 22,856-token entry file becomes a 3,821-token entry plus five `rules/*.md`
files, converging objectstack-ui on the catalog's declared anatomy
(`skills/README.md`, Skill anatomy) that data, platform and query already use.
Text MOVES; it is not rewritten. The only text that is not a moved line is five
file titles and five one-line pointers. Deleted, all of it restatement the
reassembly exposes:
UI-B-02 the forward reference from `## Dashboards` to "the Production Pattern
section below" (-75), the re-introduction paragraph under the second
dashboards heading (-33), and the duplicated Date Macros pointer
blockquote (-69) -- the two dashboard sections, previously 780 lines
apart, now share one home in `rules/dashboards.md`.
UI-B-05 the prose prop list for the two react blocks (-53 -57 with its trailing
clause), which restated the generated contract that the very next
blockquote makes authoritative.
`check:skill-identifier-liveness` Leg 2 binds three sections to this file BY
PATH, so `## Report Types`, `### Action Types` and `### Navigation Item Types`
keep their exhaustive tables in the entry while their bodies move -- one topic
across two files, in three places. Nothing in that script changed.
Ratchet: one row per new file, pinned at its landed count; the entry row
re-locked 25445 -> 3821. No other row moves.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
Sweeping every "above" / "below" in the new tree for a target that is no longer
in the same file found three, all dead on arrival and all deleted rather than
rewritten -- a dead pointer is removed text, not an occasion for new prose:
SKILL.md "There is no `chart` report type ... (see the example
below)" -- the report example moved to rules/dashboards.md.
rules/navigation "assign a record `Page` (below)" -- Pages moved to
rules/pages.md.
rules/pages page type `list` "(see the iron rule above)" -- the iron
rule moved to rules/navigation.md.
-14 tokens. The three ratchet rows are re-pinned at the new landed counts so
every objectstack-ui row keeps exactly zero headroom; package 33,957 -> 33,899,
net -58.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
Pure relocation, not an admission. The baseline is keyed by PATH, and the two
occurrences it already carried for `skills/objectstack-ui/SKILL.md` moved into
`rules/list-views.md` ("the tab-bar role") and `rules/navigation.md` ("semantic
roles") -- byte-identical lines, so `--update` reads the same two occurrences
at two new paths and drops the old row:
- "skills/objectstack-ui/SKILL.md": 2
+ "skills/objectstack-ui/rules/list-views.md": 1
+ "skills/objectstack-ui/rules/navigation.md": 1
The whole baseline diff is those three lines: no other file was re-baselined,
and the total is unchanged at 2, so the shrink-only ratchet is not weakened.
This is the case the gate's ratchet-DOWN remedy names, kept in its own commit.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@os-litant@os-zhuang@claude