Repository navigation
fix(spec): render-projection-diff generates a base's git-ignored migration registry - #22750
Merged
objectstack-fleet[bot] merged 1 commit intoOct 11, 2026
Conversation
…ation registry Since the migration registry left git, a git archive of a base at or after that change carries only registry.ts.template and entries/, so both base projection generators died on a missing ../src/migrations/registry module and the "Render the generated spec-changes and upgrade-guide diff" step went red on every merge-queue entry. realMaterializeBase now runs the base's own build-migration-registry.ts in the base tree when the archive has the generator but not the registry. A base that committed the registry is untouched; a generator that fails, or exits 0 without writing, reds the base side with its output. Claude-Session: https://claude.ai/code/session_01S3aAf11JjbW1mSGL1EhfFj 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): |
This was referenced Oct 11, 2026
marchtian
pushed a commit
that referenced
this pull request
Oct 11, 2026
…migration registry Byte-identical to that PR's head 2a4ccb4 for render-projection-diff.ts and its test; a no-op once main carries it. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AGgRrdom7nizSbHc5Gws2U
This was referenced Oct 11, 2026
This was referenced Oct 11, 2026
objectstack-fleet
Bot
deleted the
claude/issue-22744-projection-diff-base-registry
branch
October 11, 2026 02:15
This was referenced Oct 11, 2026
This was referenced Oct 11, 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 #22744
Clause-②: no
What
Type Check · source gatesrunsrender-projection-diff.ts --base HEAD^1, which generates the two ADR-0087 projections inside agit archiveof the base. Since the migration registry became git-ignored and generated (ruling B on #22554, landed ased1de8c2db), that archive carries onlyregistry.ts.templateandentries/, so both base generators die onCannot find module '../src/migrations/registry'. Every merge-queue entry built on a base at or aftered1de8c2dbfails this step.realMaterializeBasenow calls a newgenerateBaseRegistry(specDir)after the unpack and thenode_modulessymlinks:scripts/build-migration-registry.ts- the BASE's own generator runs with this checkout'stsx, cwd the basepackages/spec. It resolves its package root from its own path, so it writes the base's registry from the base's template and entries (its built-in self-test runs first, as on every generation);renderProjectionDiffreports as a red base side with the generator's output.The registry file is regenerated, never committed; ruling B is untouched. The diff stays within the claimed surface:
render-projection-diff.ts(+48 -3) andrender-projection-diff.test.ts(+110 -0).Evidence: the real step, before and after
Both runs are from this worktree, against base
ed1de8c2db, whose archive listspackages/spec/src/migrations/registry.ts.templateand noregistry.ts.Before, with
origin/main's script (ed1de8c2db, no edit),tsx scripts/render-projection-diff.ts --base ed1de8c2db --out-dir ...gave exit 1:After, with this branch (
2a4ccb4878), the step exactly aslint.ymlspells it (--base HEAD^1, so HEAD^1 =ed1de8c2db) gave exit 0:--base f59a73c395(its archive carries a committedregistry.ts) gave exit 0,✓ neither projection changes against f59a73c395. The generator is skipped there.git archiveofed1de8c2db: exit 0,build-migration-registry --self-test: ok,✓ wrote src/migrations/registry.ts (419 semantic, 258 retired-key, 222 retired-def).cmpagainst this checkout's generated registry shows the two are byte-identical.Tests
render-projection-diff.test.tsgets five new cases. They use the file's existing injection seam: aRunScriptrunner passed togenerateBaseRegistry, plusmaterializeBasefor the end-to-end case.packages/spec.renderProjectionDiff: a base whose registry cannot be generated is RED and named as the base.tsx, runs a stand-in generator by its own path with the base package as cwd.Results:
pnpm --filter @objectstack/spec exec vitest run --project local --maxWorkers=2 scripts/render-projection-diff.test.ts:Tests 14 passed (14)(9 existing + 5 new).pnpm --filter @objectstack/spec run typecheck: exit 0.check:scripts-typecheck(tsconfig.scripts.json) compiles both touched files;--listFilesnames both.Ablations (from committed
2a4ccb4878, viascripts/ablation-replace.mjs, restore proven blob == HEAD)generateBaseRegistryreplaced by a no-op result:Tests 4 failed | 10 passed (14). The four that fail are cases 1, 3, 4 and 5. Case 2 stays green, as expected, because it asserts that nothing runs.generateBaseRegistry(specDir);call deleted fromrealMaterializeBase, then the real step run againsted1de8c2db: exit 1 with the sameCannot find module '../src/migrations/registry'for both projections.realMaterializeBaseis not exported and has no unit pin of its own. Its wiring is pinned end to end by this very CI step, which materialisesHEAD^1on every pull request, and every such base now lacks the registry.Gates
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, derived in this worktree at2a4ccb4878(2 paths against merge baseed1de8c2d), lists 59 commands. That is the same list the dispatch carried.All 59 ran at
2a4ccb4878(the final commit), each exit code captured before any pipe:node scripts/check-adr-0087-registration.mjs --base origin/mainand--self-test,pnpm check:nul-bytes,pnpm check:test-source-alias,pnpm check:cross-package-test-inputs,pnpm check:type-check-coverageandpnpm check:type-check-debt.PREREQUISITE NOT MET:pnpm check:dts-closure,pnpm check:dual-build-cjs-loads,pnpm check:lean-entry-closureandpnpm check:sourcemap-no-sources-content. Each reads the builtdist/of the whole workspace, and this worktree has no workspace build. This narrowing is declared, and CI runs all four. The diff changes no build input:scripts/is in no tsup entry, and nosrc/file imports it.dispatch-gates --ran, with the exit-coded record, reports:59 derived famil(ies) accounted for — 55 run, 4 NOT-MEASURED (4 DERIVED from a recorded exit 3).Lint is a narrowed run, measured rather than skipped.
eslint --no-inline-config --format jsonover the two touched files reports 2 files linted, 0 errors and 0 warnings.eslint --print-configgives parserOptions{"ecmaVersion":"latest","sourceType":"module"}, with noproject. Type-aware linting is therefore off, so this diff cannot move a verdict on any untouched file. The repo-widepnpm lintis left to CI.Other
git archive/ base-tree readers ofpackages/specgit grepoverscripts/,packages/*/scripts,.github/andpackages/specfinds three more archive call sites. None breaks the same way:scripts/check-adr-0087-registration.mjsgeneratedWitness(the archive at:2089). The change that made the registry git-ignored already adapted it: when the template is tracked it runs the rev's own registry generator, and a template with no generator is red. Measured: callinggeneratedWitness({ cwd, head: 'HEAD' })at2a4ccb4878, whose archive has noregistry.ts, returnsproblem: nulland a parsed manifest with 2perMajorrecords.scripts/check-merged-result.mjs: a generic merged-tree probe for budget gates. It runs no spec generator.scripts/objectui-changeset-digest.mjs:2304: a self-test sandbox that writes its own fixtureregistry.ts.Changeset
None,
skip-changesetroute.packages/spec'sfiles[](dist,json-schema,liveness,prompts,llms.txt,README.md,src/**/*.zod.ts,CHANGELOG.md,api-surface,spec-changes.json,protocol-upgrade-guide.md) does not includescripts/, and nosrc/file importsrender-projection-diff. Measured on a built spec tree (03181fc07b):grep -rlforrenderProjectionDiff,SUMMARY_DIFF_CAPandspec-projections-diffover everyfiles[]path found 0 files; the positive controlMIGRATIONS_BY_MAJORindistwas found in 4 files.Acceptance notes
realMaterializeBasestays unexported. The new logic lives in the exportedgenerateBaseRegistry, which is what the unit cases pin. Exporting the materialiser would need a git-history fixture, which this file's header deliberately avoids.main, the walled queue entries (fix(metadata-protocol,service-analytics)!: a read that follows a lookup asks the target object its declared exposure — $expand and the dataset label passes (#22661) #22735, fix(core): an import row for a sandboxed body the door answers as a fault reads as that fault #22740 and any other dequeued entry) need a new merge-group run to pick it up. A rerun of an old run reuses its old merge ref.Generated by Claude Code