Skip to content

finding: on npm 10 (Node 22's bundled major), npm install of a scaffold that declares vitest ^4.0.0 (SCAFFOLD_VITEST_RANGE: objectstack init -t plugin, objectstack create plugin) crashes with "Cannot read properties of null (reading 'edgesOut')" #22912

Description

@objectstack-fleet

Filing gate ①: a product defect with a public door measured and a named landing point. Class (a): a user-visible on-ramp failure. reach: npm install of a scaffolded manifest, measured on npm 10.9.4 and 10.9.9.

Filed by domain:cli seat 2 (#22648) · os-steve · session session_01VoSxBQujKLZKPwK2u5ehQ6, from #15952's dev (os-dev-report on #15952, out-of-scope finding 2 and open question 2; PR #22910). ⛔ Not a claim. Lane and grade are triage's.

Reader who acts: triage grades it. The range is SCAFFOLD_VITEST_RANGE = '^4.0.0' in packages/cli/src/commands/init.ts:383, used by create.ts, so the reader is domain:cli. It also gates #15952's held scaffold half, whose blank starter adds the same devDependency.

What is measured

Why (upstream, as measured)

The npm log walks into vite's optional @vitejs/devtools* peers, and @vitejs/devtools-vitest peers vitest@*. vite 7.3.7 and 8.3.4 were published 2026-10-06 to 10-08. So the cause is the upstream peer graph meeting npm 10's arborist, not ObjectStack code. But it reaches every scaffolder that declares SCAFFOLD_VITEST_RANGE. npx create-objectstack falls back to npm when pnpm is absent, and Node 22 bundles npm 10.

Not measured

  • The CLI-emitted plugin manifest itself (transcribed, not emitted).
  • Whether a vite or vitest patch release has since fixed it. Re-measure with the one-line manifest before any repair.

Direction (not a ruling)

Dedupe

MCP search_issues on this repo, closed included:

Dedupe words: npm 10 edgesOut crash; vitest npm install loadPeerSet; scaffold npm install vite devtools; SCAFFOLD_VITEST_RANGE npm.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade, bug · priority:p2 · domain:cli · area:devpath, into pm:queue. Re-measure first; if still broken, the shared range moves to one npm 10 installs

    Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-12T00:54Z. ⛔ Not a claim, ⛔ not a dispatch.

  2. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 2 · 2026-10-12T01:19Z
    Session: session_01VoSxBQujKLZKPwK2u5ehQ6
    Account: os-steve (the seat's linked user as GET /user answers it; the card's assignee from this act)
    Branch: claude/issue-22912-scaffold-vitest-range-npm10
    Worktree: objectstack-issue-22912
    Domain: domain:cli
    Seat: domain:cli#2 (seat post #22648)
    File surface (read on origin/main 7de0265fc7; stop on a breach and explain it in the report):


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 22912,
      "status": "done",
      "branch": "claude/issue-22912-scaffold-vitest-range-npm10",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/22920",
      "session": "session_01VoSxBQujKLZKPwK2u5ehQ6 — mode:subagent, so this is the dispatching PM's harness-stamped id (the Claude-Session trailer on cd7e34ee27)",
      "premise_still_valid": true,
      "summary": "Re-measured from scratch: the card's one-line manifest {\"devDependencies\":{\"vitest\":\"^4.0.0\"}} still crashes on npm 10.9.4 and 10.9.9 (edgesOut, arborist #loadPeerSet) and installs on npm 11.21.0, so upstream has not fixed it. SCAFFOLD_VITEST_RANGE (packages/cli/src/commands/init.ts) moves ^4.0.0 -> ~4.0.0, the narrowest range that installs on both majors: it resolves vitest 4.0.18 + vite 7.3.7, and both real CLI-emitted plugin manifests (os init -t plugin, os create plugin) now install on npm 10.9.4, 10.9.9 and 11.21.0 (both crashed before). Measured mechanism: npm 10 crashes when vite 8 is in the tree (its optional @vitejs/devtools peer leads to @vitejs/devtools-vitest, which peers vitest@*) AND the root vitest is not the version `latest` names; every vitest 4.1.x admits vite 8, all 19 vitest 4.0.x admit only vite ^6 or ^7, and no vite 6/7 release declares the devtools peer. ^5.0.0 installs today only because it resolves to the current latest (exact 5.0.0 and 5.0.2 crash), so it was not chosen; that choice against the decision's word 'newest' is open question 1. The one-range pin already exists (nightly-tier scaffold-emission-policy.e2e.test.ts, constant-derived, unchanged); a copied-literal ablation turned it red (3 failed). No unit test added; one patch changeset; draft PR #22920 assigned os-steve.",
      "tests": "All at cd7e34ee27 (PR head, final commit; nothing pushed after). (1) Closure build `pnpm --workspace-concurrency=2 --filter '@objectstack/cli^...' build` via os-verify-lock: VERDICT command-exit 0 (held 7m09s). (2) `pnpm --filter @objectstack/cli typecheck`: VERDICT command-exit 0 (tsc --noEmit; check:test-typecheck OK, 3 file(s)/28 error(s)/6 pinned signature(s) held in the ledger). (3) `pnpm --filter @objectstack/cli exec vitest run --project unit --maxWorkers=2`: 'Test Files 282 passed (282) / Tests 4262 passed (4262)', VERDICT command-exit 0. Integration layer declared to CI (no integration-layer file or spawn entry touched). (4) `OS_TEST_TIERS=nightly pnpm --filter @objectstack/cli exec vitest run --maxWorkers=2 test/scaffold-emission-policy.e2e.test.ts`: 'Tests 10 passed (10)', VERDICT command-exit 0. (5) Ablation, one-shot, scripts/ablation-replace.mjs wrap mode inside the lock: create.ts `vitest: SCAFFOLD_VITEST_RANGE,` -> `vitest: '^4.0.0',`; on-disk proof 'anchor x1 -> x0, replace x0 -> x1, blob d2c94f6a66f5 -> 98d8393f80b4'; run 'Tests 3 failed | 7 passed (10)' (one range per dependency; exported constant; across ALL THREE scaffolders); restore 'blob == HEAD (d2c94f6a66f5) and git diff HEAD is empty'; git status --porcelain 0 lines after. Subject is imported by relative src path, so no dist rebuild applies. (6) Gates: `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` (no paths) = 59; all 59 run, each exit 0; `--ran` verdict: 'Run reconciliation — 59 derived, 59 run, 0 NOT-MEASURED, 0 UNRUN' (derived zero, all 59 exit-coded). check:dual-build-cjs-loads and check:i18n-coverage first exited 3 (PREREQUISITE NOT MET, 10 packages without dist/); after `turbo run build --concurrency=2` of those 10 under the lock (59 tasks, VERDICT command-exit 0, tree clean) both exited 0: '107 published require entry point(s) across 66 package(s) load' and 'check-i18n-coverage: OK (13 config(s), 621 baselined untranslated string(s), none new)'. check:scaffold-emission-policy: '2 carrier(s) emit the shared policy'. check:nul-bytes: 'OK (scanned 10955 text file(s)...)'. (7) Lint, proven narrowing: `pnpm exec eslint --no-inline-config --format json packages/cli/src/commands/init.ts` exit 0; JSON: files 1, errors 0, warnings 0; population from eslint itself: --print-config resolves 5 rules for the file (not ignored); invariance: config has no parserOptions.project / projectService (0 hits; --print-config shows null for both; the config's own comment states it never enables type-aware linting), so no untouched file's verdict can move. Repo-wide pnpm lint is CI's. (8) Install matrix: see install_matrix; measured with npm 10.9.9 / 11.21.0 installed into scratch prefixes and run by path (not npx); container global npm 10.9.4 unchanged.",
      "mcp_calls": "0 — no MCP GitHub tool called",
      "api_writes": "3 REST writes as objectstack-fleet[bot], through 2 fleet-write relay strokes (each one POST /repos/objectstack-ai/objectstack/dispatches from this session): stroke 1 (run 38196429205, success) = POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /repos/objectstack-ai/objectstack/issues/22920/assignees [os-steve]; stroke 2 = POST /repos/objectstack-ai/objectstack/issues/22912/comments (this os-dev-report). One git push of the branch (fast-forward 7de0265fc7..cd7e34ee27) is not a REST write. Zero label writes.",
      "open_questions": [
        {
          "question": "The decision says the range moves to 'the newest vitest range that installs on both npm 10 and npm 11'. Measured, ^5.0.0 is newer than ~4.0.0 and installs on both today. This PR ships ~4.0.0. Keep it?",
          "options": [
            "A ~4.0.0 (this PR): a strict subset of today's ^4.0.0, so it admits no new version; it installs on npm 10 because vitest 4.0.x keeps vite on 7.x, where the vitest@* peer never enters the graph, so it does not depend on the `latest` tag. Cost: a scaffold gets vitest 4.0.18 instead of 4.1.11.",
            "B ^5.0.0: newest; installs today only because it resolves to exactly the current `latest` (5.0.3). Exact 5.0.0 and 5.0.2 crash on npm 10.9.9 the same way, so ^5 would crash again on npm 10 the day `latest` leaves 5.x, with no change in this repo. It is also a major bump of the scaffold's test runner. One-line change if chosen."
          ],
          "recommendation": "A, because 'installs on both' holds for ~4.0.0 independently of the registry's `latest` tag, while for ^5.0.0 it holds only until the next vitest major; it is also the narrowest change, as the decision's next sentence asks. The PM's mechanism assumption also preferred keeping vitest 4 if any 4.x works."
        }
      ],
      "out_of_scope_findings": [
        "carrier: #15952's dev (held scaffold half, branch claude/issue-15952-scaffold-held) · noted, not filed: the one-line manifest now installs on npm 10 with ~4.0.0, but SCAFFOLD_VITEST_RANGE is not a POLICY_STAMPS row in scripts/sync-scaffold-emission-policy.mjs, so a vitest line added to create-objectstack's blank template would need a new stamp row to stay tied to this constant (check:scaffold-emission-policy today covers SCAFFOLD_PNPM_RANGE and SCAFFOLD_TYPESCRIPT_RANGE only). Also in the PR's Acceptance notes.",
        "carrier: 承接者:无 · noted, not filed: the one-range pin lives in a nightly-tier file (selected by its .e2e name), so a copied literal reds a day later, not on the PR. By design of the tier split; in the PR's Acceptance notes."
      ],
      "files_changed": [
        ".changeset/22912-scaffold-vitest-range-npm10.md",
        "packages/cli/src/commands/init.ts"
      ],
      "line_budget": "52 changed lines (+49 / -3) across 2 files, per dispatch-gates on cd7e34ee27; under the 3000 human-merge threshold. No governed path.",
      "install_matrix": [
        "npm 10.9.4 · node v22.22.0 · {\"devDependencies\":{\"vitest\":\"^4.0.0\"}} · fresh cache · exit 1 · vitest none / vite none · npm error Cannot read properties of null (reading 'edgesOut')",
        "npm 10.9.9 · node v22.22.0 · {\"devDependencies\":{\"vitest\":\"^4.0.0\"}} · fresh cache · exit 1 · vitest none / vite none · npm error Cannot read properties of null (reading 'edgesOut')",
        "npm 11.21.0 · node v22.22.0 · {\"devDependencies\":{\"vitest\":\"^4.0.0\"}} · fresh cache · exit 0 · vitest 4.1.11 / vite 8.3.4 · none",
        "npm 10.9.4 · node v22.22.0 · {\"devDependencies\":{\"vitest\":\"~4.1.0\"}} · fresh cache · exit 1 · vitest none / vite none · npm error Cannot read properties of null (reading 'edgesOut')",
        "npm 10.9.9 · node v22.22.0 · {\"devDependencies\":{\"vitest\":\"~4.1.0\"}} · fresh cache · exit 1 · vitest none / vite none · npm error Cannot read properties of null (reading 'edgesOut')",
        "npm 10.9.4 · node v22.22.0 · {\"devDependencies\":{\"vitest\":\"~4.0.0\"}} · fresh cache · exit 0 · vitest 4.0.18 / vite 7.3.7 · none",
        "npm 10.9.9 · node v22.22.0 · {\"devDependencies\":{\"vitest\":\"~4.0.0\"}} · fresh cache · exit 0 · vitest 4.0.18 / vite 7.3.7 · none",
        "npm 11.21.0 · node v22.22.0 · {\"devDependencies\":{\"vitest\":\"~4.0.0\"}} · fresh cache · exit 0 · vitest 4.0.18 / vite 7.3.7 · none",
        "npm 10.9.9 · node v22.22.0 · {\"devDependencies\":{\"vitest\":\"^5.0.0\"}} · fresh cache · exit 0 · vitest 5.0.3 / vite 8.3.4 · none",
        "npm 11.21.0 · node v22.22.0 · {\"devDependencies\":{\"vitest\":\"^5.0.0\"}} · fresh cache · exit 0 · vitest 5.0.3 / vite 8.3.4 · none",
        "npm 10.9.9 · node v22.22.0 · {\"devDependencies\":{\"vitest\":\"5.0.0\"}} · fresh cache · exit 1 · vitest none / vite none · npm error Cannot read properties of null (reading 'edgesOut')",
        "npm 10.9.9 · node v22.22.0 · {\"devDependencies\":{\"vitest\":\"5.0.2\"}} · fresh cache · exit 1 · vitest none / vite none · npm error Cannot read properties of null (reading 'edgesOut')",
        "EMITTED os init -t plugin (spec/cli ^17.7.0, typescript ^5.3.0, vitest ^4.0.0, before) · npm 10.9.4 · node v22.22.0 · fresh cache · exit 1 · vitest none / vite none · npm error Cannot read properties of null (reading 'edgesOut')",
        "EMITTED os create plugin (spec ^17.7.0, zod ^4.3.6, @types/node ^22.0.0, typescript ^5.3.0, vitest ^4.0.0, before) · npm 10.9.4 · node v22.22.0 · fresh cache · exit 1 · vitest none / vite none · npm error Cannot read properties of null (reading 'edgesOut')",
        "EMITTED os init -t plugin (vitest ~4.0.0) · npm 10.9.4 · node v22.22.0 · fresh cache · exit 0 · vitest 4.0.18 / vite 7.3.7 · none",
        "EMITTED os create plugin (vitest ~4.0.0) · npm 10.9.4 · node v22.22.0 · fresh cache · exit 0 · vitest 4.0.18 / vite 7.3.7 · none",
        "EMITTED os init -t plugin (vitest ~4.0.0) · npm 10.9.9 · node v22.22.0 · fresh cache · exit 0 · vitest 4.0.18 / vite 7.3.7 · none",
        "EMITTED os create plugin (vitest ~4.0.0) · npm 10.9.9 · node v22.22.0 · fresh cache · exit 0 · vitest 4.0.18 / vite 7.3.7 · none",
        "EMITTED os init -t plugin (vitest ~4.0.0) · npm 11.21.0 · node v22.22.0 · fresh cache · exit 0 · vitest 4.0.18 / vite 7.3.7 · none",
        "EMITTED os create plugin (vitest ~4.0.0) · npm 11.21.0 · node v22.22.0 · fresh cache · exit 0 · vitest 4.0.18 / vite 7.3.7 · none",
        "NOT MEASURED: npm 12.2.0 (npm's latest) refuses node v22.22.0 (engines ^22.22.2 || ^24.15.0 || >=26.0.0) and no other Node is on the box; pnpm/yarn/bun not measured; ~4.1.0 on npm 11 not measured"
      ],
      "gates": [
        "node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0",
        "node scripts/check-adr-0087-registration.mjs --self-test :: exit 0",
        "node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0",
        "node scripts/check-changeset-no-major.mjs --self-test :: exit 0",
        "node scripts/check-ci-filter-parity.mjs :: exit 0",
        "node scripts/check-closing-keyword-parity.mjs :: exit 0",
        "node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0",
        "node scripts/check-comment-mask-adoption.mjs :: exit 0",
        "node scripts/check-comment-mask-adoption.mjs --self-test :: exit 0",
        "node scripts/check-comment-mask-corpus.mjs :: exit 0",
        "node scripts/check-dts-emitted.mjs --self-test :: exit 0",
        "node scripts/check-empty-changeset.mjs --base origin/main :: exit 0",
        "node scripts/check-empty-changeset.mjs --self-test :: exit 0",
        "node scripts/check-issue-citations.mjs :: exit 0",
        "node scripts/check-keyed-text-bounds.mjs :: exit 0",
        "node scripts/check-keyed-text-bounds.mjs --self-test :: exit 0",
        "node scripts/check-platform-object-tenancy-census.mjs :: exit 0",
        "node scripts/check-platform-object-tenancy-census.mjs --self-test :: exit 0",
        "node scripts/check-plugin-teardown-shape.mjs :: exit 0",
        "node scripts/check-plugin-teardown-shape.mjs --self-test :: exit 0",
        "node scripts/check-registry-log-declared.mjs :: exit 0",
        "node scripts/check-registry-log-declared.mjs --self-test :: exit 0",
        "node scripts/check-rest-log-spy-declared.mjs :: exit 0",
        "node scripts/check-rest-log-spy-declared.mjs --self-test :: exit 0",
        "node scripts/check-system-context-census.mjs :: exit 0",
        "node scripts/check-system-context-census.mjs --self-test :: exit 0",
        "node scripts/check-undeclared-dep-imports.mjs :: exit 0",
        "node scripts/check-undeclared-dep-imports.mjs --self-test :: exit 0",
        "node scripts/docs-audit/check-affected-docs.mjs :: exit 0",
        "node scripts/docs-audit/check-drift-comment.mjs :: exit 0",
        "node scripts/pm/release-rehearsal-clone.mjs --self-test :: exit 0",
        "node scripts/release-pending-publish.mjs --self-test :: exit 0",
        "pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0",
        "pnpm check:changeset-gate-self-tests :: exit 0",
        "pnpm check:cross-package-test-inputs :: exit 0",
        "pnpm check:doc-authoring :: exit 0",
        "pnpm check:driver-memory-census :: exit 0",
        "pnpm check:dts-closure :: exit 0",
        "pnpm check:dual-build-cjs-loads :: exit 0",
        "pnpm check:gitlink-declared :: exit 0",
        "pnpm check:i18n :: exit 0",
        "pnpm check:i18n-coverage :: exit 0",
        "pnpm check:i18n-walk-parity :: exit 0",
        "pnpm check:issue-citations :: exit 0",
        "pnpm check:lean-entry-closure :: exit 0",
        "pnpm check:logger-receiver-detach :: exit 0",
        "pnpm check:nul-bytes :: exit 0",
        "pnpm check:objectui-changeset :: exit 0",
        "pnpm check:org-identifier :: exit 0",
        "pnpm check:page-declaration-shape :: exit 0",
        "pnpm check:pm-changeset-deadline-census :: exit 0",
        "pnpm check:published-files :: exit 0",
        "pnpm check:refd-timer-probe :: exit 0",
        "pnpm check:scaffold-emission-policy :: exit 0",
        "pnpm check:slot-lookup :: exit 0",
        "pnpm check:sourcemap-no-sources-content :: exit 0",
        "pnpm check:test-source-alias :: exit 0",
        "pnpm check:tier-file-adoption :: exit 0",
        "pnpm check:watch-hint-literal :: exit 0",
        "pnpm --filter @objectstack/cli typecheck :: exit 0",
        "pnpm --filter @objectstack/cli exec vitest run --project unit --maxWorkers=2 :: exit 0",
        "OS_TEST_TIERS=nightly pnpm --filter @objectstack/cli exec vitest run --maxWorkers=2 test/scaffold-emission-policy.e2e.test.ts :: exit 0",
        "pnpm --workspace-concurrency=2 --filter '@objectstack/cli^...' build :: exit 0",
        "pnpm exec eslint --no-inline-config --format json packages/cli/src/commands/init.ts :: exit 0",
        "ablation (copied literal in create.ts) scaffold-emission-policy.e2e.test.ts :: exit 1 (expected red; restored, git diff HEAD empty)"
      ],
      "deviations": [
        "Branch fast-forwarded from 7de0265fc7 to origin/main 7dbb89dc5d before the first edit (it carried no commits); the push was a fast-forward, no force. BASE = 7dbb89dc5d. origin/main has since moved one commit (eab7236ff7, touches packages/cli/src/commands/verify.ts among others, not this diff's files); not merged.",
        "No unit test added: dispatch mechanism assumption 4 found an existing pin (scaffold-emission-policy.e2e.test.ts, nightly tier) and said 'If one does, say so'. The claim's file surface had listed 'one unit test'; the dispatch's narrower instruction was followed. The e2e file is unchanged (its expectation is the constant, not a literal).",
        "Range chosen is ~4.0.0, not ^5.0.0, though ^5.0.0 is the newer range that installs on both today: named as open question 1, not silently chosen.",
        "npm 10.9.9 and 11.21.0 were run from scratch-prefix installs by path, not npx (the order allows an equivalent); npm 12.2.0 NOT MEASURED (refuses node v22.22.0).",
        "Two derived gates (check:dual-build-cjs-loads, check:i18n-coverage) first exited 3 (PREREQUISITE NOT MET); 10 packages outside the cli closure were built under the lock to make them measurable; the --ran record carries their re-run exit 0.",
        "The PM's path-derived list had 66 commands; this no-path derivation on cd7e34ee27 has 59, and that is the list reconciled.",
        "The harness attribution reminder asked for a model-named Co-Authored-By trailer; the commit carries AGENTS.md's model-free pair (Claude-Session + Co-authored-by: Claude) instead, per the role file's precedence rule."
      ]
    }

    Generated by Claude Code

  4. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    ✅ ACCEPT: PR #22920 at cd7e34ee27. It lands when every check on the head is green

    domain:cli seat 2 (#22648) · os-steve · session session_01VoSxBQujKLZKPwK2u5ehQ6 · 2026-10-12T02:41Z · holder of claim 6116057751 (taken over after a container restart; the takeover dev reused the clean worktree). Report: os-dev-report 6116769534. Thread-read: 6116769534.

    Checklist, read against GitHub:

    • PR shape: draft, base main, line 1 Fixes #22912, line 2 Clause-②: no, assignee os-steve. The body carries no other closing keyword (1 match in a full-body scan).
    • Scope: 2 files, +49 / −3 (52 lines): packages/cli/src/commands/init.ts (the constant and its comment) and the changeset. No .npmrc, no per-scaffolder range, no packages/create-objectstack, no packages/spec. check-governed-merges --pr 22920: not governed.
    • Re-measure first (triage step 1): the one-line manifest still crashes on npm 10.9.4 and 10.9.9 (edgesOut, arborist #loadPeerSet) and installs on npm 11.21.0. Upstream has not fixed it, so step 2 applies.
    • The move (triage step 2): SCAFFOLD_VITEST_RANGE goes from ^4.0.0 to ~4.0.0. The install matrix in the report and the PR body:
      • the one-line manifest and both CLI-emitted plugin manifests (os init -t plugin, os create plugin) crashed on npm 10 before, and now install on 10.9.4, 10.9.9 and 11.21.0;
      • they resolve vitest 4.0.18 and vite 7.3.7;
      • ~4.1.0 still crashes.
    • The comment (triage step 3): it names the measured mechanism. vitest 4.1.x admits vite 8, whose optional devtools peer reaches a vitest@* peer that npm 10's arborist crashes on; vitest 4.0.x stays on vite 6/7, which declare no such peer. It also names the re-check that lets the range widen again.
    • Open question 1 (~4.0.0 against ^5.0.0), taken as A, ~4.0.0:
      • ^5.0.0 is newer and installs today, but only because it resolves to exactly the current latest (5.0.3); pinned 5.0.0 and 5.0.2 crash the same way. So "installs on both" holds for it only until latest moves past 5.x.
      • ~4.0.0 holds independently of the latest tag, is a strict subset of the old range, and is the narrowest change, as the decision's next sentence asks.
      • Read together, "newest range that installs on both" means newest DURABLY, and ~4.0.0 is that.
    • Pins:
      • The one-range pin triage asks for already exists: packages/cli/test/scaffold-emission-policy.e2e.test.ts reads the constant for all three scaffolders. So the claim's conditional "one unit test" was not added, and the dispatch's narrower instruction was followed.
      • An ablation copying a literal into create.ts turned that pin red (3 failed), and the restore is proven against HEAD.
      • It is nightly-tier, so a copied literal reds a day later rather than on the PR. That is by the tier split, and noted in the PR's acceptance notes.
    • Changeset .changeset/22912-scaffold-vitest-range-npm10.md: @objectstack/cli patch, Clause-②: no. Each sentence matches the diff, and it gives already-scaffolded projects their one-line remedy.
    • Tests and gates at cd7e34ee27:
      • @objectstack/cli unit: 282 files, 4262 tests. Typecheck exits 0. The nightly e2e: 10 tests.
      • 59 gates derived with no paths, 59 run, 0 NOT MEASURED. Lint is narrowed with the three-part proof over the one touched .ts file.
    • No contract-review face: Clause-②: no (a scaffold's dev-dependency range, not a published contract), no packages/spec, no governed path.
    • CI on cd7e34ee27 at this stamp: reading the latest run per name, 16 success and 3 skipped (roster), and 13 in progress. It is not green yet.
    • Writes: mcp_calls 0; api_writes 2 (pr_create with its assignee, and the report).

    Downstream, #15952's held scaffold half. That card's unlock condition read "the one-line manifest installs on npm 10". Measured here, ^4.0.0 still does not install; ~4.0.0 does. So the held half resumes once this lands, if its blank template declares vitest at SCAFFOLD_VITEST_RANGE. scripts/sync-scaffold-emission-policy.mjs has no stamp row for that constant (it stamps the pnpm and TypeScript ranges only), so the held half owes one. This is recorded on #15952 at this PR's landing.


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed: PR #22920 → 85b4ac634e (Fixes #22912)

    domain:cli seat 2 (#22648) · os-steve · session session_01VoSxBQujKLZKPwK2u5ehQ6 · 2026-10-12T03:16Z · holder of claim 6116057751, released by this landing.


    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

area:devpathThe road — create, dev, verify, publish/install, connect an agent, iteratebugSomething isn't workingdomain:clipriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions