Skip to content

Commit 9f024d8

Browse files
feat(spec): BlueprintViewSchema and StrictView declare filters and sort, so an AI-built view carries its own filter (#24152)
Fixes #24129 Clause-②: yes (widening) ## What A solution-blueprint view can now carry the filter its name promises. `BlueprintViewSchema` (lenient, what `apply_blueprint` parses) and `StrictView` inside `SolutionBlueprintStrictSchema` (the OpenAI-strict `generateObject` contract the design model generates against) both declare `filters` and `sort`. This is ruling A on objectstack-ai/cloud#2932 (「2932 同意」), as the card restates it; the cloud ruling text is not readable from this session. Before this, a plan could say 「overdue only」 in a view's name and nowhere else, so the applier shipped an unfiltered grid under that name (objectstack-ai/cloud#2922). Neither key invents a format. ### `filters`: which records the view shows, ANDed | | Lenient `BlueprintViewSchema.filters` | Strict `StrictView.filters` | |:--|:--|:--| | presence | optional | required, nullable (null = a view over every record) | | element | `ViewFilterRuleSchema` itself (identity-pinned in the test) | inline `StrictViewFilterRule`, keys pinned equal to `ViewFilterRuleSchema`'s | | `field` | `string` | `string` (no `SNAKE_CASE` on either side: value parity) | | `operator` | `z.preprocess(fold, z.enum(VIEW_FILTER_OPERATORS))`: canonical, legacy spellings folded | `z.enum(VIEW_FILTER_OPERATORS)`: canonical only, no fold | | `value` | optional; string, number, boolean, null, or a list of strings or numbers | required, nullable; string, number, boolean, or a list of strings or numbers | | operator/value shape (`in` takes an array, `between` takes `[min, max]`, `icontains` takes a non-empty string) | refused by the reused refinement | not expressed | Why each strict-side difference exists: - **`value` nullable, not optional.** Strict mode needs every key listed in `required`, and null is how this mirror spells "optional". It is also the spelling the unary operators use. The blueprint tools strip nulls before the lenient parse, so the lenient rule sees `value` absent, which it accepts for unary operators. - **No fold on `operator`.** The lenient `z.preprocess` is a parse-time transform with no JSON-Schema form. A model emitting the canonical vocabulary is the alias table's own contract for new producers. The strict test pins that `eq` is refused at `views.0.filters.0.operator` with `invalid_value`. - **No operator/value-shape refinement.** A refinement has no JSON-Schema form, and the strict mirror precedent already leaves out what strict mode cannot express (`questions.max(2)`, `seedData`). The lenient parse that `apply_blueprint` runs refuses these, and a test pins it (`in` with a scalar, issue at `views.0.filters.0.value`, code `custom`). The describe on the strict `value` states the shape rules for the model. ### `sort`: default record order | | Lenient | Strict | |:--|:--|:--| | presence | optional | required, nullable (null = the platform default order) | | element | the shared `SortItemSchema` (`shared/enums.zod.ts`, identity-pinned) | inline `{ field: string, order: SortDirectionEnum }`, both keys required | | form | array only; a `"field desc"` string is refused (`invalid_type` at `views.0.sort`) | array only | `ListView.sort`'s entry is an inline `strictObject` and is not exported. `SortItemSchema` is the exported shared sort item, and that entry's own comment says its titles mirror it: the same `{ field, order }` keys and the same `asc` / `desc` vocabulary. The two differ in one way. The `ListView` entry rejects unknown keys and folds `direction` to `order`. `SortItemSchema` is a plain `z.object`, so it strips unknown keys, which is the posture of every other blueprint shape. A `{ field, direction }` entry is still refused: `order` is required and has no default, so it cannot silently reverse a sort. The blueprint does not accept a string form, because `ListView.sort` no longer does. ### Describes Both sides tell the model that a view whose name or label states a condition (「overdue / 逾期」, 「my open / 我的未完成」, 「待审批」, 「本月」) MUST carry the rules that make the name true. They give worked rules that use the platform's declared tokens `{today}` (date macros) and `{current_user_id}` (context tokens). Both tokens are expanded on both sides of the wire, and `examples/app-todo`'s overdue list view uses the same rule pair. The describe prose is deliberately not pinned by a test. ## Tests (`packages/spec/src/ai/solution-blueprint.test.ts`) - Lenient: carries `filters` and `sort` through the parse; both optional; identity pins (`filters` element `toBe(ViewFilterRuleSchema)`, `sort` element `toBe(SortItemSchema)`); a bad operator is refused at `views.0.filters.0.operator` (`invalid_value`); `in` with a scalar at `views.0.filters.0.value` (`custom`); a bad `order` at `views.0.sort.0.order` (`invalid_value`); a string sort at `views.0.sort` (`invalid_type`). - Strict: carries rules, including `in` with a list and `is_null` with null; null accepted for both keys; each key is required (omitting it gives `invalid_type` at that key); a rule's `value` key is required (`invalid_union`); `eq` is refused; a bad `order` is refused. The existing gallery/gantt strict fixture now sends `filters: null, sort: null`. - Key parity, extended a level further out (fields, then objects, then nav items, now VIEWS): the view key sets are equal, with no deliberate exclusions. The nested filter-rule and sort-entry key sets are equal. The strict operator enum equals the lenient one, and the strict `order` enum equals the lenient one. The VALUE-parity walker covers the new string leaves automatically: `views[].filters[].field` and `views[].sort[].field` carry no pattern on either side. ## Generated and ledger artifacts - Regenerated by the generators: `packages/spec/authorable-surface/ai.json` (+`BlueprintView:filters`, +`BlueprintView:sort`), `content/docs/references/ai/solution-blueprint.mdx`, `docs/audits/2026-07-unknown-key-strictness-ledger.counts/ai.md` (ai sites 78 to 80: the two inline strict shapes), and `skills/objectstack-ai/references/_index.md` (see below). `api-surface/`, `json-schema.manifest/`, `declaration-map/`, `export-origins/` and `authorable-surface.base.json` did not move, because there are no new exports. - **Hand-edited ledger, as `build-schemas.ts` requires:** `packages/spec/dropped-refinements.baseline.json` gains `ai/BlueprintView: ["filters.element"]` and `views.element.filters.element` on `ai/SolutionBlueprint` (sites 764 to 766, schemas 234 to 235). This is the `ViewFilterRuleSchema` refinement that the published lenient JSON Schema cannot carry. `ui/ListView` already declares the same gap as `filter.element`. The strict schema carries no refinement and drops nothing. - **The published strict JSON Schema** (`json-schema/ai/SolutionBlueprintStrict.json`, built locally): `views.items.required` is now `object, name, label, type, columns, groupBy, filters, sort`, with `additionalProperties: false`. The rule item requires `field, operator, value`, and `operator` is the 20-member canonical enum. The sort item requires `field, order`, and `order` is the enum `asc, desc`. ### `skills/**`: one generator-owned file moves `gen:skill-refs` lists each skill's transitive spec modules. The blueprint now imports `ui/view.zod` and `shared/enums.zod`, so `skills/objectstack-ai/references/_index.md` gains 7 pointer lines (`shared/enums.zod`, `shared/http.zod`, and `ui/view.zod` with its `bulk-action`, `chart`, `i18n` and `sharing` modules). Without it, the required `check:skill-refs` is red. - Readings: the changed file goes from 43 to 50 lines. The whole published skill package (the sum of all `skills/*/SKILL.md`) goes from 4389 to 4389 lines: no SKILL.md is touched. - Governance, `node scripts/pm/check-governed-merges.mjs --branch claude/issue-24129-blueprint-view-filters-sort` on head `d896c66e6`: "governed-surface predicate: 0 of 8 path(s) hit the register after 1 generated-artifact lift(s) (7 surfaces govern objectstack). ✅ NOT governed — ordinary queue landing applies to a PR with exactly this file list." The index is a PURE REGENERATION, byte-equal to `pnpm --filter @objectstack/spec gen:skill-refs` recomputed on this tree. That is the generator-owned carve-out in that script, and `governed-surface-guard.yml` installs the toolchain so the queue guard can recompute the same answer. No hand-authored `skills/**` content moves. Size: 325 changed lines (+318 / -7), under the 3000 threshold. ## Local verification - `pnpm --filter @objectstack/spec build`: exit 0. `pnpm --filter @objectstack/spec exec vitest run --project local --maxWorkers=2`: 692 files, 20969 passed, 1 todo, exit 0. `pnpm --filter @objectstack/spec typecheck`: exit 0. These ran at `0b87a3245`. The later merge of `origin/main` (`d896c66e6`) brings only `docs/qa/**` and `examples/app-showcase/**`, so no spec input moved. - `pnpm --filter @objectstack/spec check:generated`: "✓ All 14 generated artifacts are up to date", on `d896c66e6`. - `node scripts/pm/dispatch-gates.mjs --commands` derived 113 commands, and all 113 ran on `d896c66e6` with exit 0. `--ran` reconciliation: "113 derived, 113 run, 0 NOT-MEASURED, 0 UNRUN". On the first pass (at `0b87a3245`), seven gates refused with exit 3 because a prerequisite was unbuilt or a fixture commit was not in the shallow clone. They were re-run green after `turbo run build` of formula, lint, client, client-react and objectql, and a depth-1 fetch of the fixture commit. - `pnpm check:dev-prereqs` (local-only family): exit 0. - Not run locally, left to CI: the `test:repo` project, the integration tiers, and the path-scheduled CI jobs `dispatch-gates` lists (Test Core shards, Build Core, Build Docs, dogfood). ## Acceptance notes - **Key name.** The blueprint key is `filters`, as the ruling and the card name it. The runtime `ListView` key is `filter`. The applier (cloud, not readable here) is what expands a blueprint view into a `ListView` body, so the mapping between the two spellings lives there. The lenient blueprint schemas are `z.object`s and strip undeclared keys, so a hand-authored blueprint view that writes the singular `filter` loses it silently. The same is true of every other undeclared blueprint key, and the strict path cannot emit an undeclared key at all. - **The strict mirror's own accept set narrows.** A strict document without `filters` / `sort` on a view parsed before and is refused now. That holds for every key ever added to this mirror (`viewName`, `nameField`, `sharingModel`, `expression` all shipped the same required-nullable way, under Minor Changes). The mirror is a generation contract, so its only producer is the model, which receives the new JSON Schema. It is declared `Clause-②: yes (widening)` as the card rules. The contract review may weigh this. - **In-repo consumers** (`git grep` on this head, outside `packages/spec`): only a comment in `packages/cli/src/lint/metadata-eval.ts` (the type name `SolutionBlueprint`), plus the generated docs. The real producer and consumer are cloud's `propose_blueprint` / `apply_blueprint`. Its interim `.extend()` (cloud PR #2931) is not readable here, and its key spelling was not compared. - **Surface beyond the claim's file list**, all mechanically required: the dropped-refinements ledger lines, the strictness-ledger count shard, and the skill index regeneration. --- _Generated by [Claude Code](https://claude.ai/code/session_01HSDGREvqxQUt7K7pjHXMyC)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 6dede7a commit 9f024d8

8 files changed

Lines changed: 318 additions & 7 deletions

File tree

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
'@objectstack/spec': minor
3+
---
4+
5+
feat(spec): a solution blueprint view declares `filters` and `sort`, so a view named by a condition can carry that condition
6+
7+
Clause-②: yes (widening)
8+
9+
`BlueprintViewSchema` and the strict structured-output mirror `SolutionBlueprintStrictSchema.views[]` gain two keys. Before this, a blueprint could say "overdue only" in a view's name and nowhere else, and the built view showed every record.
10+
11+
- **`filters`** — which records the view shows, as list-view filter rules `[{ field, operator, value }]`, ANDed.
12+
- Lenient (`BlueprintViewSchema`): optional, and the array element IS `ViewFilterRuleSchema` (the rule `ListView.filter` declares), so it takes the same operators, folds the same legacy spellings, and refuses the same operator/value-shape mismatches (`in` without an array, `between` without `[min, max]`, `icontains` without a non-empty string).
13+
- Strict (`SolutionBlueprintStrictSchema`): required and nullable (null = a view over every record). Each rule carries the same three keys, every one present: `operator` is the canonical vocabulary only (`VIEW_FILTER_OPERATORS`, no legacy shorthand such as `eq`), and `value` is nullable (null for the unary operators). The operator/value-shape coupling is not in the strict mirror's JSON Schema; the lenient parse refuses it.
14+
- **`sort`** — the default record order, `[{ field, order }]` with `order` `asc` or `desc`, the first entry sorting first. Lenient: optional, the element is the shared `SortItemSchema` (the `{ field, order }` pair `ListView.sort` declares; array only, a `"field desc"` string is refused). Strict: required and nullable, `{ field, order }` with both keys present.
15+
- Both describes tell the model that a view whose name or label states a condition ("overdue", "my open") must carry the matching filter, with worked rules using the platform tokens `{today}` and `{current_user_id}`.
16+
- Additive only: every blueprint that parsed before still parses with the lenient schema. A producer of the STRICT shape must now send `filters` and `sort` on each view (null when it has none), as with every other key in that mirror.

‎content/docs/references/ai/solution-blueprint.mdx‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,27 @@ const result = BlueprintAppSchema.parse(data);
271271
| **type** | `Enum<'list' \| 'form' \| 'kanban' \| 'calendar' \| 'gallery' \| 'gantt'>` | optional (default: `"list"`) | View kind. Pick the surface that fits the data: "gallery" for a visual card/cover browse when the user asks for a 画廊/相册/卡片墙/封面/海报/图集 (a gallery / card wall / cover / poster grid) or the object has an image/avatar/file field worth showing as a card cover; "gantt" for a 甘特图/时间线/排期 (timeline / schedule) when the object has BOTH a start and an end date field; "kanban" for a board grouped by a status/select field; "calendar" for a single-date schedule; "form" for a record editor; else "list". |
272272
| **columns** | `string[]` | optional | Field names shown as columns (in order). For a gallery, INCLUDE the image/avatar/file field (it becomes the card cover); for a gantt, INCLUDE the start date column before the end date column. |
273273
| **groupBy** | `string` | optional | REQUIRED for kanban views: the select/status field whose options become the board columns (e.g. "stage", "status"). Without it a kanban renders as a plain list. Optional for gantt (groups leaf tasks into summary rows). |
274+
| **filters** | `{ field: string; operator: Enum<'equals' \| 'not_equals' \| 'contains' \| 'not_contains' \| 'icontains' \| …>; value?: string \| number \| boolean \| null \| (string \| number)[] }[]` | optional | Which records this view shows: the list-view filter rules [`{ field, operator, value }`] the built view carries, ANDed. REQUIRED whenever the view's name or label states a condition — an 「overdue / 逾期」, 「my open / 我的未完成」, 「待审批」 or 「本月」 view MUST carry the rules that make its name true, e.g. overdue → [`{ field: "due_date", operator: "less_than", value: "{today}" }`, `{ field: "status", operator: "not_equals", value: "completed" }`]; my open → [`{ field: "owner", operator: "equals", value: "{current_user_id}" }`, `{ field: "status", operator: "equals", value: "open" }`]. WITHOUT it the view shows EVERY record under a name that promises a subset. For a select field compare its option VALUE, never its label. Omit for a view that genuinely spans every record. |
275+
| **sort** | `{ field: string; order: Enum<'asc' \| 'desc'> }[]` | optional | Default record order: [`{ field, order }`] with order "asc" or "desc"; the first entry sorts first (e.g. an overdue list → [`{ field: "due_date", order: "asc" }`]). Omit for the platform default order. |
276+
277+
### Nested Shape: `BlueprintView.filters[number]`
278+
279+
View filter rule
280+
281+
| Property | Type | Required | Description |
282+
| :--- | :--- | :--- | :--- |
283+
| **field** | `string` | ✅ | Field name to filter on |
284+
| **operator** | `Enum<'equals' \| 'not_equals' \| 'contains' \| 'not_contains' \| 'icontains' \| …>` | ✅ | Filter operator |
285+
| **value** | `string \| number \| boolean \| null \| (string \| number)[]` | optional | Filter value. The accepted SHAPE depends on the operator: `in` / `not_in` take an array (any length, including []), `between` takes exactly [min, max], every other operator takes a scalar. The unary operators (is_empty / is_not_empty / is_null / is_not_null) take their direction from the operator name and ignore this key. One operator bounds the VALUE as well as the shape: `icontains` takes a NON-EMPTY STRING, the comparand the Filter Protocol conformance table declares for it — an empty comparand constrains nothing and a non-string one would answer a query nobody wrote, and both are refused at the query path too. |
286+
287+
### Nested Shape: `BlueprintView.sort[number]`
288+
289+
Sort field and direction pair
290+
291+
| Property | Type | Required | Description |
292+
| :--- | :--- | :--- | :--- |
293+
| **field** | `string` | ✅ | Field name to sort by |
294+
| **order** | `Enum<'asc' \| 'desc'>` | ✅ | Sort direction |
274295

275296

276297
---
@@ -324,6 +345,8 @@ const result = BlueprintAppSchema.parse(data);
324345
| **type** | `Enum<'list' \| 'form' \| 'kanban' \| 'calendar' \| 'gallery' \| 'gantt'>` | optional (default: `"list"`) | View kind. Pick the surface that fits the data: "gallery" for a visual card/cover browse when the user asks for a 画廊/相册/卡片墙/封面/海报/图集 (a gallery / card wall / cover / poster grid) or the object has an image/avatar/file field worth showing as a card cover; "gantt" for a 甘特图/时间线/排期 (timeline / schedule) when the object has BOTH a start and an end date field; "kanban" for a board grouped by a status/select field; "calendar" for a single-date schedule; "form" for a record editor; else "list". |
325346
| **columns** | `string[]` | optional | Field names shown as columns (in order). For a gallery, INCLUDE the image/avatar/file field (it becomes the card cover); for a gantt, INCLUDE the start date column before the end date column. |
326347
| **groupBy** | `string` | optional | REQUIRED for kanban views: the select/status field whose options become the board columns (e.g. "stage", "status"). Without it a kanban renders as a plain list. Optional for gantt (groups leaf tasks into summary rows). |
348+
| **filters** | `{ field: string; operator: Enum<'equals' \| 'not_equals' \| 'contains' \| 'not_contains' \| 'icontains' \| …>; value?: string \| number \| boolean \| null \| (string \| number)[] }[]` | optional | Which records this view shows: the list-view filter rules [`{ field, operator, value }`] the built view carries, ANDed. REQUIRED whenever the view's name or label states a condition — an 「overdue / 逾期」, 「my open / 我的未完成」, 「待审批」 or 「本月」 view MUST carry the rules that make its name true, e.g. overdue → [`{ field: "due_date", operator: "less_than", value: "{today}" }`, `{ field: "status", operator: "not_equals", value: "completed" }`]; my open → [`{ field: "owner", operator: "equals", value: "{current_user_id}" }`, `{ field: "status", operator: "equals", value: "open" }`]. WITHOUT it the view shows EVERY record under a name that promises a subset. For a select field compare its option VALUE, never its label. Omit for a view that genuinely spans every record. |
349+
| **sort** | `{ field: string; order: Enum<'asc' \| 'desc'> }[]` | optional | Default record order: [`{ field, order }`] with order "asc" or "desc"; the first entry sorts first (e.g. an overdue list → [`{ field: "due_date", order: "asc" }`]). Omit for the platform default order. |
327350

328351
### Nested Shape: `SolutionBlueprint.dashboards[number]`
329352

@@ -387,6 +410,8 @@ const result = BlueprintAppSchema.parse(data);
387410
| **type** | `Enum<'list' \| 'form' \| 'kanban' \| 'calendar' \| 'gallery' \| 'gantt'> \| null` | ✅ | View kind, or null for list. "gallery" = visual card/cover browse (画廊/相册/卡片墙/封面/海报, or an object with an image/avatar/file field); "gantt" = timeline/schedule (甘特图/时间线/排期, object with BOTH a start and an end date field); "kanban" = board grouped by a status/select field; "calendar" = single-date schedule; "form" = record editor. |
388411
| **columns** | `string[] \| null` | ✅ | Field names shown as columns, or null. For a gallery, INCLUDE the image/avatar/file field (becomes the card cover); for a gantt, INCLUDE the start date column before the end date column. |
389412
| **groupBy** | `string \| null` | ✅ | REQUIRED for kanban: the select/status field whose options become the board columns (e.g. "stage"). Optional for gantt (groups leaf tasks). Null for list/form/calendar/gallery. |
413+
| **filters** | `{ field: string; operator: Enum<'equals' \| 'not_equals' \| 'contains' \| 'not_contains' \| 'icontains' \| …>; value: string \| number \| boolean \| (string \| number)[] \| null }[] \| null` | ✅ | Which records this view shows: list-view filter rules [`{field, operator, value}`], ANDed, or null for a view over EVERY record. REQUIRED whenever the view's name or label states a condition — an 「overdue / 逾期」, 「my open / 我的未完成」, 「待审批」 or 「本月」 view MUST carry the rules that make its name true, e.g. overdue → [`{field:"due_date",operator:"less_than",value:"{today}"}`,`{field:"status",operator:"not_equals",value:"completed"}`]; my open → [`{field:"owner",operator:"equals",value:"{current_user_id}"}`,`{field:"status",operator:"equals",value:"open"}`]. Null under such a name ships a view that shows every record while its name promises a subset. |
414+
| **sort** | `{ field: string; order: Enum<'asc' \| 'desc'> }[] \| null` | ✅ | Default record order: [`{field, order}`] with order "asc" or "desc"; the first entry sorts first (e.g. an overdue list → [`{field:"due_date",order:"asc"}`]), or null for the platform default order. |
390415

391416
### Nested Shape: `SolutionBlueprintStrict.dashboards[number]`
392417

‎docs/audits/2026-07-unknown-key-strictness-ledger.counts/ai.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,4 @@ hand-patch a number here** — fix the code or the verdict and regenerate.
1919

2020
| Dir | Sites |
2121
|---|---|
22-
| `ai/` | 78 |
22+
| `ai/` | 80 |

‎packages/spec/authorable-surface/ai.json‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,12 @@
7676
"ai/BlueprintSummaryOperations:object",
7777
"ai/BlueprintSummaryOperations:relationshipField",
7878
"ai/BlueprintView:columns",
79+
"ai/BlueprintView:filters",
7980
"ai/BlueprintView:groupBy",
8081
"ai/BlueprintView:label",
8182
"ai/BlueprintView:name",
8283
"ai/BlueprintView:object",
84+
"ai/BlueprintView:sort",
8385
"ai/BlueprintView:type",
8486
"ai/BlueprintWidgetCondition:field",
8587
"ai/BlueprintWidgetCondition:op",

‎packages/spec/dropped-refinements.baseline.json‎

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
"description": "Shrink-only ledger of every PUBLISHED JSON Schema that is STILL WIDER than the Zod type it was generated from, because a rule written as `.refine()` reaches the runtime and not the file (#18670). `z.toJSONSchema()` has no arm for a `custom` check: a plain record, the same record with a `.refine()`, and the same record with an ABORTING `.refine()` all project byte-identically (measured on zod 4.4.3, the version packages/spec resolves). So a document one of these files ACCEPTS can still be refused at parse time, and an author -- or an AI -- validating against packages/spec/json-schema/** finds out a release later. Each `sites` path is a position under that schema at which a refinement is dropped; the same paths are written onto the artifact itself as `x-dropped-refinements`. Item 2 closed the first patterns: a refinement DECLARED through the closed list in src/shared/refinement-projection.ts is emitted into the published file, reads `projected` rather than `dropped`, and its row LEAVES this ledger in the same PR -- which is why the ledger shrinks and never grows on a repair. Every refinement outside that closed list stays here, and adding an arm to the list is a public-contract decision, not a refactor. Hand-edited on purpose and with no `gen:` script: a generator would let a new gap be admitted by running a command instead of by a decision, which is the silence this ledger exists to end. Adding, removing or moving a site fails packages/spec/scripts/build-schemas.ts until the line moves with it, and the failure prints the corrected entry in full. ⛔ Do not delete or weaken a refinement to shorten this file -- the runtime rule is correct; it is the projection that is silent, and the remedy is to teach the closed list a NAMED pattern, never to drop the rule.",
33
"measured": {
44
"zod": "4.4.3",
5-
"publishedSchemasWithDroppedRefinements": 234,
6-
"droppedRefinementSites": 764,
5+
"publishedSchemasWithDroppedRefinements": 235,
6+
"droppedRefinementSites": 766,
77
"refinementSitesThatDidProject": 369,
88
"refinementSitesWithNoJsonFormToCompare": 0
99
},
@@ -29,6 +29,11 @@
2929
"filter.lazy"
3030
]
3131
},
32+
"ai/BlueprintView": {
33+
"sites": [
34+
"filters.element"
35+
]
36+
},
3237
"ai/Skill": {
3338
"sites": [
3439
"triggerConditions.element"
@@ -41,7 +46,8 @@
4146
},
4247
"ai/SolutionBlueprint": {
4348
"sites": [
44-
"objects.element.fields.element.summaryOperations.filter.lazy"
49+
"objects.element.fields.element.summaryOperations.filter.lazy",
50+
"views.element.filters.element"
4551
]
4652
},
4753
"ai/StructuredOutputConfig": {

0 commit comments

Comments
 (0)