Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

tooling(objectui-readiness 4): paths handed to git use git's cwd-relative forms, so the scripts read the same files under the monorepo's ui/ (objectstack#25728) - #13491

Merged
objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/project-thread-ulxm6b
Oct 25, 2026
Merged

objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/project-thread-ulxm6b

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Tesla · project thread

Part of objectstack#25728 (sub-issue 2d of the epic). Part of objectstack#25677.
Clause-②: no
Metadata-protocol: none

Why

Standalone, the git repository root is the objectui tree. Under the objectstack monorepo it is one level up, and the tree is ui/. Git reads a path in git show REF:PATH from the repository root, whatever cwd it runs in, and prints git diff --name-only and ls-tree --full-tree paths from that root too. On the verification PR objectstack#25718 (run 4) Type Check UI went red at check:i18n-drift with cannot read b77bb37eb2…:packages/i18n/src/locales/en.ts. The ref was in the clone. The path had no ui/.

The idiom (one, for every script)

It is written down in the header of scripts/workspace-root.mjs, section "Paths handed to git". The scripts use git's own cwd-relative forms, not nestedPrefix():

  • git runs with its cwd at the tree it judges (uiRoot(), or the scratch repository a gate's tests drive it against);
  • a path into a revision is revPath(ref, path), which spells REF:./PATH. Git resolves ./ against the cwd, so the same spelling names the same file in both layouts;
  • a path listing out of diff / diff-tree / log / show carries --relative;
  • ls-files, ls-tree, grep and pathspecs after -- are already cwd-relative, so they never carry --full-name / --full-tree.

Standalone each of these is a no-op, because the cwd is the repository root. nestedPrefix() was not chosen because it is the workspace's answer: a scratch repository in a test has no pnpm-workspace.yaml, and git already knows where its cwd sits. The repository already used this form in two places (check-new-cross-file-line-citations.mjs and select-type-check-scope.mjs).

Triage

Population: every scripts/*.mjs that spawns git. 45 files name git. The census the card cites (31) counted comment mentions too, for example markdown-test-inputs.mjs spawns no git at all. Class (a) is a path into git, (b) is a root-relative path out of git, (c) is no path.

Script Call Class Change
check-i18n-en-drift.mjs show REF:packs, show REF:designer table (a) revPath; plus the base-without-tree rule below
check-changeset-presence.mjs diff --name-only (changedFiles, shared by claims and overwrite) (b) --relative
check-changeset-presence.mjs show REF:manifest, show HEAD:changeset (a) revPath
check-changeset-claims.mjs ls-tree -r --name-only --full-tree (treeIndex, compared with ls-files on the other side) (b) drop --full-tree
check-changeset-claims.mjs cat-file --batch input, show base:file, show commit:file (a) revPath
check-changeset-overwrite.mjs show REF:file (a) revPath
check-lockfile-integrity.mjs show REV:pnpm-lock.yaml (cwd = workspace root) (a), already correct revPath for the one idiom, and its error message
select-affected-tests.mjs diff --name-only base...head (b) --relative
check-governed-queue-guard.mjs diff-tree --name-only matched against governed surfaces (b), on purpose none. Its subject is the repository root (AGENTS.md, .github/workflows/**), and under the monorepo the register is objectstack's own (objectstack#25712). Allowlisted with that reason
objectstack-pin.mjs status --porcelain of the objectstack tree other repository none. Already allowlisted, deleted at cutover
ls-files callers (check-bash32-floor, check-comment-mask-corpus, check-control-bytes, check-installed-spec-pin-claims, check-readme-exports, check-test-path-roots, check-vi-mock-inherit, check-vi-mock-override-shape, check-vi-mock-specifiers, cross-file-line-citation-census, dollar-dialect-alias-census, census-recorder-wait-shape, select-affected-tests trackedFiles, coverage-red-cause-census ls-tree) ls-files / ls-tree from the tree cwd-relative already none
check-new-cross-file-line-citations, select-type-check-scope --relative, REV:./PATH already the idiom none
check-lint-rule-coverage, measure-strict-authoring-face, objectstack-floor, rev-parse / merge-base / cat-file -e everywhere check-ignore, grep, pathspecs, no path (c) none

Tests that spawn git (scripts/__tests__, packages/**) were read too. Each uses ls-files, grep or check-ignore from the tree, so they are already cwd-relative. The one exception was bump-objectstack.test.ts: it ran show --name-only and show HEAD:… in its scratch repository, and both are now spelled the idiom's way (same answer there).

A base commit with no objectui tree at all (measured, not in the card)

With the paths fixed, check:i18n-drift on the merged layout still went red, and this time correctly. The merge base b77bb37eb2 is objectstack main without ui/ (git ls-tree of it has no ui entry and no packages/i18n). So the packs are addressed right and are absent there. The PR that imports objectui as ui/, and every branch cut from it before it lands, has no before side. analyze now asks git whether the tree itself (REF:./) exists at the base. Only when it does not is the before side empty, and the CLI prints that ("this tree does not exist at the base commit (the change imports it)…"). The designer table already had the same rule for a missing file. Standalone the tree is the repository root, which exists at every commit, so the rule never fires there. A tree that exists at the base with a pack missing still throws (pinned).

Regrowth gate

check:ui-root-lookups gains two shapes:

  • git-rev-path: a show / cat-file argv, or the call that spawns one (so a cat-file --batch input: is covered), that holds a REF:PATH string or template whose path does not start with ./;
  • git-root-listing: a diff-family argv with a path-listing flag and no --relative, or an ls-files / ls-tree / grep argv with --full-name / --full-tree.

An argv is an array whose head is a git subcommand (after -C / -c pairs), the string arguments of a git…-named wrapper, or a git … string command. 20 new self-test cases cover both directions. The header states the bound: argv assembled from names only, rev paths built outside the call, patch-header parsing, status --porcelain, and a cwd other than the tree are out of its reach.

Reverse check. The new gate, run on the pre-fix tree (c85408f with only the gate file replaced), fires at exactly the 15 sites this PR changes, and nowhere else outside the allowlist. The only new allowlisted hit is the governed guard.

Verification

objectui standalone (this branch, after pnpm run setup). Every command exited 0:

pnpm check:ui-root-lookups · node scripts/check-ui-root-lookups.mjs --self-test (37 cases) · pnpm check:i18n-drift · node scripts/check-changeset-presence.mjs (no changeset owed: scripts only) · node scripts/check-changeset-overwrite.mjs · pnpm check:changeset-claims · pnpm check:lockfile-integrity · pnpm check:lockfile-dedupe · pnpm check:new-line-citations · pnpm check:control-bytes · pnpm check:pre-install-import-graph · pnpm check:test-path-roots · pnpm check:comment-mask-corpus · pnpm check:lint-rule-coverage · pnpm type-check:scripts · node scripts/check-hand-rolled-comment-mask.mjs · pnpm exec eslint over the changed files.

pnpm exec vitest run scripts/__tests__ was run whole in three shards (--shard=K/3, under the verify lock): 196 files passed. Two files were skipped by their own IS_CHILD conditions (the network-escape worker children).

scripts/__tests__/git-paths-nested-layout.test.ts builds a scratch repository of each layout (standalone, and nested under ui/ beside a file of the monorepo's own) and holds readPacks/analyze, changedFiles (presence and affected-tests), treeIndex/readBlobs and collisions to the same answer in both. Its control is that the root-relative show spelling must throw in the nested repository. It also covers the import-commit case. Reverse check: with the five readers reverted to c85408f, 4 nested cases fail and every standalone case passes.

Merged layout. I used a scratch worktree of the verification branch head d17ed5edf9 (objectstack#25718: ui/ imported, adapted and locked) and applied this branch's diff under ui/ with git apply --directory=ui. Then I ran pnpm install --frozen-lockfile (exit 0) and the CI build of the seven @objectstack packages (exit 0). The merge base with origin/main resolves to b77bb37eb2, the run-4 base.

  • Control, before the patch: pnpm --dir ui run check:i18n-drift exits 1 with cannot read b77bb37eb2…:packages/i18n/src/locales/en.ts, the run-4 red.
  • After the patch, the Type Check UI script chain in CI order exits 0 at every step: type-check:coverage, check:phantom-deps, check:self-import, check:unreferenced-sources, check:doc-example-readers, check:handler-key-reads, check:metadata-write-doors, check:published-tsconfig-exclude, check:side-effects-array, check:element-data-source-declaration, check:esm-specifiers, check:spec-symbols, check:action-forward-parity, check:designer-field-key-parity, check:icon-record-names, check:i18n-keys, check:i18n-drift, check:i18n-designer-parity, type-check:scripts, type-check:vitest-config and type-check:e2e. check:i18n-drift reports 3611 en keys added with no before side. The next CI step is the turbo type-check over the ui packages, which is not run here (it belongs to objectstack#25727). type-check:vitest-setup comes after it in CI and exits 2 locally, because it needs the @object-ui builds that step produces.
  • The touched scripts reach real verdicts: check-changeset-presence (9195 files changed against b77bb37eb2, 3 changesets declared, OK), check-changeset-overwrite (OK), check:changeset-claims (OK), select-affected-tests --explain (mode=full), check:ui-root-lookups (OK). check:lockfile-integrity exits 1 with its real verdict, 17 duplications in the merged lockfile. That is the dependency-resolution class of objectstack#25726, not a path error.

Out of scope

The lucide record-icon list, dependency versions (objectstack#25726), spec drift (objectstack#25727), .github/**.

🤖 Generated with Claude Code

https://claude.ai/code/session_011zu1DRQQFNb42ves1suAuk

…tive forms, so the scripts read the same files under the monorepo's ui/ (objectstack#25728)

Standalone the git repository root is the objectui tree; under the
objectstack monorepo it is one level up, and git resolves `<ref>:<path>`
and prints `diff --name-only` / `ls-tree --full-tree` paths from that root
whatever cwd it runs in. The merged tree's Type Check UI went red at
check:i18n-drift on exactly that.

One idiom, written down in scripts/workspace-root.mjs ("Paths handed to
git"): git runs in the tree, a path into a revision is revPath(ref, path)
= `<ref>:./<path>`, a path listing carries `--relative`, and ls-files /
ls-tree / grep never carry --full-name / --full-tree. Standalone every one
of these is a no-op.

Fixed: check-i18n-en-drift (2 show), check-changeset-presence (diff
--name-only, 2 show), check-changeset-claims (ls-tree --full-tree,
cat-file --batch input, 2 show), check-changeset-overwrite (show),
check-lockfile-integrity (show + its message), select-affected-tests
(diff --name-only); bump-objectstack.test.ts spelled to the idiom.

check:ui-root-lookups now also refuses the root-relative spellings
(git-rev-path, git-root-listing), with self-test cases both ways; the
governed-surface guard is allowlisted because its subject is the
repository root. git-paths-nested-layout.test.ts holds the fixed readers
to the same answer in a standalone and a nested scratch repository.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011zu1DRQQFNb42ves1suAuk
…e working-tree side too (objectstack#25728)

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011zu1DRQQFNb42ves1suAuk
… side when the tree does not exist at its base (objectstack#25728)

Measured on the merged layout (verify head d17ed5edf9) with the paths
fixed: the merge base b77bb37eb2 is objectstack main WITHOUT ui/, so the
packs are correctly addressed and still absent there. The change that
imports objectui as ui/ (and every branch cut from it) has no before
side; drift between two sides needs two. treeExistsAt asks git whether
`<base>:./` exists; only when it does not is the before side empty, and
the CLI says so. Standalone the tree is the repository root, so this
never fires; a tree present at the base with a pack missing still throws.
The read labels now name what git was asked (`<ref>:./<path>`).

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011zu1DRQQFNb42ves1suAuk
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Dispatch seat record. ACCEPTed on card objectstack#25728. check-governed-merges --pr objectstack-ai/objectui#13491 on the final file list: NOT governed (0 of 11 paths in the register; 7 surfaces govern objectui), 493 changed lines (+463/−30) under the 3000-line human-merge threshold. CI 36/36 green on head f8fa141862. Flipping ready and arming auto-merge (ordinary queue landing). No reviewer requested; this lands on the dispatch seat's verdict.


Generated by Claude Code

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants