From a8d7b5d6d107ea42b23d4c65af36adabf570425b Mon Sep 17 00:00:00 2001 From: Robert Blust Date: Thu, 10 Sep 2026 07:43:57 +0200 Subject: [PATCH] Both pins take core 0.17.0, and the ledger check stops racing the fetch The profile's tagline is the claim now rather than a description of the person, which core 0.17.0 makes room for and the instance took, so the model page and every page drawing the profile show it. Both pins move together because both point at the same release: the commit in source.json and the tag the parser comes by. The kinds check was reading the page before it had one. The ledger has been built from a fetched model.json since design v0.55.0, so a goto resolves before there is anything to read, and the check written for that parameter this morning asserted against the page as it was a moment earlier. It passed on the run that shipped it and failed on the run after this re-pin, which is what a race looks like from the outside. Both of its gotos now wait for a row to exist. Verified: npm run verify passes three times running against a served copy, where it failed once before the wait; model:check, pages:check, design:check, pin:check, og:check after npm run og, test:og, test:build, test:dupes, conventions-check and conventions-sync check all pass. Co-Authored-By: Claude Opus 5 (1M context) --- model.json | 8 ++++---- model/og.sha | 2 +- package-lock.json | 6 +++--- package.json | 2 +- principles/index.html | 2 +- principles/og.sha | 2 +- source.json | 2 +- timeline/og.sha | 2 +- verify/check.mjs | 6 ++++++ 9 files changed, 19 insertions(+), 13 deletions(-) diff --git a/model.json b/model.json index 9702708..a8cc47d 100644 --- a/model.json +++ b/model.json @@ -1,5 +1,5 @@ { - "commit": "2241591106e36cc8c4c616d6028173341db036ae", + "commit": "d7c2de52805664dc418c5d9c722bc75c8c51218f", "root": "Robert Blust", "rootId": "identity", "types": [ @@ -288,7 +288,7 @@ "id": "profiles/robert-blust", "type": "profile", "name": "Robert Blust", - "tagline": "Technology executive and business architect — over 25 years building platforms and products from explicit models, now modeling the company itself so people and AI agents can both work inside it.", + "tagline": "Building fast is solved. Deciding well is not.", "fields": { "source": "Local" }, @@ -4567,12 +4567,12 @@ "sections": [ { "heading": "What it shows", - "text": "- **Headline** — the slogan the blust.ch landing page carries as its H1, and nothing beside it.\n- **Location** — the metropolitan area the network's own list offers for the identity's\n `location`.\n- **About** — the profile's `## Summary`, rewritten in this surface's register.\n- **Experience** — the experiences of kind `Role`, kind `Independent` and kind `Community`.\n- **Projects** — the experiences of kind `Project`.\n- **Education** — the experiences of kind `Education`.\n- **Skills** — five skills of the profile's, chosen by the owner.\n- **Languages** — the two languages `conventions/WRITING.md` names, English and Swiss German.", + "text": "- **Headline** — the profile's tagline, and nothing beside it.\n- **Location** — the metropolitan area the network's own list offers for the identity's\n `location`.\n- **About** — the profile's `## Summary`, rewritten in this surface's register.\n- **Experience** — the experiences of kind `Role`, kind `Independent` and kind `Community`.\n- **Projects** — the experiences of kind `Project`, each with the role the entry names.\n- **Education** — the experiences of kind `Education`.\n- **Skills** — five skills of the profile's, chosen by the owner.\n- **Languages** — the two languages `conventions/WRITING.md` names, English and Swiss German.", "tables": [] }, { "heading": "Projection rules", - "text": "- Everything written for this surface is in the prose register of `conventions/WRITING.md`,\n aimed at a visitor who has not decided to stay: the first line carries the point, sentences\n run short because the profile is read on a phone, and a claim it opens with is a claim it then\n shows.\n- An entry carries the title and the period of the experience it was made from, and its body is\n written rather than copied. What the entry holds was written for a reader who came to read.\n- The model is a company of one, so an experience nobody commissioned or hosted was the\n company's own work: an entry whose experience carries no `organization` names the identity.\n The network asks for a company on every entry and this answers it from the model rather than\n by inventing a name.\n- An entry's body runs to one paragraph, and an entry whose period is a single day runs to a\n sentence or two. The dates say which an entry is, so no count is needed here, and the register\n holds either way: the first sentence carries the point.\n- For a talk, an article or a published tool the address is most of what the entry is, so an\n entry whose experience carries a `url` shows it. An entry whose experience carries none shows\n no link: the model holds an address or it does not, and this surface invents none.\n- The About text is the profile's `## Summary` rewritten the same way. The sentence naming the\n security and compliance standards is not carried, because the LIKE MAGIC entry names those\n standards beside the work that met them, and a standard named without its work is a claim the\n reader cannot place.\n- Every dated unit runs newest first by `end`, with an experience that has none — a period still\n running — above them all, and `start` breaking a tie. Not by `start`: a position starts once\n and then runs for years, so ordering by it buries a long role under everything that began\n while it was running, and a talk given during a job would stand above the job. What a reader\n wants first is what ended last.\n- Every experience reaches a dated unit and each kind reaches one: `Role`, `Independent` and\n `Community` are Experience, `Project` is Projects, `Education` is Education. Nothing here reads\n what an experience produced or who it was for, because the kind already says both and the\n model records nothing finer.\n- The Skills unit shows five because the network shows five on this account. Which five is the\n owner's choice at each rebuild and not a rule: the model holds seventy skills and no ordering\n among them, so nothing here could derive the five without inventing a ranking.\n- The Skills unit carries no proficiency level. The surface shows names alone, and a level\n beside a name the surface does not explain reads as a grade.\n- The profile's tagline reaches no unit. It is the profile's `## Summary` compressed, the About\n text is that Summary rewritten, and the headline states a value instead, so the tagline\n wherever it landed would be the same claim a second time.\n- The model's values and its vision reach no unit. The surface has no unit for a stated\n principle, and the About text is the only place one could go, where it would take the room\n that text has for the work the principle was held during.\n- An experience's `## References` and its `skills` reach no unit either. The references are the\n documents a claim rests on, which a reader of the model follows and a reader of a profile does\n not — the entry's own address is what they came for. The skills are already on the surface, as\n the five the Skills unit carries, and a list per entry would be the same claim told longer.\n- Nothing else the model holds reaches this surface: the standing links of the profile's\n `## Also at`, the identity's `email`, the proficiency levels, the experience kinds, the\n sources and this file's own type. Each is either how the model is kept, or a way to reach the\n subject that the network already provides.", + "text": "- Everything written for this surface is in the prose register of `conventions/WRITING.md`,\n aimed at a visitor who has not decided to stay: the first line carries the point, sentences\n run short because the profile is read on a phone, and a claim it opens with is a claim it then\n shows.\n- An entry carries the title and the period of the experience it was made from, and its body is\n written rather than copied. What the entry holds was written for a reader who came to read.\n- An experience's own tagline supplies the role an entry was played in, where it names one:\n several read `3AP · Lead Architect & Developer` and no other field carries that, so without\n this rule a reader learns what was delivered and never what part in it was yours.\n- A body is written from the experience's `## Achievements`, and from its `## Ending` where the\n ending states a fact the achievements do not. An ending says why a period closed and what it\n left, and on some entries that is the only place the outcome is written down.\n- The model is a company of one, so an experience nobody commissioned or hosted was the\n company's own work: an entry whose experience carries no `organization` names the identity.\n The network asks for a company on every entry and this answers it from the model rather than\n by inventing a name.\n- An entry's body runs to one paragraph, and an entry whose period is a single day runs to a\n sentence or two. The dates say which an entry is, so no count is needed here, and the register\n holds either way: the first sentence carries the point.\n- For a talk, an article or a published tool the address is most of what the entry is, so an\n entry whose experience carries a `url` shows it. An entry whose experience carries none shows\n no link: the model holds an address or it does not, and this surface invents none.\n- The About text is the profile's `## Summary` rewritten the same way. The sentence naming the\n security and compliance standards is not carried whole, because the LIKE MAGIC entry names\n those standards beside the work that met them, and a standard named without its work is a\n claim the reader cannot place. The claim that sentence also makes about AI goes with it, and\n is not restored elsewhere in the About text: the headline is that claim, and this surface does\n not say one thing twice.\n- Every dated unit runs newest first by `end`, with an experience that has none — a period still\n running — above them all, and `start` breaking a tie. Not by `start`: a position starts once\n and then runs for years, so ordering by it buries a long role under everything that began\n while it was running, and a talk given during a job would stand above the job. What a reader\n wants first is what ended last.\n- Every experience reaches a dated unit and each kind reaches one: `Role`, `Independent` and\n `Community` are Experience, `Project` is Projects, `Education` is Education. Nothing here reads\n what an experience produced or who it was for, because the kind already says both and the\n model records nothing finer.\n- The Skills unit shows five because the network shows five on this account. Which five is the\n owner's choice at each rebuild and not a rule: the model holds seventy skills and no ordering\n among them, so nothing here could derive the five without inventing a ranking.\n- The Skills unit carries no proficiency level. The surface shows names alone, and a level\n beside a name the surface does not explain reads as a grade.\n- The headline is the profile's tagline, carried whole. The tagline states the claim this work\n makes rather than describing it, which core admits since 0.17.0 and holds to one condition:\n the claim is one the model keeps elsewhere. This one is, as the value Decide well over build\n fast, so a reader who wants the argument behind the line has somewhere to go.\n- The model's values and its vision reach no unit. The surface has no unit for a stated\n principle, and the About text is the only place one could go, where it would take the room\n that text has for the work the principle was held during.\n- An experience's `## References` and its `skills` reach no unit either. The references are the\n documents a claim rests on, which a reader of the model follows and a reader of a profile does\n not — the entry's own address is what they came for. The skills are already on the surface, as\n the five the Skills unit carries, and a list per entry would be the same claim told longer.\n- Nothing else the model holds reaches this surface: the standing links of the profile's\n `## Also at`, the identity's `email`, the proficiency levels, the experience kinds, the\n sources and this file's own type. Each is either how the model is kept, or a way to reach the\n subject that the network already provides.", "tables": [] }, { diff --git a/model/og.sha b/model/og.sha index 661fe24..61ecd00 100644 --- a/model/og.sha +++ b/model/og.sha @@ -1 +1 @@ -85ebc71f69b46e33a3918f075defcc5fa115fefe481b5c21bbdbb27f6644262f +ed150dfbd9bb276d6d2dd4fd10846bdff8dbf8089cb032cb521ce44ff4ab3d3b diff --git a/package-lock.json b/package-lock.json index 4b589c4..d3e83bf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "1.0.0", "devDependencies": { "@robertblust/design": "github:robertblust/design#v0.55.0", - "companygraph-meta-model": "github:companygraph/meta-model#v0.16.0", + "companygraph-meta-model": "github:companygraph/meta-model#v0.17.0", "pdf-lib": "^1.17.1", "playwright": "^1.63.0" } @@ -47,8 +47,8 @@ } }, "node_modules/companygraph-meta-model": { - "version": "0.16.0", - "resolved": "git+ssh://git@github.com/companygraph/meta-model.git#7b94d6dbde8b36c25e4b83b0176d0a23a700bd35", + "version": "0.17.0", + "resolved": "git+ssh://git@github.com/companygraph/meta-model.git#238ee3542246d3b0bb496d2226b4287b0816865f", "dev": true, "engines": { "node": ">=22" diff --git a/package.json b/package.json index e75ec9b..cd67e58 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ }, "devDependencies": { "@robertblust/design": "github:robertblust/design#v0.55.0", - "companygraph-meta-model": "github:companygraph/meta-model#v0.16.0", + "companygraph-meta-model": "github:companygraph/meta-model#v0.17.0", "pdf-lib": "^1.17.1", "playwright": "^1.63.0" } diff --git a/principles/index.html b/principles/index.html index 824660a..37aa5b4 100644 --- a/principles/index.html +++ b/principles/index.html @@ -650,7 +650,7 @@

