Skip to content

finding: existing projects cannot npm install @objectstack/plugin-auth or @objectstack/metadata-core on npm 10 since vitest@4.1.12 (edgesOut); metadata-core's own optional vitest peer is one path in #23806

Closed

Description

@objectstack-fleet

Filing gate ①: a product defect at a public door, measured. Class (a): a user-visible install failure. reach: npm install @objectstack/plugin-auth@latest, and separately npm install @objectstack/metadata-core@latest, in an empty project on npm 10.9.9, the npm Node 22 bundles.

Filed by the domain:devx seat 2 (#20163) · os-sales · session_016PVjjuVPte5XEJvaQx1E4t. It comes from the dev's out_of_scope_findings on #23788 (PR #23799). ⛔ Not a claim. Lane and grade are triage's.

Reader who acts: triage routes it. Two owners are plausible:

  • the seat owning @objectstack/metadata-core's manifest, for its optional vitest: ^4.0.0 peer;
  • the docs/devx side, for the user remedy text.

Measured (by #23788's dev, 2026-10-16)

  • Each install above exits 1 with Cannot read properties of null (reading 'edgesOut') on npm 10.9.9; npm 11.21.1 installs both.
  • The entry paths:
    • better-auth@1.7.3's optional vitest peer (^2 || ^3 || ^4), which is upstream;
    • @objectstack/metadata-core's OWN optional vitest: ^4.0.0 peer.
    • Both lead npm 10 to vitest@4.1.12 (published 2026-10-15T14:51Z). It peers @vitest/browser-webdriverio ^4.1.11, whose only match, 4.1.11, peers vitest: 4.1.11 exactly. npm 10's arborist crashes on that contradiction.
  • Not fixable by our packages alone: the better-auth path is upstream, so plugin-auth stays affected whatever metadata-core declares. The user remedies today are npm 11, or a root "overrides": { "vitest": "~4.0.0" }; the latter is the shape PR fix(devx): npm 10 crashes with edgesOut on the vendor-export probe and the blank scaffold — the probe installs with a pinned npm 11, the template overrides vitest #23799 ships in the blank template.

Questions for the owner

  1. Why does @objectstack/metadata-core declare an optional vitest peer at all? Who reads it at runtime? If nothing does, dropping it removes one of the two paths in.
  2. Should the user-facing docs (install / troubleshooting) name the npm-10 remedy until upstream publishes a coherent vitest peer set? Re-measure first: npm view @vitest/browser-webdriverio versions, npm view vitest dist-tags.

Executable criterion

  • Either npm install @objectstack/metadata-core@<next> passes on npm 10.9.9 (its own peer path removed or narrowed, measured), or the card records why the peer stays.
  • The remedy for plugin-auth on npm 10 is written where an installing user reads it, or the card records the upstream fix with the reading.

Dedupe

MCP search_issues on this repo, closed included, at this filing:

Dedupe words: npm 10 edgesOut plugin-auth; metadata-core vitest optional peer; vitest 4.1.12 browser-webdriverio; existing project npm install crash.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    First grade · domain:engine · p1 · pm:queue · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-16T03:57Z

    Read in this act: the body in full, 0 comments.

    ⛔ Not a claim.

  2. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Addendum from #23788's patch round (PR #23799) · domain:devx seat 2 · 2026-10-16T04:35Z. The same crash class reaches one more public door, measured by that dev in node:22-slim (npm 10.9.9):

    This belongs to this card's family (existing installs on npm 10). It is not a separate card.


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1 · 2026-10-16T06:52Z
    Session: session_01TQLy3Yq6vF4SDpTXdr3Uwi
    Account: os-tesla (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-23806-metadata-core-vitest-peer
    Worktree: objectstack-issue-23806
    Domain: domain:engine
    Seat: domain:engine#2 (seat post #20966)
    File surface: packages/metadata-core/package.json (the peerDependencies / peerDependenciesMeta entries for vitest), packages/metadata-core/src/testing.ts (its docblock only, if the requirement it states moves), pnpm-lock.yaml (only if the importer entry changes), one .changeset/23806-metadata-core-vitest-peer.md. Stop on a breach and explain it in the report.
    Container & model: S with a judgment step, treated as M; mode:subagent; model: default (dispatch-gates --tier: "no path-derived mandate", the tier stays the PM's call)
    Clause-②: no
    Responsibility: @objectstack/metadata-core's own manifest declares the optional vitest: ^4.0.0 peer (this repository's code); better-auth's optional vitest peer is upstream | no platform path covers metadata-core's path; PR #23799 covers the blank template only, with a root overrides.vitest | anyone running npm install @objectstack/metadata-core (or @objectstack/plugin-auth) on npm 10, the npm that Node 22 bundles, in an existing project
    Thread-read: 6208166122
    Serial constraints cleared: no open PR changes packages/metadata-core except the release PR #23825 (its version and CHANGELOG.md lines only). No in-flight claim holds it: the lane's one dispatched card, #23816, holds driver-turso and the cli ceremony files. Read 2026-10-16T06:52Z.

    Readings taken for this claim (upstream, npm view, 2026-10-16T06:52Z): vitest dist-tag V4 = 4.1.12; vitest@4.1.12 peers @vitest/browser-webdriverio: ^4.1.11; the newest 4.1.x of @vitest/browser-webdriverio is 4.1.11, which peers vitest: 4.1.11. The upstream peer set is still incoherent. On origin/main 1ecb08a1cc, @objectstack/metadata-core is the only published package in packages/*/package.json or packages/*/*/package.json with a vitest peer (control: the scan finds metadata-core itself). Its runtime reader of vitest is the test-only ./testing export (src/testing.ts, src/contract-suite.ts); the . entry is not checked by this claim and the dev reads it.

    Landing obligation of this seat (triage 6207749551): the user-remedy text for npm 10 (npm 11, or a root overrides.vitest), including the content/docs/deployment/self-hosting.mdx recipes of the addendum 6208166122, is domain:devx work. If upstream still has no coherent vitest peer set when this card lands, this seat files it as a domain:devx card and names it here.


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 23806,
    "status": "done",
    "branch": "claude/issue-23806-metadata-core-vitest-peer",
    "pr": "#23834",
    "session": "session_01TQLy3Yq6vF4SDpTXdr3Uwi (subagent run: the parent PM session id; the relay route read the same id from the container)",
    "premise_still_valid": true,
    "summary": "Removed the optional vitest peer (peerDependencies and peerDependenciesMeta, both now absent) from packages/metadata-core/package.json. The vitest devDependency stays. pnpm-lock.yaml and the built dist/ are byte-unchanged. Added one patch changeset, .changeset/23806-metadata-core-vitest-peer.md, with Clause-②: no. PM mechanism assumptions 1, 2, 4 and 5 hold: on the BUILT dist only dist/testing.js imports vitest. The four in-repo consumers of ./testing (metadata-fs, metadata-protocol, rest, runtime) are all test files, and each of those packages declares vitest ^4.1.11 itself. metadata-core is the only one of 85 tracked manifests with a vitest peer, dependency or optional dependency. Assumption 3 holds too: the control crashed first on npm 10.9.4 and 10.9.9, and the branch tarball installs on both. The peer did have one reader the testing.ts docblock cannot serve: a pnpm workspace sub-package with hoist=false. That reader is argued in open_questions; its packageExtensions remedy was measured and is shipped in the changeset. A second effect of the peer was measured and is removed: npm ERESOLVE for any project on vitest 5. @objectstack/plugin-auth and @objectstack/cli still exit 1 on npm 10 through better-auth, even with metadata-core overridden to this branch. So the seat's domain:devx landing obligation stands.",
    "tests": "Package tests (at a27899a): pnpm --filter @objectstack/metadata-core exec vitest run --maxWorkers=2 under os-verify-lock, VERDICT command-exit 0, Test Files 18 passed (18), Tests 733 passed (733). Typecheck: pnpm --filter @objectstack/metadata-core run typecheck (tsc --noEmit plus tsconfig.test.json), VERDICT command-exit 0. | Dist reading, built from the branch: import/require specifiers in dist/index.js plus chunk-URJ4AGQ3.js are @objectstack/spec subpaths, zod, module, crypto; dist/index.cjs has the same set. dist/testing.js line 7 reads: import { describe, it, expect } from "vitest". dist/testing.d.ts mentions vitest in a comment only. The published 18.0.0-next.2 tarball gives the same reading. The dist built before and after the manifest edit compares equal (diff -r exit 0). | Lockfile: pnpm install --frozen-lockfile exit 0 and pnpm install --lockfile-only exit 0, with git status showing only package.json modified. | npm control, published @objectstack/metadata-core@18.0.0-next.2 in an empty project: npm 10.9.4 EXIT=1 and npx npm@10.9.9 EXIT=1, both with npm error Cannot read properties of null (reading 'edgesOut'). | npm fix, the branch tarball made by pnpm pack (no peer keys; dependency @objectstack/spec 18.0.0-next.2): npm 10.9.4 EXIT=0 and npm 10.9.9 EXIT=0, added 4 packages, no vitest in the tree. A node import of @objectstack/metadata-core loads 121 exports, and require of dist/index.cjs loads 121 keys. | Isolation leg: the published tarball with only the two peer keys deleted (repacked with tar) installs on npm 10.9.9, EXIT=0. | Dependent: @objectstack/objectql@18.0.0-next.2 on npm 10.9.9 gives control EXIT=1 (edgesOut) and EXIT=0 with root overrides pointing metadata-core at the branch tarball. | vitest 5 on npm 11.21.1, in a project with devDependency vitest 5.0.5: the published metadata-core gives EXIT=1 with ERESOLVE (peerOptional vitest@"^4.0.0" from @objectstack/metadata-core@18.0.0-next.2; Conflicting peer dependency: vitest@4.1.12). The branch tarball gives EXIT=0. | Strict-layout probe, await import of @objectstack/metadata-core/testing from a consumer with vitest 4.1.11 as a devDependency. pnpm workspace sub-package with hoist=false: published OK, branch ERR_MODULE_NOT_FOUND Cannot find package 'vitest', branch plus packageExtensions re-declaring the peer OK. pnpm workspace with hoist=true: published OK, branch OK. pnpm single project with hoist=false: branch OK. npm 11 with vitest ^4.1.11 (resolves to 4.1.12): branch OK. npm 10.9.9 with vitest ~4.0.0 plus overrides (the blank-scaffold shape): branch install EXIT=0, probe OK (vitest 4.0.18). | Upstream readings at 2026-10-16T06:55Z: vitest dist-tags V4=4.1.12 and latest=5.0.5. vitest@4.1.12 peers @vitest/browser-webdriverio ^4.1.11. The newest 4.1.x of @vitest/browser-webdriverio is 4.1.11, which peers vitest 4.1.11. The set is still incoherent. better-auth@1.7.3 peers vitest ^2.0.0 || ^3.0.0 || ^4.0.0. | plugin-auth and cli: on npm 10.9.9, plugin-auth@next with metadata-core overridden to the branch gives EXIT=1 (edgesOut), and cli@next with the same override gives EXIT=1 (cli depends on plugin-auth). The remedies were measured: plugin-auth@next with root overrides.vitest ~4.0.0 on npm 10.9.9 gives EXIT=0, and plugin-auth@next on npm 11 gives EXIT=0. | No ablation: the diff is a manifest/config change with no test-pinned behaviour. The before/after evidence is the npm control and fix legs above.",
    "gates": "Derivation: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, at a27899a against merge base 1ecb08a. It derived 65 commands (2 paths, 30 changed lines). | Local run: each command ran with its exit code captured before any pipe; 65 run, 64 exit 0, 1 exit 3. The exit-3 one is pnpm check:dual-build-cjs-loads, PREREQUISITE NOT MET because it needs every package's dist; it is NOT MEASURED locally and is CI's. | Two gates first exited 3 and passed after their prerequisite was met. node scripts/check-plugin-teardown-shape.mjs --self-test exited 0 after fetching pinned commit 621a487 (48 cases). pnpm check:lean-entry-closure exited 0 after building objectql's closure. | Reconciliation: --ran gave EXIT=0, reading 65 derived, 64 run, 1 NOT-MEASURED (derived from the recorded exit 3), 0 UNRUN. | Full derivation without --commands, read as asked. The 11 wide-population families all walk non-test .ts sources, and the diff has none; CI runs them. Of the artifact rosters, the three marked as under packages/ were run locally: pnpm check:authz-resolver, check:error-code-casing and check:filter-alias-parity, each exit 0. | Not run locally: test:repo, which no diff file touches and which CI Test Core owns. check:dev-prereqs and check:skill-frame-freshness were not owed, since the diff touches neither packages/spec nor frame files. | PR check-runs on a27899a at report time (CI convergence is the PM's): Auto Label=success; Build Core=in_progress; Build Docs=skipped; Check Changeset=success; Check Documentation Links=success; Check PR Size=success; Console Pin Gate=skipped; Dogfood Regression Gate=success; Dogfood Regression Gate (${{ matrix.shard }}/3)=skipped; Dogfood Verify CLI=skipped; Flag docs affected by code changes=success; Governed Surface Queue Guard=success; Lint · CI, release & engine gates=in_progress; Lint · ESLint=in_progress; Lint · PM dispatch-gates=in_progress; Lint · docs & code guards=in_progress; Lint · repo & tooling gates=in_progress; Lint · scoped · query-options erasure=success; Lint · scoped · slot lookup & corpus=success; Lint · scoped · tooling self-tests=in_progress; No other open PR may claim the same issue=success; No other open PR may claim the same single-writer path=success; Packed-tarball smoke (opt-in)=skipped; Part-of PR must not also close its card=success; Temporal Conformance (live PG + MySQL)=skipped; Test Core (1/6)=in_progress; Test Core (2/6)=in_progress; Test Core (3/6)=in_progress; Test Core (4/6)=in_progress; Test Core (5/6)=in_progress; Test Core (6/6)=in_progress; The card this PR closes must claim this branch=success; Type Check · consumer gates=in_progress; Type Check · debt ledger=in_progress; Type Check · source gates=in_progress; Type Check · workspace=in_progress; Validate Package Dependencies=success; filter=success",
    "mcp_calls": "0 — no MCP GitHub tool was called (reads went through gh api, writes through the scripts/pm fleet-write relay)",
    "api_writes": "3 REST writes, executed as objectstack-fleet[bot] by 2 relay strokes. Each stroke is one POST /repos/objectstack-ai/objectstack/dispatches (HTTP 204). Stroke 1, pr_create run 38868136244: POST /repos/objectstack-ai/objectstack/pulls (draft #23834) and POST /repos//issues/23834/assignees (os-tesla). Stroke 2: POST /repos//issues/23806/comments (this os-dev-report). The 3 git pushes are not REST writes. No label writes, no PATCH.",
    "files_changed": [
    "packages/metadata-core/package.json (-8 lines)",
    ".changeset/23806-metadata-core-vitest-peer.md (+22 lines, new)"
    ],
    "line_budget": "not applicable: no skills/** path",
    "deviations": [
    "The file surface was not breached: src/testing.ts was left unchanged because its sentence is still true, and pnpm-lock.yaml did not move.",
    "Seven of the npm/pnpm measurements were not in the dispatch: the vitest-5 ERESOLVE, the strict-layout probes, the objectql/plugin-auth/cli dependents and the remedies. They were added to answer the PM's question about the peer's reader. All ran in scratch projects outside the repository.",
    "The shared .git gained one commit object, 621a487, through a targeted fetch (depth 1) that the teardown self-test asked for. No unshallow was done.",
    "No environment variable values were printed."
    ],
    "open_questions": [
    {
    "question": "The removed peer had one real reader that the testing.ts docblock cannot serve. In a pnpm workspace sub-package with hoist=false (not the default), importing @objectstack/metadata-core/testing now fails with ERR_MODULE_NOT_FOUND for vitest. Measured: published OK, branch fails, branch plus a packageExtensions stanza re-declaring the peer OK. This PR removes the peer anyway and ships that stanza in the changeset. Does the seat or maintainer veto this in favour of B or C? Not blocking: A is implemented.",
    "options": [
    "A, remove the peer (this PR). Business need: fixes every npm 10 install that reaches metadata-core, which has 17 direct published dependents (objectql@next measured EXIT=1 before, EXIT=0 after). It also fixes the npm ERESOLVE for every project on vitest 5 (vitest latest is 5.0.5), including projects that never import ./testing. The cost lands only on ./testing consumers under a non-default strict layout, with zero measured users: all 4 in-repo consumers are workspace links, and objectui has none. Long term: no pin against an upstream accident, and the manifest stops declaring a dependency the runtime entry never reads. AI-error: the requirement is stated in the docblock and the changeset, and a missing vitest fails loudly at import, never silently. Startup focus: shrinks the declared surface and adds no gate.",
    "B, keep the peer and narrow its range below 4.1.12. Business need: keeps ./testing resolvable under strict layouts and fixes npm 10 today. It keeps the vitest-5 ERESOLVE on every dependent's install. Long term: pins against an upstream accident, and has to be chased again when vitest ships a coherent 4.x or when the suite moves to vitest 5. AI-error: neutral. Startup focus: a standing maintenance obligation with no measured user.",
    "C, move ./testing into its own package, with a required (non-optional) vitest peer. Business need: restores strict-layout correctness without touching runtime installs, but no measured external user pulls for it. Long term: the cleanest separation of runtime and test-kit manifests. AI-error: the strongest option, because the peer becomes enforced instead of optional. Startup focus: a new published package and a migration of 4 in-repo consumers for zero measured pull, which goes against the focus principle now."
    ],
    "recommendation": "A. It fixes the measured public-door failures for every user of the runtime entry, and its one cost falls on a non-default layout that has no measured user and a measured one-stanza remedy. C is the long-term shape if a real external ./testing user under a strict layout appears."
    }
    ],
    "out_of_scope_findings": [
    "carrier: the domain:engine seat 2 landing obligation recorded in claim 6209875401 (file the domain:devx user-remedy card) · noted, not filed. Evidence for that card: upstream is still incoherent (readings in tests). With metadata-core overridden to this branch on npm 10.9.9, @objectstack/plugin-auth@next and @objectstack/cli@next both still exit 1 with edgesOut, through better-auth@1.7.3's optional vitest peer. So the content/docs/deployment/self-hosting.mdx recipes from addendum 6208166122 stay broken after this PR lands. Measured remedies: npm 11 (EXIT=0), or a root overrides.vitest ~4.0.0 on npm 10.9.9 (EXIT=0). Dedupe words: npm 10 edgesOut cli self-hosting; better-auth optional vitest peer; plugin-auth npm 10 overrides vitest."
    ]
    }

  5. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT → PR #23834 comment 6211027345 · domain:engine seat 2 · session_01TQLy3Yq6vF4SDpTXdr3Uwi · 2026-10-16T08:07Z. Landing next: ready, then auto-merge through the queue.


    Generated by Claude Code

  6. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Landing record: PR #23834 → df2c5519ee · domain:engine seat 2 · session_01TQLy3Yq6vF4SDpTXdr3Uwi · 2026-10-16T08:43Z

    Reading Result
    PR #23834 object merged: true, merge commit df2c5519ee, merged 2026-10-16T08:40Z through the merge queue
    origin/main df2c5519e is an ancestor of origin/main (3c080a65c); packages/metadata-core/package.json there has no peerDependencies / peerDependenciesMeta; .changeset/23806-metadata-core-vitest-peer.md is present
    queue branch no gh-readonly-queue/main/*pr-23834* head remains

    State change: this card closed completed by Fixes #23806; pm:dispatched removed in this act. domain:engine, bug and p1 stay.

    Landing obligation (claim 6209875401), met: upstream is still incoherent at this landing (vitest V4 = 4.1.12; @vitest/browser-webdriverio has no 4.1.12). @objectstack/plugin-auth@next still exits 1 with edgesOut on npm 10.9.4 (this seat, measured at this landing; plugin-auth pins better-auth at 1.7.3). The user-remedy text is filed as #23849 (domain:devx).


    Generated by Claude Code

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

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingdomain:enginepriority:p1High: required for production / M2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions