Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions .changeset/4895-retire-block-schema-family.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
---
'@object-ui/types': minor
'@object-ui/components': patch
---

Removed the block schema family (objectui#4895, ADR-0049 enforce-or-remove, maintainer
ruling 2026-09-02 — option C1, retire the family in one change, no transition window).

**Breaking on a published surface, deliberately.** These names are gone from
`@object-ui/types`, from both subpaths that carried them:

- `.` (types): `BlockSchema`, `BlockSlot`, `BlockLibrarySchema`, `BlockEditorSchema`,
`BlockInstanceSchema`, plus the support types with no other reader — `BlockVariable`,
`BlockMetadata`, `BlockLibraryItem` — and `ComponentSchema`.
- `./zod` (runtime validators): `BlockVariableSchema`, `BlockSlotSchema`,
`BlockMetadataSchema`, `BlockSchema`, `BlockLibraryItemSchema`, `BlockLibrarySchema`,
`BlockEditorSchema`, `BlockInstanceSchema`, `ComponentSchema`, and the
`BlockComponentSchema` union over them — which was also `AnyComponentSchema`'s block arm.

The zod half is the one that mattered. `AnyComponentSchema.safeParse({ type:
'block-library' })` returned **success** on 17.6.0 for a node no page can render, so an
author who copied the documented shape was told green by the shipped validator and then got
the registry's `OBJUI-001` "Unknown component type" panel. Validated-then-broken is worse
than never-validated, because the green light is what the author trusted. All five
discriminants — `block`, `block-library`, `block-editor`, `block-instance`, `component` —
are now **refused**, pinned in `phase2-schemas.test.ts` alongside the theme refusals
retired the same way.