Production is the finish line

-

Generated from robertblust/mental-model@2241591 — model/vision.md and model/values/. That repository is an instance of CompanyGraph, a meta-model for describing a company as a graph of Markdown.

+

Generated from robertblust/mental-model@d7c2de5 — model/vision.md and model/values/. That repository is an instance of CompanyGraph, a meta-model for describing a company as a graph of Markdown.

diff --git a/principles/og.sha b/principles/og.sha index dd0cf25..5be6793 100644 --- a/principles/og.sha +++ b/principles/og.sha @@ -1 +1 @@ -842f7a3d99dab59855c4c014414864aac2ed651799bff302e4c539941181eb8f +ce9ee36aa145b84a50dc14c368181845dbf57f056b11e3f55cbbd3562ac59439 diff --git a/source.json b/source.json index 81fb1b8..b6b7d4b 100644 --- a/source.json +++ b/source.json @@ -1 +1 @@ -{"repo": "robertblust/mental-model", "commit": "2241591106e36cc8c4c616d6028173341db036ae"} +{"repo": "robertblust/mental-model", "commit": "d7c2de52805664dc418c5d9c722bc75c8c51218f"} diff --git a/timeline/og.sha b/timeline/og.sha index 5404537..942a7e0 100644 --- a/timeline/og.sha +++ b/timeline/og.sha @@ -1 +1 @@ -20d7f9508b49fe602c23b294cfb7c4f440fa6ccedb839c828b9f372603ae3523 +aa2899068465d2c2d10206c800661b7f446b59ad5797c69862e55099549fccd7 diff --git a/verify/check.mjs b/verify/check.mjs index f715552..7266c8d 100644 --- a/verify/check.mjs +++ b/verify/check.mjs @@ -316,6 +316,11 @@ const CHECKS = { // is remembered as if the menu had been used. A name the model does not know is ignored, // and a list naming no kind at all is ignored whole. await page.goto(BASE + spec.path + "?kinds=" + kindOff.toLowerCase() + ",nosuchkind"); + // The ledger is built from a fetch, not from a block the page carries, so a goto resolves + // before there is anything to read. Every assertion below reads state the page writes after + // that fetch lands; without this wait they read the page as it was a moment earlier, which + // fails as a filter that reads "All kinds" about one in several runs. + await page.waitForFunction(() => document.querySelectorAll("#ledger details").length > 0); const linked = await page.evaluate((kind) => ({ hidden: [...document.querySelectorAll("#ledger li.k-" + kind.toLowerCase())].filter(li => li.hidden).length, others: [...document.querySelectorAll("#ledger li:has(details)")].filter(li => !li.classList.contains("k-" + kind.toLowerCase()) && !li.hidden).length, @@ -327,6 +332,7 @@ const CHECKS = { if (linked.search) return `the address still carries ${linked.search}`; if (!linked.stored || linked.stored[kindOff] !== true || Object.keys(linked.stored).some(k => k !== kindOff && linked.stored[k])) return `?kinds=${kindOff} was not remembered: ${JSON.stringify(linked.stored)}`; await page.goto(BASE + spec.path + "?kinds=nosuchkind"); + await page.waitForFunction(() => document.querySelectorAll("#ledger details").length > 0); const ignored = await page.evaluate(() => ({ hidden: [...document.querySelectorAll("#ledger li:has(details)")].filter(li => li.hidden).length, label: document.getElementById("kindslabel").textContent })); if (ignored.label !== kindOff) return `?kinds naming no kind changed the selection to ${JSON.stringify(ignored.label)}`; // Leave the page as it was found — at rest, every kind on, no row open — for whatever