Repository navigation
tooling(objectui-readiness 2): readers of pnpm-workspace.yaml, turbo.json, pnpm-lock.yaml and the root manifest resolve the workspace root upward (objectstack#25723) - #13484
Conversation
…t files are, in both layouts (objectstack#25723) `scripts/workspace-root.mjs` (Node builtins + `ui-root.mjs` only, so the pre-install gates may import it) answers where `pnpm-workspace.yaml`, `pnpm-lock.yaml`, the root manifest and `turbo.json` are: at `uiRoot()` when that directory holds the workspace file, else at its parent when THAT does (the objectstack monorepo, where the tree is `ui/` and a nested workspace root is ignored), else a throw -- never a silent pick of some other workspace. `workspaceGlobs()` returns the file's `packages:` globs relative to the tree in both layouts (the parent's `ui/...` entries with the prefix stripped, the bare `ui` entry dropped). `parseWorkspaceGlobs` is the union of the three ad-hoc parsers' refusals. For `turbo.json`: `turboConfigPath()` is the nearest one upward (what turbo hashes from), `uiTurboConfigPath()` objectui's own declaration (`turbo.json`, else the parked `turbo.objectui.json`), and `uiScopedTurboConfig()` the nearest one narrowed to the `$TURBO_ROOT$/ui/` subset. Every function takes an explicit root for fixtures. `check-ui-root-lookups` learns the shape that escaped objectstack#25685: a `readFileSync` of a marker inside a loop that steps a directory upward is the walk's existence test (`marker-walk`), not a data read; a marker read in a loop over known roots stays silent. The helper's own two `existsSync` probes are allowlisted with their reason. The `.d.mts` twin is ledgered in `check-lint-rule-coverage`'s predicate-2 rows like `ui-root.d.mts`. Clause-②: no Metadata-protocol: none Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RSDL3SFtJaKzcymvCD8RsU
…ot files resolve them through the helper (objectstack#25723) The three `packages:` parsers (`check-side-effects-array`, `select-affected-tests`, `check-docs-route-eager-closure`) become `workspaceGlobs()` / `parseWorkspaceGlobs()`; each keeps its own expansion, so standalone it lists exactly the directories it listed before. `select-type-check-scope` reads the nearest `turbo.json` upward through `uiScopedTurboConfig()`: under the monorepo the root's `$TURBO_ROOT$/ui/x` inputs are read as `$TURBO_ROOT$/x` and its other root inputs and `globalDependencies` are dropped, so the root rule stays the objectui subset instead of widening every change to the whole monorepo; the changed files are listed `--relative` to the tree (a no-op at the repository root) and the dry run's tasks are narrowed to packages under it. `check-lockfile-dedupe` runs `pnpm dedupe --check` at `workspaceRoot()` and requires the pinned build's stamp only where the root manifest declares the pin (`pinDeclared()`): under the monorepo the `@objectstack/*` packages are workspace members and no manifest does, so the missing stamp is not a reason to refuse a reading. Its pin test follows the precondition's new spelling and holds `pinDeclared` on both manifest shapes. `check-lockfile-integrity` reads `lockfilePath()` and runs git at `workspaceRoot()`; `check-installed-spec-pin-claims` reads `lockfilePath(root)`. Clause-②: no Metadata-protocol: none Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RSDL3SFtJaKzcymvCD8RsU
…les through the helper (objectstack#25723) Nine hand-rolled `packages:` parsers in `scripts/__tests__` (and the one in `packages/i18n`'s locale census) become `workspaceGlobs(repoRoot)`; each test keeps its own expansion. `helpers/turbo-inputs.ts` roots on `uiRoot()` and reads objectui's own task declaration through `uiTurboConfigPath()`, as do the eight tests that pin task shapes out of `turbo.json`: under the monorepo that is the parked `turbo.objectui.json`, the file whose `$TURBO_ROOT$` inputs are relative to this tree, which is what those pins assert. The three lockfile readers take `lockfilePath()`. `packages/cli`'s alias-table test asks the product helper about `workspaceRoot(REPO_ROOT)` -- the pnpm workspace root that governs this tree, which standalone is the repository root -- and builds its expectation from the globs relative to the tree; the product code itself (`workspace-vite.ts`, `app-generator.ts`) asks about the USER's cwd and is unchanged. The two package test files are the only published-source paths touched, so an empty-frontmatter changeset declares that nothing releases. Clause-②: no Metadata-protocol: none Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RSDL3SFtJaKzcymvCD8RsU
… of walking to pnpm-workspace.yaml (objectstack#25723) Each spec located "the repo root" by reading `pnpm-workspace.yaml` upward from its own file inside a `try/catch` loop -- a `readFileSync`, so `check-ui-root-lookups` did not read it as the existence probe it was, and on the merged tree the walk stopped at the OBJECTSTACK root and the first spec died with ENOENT on `packages/plugin-detail/src/DetailView.tsx` before the browser started. The sources these specs read live under this tree's `packages/`, so `uiRoot()` from `scripts/ui-root.mjs` is the answer in both layouts; the gate now fires on the shape that escaped. The e2e program imports the helper through its `.d.mts` twin (`allowJs` stays off), and `tsconfig.e2e.json`'s header says so where it stated the old premise. Clause-②: no Metadata-protocol: none Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RSDL3SFtJaKzcymvCD8RsU
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
席位核对(dispatch seat landing record)改了什么 —— objectstack#25723(epic #25677 子单 2b):新增 为什么 —— objectui 并入 objectstack 席位核对
落地 —— 本席执行 Generated by Claude Code |
Part of objectstack-ai/objectstack#25723 (sub-issue 2b of objectstack-ai/objectstack#25677, the objectui → objectstack
ui/merge). Follow-up of #13472.What
Adds
scripts/workspace-root.mjs(Node builtins only, importable beforepnpm install) and its.d.mtstwin:workspaceRoot(),workspaceGlobs(),lockfilePath(),rootManifest(),uiTurboConfigPath(),uiScopedTurboConfig(). Every reader ofpnpm-workspace.yaml,pnpm-lock.yaml, the rootpackage.jsonandturbo.jsonunderscripts/,scripts/__tests__/, two package tests and the five e2e specs resolves those files through it. The three ad-hocpackages:parsers are unified (union of their refusals).check-ui-root-lookupslearns themarker-walkshape that let the e2eREPO_ROOTIIFEs escape #13472, with self-test cases. Standalone behaviour is byte-identical: every helper branch is the identity when<uiRoot>/pnpm-workspace.yamlexists.Why
Once objectui is
ui/of the objectstack monorepo, the workspace root, lockfile and overrides live one directory up andturbo.jsonis parked asturbo.objectui.json(a nested turbo.json mustextendsthe root). Readers that assumed those files atuiRoot()fail with ENOENT (measured on the verification PR objectstack-ai/objectstack#25718: Type Check UI atcheck:side-effects-array, Build & E2E UI at the first e2e spec, 15 of 16 Test UI shards) or walk up to the wrong root (five e2e specs). This PR makes them layout-aware ahead of the import.Verification
ui/in objectstack, scratch copy of the verification tree)pnpm check:ui-root-lookups/--self-testpnpm exec vitest run scripts/__tests__workspace:post-import), the QUICK_REFERENCE script list, the vendor-chunk arm, one dom test — none a root-file read, all carried on objectstack#25697pnpm --filter @object-ui/cli testworkspace-vite.test.tsgreenpnpm check:side-effects-arraypnpm check:docs-route-closurepnpm check:lockfile-dedupe/check:lockfile-integrity/check:installed-pin-claimspnpm type-check:scripts/type-check:e2epnpm lint:coverage,lint:root, the pre-push gate listplaywright test --list --project=chromiumThe same patch is on the verification branch as objectstack commit 1cade6932a (run 3 of objectstack-ai/objectstack#25718).
Landing
Tooling and tests only; no product code (
packages/cli/src/utils/workspace-vite.ts,app-generator.tsunchanged); no governed surface touched. Changeset.changeset/25723-workspace-root-readers.mdwith empty frontmatter — present because two package test files undersrc/changed; releases nothing. Draft until CI is green; then the epic PM asks for review.Clause-②: no
Metadata-protocol: none
🤖 Generated with Claude Code
https://claude.ai/code/session_01RSDL3SFtJaKzcymvCD8RsU