Repository navigation
spec(lint): the view publish door accepts a chart list view whose dataset does not exist or whose values names no measure of its dataset #26847
Description
Filing gate: class (a), a reachable defect. Measured by the #26719 card thread on c8583f80 (os-dev-report 6450182672, out-of-scope finding 1). Filed by domain:spec seat 1 (#6017, session session_01WGufzfhobWEgUUrjz4rrbh). ⛔ Not a claim.
What was measured
PUT /api/v1/meta/viewpublishes a chart list view and answers200in two cases: itschart.datasetnames no declared dataset (no_such_dataset), or itschart.valuesnames no measure of that dataset (ghost_measure). Both were measured as a view item and as a containerlistViewsmember.os validatedoes report the same stack.validateChartBindings(packages/lint/src/validate-chart-bindings.ts) ownschart-dataset-unknownand the measure check for list-view charts (section 2,views[].list,views[].listViews.KEY,objects[].listViews.KEY).- The publish door never runs it for a view.
packages/lint/src/reference-integrity-suite.tsregistersvalidateChartBindingswithruntimeTypes: ['flow', 'report'], and the comment above that row saysviewwas left out on purpose. Its reason was that the view-write snapshot did not carry the report and board collections the rule walks. A list-view chart resolves only againststack.datasets, whichruntime-gate.tslists as context. validateChartBindingswalksviews[].listandlistViewsbut not the view-item (config) and flattened list shapes the view door hands the suite. So addingviewtoruntimeTypesalone may still leave a published view item unjudged.
Re-check: grep -n "name: 'validateChartBindings'" packages/lint/src/reference-integrity-suite.ts. While the row reads ['flow', 'report'], the gap is open.
Wanted
A chart list view whose dataset does not resolve, or whose values names no measure of its dataset, is refused at the view publish door (422, located at chart.dataset or chart.values[i]), with the same verdicts os validate already gives. That means:
- the rule reaches the shapes the view door carries, and
view(andobject, forobjects[].listViews) joins itsruntimeTypes.
This is a refusal widening, so measure the shipped view corpus at the door's snapshot shape before crossing, as #19542 did for report. Pin a lit probe for each verdict at the door.
Business reason: a Studio or MCP author who mistypes a dataset name, or names a measure the dataset lacks, gets a saved view that renders an empty or broken chart. Nothing says why, and the CLI would have refused the same file.
Reader who acts: domain:spec (packages/lint, the reference-integrity suite).
Related: #26719 (PR #26842) adds the sibling list-view-chart-dataset-foreign-object in validateListViewFieldRefs, which already runs at the view door.
Dedupe: open issues searched for "chart list view unknown dataset publish 200 view door", "validateChartBindings runtimeTypes view" and "chart-dataset-unknown view item": none. Closed #22491 is the missing-chart-block case, a different verdict.
Clause-②: no (narrowing)
Metadata-protocol: narrowed
Activity
objectstack-fleet commentedon Oct 27, 2026
Triage: audit line · triage seat ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-27T19:02Z⛔ Not a claim, ⛔ not a dispatch.
domain:spec·area:reports. The publish door runs the samevalidateChartB…checkos validatealready runs, so a chart view naming no dataset, or a measure that is not in it, is refused. It refuses what publishes today, soClause-②: yes (narrowing). It is a sibling of spec: a chart list view on object A accepts a dataset bound to another object or another package without refusal #26719 (a foreign dataset), and one PR may take both.Generated by Claude Code
objectstack-fleet commentedon Oct 27, 2026
Claim: PM loop round 1 · 2026-10-27T19:40Z
Session:
session_01WGufzfhobWEgUUrjz4rrbhAccount:
os-support-aiBranch:
claude/project-thread-rf1hg1(card threadsession_01WGufziFPBpGc76tAFHbB8v. The platform assigns the thread's branch and the thread can push only that one, so the branch is written as measured instead ofclaude/issue-26847-<slug>.)Worktree:
objectstack-issue-26847Domain:
domain:specSeat:
domain:spec#1File surface:
packages/lint:validate-chart-bindings.ts, so that it reaches the view-item (config) and flattened list shapes the view door carries, and thevalidateChartBindingsrow ofreference-integrity-suite.ts(runtimeTypesgainsviewandobject; the comment above the row is rewritten). The surface also covers its tests and door probes, any example, app or platform-objects view the narrowing would refuse (fixed, not tolerated), docs, and one root.changesetentry. Stop on a breach and explain it in the report.Container & model:
M,mode:thread,model: TIER_DEFAULT,effort: highClause-②: no (narrowing). A chart list view that publishes
200today with an unknown dataset or measure is refused, so a contract-tier review is owed before the queue.Metadata-protocol: narrowed
Responsibility: n/a. A finding from the #26719 card thread (os-dev-report 6450182672).
Thread-read: 6451024495
Premise: unverified at
origin/main20457f6f. The finding was measured atc8583f80, so the dev re-measures before editing.Serial constraints cleared: yes. #26719 (PR #26842) landed in
20457f6fand is in this branch's base. #26711 (PR #26851, seat 1) narrows theviewenvelope inpackages/spec, a different file. Whichever lands second mergesmain.Ruling-ref: none — triage
6451024495objectstack-fleet commentedon Oct 27, 2026
os-dev-report
{
"issue": 26847,
"status": "done",
"branch": "claude/project-thread-rf1hg1",
"pr": "#26906",
"session": "session_01WGufziFPBpGc76tAFHbB8v",
"premise_still_valid": true,
"summary": "Re-measured on main 20457f6 through the real PUT /api/v1/meta/view route (RestServer + saveMetaItem + ObjectQL/SQLite, lead_metrics dataset published first): a chart list view with chart.dataset no_such_dataset, or chart.values naming ghost_measure, answered 200 and was stored as a view item (config), a flattened list overlay and a container listViews member alike (6/6), controls 200. Fix: validateChartBindings' list-view walk now opens the flattened overlay (viewKind list, chart at top level) and the ViewItem config, its early return also considers objects, and the reference-integrity suite row is runtimeTypes ['flow','report','view','object'] with the comment above it rewritten. Same 6 PUTs now answer 422 INVALID_METADATA with chart-dataset-unknown at views[0].config.chart.dataset / views[0].chart.dataset / views[0].listViews.pipeline.chart.dataset and chart-measure-unknown at the matching .values[0]; controls 200. Corpus at the door's snapshot shape (runRuntimeAuthoringRules type view per view, type object per object with listViews, own stack's objects+datasets as context) on 21e8217: app-crm 3 views/6 objects, app-todo 1/1, app-showcase 6 views/24 objects/4 datasets, app-multi-package none, platform-objects 53 objects (29 with listViews); 2 chart list views (showcase task.chart, project.budget_chart), 0 chart findings at either door, lit probe refused. Re-judged: view and object member-surface roster pins gain validateChartBindings; the #26719 save-door probes selected status/task_count against the person dataset and now select names their dataset declares; the #22491 REST file's boot() publishes the lead_metrics dataset its control binds. Changeset in root .changeset, @objectstack/lint minor, Clause-②: no (narrowing), Metadata-protocol: narrowed, ADR-0087 not-required (no-migration-prescription), 'The remedy.' label. Docs: one paragraph in content/docs/data-modeling/analytics.mdx.",
"tests": "head 35d40a9, all under os-verify-lock with VERDICT command-exit 0. lint test: Test Files 169 passed (169), Tests 7490 passed (7490); lint typecheck exit 0. rest test: Test Files 328 passed (328), Tests 6522 passed | 326 skipped. metadata-protocol test: Test Files 270 passed | 4 skipped (274), Tests 21666 passed | 26 skipped. New pins: validate-chart-bindings.test.ts -t 26847 24 passed; meta-view-chart-binding.test.ts 13 passed (9 new). Before/after proof is the door measurement in summary (lint dist rebuilt from each tree: main 6x200, branch 6x422); no separate ablation leg, since that measurement is the same harness with the change absent. eslint --no-inline-config on the 7 changed source/test files exit 0.",
"gates": "dispatch-gates --commands (merge base 20457f6, 6 paths): 88 derived families. First pass before the full build: 86 exit 0, check:skill-examples and check:dual-build-cjs-loads exit 3 (prerequisite). After pnpm build (VERDICT command-exit 0, 7m07s), all 88 re-ran on 35d40a9: 88 exit 0. --ran: '88 derived famil(ies) accounted for — 88 run, 0 NOT-MEASURED'. PR check-runs on 35d40a9: Lint & Repo Gates success, TypeScript Type Check success, Test Core success (8/8 shards success), Build Core success, Governed Surface Queue Guard success, Type Check UI success, Test UI success, Build & E2E UI success, Lint UI skipped (no ui/ paths), Check Changeset success, Dogfood Regression Gate success.",
"dogfood_battery": "35d40a9e7 · os-verify-lock: VERDICT command-exit 0 (held 27m02s, shared box) · Test Files 327 passed | 3 skipped (330) · Tests 2683 passed | 20 skipped (2703) · no failures",
"mcp_calls": "4 — mcp__github__issue_read x2 (issue + comments), mcp__github__pull_request_read x2 (get, get_check_runs); no MCP write",
"api_writes": "4 relay strokes as objectstack-fleet[bot]: pr_create #26906 draft with assignee leg (POST /repos/objectstack-ai/objectstack/pulls, POST /repos//issues/26906/assignees; 9170 bytes sent, 9170 stored, identical), pr_request_reviewers os-support-ai (POST /repos/objectstack-ai/objectstack/pulls/26906/requested_reviewers, the session's standing request), and this os-dev-report comment (POST /repos//issues/26847/comments); plus 4 git pushes",
"open_questions": [],
"out_of_scope_findings": []
}
Generated by Claude Code
objectstack-fleet commentedon Oct 27, 2026
Landed ·
domain:specseat 1 (#6017) · sessionsession_01WGufzfhobWEgUUrjz4rrbh· 2026-10-27T22:47ZPR #26906 merged at
216a39e7, which is an ancestor oforigin/main. On all 9 paths the PR touched, the merge tree matches the accepted head96844466byte for byte.The view and object publish doors (
PUT /api/v1/meta/view,PUT /api/v1/meta/object) now runvalidateChartBindings. A list view whosechart.datasetnames no declared dataset, or whosechart.dimensions/chart.valuesnames a dimension or measure its dataset does not declare, is refused422with the verdictos validategives:chart-dataset-unknown,chart-dimension-unknownorchart-measure-unknown. This holds for the view itemconfig, the flattened list overlay and an object's ownlistViews.os validate/os buildnow also report the two shapes they used to skip. Drafts are not gated.@objectstack/lintis minor, with a BREAKING banner and ADR-0087not-required (no-migration-prescription).Clause-②: no (narrowing)andMetadata-protocol: narrowed. The card closed throughFixes #26847, and this seat removespm:dispatched.