Repository navigation
content(blog): views, dashboards and apps are projections of the ontology — the naming test, measured on app-todo (slot 2026-11-10) - #263
Conversation
…logy — the naming test, measured on app-todo (slot 2026-11-10) One new post directory: en and zh-Hans authored, zh-Hant generated, two SVG pairs. The proof artifact is a one-field diff on examples/app-todo at objectstack 43567a8f, run on the published 18.0.0-next.2 packages and read before and after on the table, REST, metadata, MCP, Console, views, translation and dataset surfaces. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017GeNDQH7E5S2rX8ajVAPxv
…ded) into claude/sharp-mendel-1087cg-issue-262 Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017GeNDQH7E5S2rX8ajVAPxv
…n surfaces follow; not every surface The share image travels alone (writing rule 7): the headline now matches the post's own reading, seven derived surfaces followed and four pinned projections did not. Layout unchanged; zh re-derived, not translated. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017GeNDQH7E5S2rX8ajVAPxv
席位核对ACCEPT, held for the slot.
Follow-up: once #265 lands, the zh-Hans Pointer for #262: Generated by Claude Code |
…luster links, #265) into claude/sharp-mendel-1087cg-issue-262 Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017GeNDQH7E5S2rX8ajVAPxv
…zh-hant rewrites marketing-page links The inline-code mention was a detour around the generator gap (#265, landed as 3c5b6c6); the zh-Hans post now links /zh-Hans/ontology/ like the en post links /en/ontology/, and the generated zh-Hant file carries /zh-Hant/ontology/. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017GeNDQH7E5S2rX8ajVAPxv
席位核对 — re-recorded on head
|
| Check | Result |
|---|---|
Delta since db59562 |
The merge commit 6a8b1a8 brings in origin/main 3c5b6c6 and changes no post file. 0b2ee78 changes 2 lines: in index.zh-Hans.mdx the inline-code /zh-Hans/ontology/ becomes [本体页](/zh-Hans/ontology/), and the regenerated index.zh-Hant.mdx carries [本體頁](/zh-Hant/ontology/). |
File surface vs main |
Still the 7 post files only (git diff --stat origin/main... → 7 files, +753). |
| CI on head | Build and deploy: completed/success on 0b2ee78. |
Pointer for #262: ACCEPT (held to 2026-11-10) → PR #263 comment (this one).
Generated by Claude Code
…and backfill five locales Re-ran the eleven readings on the published 18.3.0 packages (npm latest on 2026-11-06) with examples/app-todo at the @objectstack/cli@18.3.0 release commit 83d7e4ae. Relabelled prose, cover footers and naming-test SVGs to 18.3.0 and updated what drifted: 28 -> 29 columns/keys/metadata fields, MCP describe_object now 28 -> 29 (it serves system fields), OpenAPI 17 paths, 63 author-time rules, the gate's rule line, the Console URL and the Overview tab. The Overdue paragraph now quotes due_date's dueLike + settledWhen (task.object.ts:73-74) and notes the keys are display-only. The ObjectOS paragraph follows E1 (export is planned), and the post links The Ontology Is the Software. Adds ja, ko, de, es and fr translations; zh-Hant regenerated with pnpm gen:zh-hant. date is unchanged. Co-Authored-By: Claude <noreply@anthropic.com>
…d ObjectOS line The closing paragraph in all eight locales quoted the retired "same loop hosted … commercial runtime environment" T4, which src/lib/positioning.ts says must not be reintroduced. It now quotes the current T4 verbatim (T4_STANDALONE for en, each locale's positioning t4 elsewhere), drops the hosted/self-managed sentence that restated the old quote, and keeps the E1 "export is planned" sentence. zh-Hant regenerated with pnpm gen:zh-hant. Co-Authored-By: Claude <noreply@anthropic.com>
Fixes #262
Refs #236 (item C)
Slot:
date: 2026-11-10(Tuesday). The seat merges on that day and no earlier (www AGENTS.md, "Publishing cadence"); this PR stays a draft until then. TheDate is in the futureadvisory fromcontent:lintis expected until the slot.What this adds
One new directory,
content/blog/views-dashboards-apps-are-projections-of-the-ontology/:index.mdx(en, authored) andindex.zh-Hans.mdx(zh-Hans, re-derived rather than translated);index.zh-Hant.mdxgenerated bypnpm gen:zh-hant. No further locales.cover-en.svg/cover.svgandnaming-test-en.svg/naming-test.svg(the English-text pair for every non-Chinese locale, the Chinese-text pair for zh-Hans/zh-Hant). Every text node carries an explicitfill;pnpm svg:lintpasses on all four (162 text boxes). Rendered at native size and at 390 px and looked at.Nothing else in the tree changes.
The post, in one paragraph
The thesis is in the first hundred words: reviewing the definition line reviews every surface derived from it, because the derived surfaces name only the object and ask the definition on every call; the projections that name the field (view columns, dataset measures, translation labels) are pinned and stay as authored. The ownable concept is the naming test — if a projection names the field, you review it; if it names only the object, the runtime already did — a companion to #211's removal test. The number behind it: one five-line diff, seven surfaces followed with zero edits, four projections unchanged, and the build gate (
field-no-consumers) said so before boot.Overlap fence
The definition of a projection and the removal test are linked, not restated: the #211 post (
/en/blog/what-does-the-ontology-is-the-software-mean/), the/ontology/page (its "Projections" section) and theontology-projectionglossary term from PR #259. The post starts at the review angle.Proof artifact, measured
Setup:
examples/app-todocopied out of objectstack atorigin/main43567a8f(2026-10-16) into my scratchpad, itsworkspace:dependencies pinned to the published18.0.0-next.2packages (thenextdist-tag; the repo's package versions at that commit are18.0.0-next.2), booted withos devon the default SQLite file, API key minted overPOST /api/v1/keysfrom the seeded dev admin. The shared objectstack checkout has nonode_modulesordist, so a run from source was not available; nothing was run or edited inside the www tree or the objectstack checkout.The diff (the only change between the two readings):
todo_task(PRAGMA table_info)days_overduehas none)budget floatadded to the existing tablepackages/drivers/driver-sql/src/sql-driver.ts,initObjectscreate/alter branches (walksobj.fields,createColumnper entry);schema-drift.tsheader: the sync is additive-onlyGET /api/v1/data/todo_taskpackages/rest/src/rest-route-ledger.tsrowsGET/POST /api/v1/data/:object(per object, not per field)POST /api/v1/data/todo_taskwithbudget: 1200400{"error":"Unknown field 'budget' on object 'todo_task'","code":"INVALID_FIELD"}201GET /api/v1/meta/object/todo_taskitem.fields{label:'Budget',type:'currency',min:0,…}GET /api/v1/meta/:type/:name(route ledger)tools/listbudgetin no schemapackages/mcp/src/mcp-http-tools.ts(registerToolsites)describe_objectpackages/mcp/src/stdio-data-bridge.tsdescribeObject:Object.entries(def.fields)query_recordswhere budget >= 1000,fields [subject, budget][["Renew the domain", 1200]]query/api/v1/openapi.jsontodo_taskpaths, no field schemapackages/rest/src/openapi-endpoints.ts/_console/apps/todo_app/todo_task/newpackages/app-shell/src/utils/recordFormNavigation.tsresolveFormViewLayout(no form view ⇒ no sections) andMetadataProvider.tsx("the dialog lays out the object's own fields")BUDGET 1,200.00in Details; the old record's collapsed group went from "Show 6 empty fields" to 7examples/app-todo/src/views/task.view.ts(columnsby field name);GET /api/v1/meta/viewanswers the same 3 views before and afterzh-CNlabel (Accept-Language: zh-CN)subject→ 主题budget→Budgetexamples/app-todo/src/translations/zh-CN.tsnames 19 fieldstask_metrics/ dashboardsrc/datasets/task.dataset.ts,src/dashboards/task.dashboard.ts⚠ object "todo_task" · field "budget": declared, but nothing in this stack displays or reads it (inert) … rule: field-no-consumersos dev --compilelog (49 author-time rules); rule text fromos explain field-no-consumersHonesty notes carried into the post: the Console grid did not follow (pinned columns); the
zh-CNlabel falls through to English; the dataset cannot chart the field until a measure names it; MCPtools/listand the OpenAPI document are object-level and unchanged by design; a removal would not follow in the table (additive-only sync, drift viaos migrate); the status-option example (cancelledcounted as overdue by the view filterstatus not_equals completedand the dashboard metricstatus: { $ne: 'completed' }) is stated as a reading oftask.view.ts/task.dashboard.ts, not a run. The same gate also flags five of the example's own existing fields as carrier-only; the post does not claim the example is clean.Positioning lines are quoted from
src/lib/positioning.ts(T4_STANDALONEande1, en and zh-Hans) verbatim. No token figures. No model identifiers.Variation against the siblings (writing rule 9)
Opening: the diff itself, then the answer (#211 opens with a definition paragraph, post A with three bold words, #237 with two tool-call outputs, #244 with a definition contrast and a key, #245 with a claim and a run). Proof artifact: an eleven-row before/after measurement table plus the gate's own line (siblings use a line count, a sourced mapping table, a two-user run, a removed key, and a three-mistake gate run). Structure: no separate "Hosted" section; T4/E1 close the CTA. The diagram is a two-column sort around the diff, not a pipeline.
Two dependencies, stated
ontology-projection). The post links/en/glossary/ontology-projection/(zh:/zh-Hans/glossary/ontology-projection/) as the card asks. Until content(positioning): speak the ontology below the hero — capability pages, home, glossary, llms.txt, the AI-native cluster #259 lands,content:lint(source mode and--published, whichpnpm buildruns first) reports the link as a blocking dangling link andpnpm buildexits 1. Measured both ways on this branch: with content(positioning): speak the ontology below the hero — capability pages, home, glossary, llms.txt, the AI-native cluster #259's two term files copied in untracked, every gate below is green; without them, the one red is exactly✗ content/blog/views-dashboards-apps-are-projections-of-the-ontology/index.mdx: Dangling internal link [glossary entry](/en/glossary/ontology-projection/): no term file content/glossary/*/ontology-projection.ts — create it, or fix the slug(and the same line for the zh-Hans and zh-Hant files). content(positioning): speak the ontology below the hero — capability pages, home, glossary, llms.txt, the AI-native cluster #259 lands before the 2026-11-10 slot; a CI re-run then goes green. The link is kept rather than dropped, per the card.scripts/gen-zh-hant.mjszhHantTargetBuildsrewrites/zh-Hans/…to/zh-Hant/…only for the locale home, static routes, blog posts and glossary terms; it has no branch for marketing pages although its own header says marketing pages derive zh-Hant from zh-Hans. So a zh-Hans post linking/zh-Hans/ontology/produces a zh-Hant file thatcontent:lint --publishedrejects ("/zh-Hant/ontology/ IS built … change the locale segment"), and a cross-locale/en/ontology/link is rejected in both zh files. Measured here: exit 1 with that line in both cases. Consequence for this PR: the zh-Hans post names the/ontology/page with its path in inline code instead of a hyperlink (the en post links it). Restoring the link is a one-word edit once the generator carries a marketing-page branch mirroring its glossary one. Filed for the seat in the report as an out-of-scope finding.Gates (worktree HEAD
13a6486; every command re-run after the final commit; exit codes captured before any pipe)With #259's term files present (untracked, removed before commit):
pnpm content:lint— exit 0 —✓ content lint passed (350 files, 46 glossary terms checked); advisories only (title width, description width, future date).pnpm check— exit 0 —Result (158 files): 0 errors, 0 warnings, 0 hints(underos-verify-lock.sh,VERDICT command-exit 0).pnpm build(=gen:zh-hant→content:lint --published→svg:lint→astro build→og:images→content:lint --dist) — exit 0 underos-verify-lock.sh(VERDICT command-exit 0 · held the lock 91s) —✓ zh-Hant: generated 48, kept 0 hand-maintained, 8 with body links pointed at /zh-Hant/·✓ content lint passed (350 files, 46 glossary terms checked)·915 page(s) built in 64.22s·✓ share images: 91 rendered at 1200x630·✓ content lint --dist links passed (98734 internal links in 915 built pages resolve to built files); tree clean after the build (only the generatedindex.zh-Hant.mdx, committed).pnpm seo:smoke— exit 0 —SEO smoke test passed (905 HTML pages checked; 589 sitemap URLs against 316 noindexed pages; 5619 canonical/hreflang annotations; 17058 prose blocks language-checked; 98724 internal links redirect-checked).pnpm svg:linton the four new SVGs — exit 0 —svg-text-fit: OK … 4 SVGs, 162 text boxes.Without #259's term files (the state CI will see until #259 lands):
pnpm content:lint— exit 1 —✗ content/blog/views-dashboards-apps-are-projections-of-the-ontology/index.mdx: Dangling internal link [glossary entry](/en/glossary/ontology-projection/): no term file content/glossary/*/ontology-projection.ts — create it, or fix the slug(and the same line for the zh-Hans and zh-Hant files).Browser check (Playwright, Chromium, against
astro previewof the builtdist/)Pages: the en, zh-Hans and zh-Hant post and the en and zh-Hans blog lists, each at 1440×750 and 390×844.
scrollWidth == clientWidthat both widths (no horizontal page overflow); 0 page errors.loading="lazy", scrolled into view anddecode()d, 860×545 / 358×227). No imagesrcrepeated: the cover is rendered by the layout once and not in the body.display: block; overflow-x: auto, scrollWidth 521 vs clientWidth 358,scrollLeftsettable); at 1440 it lays out in 860 px. Looked at both./en/blog/, the two topic hubs, the Post (slot Thu 2026-10-08): What Does "The Ontology Is the Software" Mean? An Executable Business Ontology, Defined #211 post,/en/ontology/,/en/glossary/ontology-projection/, the diagram asset, the review-checklist post, the point-your-agent post, and the layout's related post. The glossary link answers 404 onmainuntil content(positioning): speak the ontology below the hero — capability pages, home, glossary, llms.txt, the AI-native cluster #259 lands (dependency 1)./en/blog/, built): the post is the first card under "Latest Articles", after the four hand-picked "Recommended" cards; its cover renders there (eager, 584×357).Acceptance notes
content:lintadvisory about search-result width, same shape as Post (slot Thu 2026-10-08): What Does "The Ontology Is the Software" Mean? An Executable Business Ontology, Defined #211's 93-char title).main; see dependency 1.Generated by Claude Code
Patch round 1 (added by the seat)
db59562:13a6486+ a merge oforigin/main45d5ce9(838e901) + the cover fix.45d5ce9and is merged into this branch, so/en/glossary/ontology-projection/and/zh-Hans/glossary/ontology-projection/resolve here. The "red without the content(positioning): speak the ontology below the hero — capability pages, home, glossary, llms.txt, the AI-native cluster #259 term files" reading above is historical.One field, / seven surfaces.(wasOne field. / Every surface.) and 「改一个字段,/ 七个面自己跟上。」 (was 「改一个字段,/ 动到每个面。」).db59562:content:lint0;check0 (160 files);build0 (915 pages,--distlinks 98822);seo:smoke0;svg:lint0. CIBuild and deploy: success.pnpm build(content-lint cross-locale rule) #265. Until it lands, the zh-Hans/ontology/mention stays inline code.Patch round 2 (added by the seat)
0b2ee78:db59562+ a merge oforigin/main3c5b6c6(6a8b1a8; gen-zh-hant never rewrites a /zh-Hans/ link to a marketing page, so a zh-Hans post that links /zh-Hans/ontology/ failspnpm build(content-lint cross-locale rule) #265's generator fix, PR fix(gen-zh-hant): rewrite /zh-Hans/ links to marketing pages and clusters #266) + the zh-Hans link restore.[本体页](/zh-Hans/ontology/), and the generated zh-Hant file carries[本體頁](/zh-Hant/ontology/). All three definition places are now hyperlinked in every authored locale.0b2ee78:content:lint0;check0 (160 files);build0 (915 pages,--distlinks 98824);seo:smoke0. CIBuild and deploy: success.Addendum 2026-11-06: slot-ahead refresh on 18.3.0 (www seat 1)
Addendum: re-measured on ObjectStack 18.3.0 (refresh commit c8eb1ab)
This is a correction of the existing post under the maintainer's 18.1 A ruling. The post's argument is unchanged. The refresh is one commit on top of a
--no-ffmerge oforigin/main(2416a44).date:is unchanged.What was re-measured, and how
npm view @objectstack/cli dist-tagson 2026-11-06 02:24Z returned{ next: '18.2.0', latest: '18.3.0' }. The example came from the@objectstack/cli@18.3.0tag, which is commit83d7e4ae("chore: version packages (#26517)", 2026-11-03).git archive '@objectstack/cli@18.3.0' examples/app-todo, replaced theworkspace:dependencies with18.3.0(all 14@objectstack/*packages are published at 18.3.0) and ranpnpm install.npx os --versionreturned@objectstack/cli/18.3.0 linux-x64 node-v22.22.0. The server wasos dev --no-watch -p 49880 -d file:./db.sqlite, which usesSqlDriver(better-sqlite3). The API key came fromPOST /api/v1/keys(201). For the "after" readings I applied the same five-linebudget: Field.currency({ label: 'Budget', min: 0 })diff afteractual_hoursand restarted with--compile.PRAGMA table_info(todo_task)budget floatGET /api/v1/data/todo_taskkeys per recordPOST /api/v1/data/todo_taskwithbudget: 1200400 {"error":"Unknown field 'budget' on object 'todo_task'","code":"INVALID_FIELD",…}201 {"id":…}GET /api/v1/meta/object/todo_taskfields{label:'Budget',type:'currency',min:0,…}describe_objectfieldsquery_recordswhere budget $gte 1000INVALID_FIELD[{subject:'Renew the domain', budget:1200}]tools/listtodo_taskbudgetanywhere in the docbudgetBUDGET 1,200.00on the Overview tabtodo_task.default/.overdue/.due_todaycolumnsAccept-Language: zh-CN)subject→ 主题budget→Budgettask_metricsbudget→ Running author-time rules (63)...fix:line is unchanged. Therule:line now ends with— `os explain field-no-consumers` for what counts as a consumer.os explain field-no-consumers(exit 0). All three quoted passages are still verbatim: the consumer list, "names a field without reading it" with its carrier examples, and "a consumer can legitimately live outside the stack — …". The consumer definition now also counts a declared field group and a seed or import-mapping match key.describe_objectjumped from 19 to 28. At43567a8f,describeObjectreadmetadataService.getObject(the authored object). At 18.3.0 it readsobjectView.getObject(the served object, which includes system fields) inpackages/mcp/src/stdio-data-bridge.ts:942-958. TheObject.entries(fields)mapping the post cites is still there.examples/app-todo/src/objects/task.object.ts:73-74at the tag readsdueLike: true,andsettledWhen: P`record.status == 'completed'`,. The spec says "Display only: nothing on the write path reads either key. The consumer is the renderer — objectui's date and datetime cells" (packages/spec/src/data/field.zod.ts:2324-2326). The overdue view filter (status not_equals completed) and the dashboard metric (status: { $ne: 'completed' }) still state the rule separately.packages/drivers/driver-sql/src/schema-drift.ts:6-7.connect-mcp.mdx:225still says "Twelve tools".What changed in the post
83d7e4ae, the 18.3.0 release tag.describe_objectis now 28→29. The Console URL is now/_console/apps/com.example.todo/todo_task/new, which is wheretodo_appredirects. The record detail is on the Overview tab. OpenAPI is 17 paths. The gate'srule:line is updated.os explain: added the clause about the newly counted consumers. The quotes are unchanged.due_datedeclares the definition once (dueLike+settledWhen, task.object.ts lines 73–74 at 18.3.0). These keys are display-only, so the view filter and the metric restate the rule. The phrase "both projections namestatus" became "all three", and "view and dataset definitions" became "view, dashboard and object definitions", because the metric is a dashboard widget.src/lib/positioning.tsE1.Five locales added
index.ja.mdx,index.ko.mdx,index.de.mdx,index.es.mdxandindex.fr.mdx. Each is translated from the corrected English and reusescover-en.svgandnaming-test-en.svg, as AGENTS.md "Blog Content" says translated locales do. Terms follow the existing locale posts (definition post: 中核/投影/削除テスト, 핵심/투영/제거 테스트, Kern/Projektion/Entfernungstest, núcleo/proyección/prueba de eliminación, noyau/projection/test de suppression), and so do the tags. The Englishos explainand gate quotes are marked<span lang="en">…</span>with a translation after them, as in 217094b. Links go to the locale's own definition and ontology posts; links to English-only targets go to/en/. zh-Hant was regenerated withpnpm gen:zh-hant.Gates (tree = c8eb1ab)
pnpm install --frozen-lockfile: exit 0.pnpm content:lint:✓ content lint passed (422 files, 46 glossary terms checked). The only warnings for this post are title/description width and the future date, the same kind the corpus already carries.pnpm check, under the lock:0 errors, 0 warnings, 0 hints,VERDICT command-exit 0.pnpm build, under the lock:VERDICT command-exit 0. svg-text-fit OK (173 SVGs), and content-lint--distpassed for links, CJK breaks and quotation marks.pnpm seo:smoke: passed (993 pages, 21770 prose blocks language-checked).Word-break probe for all 8 locales at 390 and 360 (post h1/h2/h3 and the blog-index first card): 2 splits, both CSS dictionary hyphenation with a rendered hyphen (es h1 "proyec-ciones" at 360, de index card "Projek-tionen" at 390, checked in screenshots). There were 0 splits without a hyphen.
Screenshots: the post top in all 8 locales at 1440 light, plus en and zh-Hans at 390, and the four SVGs at native size. All were looked at.
Rework round 1 (156848a): removed the retired T4 quote ("Want the same loop hosted … commercial runtime environment built on ObjectStack") from all eight locales. Each locale now quotes the current T4 verbatim from
src/lib/positioning.ts(T4_STANDALONEfor en, each locale's ownt4elsewhere, zh-Hant regenerated). I dropped the hosted/self-managed sentence and kept the E1 "export is planned" sentence.grep -rn "same loop\|commercial runtime"on the post folder prints nothing. content:lint 0, check 0, build 0, the last two under the lock.