Evidence the family was declared-but-unenforced: zero `ComponentRegistry.register(...)`
sites claimed any of the five keys (positive control `'table'` resolves to two), zero
renderers, and zero readers outside `packages/types/src`. The liveness pass this card's
earlier deferral was keyed to (objectui#6935) established that external consumption of this
package is structurally unmeasurable — the certainly-live control `TableSchema` returns the
same zero external consumers — so the ruling was taken on the evidence in hand rather than
on a deferral whose exit cannot fire.

⚠️ **Not this family, and not touched.** The live slotted record-page vocabulary —
`PageNodeSchema.kind === 'slotted'` with `slots?: PageSlotMap` (`packages/types/src/layout.ts`),
rendered by `usePageAssignment` / `PageBlockCanvas` / `PageBlockInspector` in
`@object-ui/app-shell` — shares the words "block" and "slot" with the retired family and
shares no declaration, type or file with it. Neither is the `type: 'component'` NAVIGATION
item kind (`{ type: 'component', componentRef }`, `NavigationItemSchema` in
`zod/app.zod.ts`), a different declaration in a different module.

`@object-ui/components` carries one forced consequence: `renderers/feedback/empty.tsx`
annotated its `action` child as the retired `ComponentSchema` and now says `SchemaNode`,
the node type `SchemaRenderer` actually takes.

`packages/types/src/blocks.ts` and `packages/types/src/zod/blocks.zod.ts` are kept as
ADR-0049 tombstones exporting nothing, and `block-family-retired-4895.test.ts` pins every
retired name out of them. `content/docs/blocks/block-schema.mdx` is deleted with the family,
and objectui#7023 — the narrower validator-only fix — dissolves into this retirement.
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -48,7 +48,7 @@ You don't just build components — you build a **Renderer** that interprets JSO

| Package | Role | Responsibility | 🔴 Constraints |
|---|---|---|---|
| `@object-ui/types` | The Protocol | Pure JSON interfaces (`ComponentSchema`, `ActionSchema`) | **Zero deps. No React.** |
| `@object-ui/types` | The Protocol | Pure JSON interfaces (`BaseSchema`, `ActionSchema`) | **Zero deps. No React.** |
| `@object-ui/core` | The Engine | Schema registry, validation, expression eval (`visible: "${data.age > 18}"`) | No UI-lib deps. Logic only. |
| `@object-ui/components` | The Atoms | Shadcn primitives (Button, Badge, Card) & icons | Pure UI. No business logic. |
| `@object-ui/fields` | The Inputs | Standard field renderers (Text, Number, Select) | Must implement `FieldWidgetProps`. |
Expand Down
Loading
Loading
, '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
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions .changeset/4895-retire-block-schema-family.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
---
'@object-ui/types': minor
'@object-ui/components': patch
---

Removed the block schema family (objectui#4895, ADR-0049 enforce-or-remove, maintainer
ruling 2026-09-02 — option C1, retire the family in one change, no transition window).

**Breaking on a published surface, deliberately.** These names are gone from
`@object-ui/types`, from both subpaths that carried them:

- `.` (types): `BlockSchema`, `BlockSlot`, `BlockLibrarySchema`, `BlockEditorSchema`,
`BlockInstanceSchema`, plus the support types with no other reader — `BlockVariable`,
`BlockMetadata`, `BlockLibraryItem` — and `ComponentSchema`.
- `./zod` (runtime validators): `BlockVariableSchema`, `BlockSlotSchema`,
`BlockMetadataSchema`, `BlockSchema`, `BlockLibraryItemSchema`, `BlockLibrarySchema`,
`BlockEditorSchema`, `BlockInstanceSchema`, `ComponentSchema`, and the
`BlockComponentSchema` union over them — which was also `AnyComponentSchema`'s block arm.

The zod half is the one that mattered. `AnyComponentSchema.safeParse({ type:
'block-library' })` returned **success** on 17.6.0 for a node no page can render, so an
author who copied the documented shape was told green by the shipped validator and then got
the registry's `OBJUI-001` "Unknown component type" panel. Validated-then-broken is worse
than never-validated, because the green light is what the author trusted. All five
discriminants — `block`, `block-library`, `block-editor`, `block-instance`, `component` —
are now **refused**, pinned in `phase2-schemas.test.ts` alongside the theme refusals
retired the same way.

Evidence the family was declared-but-unenforced: zero `ComponentRegistry.register(...)`
sites claimed any of the five keys (positive control `'table'` resolves to two), zero
renderers, and zero readers outside `packages/types/src`. The liveness pass this card's
earlier deferral was keyed to (objectui#6935) established that external consumption of this
package is structurally unmeasurable — the certainly-live control `TableSchema` returns the
same zero external consumers — so the ruling was taken on the evidence in hand rather than
on a deferral whose exit cannot fire.

⚠️ **Not this family, and not touched.** The live slotted record-page vocabulary —
`PageNodeSchema.kind === 'slotted'` with `slots?: PageSlotMap` (`packages/types/src/layout.ts`),
rendered by `usePageAssignment` / `PageBlockCanvas` / `PageBlockInspector` in
`@object-ui/app-shell` — shares the words "block" and "slot" with the retired family and
shares no declaration, type or file with it. Neither is the `type: 'component'` NAVIGATION
item kind (`{ type: 'component', componentRef }`, `NavigationItemSchema` in
`zod/app.zod.ts`), a different declaration in a different module.

`@object-ui/components` carries one forced consequence: `renderers/feedback/empty.tsx`
annotated its `action` child as the retired `ComponentSchema` and now says `SchemaNode`,
the node type `SchemaRenderer` actually takes.

`packages/types/src/blocks.ts` and `packages/types/src/zod/blocks.zod.ts` are kept as
ADR-0049 tombstones exporting nothing, and `block-family-retired-4895.test.ts` pins every
retired name out of them. `content/docs/blocks/block-schema.mdx` is deleted with the family,
and objectui#7023 — the narrower validator-only fix — dissolves into this retirement.
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -48,7 +48,7 @@ You don't just build components — you build a **Renderer** that interprets JSO

| Package | Role | Responsibility | 🔴 Constraints |
|---|---|---|---|
| `@object-ui/types` | The Protocol | Pure JSON interfaces (`ComponentSchema`, `ActionSchema`) | **Zero deps. No React.** |
| `@object-ui/types` | The Protocol | Pure JSON interfaces (`BaseSchema`, `ActionSchema`) | **Zero deps. No React.** |
| `@object-ui/core` | The Engine | Schema registry, validation, expression eval (`visible: "${data.age > 18}"`) | No UI-lib deps. Logic only. |
| `@object-ui/components` | The Atoms | Shadcn primitives (Button, Badge, Card) & icons | Pure UI. No business logic. |
| `@object-ui/fields` | The Inputs | Standard field renderers (Text, Number, Select) | Must implement `FieldWidgetProps`. |
Expand Down
Loading
Loading
, '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
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions .changeset/4895-retire-block-schema-family.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
---
'@object-ui/types': minor
'@object-ui/components': patch
---

Removed the block schema family (objectui#4895, ADR-0049 enforce-or-remove, maintainer
ruling 2026-09-02 — option C1, retire the family in one change, no transition window).

**Breaking on a published surface, deliberately.** These names are gone from
`@object-ui/types`, from both subpaths that carried them:

- `.` (types): `BlockSchema`, `BlockSlot`, `BlockLibrarySchema`, `BlockEditorSchema`,
`BlockInstanceSchema`, plus the support types with no other reader — `BlockVariable`,
`BlockMetadata`, `BlockLibraryItem` — and `ComponentSchema`.
- `./zod` (runtime validators): `BlockVariableSchema`, `BlockSlotSchema`,
`BlockMetadataSchema`, `BlockSchema`, `BlockLibraryItemSchema`, `BlockLibrarySchema`,
`BlockEditorSchema`, `BlockInstanceSchema`, `ComponentSchema`, and the
`BlockComponentSchema` union over them — which was also `AnyComponentSchema`'s block arm.

The zod half is the one that mattered. `AnyComponentSchema.safeParse({ type:
'block-library' })` returned **success** on 17.6.0 for a node no page can render, so an
author who copied the documented shape was told green by the shipped validator and then got
the registry's `OBJUI-001` "Unknown component type" panel. Validated-then-broken is worse
than never-validated, because the green light is what the author trusted. All five
discriminants — `block`, `block-library`, `block-editor`, `block-instance`, `component` —
are now **refused**, pinned in `phase2-schemas.test.ts` alongside the theme refusals
retired the same way.

Evidence the family was declared-but-unenforced: zero `ComponentRegistry.register(...)`
sites claimed any of the five keys (positive control `'table'` resolves to two), zero
renderers, and zero readers outside `packages/types/src`. The liveness pass this card's
earlier deferral was keyed to (objectui#6935) established that external consumption of this
package is structurally unmeasurable — the certainly-live control `TableSchema` returns the
same zero external consumers — so the ruling was taken on the evidence in hand rather than
on a deferral whose exit cannot fire.

⚠️ **Not this family, and not touched.** The live slotted record-page vocabulary —
`PageNodeSchema.kind === 'slotted'` with `slots?: PageSlotMap` (`packages/types/src/layout.ts`),
rendered by `usePageAssignment` / `PageBlockCanvas` / `PageBlockInspector` in
`@object-ui/app-shell` — shares the words "block" and "slot" with the retired family and
shares no declaration, type or file with it. Neither is the `type: 'component'` NAVIGATION
item kind (`{ type: 'component', componentRef }`, `NavigationItemSchema` in
`zod/app.zod.ts`), a different declaration in a different module.

`@object-ui/components` carries one forced consequence: `renderers/feedback/empty.tsx`
annotated its `action` child as the retired `ComponentSchema` and now says `SchemaNode`,
the node type `SchemaRenderer` actually takes.

`packages/types/src/blocks.ts` and `packages/types/src/zod/blocks.zod.ts` are kept as
ADR-0049 tombstones exporting nothing, and `block-family-retired-4895.test.ts` pins every
retired name out of them. `content/docs/blocks/block-schema.mdx` is deleted with the family,
and objectui#7023 — the narrower validator-only fix — dissolves into this retirement.
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -48,7 +48,7 @@ You don't just build components — you build a **Renderer** that interprets JSO

| Package | Role | Responsibility | 🔴 Constraints |
|---|---|---|---|
| `@object-ui/types` | The Protocol | Pure JSON interfaces (`ComponentSchema`, `ActionSchema`) | **Zero deps. No React.** |
| `@object-ui/types` | The Protocol | Pure JSON interfaces (`BaseSchema`, `ActionSchema`) | **Zero deps. No React.** |
| `@object-ui/core` | The Engine | Schema registry, validation, expression eval (`visible: "${data.age > 18}"`) | No UI-lib deps. Logic only. |
| `@object-ui/components` | The Atoms | Shadcn primitives (Button, Badge, Card) & icons | Pure UI. No business logic. |
| `@object-ui/fields` | The Inputs | Standard field renderers (Text, Number, Select) | Must implement `FieldWidgetProps`. |
Expand Down
Loading
Loading
, '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
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions .changeset/4895-retire-block-schema-family.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
---
'@object-ui/types': minor
'@object-ui/components': patch
---

Removed the block schema family (objectui#4895, ADR-0049 enforce-or-remove, maintainer
ruling 2026-09-02 — option C1, retire the family in one change, no transition window).

**Breaking on a published surface, deliberately.** These names are gone from
`@object-ui/types`, from both subpaths that carried them:

- `.` (types): `BlockSchema`, `BlockSlot`, `BlockLibrarySchema`, `BlockEditorSchema`,
`BlockInstanceSchema`, plus the support types with no other reader — `BlockVariable`,
`BlockMetadata`, `BlockLibraryItem` — and `ComponentSchema`.
- `./zod` (runtime validators): `BlockVariableSchema`, `BlockSlotSchema`,
`BlockMetadataSchema`, `BlockSchema`, `BlockLibraryItemSchema`, `BlockLibrarySchema`,
`BlockEditorSchema`, `BlockInstanceSchema`, `ComponentSchema`, and the
`BlockComponentSchema` union over them — which was also `AnyComponentSchema`'s block arm.

The zod half is the one that mattered. `AnyComponentSchema.safeParse({ type:
'block-library' })` returned **success** on 17.6.0 for a node no page can render, so an
author who copied the documented shape was told green by the shipped validator and then got
the registry's `OBJUI-001` "Unknown component type" panel. Validated-then-broken is worse
than never-validated, because the green light is what the author trusted. All five
discriminants — `block`, `block-library`, `block-editor`, `block-instance`, `component` —
are now **refused**, pinned in `phase2-schemas.test.ts` alongside the theme refusals
retired the same way.

Evidence the family was declared-but-unenforced: zero `ComponentRegistry.register(...)`
sites claimed any of the five keys (positive control `'table'` resolves to two), zero
renderers, and zero readers outside `packages/types/src`. The liveness pass this card's
earlier deferral was keyed to (objectui#6935) established that external consumption of this
package is structurally unmeasurable — the certainly-live control `TableSchema` returns the
same zero external consumers — so the ruling was taken on the evidence in hand rather than
on a deferral whose exit cannot fire.

⚠️ **Not this family, and not touched.** The live slotted record-page vocabulary —
`PageNodeSchema.kind === 'slotted'` with `slots?: PageSlotMap` (`packages/types/src/layout.ts`),
rendered by `usePageAssignment` / `PageBlockCanvas` / `PageBlockInspector` in
`@object-ui/app-shell` — shares the words "block" and "slot" with the retired family and
shares no declaration, type or file with it. Neither is the `type: 'component'` NAVIGATION
item kind (`{ type: 'component', componentRef }`, `NavigationItemSchema` in
`zod/app.zod.ts`), a different declaration in a different module.

`@object-ui/components` carries one forced consequence: `renderers/feedback/empty.tsx`
annotated its `action` child as the retired `ComponentSchema` and now says `SchemaNode`,
the node type `SchemaRenderer` actually takes.

`packages/types/src/blocks.ts` and `packages/types/src/zod/blocks.zod.ts` are kept as
ADR-0049 tombstones exporting nothing, and `block-family-retired-4895.test.ts` pins every
retired name out of them. `content/docs/blocks/block-schema.mdx` is deleted with the family,
and objectui#7023 — the narrower validator-only fix — dissolves into this retirement.
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -48,7 +48,7 @@ You don't just build components — you build a **Renderer** that interprets JSO

| Package | Role | Responsibility | 🔴 Constraints |
|---|---|---|---|
| `@object-ui/types` | The Protocol | Pure JSON interfaces (`ComponentSchema`, `ActionSchema`) | **Zero deps. No React.** |
| `@object-ui/types` | The Protocol | Pure JSON interfaces (`BaseSchema`, `ActionSchema`) | **Zero deps. No React.** |
| `@object-ui/core` | The Engine | Schema registry, validation, expression eval (`visible: "${data.age > 18}"`) | No UI-lib deps. Logic only. |
| `@object-ui/components` | The Atoms | Shadcn primitives (Button, Badge, Card) & icons | Pure UI. No business logic. |
| `@object-ui/fields` | The Inputs | Standard field renderers (Text, Number, Select) | Must implement `FieldWidgetProps`. |
Expand Down
Loading
Loading
, '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
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions .changeset/4895-retire-block-schema-family.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
---
'@object-ui/types': minor
'@object-ui/components': patch
---

Removed the block schema family (objectui#4895, ADR-0049 enforce-or-remove, maintainer
ruling 2026-09-02 — option C1, retire the family in one change, no transition window).

**Breaking on a published surface, deliberately.** These names are gone from
`@object-ui/types`, from both subpaths that carried them:

- `.` (types): `BlockSchema`, `BlockSlot`, `BlockLibrarySchema`, `BlockEditorSchema`,
`BlockInstanceSchema`, plus the support types with no other reader — `BlockVariable`,
`BlockMetadata`, `BlockLibraryItem` — and `ComponentSchema`.
- `./zod` (runtime validators): `BlockVariableSchema`, `BlockSlotSchema`,
`BlockMetadataSchema`, `BlockSchema`, `BlockLibraryItemSchema`, `BlockLibrarySchema`,
`BlockEditorSchema`, `BlockInstanceSchema`, `ComponentSchema`, and the
`BlockComponentSchema` union over them — which was also `AnyComponentSchema`'s block arm.

The zod half is the one that mattered. `AnyComponentSchema.safeParse({ type:
'block-library' })` returned **success** on 17.6.0 for a node no page can render, so an
author who copied the documented shape was told green by the shipped validator and then got
the registry's `OBJUI-001` "Unknown component type" panel. Validated-then-broken is worse
than never-validated, because the green light is what the author trusted. All five
discriminants — `block`, `block-library`, `block-editor`, `block-instance`, `component` —
are now **refused**, pinned in `phase2-schemas.test.ts` alongside the theme refusals
retired the same way.

Evidence the family was declared-but-unenforced: zero `ComponentRegistry.register(...)`
sites claimed any of the five keys (positive control `'table'` resolves to two), zero
renderers, and zero readers outside `packages/types/src`. The liveness pass this card's
earlier deferral was keyed to (objectui#6935) established that external consumption of this
package is structurally unmeasurable — the certainly-live control `TableSchema` returns the
same zero external consumers — so the ruling was taken on the evidence in hand rather than
on a deferral whose exit cannot fire.

⚠️ **Not this family, and not touched.** The live slotted record-page vocabulary —
`PageNodeSchema.kind === 'slotted'` with `slots?: PageSlotMap` (`packages/types/src/layout.ts`),
rendered by `usePageAssignment` / `PageBlockCanvas` / `PageBlockInspector` in
`@object-ui/app-shell` — shares the words "block" and "slot" with the retired family and
shares no declaration, type or file with it. Neither is the `type: 'component'` NAVIGATION
item kind (`{ type: 'component', componentRef }`, `NavigationItemSchema` in
`zod/app.zod.ts`), a different declaration in a different module.

`@object-ui/components` carries one forced consequence: `renderers/feedback/empty.tsx`
annotated its `action` child as the retired `ComponentSchema` and now says `SchemaNode`,
the node type `SchemaRenderer` actually takes.

`packages/types/src/blocks.ts` and `packages/types/src/zod/blocks.zod.ts` are kept as
ADR-0049 tombstones exporting nothing, and `block-family-retired-4895.test.ts` pins every
retired name out of them. `content/docs/blocks/block-schema.mdx` is deleted with the family,
and objectui#7023 — the narrower validator-only fix — dissolves into this retirement.
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -48,7 +48,7 @@ You don't just build components — you build a **Renderer** that interprets JSO

| Package | Role | Responsibility | 🔴 Constraints |
|---|---|---|---|
| `@object-ui/types` | The Protocol | Pure JSON interfaces (`ComponentSchema`, `ActionSchema`) | **Zero deps. No React.** |
| `@object-ui/types` | The Protocol | Pure JSON interfaces (`BaseSchema`, `ActionSchema`) | **Zero deps. No React.** |
| `@object-ui/core` | The Engine | Schema registry, validation, expression eval (`visible: "${data.age > 18}"`) | No UI-lib deps. Logic only. |
| `@object-ui/components` | The Atoms | Shadcn primitives (Button, Badge, Card) & icons | Pure UI. No business logic. |
| `@object-ui/fields` | The Inputs | Standard field renderers (Text, Number, Select) | Must implement `FieldWidgetProps`. |
Expand Down
Loading
Loading
, '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
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions .changeset/4895-retire-block-schema-family.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
---
'@object-ui/types': minor
'@object-ui/components': patch
---

Removed the block schema family (objectui#4895, ADR-0049 enforce-or-remove, maintainer
ruling 2026-09-02 — option C1, retire the family in one change, no transition window).

**Breaking on a published surface, deliberately.** These names are gone from
`@object-ui/types`, from both subpaths that carried them:

- `.` (types): `BlockSchema`, `BlockSlot`, `BlockLibrarySchema`, `BlockEditorSchema`,
`BlockInstanceSchema`, plus the support types with no other reader — `BlockVariable`,
`BlockMetadata`, `BlockLibraryItem` — and `ComponentSchema`.
- `./zod` (runtime validators): `BlockVariableSchema`, `BlockSlotSchema`,
`BlockMetadataSchema`, `BlockSchema`, `BlockLibraryItemSchema`, `BlockLibrarySchema`,
`BlockEditorSchema`, `BlockInstanceSchema`, `ComponentSchema`, and the
`BlockComponentSchema` union over them — which was also `AnyComponentSchema`'s block arm.

The zod half is the one that mattered. `AnyComponentSchema.safeParse({ type:
'block-library' })` returned **success** on 17.6.0 for a node no page can render, so an
author who copied the documented shape was told green by the shipped validator and then got
the registry's `OBJUI-001` "Unknown component type" panel. Validated-then-broken is worse
than never-validated, because the green light is what the author trusted. All five
discriminants — `block`, `block-library`, `block-editor`, `block-instance`, `component` —
are now **refused**, pinned in `phase2-schemas.test.ts` alongside the theme refusals
retired the same way.

Evidence the family was declared-but-unenforced: zero `ComponentRegistry.register(...)`
sites claimed any of the five keys (positive control `'table'` resolves to two), zero
renderers, and zero readers outside `packages/types/src`. The liveness pass this card's
earlier deferral was keyed to (objectui#6935) established that external consumption of this
package is structurally unmeasurable — the certainly-live control `TableSchema` returns the
same zero external consumers — so the ruling was taken on the evidence in hand rather than
on a deferral whose exit cannot fire.

⚠️ **Not this family, and not touched.** The live slotted record-page vocabulary —
`PageNodeSchema.kind === 'slotted'` with `slots?: PageSlotMap` (`packages/types/src/layout.ts`),
rendered by `usePageAssignment` / `PageBlockCanvas` / `PageBlockInspector` in
`@object-ui/app-shell` — shares the words "block" and "slot" with the retired family and
shares no declaration, type or file with it. Neither is the `type: 'component'` NAVIGATION
item kind (`{ type: 'component', componentRef }`, `NavigationItemSchema` in
`zod/app.zod.ts`), a different declaration in a different module.

`@object-ui/components` carries one forced consequence: `renderers/feedback/empty.tsx`
annotated its `action` child as the retired `ComponentSchema` and now says `SchemaNode`,
the node type `SchemaRenderer` actually takes.

`packages/types/src/blocks.ts` and `packages/types/src/zod/blocks.zod.ts` are kept as
ADR-0049 tombstones exporting nothing, and `block-family-retired-4895.test.ts` pins every
retired name out of them. `content/docs/blocks/block-schema.mdx` is deleted with the family,
and objectui#7023 — the narrower validator-only fix — dissolves into this retirement.
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -48,7 +48,7 @@ You don't just build components — you build a **Renderer** that interprets JSO

| Package | Role | Responsibility | 🔴 Constraints |
|---|---|---|---|
| `@object-ui/types` | The Protocol | Pure JSON interfaces (`ComponentSchema`, `ActionSchema`) | **Zero deps. No React.** |
| `@object-ui/types` | The Protocol | Pure JSON interfaces (`BaseSchema`, `ActionSchema`) | **Zero deps. No React.** |
| `@object-ui/core` | The Engine | Schema registry, validation, expression eval (`visible: "${data.age > 18}"`) | No UI-lib deps. Logic only. |
| `@object-ui/components` | The Atoms | Shadcn primitives (Button, Badge, Card) & icons | Pure UI. No business logic. |
| `@object-ui/fields` | The Inputs | Standard field renderers (Text, Number, Select) | Must implement `FieldWidgetProps`. |
Expand Down
Loading
Loading
, '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
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions .changeset/4895-retire-block-schema-family.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
---
'@object-ui/types': minor
'@object-ui/components': patch
---

Removed the block schema family (objectui#4895, ADR-0049 enforce-or-remove, maintainer
ruling 2026-09-02 — option C1, retire the family in one change, no transition window).

**Breaking on a published surface, deliberately.** These names are gone from
`@object-ui/types`, from both subpaths that carried them:

- `.` (types): `BlockSchema`, `BlockSlot`, `BlockLibrarySchema`, `BlockEditorSchema`,
`BlockInstanceSchema`, plus the support types with no other reader — `BlockVariable`,
`BlockMetadata`, `BlockLibraryItem` — and `ComponentSchema`.
- `./zod` (runtime validators): `BlockVariableSchema`, `BlockSlotSchema`,
`BlockMetadataSchema`, `BlockSchema`, `BlockLibraryItemSchema`, `BlockLibrarySchema`,
`BlockEditorSchema`, `BlockInstanceSchema`, `ComponentSchema`, and the
`BlockComponentSchema` union over them — which was also `AnyComponentSchema`'s block arm.

The zod half is the one that mattered. `AnyComponentSchema.safeParse({ type:
'block-library' })` returned **success** on 17.6.0 for a node no page can render, so an
author who copied the documented shape was told green by the shipped validator and then got
the registry's `OBJUI-001` "Unknown component type" panel. Validated-then-broken is worse
than never-validated, because the green light is what the author trusted. All five
discriminants — `block`, `block-library`, `block-editor`, `block-instance`, `component` —
are now **refused**, pinned in `phase2-schemas.test.ts` alongside the theme refusals
retired the same way.

Evidence the family was declared-but-unenforced: zero `ComponentRegistry.register(...)`
sites claimed any of the five keys (positive control `'table'` resolves to two), zero
renderers, and zero readers outside `packages/types/src`. The liveness pass this card's
earlier deferral was keyed to (objectui#6935) established that external consumption of this
package is structurally unmeasurable — the certainly-live control `TableSchema` returns the
same zero external consumers — so the ruling was taken on the evidence in hand rather than
on a deferral whose exit cannot fire.

⚠️ **Not this family, and not touched.** The live slotted record-page vocabulary —
`PageNodeSchema.kind === 'slotted'` with `slots?: PageSlotMap` (`packages/types/src/layout.ts`),
rendered by `usePageAssignment` / `PageBlockCanvas` / `PageBlockInspector` in
`@object-ui/app-shell` — shares the words "block" and "slot" with the retired family and
shares no declaration, type or file with it. Neither is the `type: 'component'` NAVIGATION
item kind (`{ type: 'component', componentRef }`, `NavigationItemSchema` in
`zod/app.zod.ts`), a different declaration in a different module.

`@object-ui/components` carries one forced consequence: `renderers/feedback/empty.tsx`
annotated its `action` child as the retired `ComponentSchema` and now says `SchemaNode`,
the node type `SchemaRenderer` actually takes.

`packages/types/src/blocks.ts` and `packages/types/src/zod/blocks.zod.ts` are kept as
ADR-0049 tombstones exporting nothing, and `block-family-retired-4895.test.ts` pins every
retired name out of them. `content/docs/blocks/block-schema.mdx` is deleted with the family,
and objectui#7023 — the narrower validator-only fix — dissolves into this retirement.
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -48,7 +48,7 @@ You don't just build components — you build a **Renderer** that interprets JSO

| Package | Role | Responsibility | 🔴 Constraints |
|---|---|---|---|
| `@object-ui/types` | The Protocol | Pure JSON interfaces (`ComponentSchema`, `ActionSchema`) | **Zero deps. No React.** |
| `@object-ui/types` | The Protocol | Pure JSON interfaces (`BaseSchema`, `ActionSchema`) | **Zero deps. No React.** |
| `@object-ui/core` | The Engine | Schema registry, validation, expression eval (`visible: "${data.age > 18}"`) | No UI-lib deps. Logic only. |
| `@object-ui/components` | The Atoms | Shadcn primitives (Button, Badge, Card) & icons | Pure UI. No business logic. |
| `@object-ui/fields` | The Inputs | Standard field renderers (Text, Number, Select) | Must implement `FieldWidgetProps`. |
Expand Down
Loading
Loading
, '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
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions .changeset/4895-retire-block-schema-family.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
---
'@object-ui/types': minor
'@object-ui/components': patch
---

Removed the block schema family (objectui#4895, ADR-0049 enforce-or-remove, maintainer
ruling 2026-09-02 — option C1, retire the family in one change, no transition window).

**Breaking on a published surface, deliberately.** These names are gone from
`@object-ui/types`, from both subpaths that carried them:

- `.` (types): `BlockSchema`, `BlockSlot`, `BlockLibrarySchema`, `BlockEditorSchema`,
`BlockInstanceSchema`, plus the support types with no other reader — `BlockVariable`,
`BlockMetadata`, `BlockLibraryItem` — and `ComponentSchema`.
- `./zod` (runtime validators): `BlockVariableSchema`, `BlockSlotSchema`,
`BlockMetadataSchema`, `BlockSchema`, `BlockLibraryItemSchema`, `BlockLibrarySchema`,
`BlockEditorSchema`, `BlockInstanceSchema`, `ComponentSchema`, and the
`BlockComponentSchema` union over them — which was also `AnyComponentSchema`'s block arm.

The zod half is the one that mattered. `AnyComponentSchema.safeParse({ type:
'block-library' })` returned **success** on 17.6.0 for a node no page can render, so an
author who copied the documented shape was told green by the shipped validator and then got
the registry's `OBJUI-001` "Unknown component type" panel. Validated-then-broken is worse
than never-validated, because the green light is what the author trusted. All five
discriminants — `block`, `block-library`, `block-editor`, `block-instance`, `component` —
are now **refused**, pinned in `phase2-schemas.test.ts` alongside the theme refusals
retired the same way.

Evidence the family was declared-but-unenforced: zero `ComponentRegistry.register(...)`
sites claimed any of the five keys (positive control `'table'` resolves to two), zero
renderers, and zero readers outside `packages/types/src`. The liveness pass this card's
earlier deferral was keyed to (objectui#6935) established that external consumption of this
package is structurally unmeasurable — the certainly-live control `TableSchema` returns the
same zero external consumers — so the ruling was taken on the evidence in hand rather than
on a deferral whose exit cannot fire.

⚠️ **Not this family, and not touched.** The live slotted record-page vocabulary —
`PageNodeSchema.kind === 'slotted'` with `slots?: PageSlotMap` (`packages/types/src/layout.ts`),
rendered by `usePageAssignment` / `PageBlockCanvas` / `PageBlockInspector` in
`@object-ui/app-shell` — shares the words "block" and "slot" with the retired family and
shares no declaration, type or file with it. Neither is the `type: 'component'` NAVIGATION
item kind (`{ type: 'component', componentRef }`, `NavigationItemSchema` in
`zod/app.zod.ts`), a different declaration in a different module.

`@object-ui/components` carries one forced consequence: `renderers/feedback/empty.tsx`
annotated its `action` child as the retired `ComponentSchema` and now says `SchemaNode`,
the node type `SchemaRenderer` actually takes.

`packages/types/src/blocks.ts` and `packages/types/src/zod/blocks.zod.ts` are kept as
ADR-0049 tombstones exporting nothing, and `block-family-retired-4895.test.ts` pins every
retired name out of them. `content/docs/blocks/block-schema.mdx` is deleted with the family,
and objectui#7023 — the narrower validator-only fix — dissolves into this retirement.
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -48,7 +48,7 @@ You don't just build components — you build a **Renderer** that interprets JSO

| Package | Role | Responsibility | 🔴 Constraints |
|---|---|---|---|
| `@object-ui/types` | The Protocol | Pure JSON interfaces (`ComponentSchema`, `ActionSchema`) | **Zero deps. No React.** |
| `@object-ui/types` | The Protocol | Pure JSON interfaces (`BaseSchema`, `ActionSchema`) | **Zero deps. No React.** |
| `@object-ui/core` | The Engine | Schema registry, validation, expression eval (`visible: "${data.age > 18}"`) | No UI-lib deps. Logic only. |
| `@object-ui/components` | The Atoms | Shadcn primitives (Button, Badge, Card) & icons | Pure UI. No business logic. |
| `@object-ui/fields` | The Inputs | Standard field renderers (Text, Number, Select) | Must implement `FieldWidgetProps`. |
Expand Down
Loading
Loading