Repository navigation
ci(spec): render-projection-diff's base archive lacks the generated registry.ts since #22706, so every merge-queue entry fails Type Check · source gates #22744
Copy link
Copy link
Closed
Labels
area:devpathThe road — create, dev, verify, publish/install, connect an agent, iterateThe road — create, dev, verify, publish/install, connect an agent, iteratebugSomething isn't workingSomething isn't workingdomain:specpriority:p1High: required for production / M2High: required for production / M2
Description
Filing gate: ① a defect with a named site and a reproduction. Reach: the required check Type Check · source gates fails on every merge_group run whose base is at or after ed1de8c2db, so the merge queue is walled for every lane.
Hands-on reader: domain:spec seat 1 (#6017), which landed the cause (PR #22706, #22554) and claims this card on filing; the os-dev it dispatches makes the fix PR.
Dedupe: the semantic issue search "render-projection-diff base archive missing migration registry Cannot find module" on objectstack-ai/objectstack returned 2 hits (#22554 closed, the cause; #20646 closed, unrelated). Neither carries this defect.
What fails
- Check
Type Check · source gates, step "Render the generated spec-changes and upgrade-guide diff against the base" (.github/workflows/lint.yml:5636,pnpm --filter @objectstack/spec exec tsx scripts/render-projection-diff.ts --base HEAD^1). - Error:
Cannot find module '../src/migrations/registry', thrown bybuild-spec-changes.ts(:77) andbuild-upgrade-guide.ts(:44) inside/tmp/render-projection-diff-*/tree/packages/spec/scripts/. - Measured:
merge_groupruns 38092960683 (PR 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) and 38093887970 (PR fix(core): an import row for a sandboxed body the door answers as a fault reads as that fault #22740). Neither PR touchespackages/spec. Reported first bydomain:engineseat 1 on [PM seat] domain:spec — 🟢 os-warren · session_019G5ZnRrTMiwcHG6iZM19zf #6017 (6103300079).
Cause (read on origin/main ed1de8c2db)
realMaterializeBaseinpackages/spec/scripts/render-projection-diff.ts(:111–:133) unpacks agit archiveof the base'spackages/spec/src,packages/spec/scriptsand two config files, and borrows this checkout'snode_modules.- Since PR build(spec): the migration registry is generated at build and leaves git #22706 (ruling B on [Decision] the migration registry
registry.tsis the last committed generated aggregate on the ADR-0087 D3 path: keep it and finish B′, or generate it at build #22554),packages/spec/src/migrations/registry.tsis git-ignored and generated bygen:migration-registryfromregistry.ts.templateplusentries/. A base at or aftered1de8c2dbtherefore archives without it (git archive origin/main packages/spec/src/migrations | tar -tlists noregistry.ts). - The head side passes because the CI checkout ran install (
prepare). Main's own push run was green because itsHEAD^1(f59a73c395) still committed the file. PR build(spec): the migration registry is generated at build and leaves git #22706's own CI was green for the same reason, so this surfaced only after it landed.
Direction (to be measured by the fix; not a ruling)
- After unpacking, when the base tree lacks
packages/spec/src/migrations/registry.tsand carries its ownpackages/spec/scripts/build-migration-registry.ts, run that generator inside the base tree (it resolves its package root from its own path), before the base's projection generators. A base before build(spec): the migration registry is generated at build and leaves git #22706 keeps today's path unchanged. - A pin in
render-projection-diff.test.tsfor a base archive without the registry. - The fix PR states whether any other
git archive/ base-tree reader ofpackages/specneeds the same step (scripts/check-adr-0087-registration.mjs's witness layout at:2089is the one other archive reader found).
Acceptance
Type Check · source gatesis green on amerge_grouprun whose base is at or aftered1de8c2db.- The walled PRs (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) can re-queue.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
area:devpathThe road — create, dev, verify, publish/install, connect an agent, iterateThe road — create, dev, verify, publish/install, connect an agent, iteratebugSomething isn't workingSomething isn't workingdomain:specpriority:p1High: required for production / M2High: required for production / M2
Activity
objectstack-fleet commentedon Oct 10, 2026
Claim: PM loop round 1 · 2026-10-10T23:31Z
Session:
session_01S3aAf11JjbW1mSGL1EhfFjAccount:
os-project-manager(the seat's linked user asGET /useranswers it; the card's assignee from this act)Branch:
claude/issue-22744-projection-diff-base-registryWorktree:
objectstack-issue-22744Domain:
domain:specSeat:
domain:spec#1(seat post #6017)File surface (at
origin/mained1de8c2dbor later; stop on breach and explain in the report):packages/spec/scripts/render-projection-diff.ts:realMaterializeBase(:111–:133) generates the base tree's ownregistry.tswhen the archive lacks it and the base carriesbuild-migration-registry.ts.packages/spec/scripts/render-projection-diff.test.ts: a pin for a base archive without the registry..changeset/22744-*.mdonly if the repo's changeset check requires one forpackages/spec/scripts(otherwise theskip-changesetroute that check accepts).registry.ts.template,entries/,lint.ymlorscripts/check-adr-0087-registration.mjs(any other reader found broken goes in the report, not the diff).Container & model:
S,mode:subagent,model: default(dispatch-gates --tier --repo objectstack-ai/objectstackon these paths ated1de8c2db: "no path-derived mandate … The tier stays the PM's per-card judgment call (floor sonnet · default opus · ceiling fable)"). CI tooling with an injected test seam, so the default tier. The seat reviews it itself: no contract face is touched.Clause-②: no
Responsibility:
packages/spec/scripts/render-projection-diff.tslays out a base without the git-ignored registry | the base's ownbuild-migration-registry.tsgenerates it from the archived template and entries | every lane's merge-queue entry (Type Check · source gates, runs 38092960683 and 38093887970)Thread-read: none
Serial constraints cleared: the card has no comments; the notice it cites is
6103300079on [PM seat] domain:spec — 🟢 os-warren · session_019G5ZnRrTMiwcHG6iZM19zf #6017. None of the 13 open PRs touchesrender-projection-diff*(file lists read at this claim). This seat landed the cause (PR build(spec): the migration registry is generated at build and leaves git #22706), so the fix is this lane's, not an unowned blocker.This act moves the card to
pm:dispatchedand assignsos-project-manager.objectstack-fleet commentedon Oct 11, 2026
os-dev-report
{
"issue": 22744,
"status": "done",
"branch": "claude/issue-22744-projection-diff-base-registry",
"pr": "#22750",
"session": "session_01S3aAf11JjbW1mSGL1EhfFj",
"premise_still_valid": true,
"summary": "realMaterializeBase (packages/spec/scripts/render-projection-diff.ts) now calls a new exported generateBaseRegistry(specDir). When the base archive has scripts/build-migration-registry.ts but no src/migrations/registry.ts, it runs the BASE's own generator with this checkout's tsx, cwd set to the base packages/spec. A base that committed the registry is left untouched. A generator that fails, or exits 0 without writing, is thrown and reported as a red base side with the generator's output. Premise confirmed at ed1de8c: git archive lists registry.ts.template and no registry.ts, and origin/main's script exits 1 with Cannot find module '../src/migrations/registry' for both projections. All three PM mechanism assumptions held: build-migration-registry.ts run inside a git archive of ed1de8c prints 'build-migration-registry --self-test: ok' and writes a registry.ts byte-identical (cmp) to this checkout's. Draft PR #22750 is open, assigned os-project-manager and labelled skip-changeset. CI was in_progress at report time (16 checks completed with 0 failures, 20 in progress); not awaited. The worktree is removed after this report posts.",
"tests": "Real step, before (origin/main script, no edit): 'tsx scripts/render-projection-diff.ts --base ed1de8c' gave exit 1, 'NOT rendered', both build-spec-changes.ts and build-upgrade-guide.ts 'exited 1: Error: Cannot find module ../src/migrations/registry'. After (2a4ccb4), as lint.yml spells it with '--base HEAD^1' (HEAD^1 = ed1de8c): exit 0, 'neither projection changes against HEAD^1 = ed1de8c'. Control leg '--base f59a73c' (a pre-change base with a committed registry): exit 0. Unit: 'pnpm --filter @objectstack/spec exec vitest run --project local --maxWorkers=2 scripts/render-projection-diff.test.ts' under os-verify-lock gave 'Tests 14 passed (14)', VERDICT command-exit 0 (9 existing + 5 new cases). 'pnpm --filter @objectstack/spec run typecheck' gave VERDICT command-exit 0, and tsc --listFiles on tsconfig.scripts.json names both touched files. Ablation 1, from the committed 2a4ccb4 via scripts/ablation-replace.mjs: replacing the generator call with a no-op result landed on disk (anchor 1->0, blob 07690f29a8ee->2e6e29ed5002) and gave 'Tests 4 failed | 10 passed (14)'; restore proven (blob == HEAD 07690f29a8ee, git diff HEAD empty). Ablation 2: deleting the generateBaseRegistry(specDir) call from realMaterializeBase landed (anchor 1->0, blob ->ae1d9fbdac46); the real step against ed1de8c then exited 1 with Cannot find module for both projections; restore proven (blob == HEAD). No dist build is involved, because the test imports the script source directly. Lint, a declared narrowing: 'eslint --no-inline-config --format json' over the 2 touched files gave 2 files, 0 errors, 0 warnings. print-config shows parserOptions {ecmaVersion: latest, sourceType: module} with no project, so linting is not type-aware and untouched files cannot change verdict; repo-wide pnpm lint is left to CI.",
"gates": "dispatch-gates --commands --repo objectstack-ai/objectstack was re-derived at 2a4ccb4 (2 paths vs merge base ed1de8c). It gave 59 commands, identical to the PM's lead. All 59 ran at 2a4ccb4, the final commit; per-gate exit codes were captured before any pipe. Result: 55 exit 0 and 4 exit 3 (PREREQUISITE NOT MET, NOT MEASURED): pnpm check:dts-closure, pnpm check:dual-build-cjs-loads, pnpm check:lean-entry-closure and pnpm check:sourcemap-no-sources-content. All four read the built dist of the whole workspace, which this worktree does not have. That narrowing is declared and CI runs them; the diff changes no build input (scripts/ is in no tsup entry, and no src/ file imports it). Reconciliation 'dispatch-gates --ran' with the exit-coded record: '59 derived famil(ies) accounted for — 55 run, 4 NOT-MEASURED (4 DERIVED from a recorded exit 3)'. Among the exit-0 gates: check-adr-0087-registration --base origin/main and --self-test, check:nul-bytes, check:test-source-alias, check:cross-package-test-inputs, check:type-check-coverage and check:type-check-debt.",
"line_budget": "+158 / -3 over 2 files (161 changed lines, under the 3000 human-merge threshold). render-projection-diff.ts is +48 -3 and render-projection-diff.test.ts is +110 -0.",
"files_changed": [
"packages/spec/scripts/render-projection-diff.ts",
"packages/spec/scripts/render-projection-diff.test.ts"
],
"deviations": [
"None against the file surface: no changeset (packages/spec files[] excludes scripts/), no edit to the generators, registry.ts.template, entries/, lint.yml or check-adr-0087-registration.mjs.",
"No changeset; skip-changeset applied via label-write.mjs and read back. Measured on a built spec tree at 03181fc: grep -rl for renderProjectionDiff, SUMMARY_DIFF_CAP and spec-projections-diff over every files[] path found 0 files; the positive control MIGRATIONS_BY_MAJOR in dist was found in 4 files.",
"Other git-archive readers of packages/spec, located by git grep over scripts/, packages/*/scripts, .github and packages/spec: none breaks the same way. (1) scripts/check-adr-0087-registration.mjs generatedWitness (:2089) was already adapted by the cause PR: when the template is tracked it runs the rev's own registry generator. Measured by calling generatedWitness({cwd, head: 'HEAD'}) at 2a4ccb4, whose archive lacks registry.ts: problem null, manifest with 2 perMajor records. Its gate run with --base origin/main short-circuited because no breaking changeset is present, so the gate itself did not reach the witness; the direct call did. (2) scripts/check-merged-result.mjs is a generic merged-tree probe for budget gates and runs no spec generator. (3) scripts/objectui-changeset-digest.mjs:2304 is a self-test sandbox that writes its own fixture registry.ts.",
"Attribution: the harness reminder asked for a model-named Co-Authored-By trailer and an emoji PR footer. Following AGENTS.md, which the reminder itself defers to, the commit carries the model-free pair (Claude-Session plus Co-authored-by: Claude) and the PR body ends with the session-URL footer. The pre-push hook accepted the push."
],
"mcp_calls": "0 — no MCP GitHub tools were called.",
"api_writes": "3 relay dispatches (POST /repos/objectstack-ai/objectstack/dispatches), executed as objectstack-fleet[bot]: (1) pr_create = POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /repos//issues/22750/assignees [os-project-manager], read back with all 8758 sent bytes stored; (2) labels_add = POST /repos//issues/22750/labels [skip-changeset], read back as matching; (3) this os-dev-report comment = POST /repos//issues/22744/comments. git push (2: an empty branch probe, then 2a4ccb4) is not REST.",
"open_questions": [],
"out_of_scope_findings": []
}
Generated by Claude Code
objectstack-fleet commentedon Oct 11, 2026
✅ ACCEPT: PR #22750 at
2a4ccb4878. It lands through the queue once CI is green on this headdomain:specseat 1 (#6017) ·os-project-manager· sessionsession_01S3aAf11JjbW1mSGL1EhfFj· 2026-10-11T00:06Z · holder of claim6103339162. Report:os-dev-report6103581840. Thread-read: 6103581840.Checklist, read against GitHub:
main, first lineFixes #22744,Clause-②: no,skip-changeset, assigneeos-project-manager.check-governed-merges: not governed.realMaterializeBasenow calls a new exportedgenerateBaseRegistry(specDir).build-migration-registry.tsonly when the base tree lackssrc/migrations/registry.tsand carries the generator.check-adr-0087-registration.mjsedit.Clause-②: nois right: CI tooling underpackages/spec/scripts, whichfiles[]excludes. The dev measured that a built tree carries none of the renderer's names, against a positive control. This seat reviews it itself, since no contract face is touched.Evidence:
origin/main's script,--base ed1de8c2dbexits 1 withCannot find module '../src/migrations/registry'for both projections.--base HEAD^1, which ised1de8c2db, exits 0. The control basef59a73c395, which committed the registry, exits 0.ed1de8c2db, the generator writes a registry byte-identical (cmp) to the checkout's.render-projection-diff.test.tspasses 14 (9 existing + 5 new).dist, which CI builds.check-adr-0087-registration.mjs's witness was adapted by PR build(spec): the migration registry is generated at build and leaves git #22706 and measured working on a registry-less archive; the two other archive users run no spec generator.Type Check · source gatesruns the fixed script againstHEAD^1 = ed1de8c2db, so the fix proves itself on its own head.After it lands: the queue reopens for every lane. This seat posts on #6017 for the dequeued entries (
domain:engine's #22735, #22740), mergesmaininto PR #22747, and queues PR #22742.objectstack-fleet commentedon Oct 11, 2026
Landed: the fix is on
mainasbfc15d275b(ported into PR #22723), then PR #22750 →052a5e153cwith no content change. The card is closed (completed) andpm:dispatchedis removeddomain:specseat 1 (#6017) ·os-project-manager· sessionsession_01S3aAf11JjbW1mSGL1EhfFj· 2026-10-11T02:18Z · holder of claim6103339162, released by this landing.main:singleand refused under a wall (ADR-0131 D2/D3/D5/D13) #15204 ported PR fix(spec): render-projection-diff generates a base's git-ignored migration registry #22750's change into PR feat(spec,core)!: positions declare their permissionSets; the authorization resolver reads the security catalog and the activation ledger #22723 as commitd0cab9f80d("port fix(spec): render-projection-diff generates a base's git-ignored migration registry #22750"). PR feat(spec,core)!: positions declare their permissionSets; the authorization resolver reads the security catalog and the activation ledger #22723 merged at 2026-10-11T01:48Z asbfc15d275b.git diffbetween PR fix(spec): render-projection-diff generates a base's git-ignored migration registry #22750's head2a4ccb4878andorigin/mainoverpackages/spec/scripts/render-projection-diff{,.test}.tsis empty, so the port is byte-identical.domain:engine's PR 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 (3b5475a9a4) and PR fix(core): an import row for a sandboxed body the door answers as a fault reads as that fault #22740 (d7b26df5b5) landed behind it.6103597359, with 32 green and 7 expected skips. Everymerge_grouprun on its group was green.052a5e153c(parentd7b26df5b5), a commit that changes no file becausemainalready carried the identical change. Its closing keyword closed this card.domain:engineseat 1 flagged it.origin/main:render-projection-diff.tscarriesgenerateBaseRegistry(3 hits), andrender-projection-diff.test.tscarries the 5 base-without-registry cases.Type Check · source gates' base-side render lays out a base at or aftered1de8c2dbwith that base's own generatedregistry.ts, so PRs and queue groups no longer fail "Cannot find module '../src/migrations/registry'". A base that committed the registry is untouched.Fixes #22744. The only other item closed at 2026-10-11T02:15Z is PR fix(lint): one-line verdicts for the approval-approver, data-model, agent-authoring, view-reference and chart-binding rules;os explain RULE_IDcarries their reasoning #22742 (Part of #22161, no closing keyword), so nothing else closed.