Repository navigation
docs(spec): the protocol upgrade guide's public address is one docs-site page per protocol major; docs/protocol-upgrade-guide.md becomes a pointer stub (#22449 B′, condition 2) - #22556
Merged
objectstack-fleet[bot] merged 14 commits intoOct 10, 2026
Conversation
Claude-Session: https://claude.ai/code/session_01VZqqwTj2wsihZEbfT6yyYN Co-authored-by: Claude <noreply@anthropic.com>
…e per major; docs/protocol-upgrade-guide.md becomes a pointer stub Claude-Session: https://claude.ai/code/session_01VZqqwTj2wsihZEbfT6yyYN Co-authored-by: Claude <noreply@anthropic.com>
…grade-guide-address
…regen merge step took from main The merge took origin/main's side of docs/protocol-upgrade-guide.md because both sides changed it; on this branch the file is a hand-written stub, so its bytes come back from 278751d. Claude-Session: https://claude.ai/code/session_01VZqqwTj2wsihZEbfT6yyYN Co-authored-by: Claude <noreply@anthropic.com>
…grade-guide-address
…ond os-regen merge took from main Claude-Session: https://claude.ai/code/session_01VZqqwTj2wsihZEbfT6yyYN Co-authored-by: Claude <noreply@anthropic.com>
Contributor
📓 Docs Drift CheckNothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs. What this run could not see
Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
…s generator's docs pages are an untracked NOT_DRIVER_MANAGED entry docs/protocol-upgrade-guide.md is a hand-written pointer stub that nothing generates, so the driver's "defer and regenerate" would keep one side whole with no generator to restore the other. Drop its .gitattributes route and correct the header prose that still called it a generated single file; move gen:upgrade-guide's disposition to NOT_DRIVER_MANAGED as the gitignored content/docs/protocol-upgrade/** pages it writes. spec-changes.json keeps its route. Claude-Session: https://claude.ai/code/session_01VZqqwTj2wsihZEbfT6yyYN Co-authored-by: Claude <noreply@anthropic.com>
…ide's removed route A merge made from a checkout carrying the new .gitattributes conflicts on the stub. A branch forked before this change still defers the guide on its first merge of main, because git reads routes from the merging checkout; the merged tree has no row to discharge the deferral against, so the next commit and the push are refused where, with the route, they passed and the stub was lost. Claude-Session: https://claude.ai/code/session_01VZqqwTj2wsihZEbfT6yyYN Co-authored-by: Claude <noreply@anthropic.com>
…regenerated guide and is kept With the guide's merge=os-regen route gone, main's regeneration (20e7d52, +3 lines) conflicted on docs/protocol-upgrade-guide.md instead of being deferred; resolved to the stub (blob 9473b0f, unchanged). Claude-Session: https://claude.ai/code/session_01VZqqwTj2wsihZEbfT6yyYN Co-authored-by: Claude <noreply@anthropic.com>
This was referenced Oct 10, 2026
…he gate already skips references content/docs/protocol-upgrade/ is the upgrade guide's docs pages, written by gen:upgrade-guide from the ADR-0087 registries and gitignored. Its fix site is the registry .ts, which this markdown gate cannot reach, the same reason content/docs/references/ is skipped. CI never generates the pages, so reading them made a local run judge a tree CI never sees: after a docs build the gate reported 99 NEW uses (17.md 56, 18.md 43) while CI was green on the same commit. The self-test's existence pin now accepts an untracked tree that the register of untracked generator output (NOT_DRIVER_MANAGED in regen-artifacts.mjs) declares, and a new case requires every such tree under a ROOT to be skipped. A new program-level battery runs the gate over a fixture page inside each skipped tree (exit 0, nothing read), the same page one level up (NEW use, exit 1), and in a sibling directory sharing the prefix (NEW use, exit 1). Claude-Session: https://claude.ai/code/session_01VZqqwTj2wsihZEbfT6yyYN Co-authored-by: Claude <noreply@anthropic.com>
…kipped, not the set itself The ablation (drop content/docs/protocol-upgrade from SKIP_SUBTREES, pages on disk) left the walk case green: it read the mutated set to decide which pages the walk must not reach, so it could not see the dropped entry. It now judges against SKIP_SUBTREES plus the register's untracked trees under a ROOT, the same union the program-level legs build from. Claude-Session: https://claude.ai/code/session_01VZqqwTj2wsihZEbfT6yyYN Co-authored-by: Claude <noreply@anthropic.com>
…ress One conflict, docs/protocol-upgrade-guide.md: main's 3e72f93 regenerated the committed guide the old way, and this branch turns that file into a hand-written pointer stub (its merge=os-regen route is removed here). Resolved to this branch's stub, blob 9473b0f, byte-identical to 7bc190c's. Every other path merged without conflict. Claude-Session: https://claude.ai/code/session_01VZqqwTj2wsihZEbfT6yyYN Co-authored-by: Claude <noreply@anthropic.com>
objectstack-fleet
Bot
deleted the
claude/issue-22483-upgrade-guide-address
branch
October 10, 2026 05:38
This was referenced Oct 10, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #22483
Clause-②: no
The protocol upgrade guide now has a public address: the docs site, one page per protocol major, at
https://objectstack.ai/docs/protocol-upgrade/MAJOR, with an index athttps://objectstack.ai/docs/protocol-upgrade. The pages are generated at docs build from the ADR-0087 registries and never committed.docs/protocol-upgrade-guide.mdstays at its path as a short, hand-written pointer stub naming that address. That is condition (2) of ruling6078203801on #22449 (B′), and the two notes in triage6081410390.The address: the seat's three hypotheses, measured first
unpkg/jsDelivr)H1, measured. The newest spec Release,
@objectstack/spec@17.7.0, carries one asset,spec-changes.json, athttps://github.com/objectstack-ai/objectstack/releases/download/%40objectstack/spec%4017.7.0/spec-changes.json(302 to the asset store, no auth). One URL per VERSION.releases/latestanswers 302 toreleases/tag/@objectstack/verify@17.7.0, another package's Release.releases/latest/download/spec-changes.jsonredirects to.../download/@objectstack/verify@17.7.0/spec-changes.json, which is 404. So no GitHub URL resolves to "the newest spec release of a major". Also, no Release carries the guide yet: the 17.7.0 tarball holdsspec-changes.jsonand no guide, because the publish lane from #22533 landed after it.H2, measured.
The build can run a spec script.
apps/docs'sbuildalready runs@objectstack/spec'sgen:schemaandgen:docsbeforenext build. Vercel runspnpm turbo run build --filter=@objectstack/docs(apps/docs/vercel.json), and CI'sBuild Docsevaluates that same string. This PR addsgen:upgrade-guideto that chain.The URLs.
SITE_ORIGINishttps://objectstack.ai(apps/docs/lib/site.ts) and the docsbaseUrlis/docs(apps/docs/lib/source.ts). So the pages are/docs/protocol-upgrade,/docs/protocol-upgrade/17and/docs/protocol-upgrade/18.The build sees unreleased majors.
maincarriesPROTOCOL_VERSION18.0.0whilepackages/spec/package.jsonsays17.7.0. npm'slatestis17.7.0, whose tarball carries protocol17.0.0(read from itsdist). So the 17 → 18 hop is unreleased, and the docs site builds frommain.Choice: mark, never hide. Every page carries one state line, judged from the tree's own
@objectstack/specversion under the lockstep contract insrc/kernel/protocol-version.ts:Every page also says it is generated from
main, ahead of the release that ships a newly landed entry. Why mark rather than hide:objectstack migrate metaalready replays the chain up to the highest registered major, so the page shows what the tool prints.18.0.0-next.Nline (.changeset/22080-v18-line-opens.md) has readers, and hiding the page would leave them no address.The local build, with and without the pages. Same box, one run each,
rm -rf .nextbefore each. Each run was under the verify lock, but unlocked sibling work was running beside it:next buildexitnext-buildRSSSo the pages add no measurable peak memory: noise between the two runs is larger than the effect. Rendered sizes:
protocol-upgrade/18.html3.48 MB,17.html1.20 MB, the index 235 KB. The sidebar shows "Protocol Upgrade Guide" after "Upgrading".Login-free. The site is public. A live probe of
objectstack.aiis NOT MEASURED: this container's proxy refuses CONNECT to that host (403).H3, measured. Not chosen: the ruling names two options and this one is outside them. It also does not key by protocol major:
npm view @objectstack/spec@18 versionanswersE404 No match found for version 18, because protocol 18 ships as18.0.0-next.Nand a bare@18range never matches a prerelease.@17resolves to17.7.0, which carries no guide, and pre mode cuts no further 17.x. Live CDN reachability is NOT MEASURED: the proxy refuses CONNECT tounpkg.comandcdn.jsdelivr.net(403).What changed
packages/spec/scripts/build-upgrade-guide.ts:build()is split into section renderers:howToUpgrade,hopSectionandfooter;--outwrites is byte-identical to before, except its second header comment. That comment now names the command that writes the file (exec tsx scripts/build-upgrade-guide.ts --out FILE), becausegen:upgrade-guideno longer does. Measured:diffof the base's and this branch's--outoutput is that one line.gen:upgrade-guide) now writes the docs pages intocontent/docs/protocol-upgrade/, neverdocs/protocol-upgrade-guide.md, so the stub cannot be overwritten.--docs DIRwrites them elsewhere.--checkand--outare unchanged.packages/spec/scripts/lib/upgrade-guide-docs.ts(new) assembles the tree:index.md, oneMAJOR.mdper hop the chain carries, and ameta.jsonlisting them newest first.apps/docs/package.json:buildrunsgen:upgrade-guidebeforenext build.content/docs/meta.json:protocol-upgradeis listed afterupgrading. When the folder is absent (a checkout that has not run the docs build), fumadocs skips the entry. Measured infumadocs-core'sresolveFolderItem: an item that resolves to no node returns without one..gitignore:content/docs/protocol-upgrade/.docs/protocol-upgrade-guide.md: the stub. It names the index, one line per major today (17 and 18), and the pattern for the next one. It also says where a release's shipped copy lives, and how to generate either form.packages/spec/scripts/check-generated.ts: thecheck:upgrade-guiderow names the docs pages as its artifact.packages/spec/scripts/lib/projection-cli.ts:committedPathis optional. The guide no longer has a committed copy, so its runner passes none. A bare run without one is a usage error (exit 2) that builds nothing..gitattributes/scripts/regen-artifacts.mjs(seat answer6092165230, option B): the guide'smerge=os-regenroute and itsREGEN_ARTIFACTSrow are removed.gen:upgrade-guideis recorded asNOT_DRIVER_MANAGEDforcontent/docs/protocol-upgrade/**(untracked). The header prose no longer calls the guide a generated single file. Thespec-changes.jsonroute stays for spec(changes): delete the committed spec-changes per-major projection and the upgrade guide copy, with their two merge=os-regen routes, once generation at publish has landed (#22449 B′) #22485.scripts/check-role-word.mjs(seat answer6093145489, Q2 → A):content/docs/protocol-upgradeis inSKIP_SUBTREES, for the reasoncontent/docs/referencesis: generated prose whose fix site, the registry.ts, this markdown gate cannot reach.NOT_DRIVER_MANAGEDdeclares where it required one on disk, and it requires every such tree under a ROOT to be skipped.content/docs/build-without-code.mdxstill exits 1, the only problem reported..changeset/22483-upgrade-guide-docs-address.md:@objectstack/specpatch. The shippedprotocol-upgrade-guide.mdchanges by its header comment, and the address is user-facing news.apps/docsis private.Every published pointer, with its resolves check
Every pointer spells the repo path
docs/protocol-upgrade-guide.mdas text, never as a URL (git grep -oover the tree: 71 baredocs/protocol-upgrade-guide.mdspellings, nogithub.com,raw.githubusercontent.comorobjectstack.aiform). The check is the same for each:https://objectstack.ai/docs/protocol-upgrade;On GitHub,
blob/claude/issue-22483-upgrade-guide-address/docs/protocol-upgrade-guide.mdand itsraw.githubusercontent.comform both answer 200, and the fetched bytes name the address 4 times.packages/client/README.md· 1 ·:141(citesbatch-options-validate-only-retired)files[]hasREADME.md)/docs/protocol-upgrade/17; that id is on the 17 page (3 hits in the built17.html)packages/cli/CHANGELOG.md· 3 ·:14221packages/client/CHANGELOG.md· 4 ·:5655packages/core/CHANGELOG.md· 1 ·:2013packages/create-objectstack/CHANGELOG.md· 1 ·:1544packages/metadata-protocol/CHANGELOG.md· 2 ·:14511packages/runtime/CHANGELOG.md· 3 ·:10073packages/services/service-automation/CHANGELOG.md· 2 ·:9260packages/services/service-package/CHANGELOG.md· 1 ·:3432packages/spec/CHANGELOG.md· 41 ·:1825protocol-upgrade-guide.md, the in-package file, which still shipspackages/spec/src/migrations/entries/README.md· 1 ·:99files[]shipssrc/**/*.zod.tsonly)These are the eleven of the ruling: ten shipped files plus the entries README. No CHANGELOG is edited. The in-repo, unpublished mentions keep resolving through the same stub: ADR-0087
:348,docs/audits/2026-08-partial-retirement-annotation-signal.md:94, the #22482 changeset, and scripts.File surface
Inside the claim: the stub,
build-upgrade-guide.tsand its tests, the docs wiring that generates the address (apps/docs/package.json,content/docs/meta.json,.gitignore),check-generated.ts's row (named by the dispatch), and one changeset.Beyond it, each named here:
scripts/check-future-spec-major.mjs: deleted oneQUOTATION_EXEMPTIONSrow. This was forced: with the stub in place the gate went red,QUOTATION_EXEMPTIONS entry 6 (docs/protocol-upgrade-guide.md, major 4997) matched NOTHING … Re-point it or delete it.The row excused the generated copy of one entry's evidence sentence, and the stub no longer carries it. After the deletion the gate reads7 witnessed ledger entr(y|ies), every witness still matching, and--self-testreports 29 cases.packages/spec/scripts/lib/projection-cli.ts: the optionalcommittedPathabove. This is the no-flag contract ofbuild-upgrade-guide.ts's default write target, the item the claim names.packages/spec/scripts/lib/upgrade-guide-docs.tsandupgrade-guide-docs.test.ts: new files in the same scripts tree..gitattributes(the guide's route line, and the header prose from:20) andscripts/regen-artifacts.mjs(the row moves toNOT_DRIVER_MANAGED), per seat answer6092165230.scripts/check-role-word.mjs(seat answer6093145489): a local docs build made the gate report 99 NEW uses (17.md 56, 18.md 43) that CI never saw, because the tree is gitignored.Removed here (seat answer
6092165230, option B)..gitattributesdrops the guide's route, and its header no longer calls the guide a generated single file.regen-artifacts.mjsdrops the row and recordsgen:upgrade-guideasNOT_DRIVER_MANAGEDcontent/docs/protocol-upgrade/**(untracked).check:merge-driverreads 17 routed paths, 42 generators with a disposition, and 4 untracked dispositions. Thespec-changes.jsonroute stays for #22485.Why it went here: the route was actively wrong for a hand-written file. Before the removal,
scripts/pm/os-regen-merge.shtwice put main's generated guide back over the stub (bd5a3284d0), and the stub was restored by blob (9473b0f21f). The scratch merge after the removal measured three cases:8f4ae58944), the same merge was silent.git mergeofmain. Its next commit and push are then refused, where with the route they passed and the stub was lost. So no direction stays silent.mainatbf6942b723conflicted on the stub and kept it.Verification
All at
7bc190c714unless a line says otherwise. The last merge oforigin/mainisbf6942b723, which brought in96e4be4829, whose20e7d52097regenerated the guide; it conflicted on the stub, which was kept (blob9473b0f21f).origin/mainhas stayed at99801d831fsince, and GitHub reports the PR mergeable.scripts/pm/os-verify-lock.sh, VERDICT command-exit 0:87a9a3435e:vitest run --project local --maxWorkers=2: 636 files passed, 18970 tests passed, 1 todo;87a9a3435e:--project repo: 54 files, 915 tests passed;bf6942b723:build-schemas-check-mode.test.ts(repo project) 88/88;7bc190c714: the five generator and ledger test files, 50/50.pnpm --filter @objectstack/spec typecheck: VERDICT command-exit 0.tsc -p tsconfig.scripts.json --listFileslists all five touched or new script files, tests included.upgrade-guide-docs.test.ts(15) andprojection-cli.test.ts(12, one new), 27 of 27 passing. The real-generator block proves three things:--docsis deterministic;--docswith--check, with--out, or with no directory exits 2 and writes nothing;node scripts/pm/dispatch-gates.mjs --commandsderived 128 at7bc190c714. All ran with the gitignored docs pages on disk (gen:upgrade-guidefirst), and--ranreports 128 derived, 128 run, 0 NOT-MEASURED, 0 UNRUN. All 128 exit 0,check:role-wordincluded. Without the pages (CI's tree)check:role-wordalso exits 0, and it reads 254 files either way. Among them:check:generated("All 15 generated artifacts are up to date"),check:upgrade-guide,check:spec-changes,check:future-spec-major,check:merge-driver,check:cross-package-test-inputs,check:doc-frontmatter,check:nul-bytesandcheck:pm-dispatch-gates.scripts/regen-artifacts.mjsandscripts/check-role-word.mjs), measured at7bc190c714, all matched byeslint.config.mjs's**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}object.--no-inline-config --format jsonreports 9 files, 0 errors and 0 warnings.parserOptions.project, so no type-aware rule can move a verdict on a file this diff does not touch.pnpm lintis CI's.apps/docspnpm build(gen chain plusnext build), exit 0, at278751de7a(this PR's content, before the merge). See H2.pnpm turbo run build --concurrency=2gave 73/73 tasks with@objectstack/docs#buildatbf6942b723(6m23s), and 73/73, all cached, at7bc190c714.Acceptance notes
6093148255). A branch forked before this PR that carries a regenerated guide defers it at its first plaingit mergeofmain. Its next commit and push are then refused bycheck-regen-pending.mjs, with a remedy that cannot apply: "absent from scripts/regen-artifacts.mjs (cannot verify)". Restoring the stub does not clear it; deleting the pending marker by hand does. spec(changes): delete the committed spec-changes per-major projection and the upgrade guide copy, with their two merge=os-regen routes, once generation at publish has landed (#22449 B′) #22485's route removal creates the same state forspec-changes.json.40735ea58d, docs(adr): ADR-0087 D4 and its P2 true-up record ruling B′ — the two projections are generated at publish, not committed (#22449) #22561) still says the guide's route goes in spec(changes): delete the committed spec-changes per-major projection and the upgrade guide copy, with their two merge=os-regen routes, once generation at publish has landed (#22449 B′) #22485 and thatgen:upgrade-guidewrites the committed copy. Per seat answer6093145489(Q3 → A), spec(changes): delete the committed spec-changes per-major projection and the upgrade guide copy, with their two merge=os-regen routes, once generation at publish has landed (#22449 B′) #22485 corrects it in its governed ADR edit.docspath filter (ci.yml) does not listpackages/spec/**. So a registry entry whose prose the docs build cannot compile would surface in Vercel's production build, not inBuild Docs. The pages are.md(CommonMark, no JSX), which parses arbitrary text, andgen:docshas the same pre-existing exposure.('field', OBJECT.NAME)with the two names in angle brackets. A Markdown renderer reads those as HTML. That is a property of the registry text, not of this change, and its rendering on the site is not measured here.Generated by Claude Code