Skip to content

test: seven suites keep their temp databases and scaffolds off the shard's shared disk (memory-backed TMPDIR) - #27379

Merged
objectstack-fleet[bot] merged 9 commits into
mainfrom
claude/project-thread-qe3lcv
Oct 29, 2026
Merged

objectstack-fleet[bot] merged 9 commits into
mainfrom
claude/project-thread-qe3lcv

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

domain:server#3 · os-bill · session_01Utp6CXc5hequf76uJfzrdK

Requested by Bill · project thread
Fixes #27306

Clause-②: no
Metadata-protocol: none

维护者速读

  • 改了什么:create-objectstack、cli、runtime、driver-turso、driver-sql、service-package、service-automation 七个包的测试配置,把测试临时目录(TMPDIR)指到内存盘 /dev/shm;新增共享助手 scripts/vitest-memory-tmp.mjs(附 .d.mts 类型声明),driver-sqlite-wasm 也改读它。不动任何产品代码、用例、断言或超时。
  • 为什么改:这些测试把 SQLite 库或脚手架目录写在系统临时目录里,CI 分片上磁盘被邻居测试占满时,fsync 和删目录要排队,用例或收尾钩子就超时;main 上两次 Test Core (5/8) 红灯落在 create-objectstack。
  • 风险与回滚:只影响测试进程的临时目录;没有可写 /dev/shm 的机器(macOS、Windows)照旧用系统临时目录。回滚即 revert 本 PR。
  • 先看:scripts/vitest-memory-tmp.mjs(理由与开关)、packages/create-objectstack/vitest.config.ts(与 main 红灯同形的那一包)、packages/cli/vitest.config.ts(两个 project 各自带 env)。
  • 两分钟验证:pnpm --filter create-objectstack test,应 19 个文件全绿;在 4 个 dd conv=fsync 写入者旁跑同一命令,改前 2 个文件因 afterAll 超时失败,改后全绿。
  • 需要你做的:无,席位落地。

What changes

No product source changed. No case, assertion, fixture, timeout or budget changed, and no retry was added (the #27076 ruling).

Why

os.tmpdir() reads TMPDIR, and a child process inherits it. Every database file and scaffold tree these suites write was measured to sit under os.tmpdir() (the card asked for this reading per package). So the one setting moves all of it off the runner's shared disk. On a Test Core shard, a case that fsyncs, or a hook that unlinks a tree, waits for the other suites' I/O, so its wall time measures the neighbours rather than the code.

create-objectstack, stated in three parts, as the seat asked:

  1. The failing case in main's two reds is NOT MEASURED. Push CI runs 40713919581 and 40718500281 (Test Core (5/8)) annotate only packages/create-objectstack … pnpm run test exited (1). Their full job logs and artifacts are served from a storage host that this cloud container's egress proxy refuses (403). The log API returns only the last 5,000 lines, and the failing segment sits near line 33,848 of 42,326.
  2. The local signature matches, but it is not proven to be the same failure. Beside four dd conv=fsync writers, all 301 cases passed while two FILES failed with Hook timed out in 10000ms. The timeouts were in the afterAll that removes the scaffolded tree (created-summary.test.ts:134, scaffold-skills-single-copy.test.ts:289). That gives a red package with no failed test named, which is the shape of the annotation.
  3. The mechanism is metadata disk load, not fsync. strace -f -c over the whole suite counted 4 fsync, 4,018 unlink and 6,202 rmdir calls. The scaffolds' creation and removal is what waits on the loaded disk. The same isolation fixes it, because every path is under os.tmpdir().

For the other packages, the mechanism is SQLite durability I/O. Under strace, one cli file (organization-ownership-apply.generation-1.test.ts) made 3,388 fsync calls. One runtime file (package-revert-stored-members.integration.test.ts) made 784 fsync and 982 unlink calls, the second being SQLite's per-transaction journal deletes.

Tests

Each package was measured three ways on the same files: idle on the base, beside four dd if=/dev/zero bs=1M count=256 conv=fsync writers on the same disk on the base, and beside the same writers on the head. All runs were on tree objectstack@6d7634a9 (base) and this branch (head), in a 4 vCPU cloud container with / on /dev/vda and /dev/shm on tmpfs, using vitest run --maxWorkers=2. Four synthetic writers are a stress, not a replay of a shard, so a red here means "exposed", not "will go red". The absolute seconds are shared-box readings.

Package (files measured) Idle, base Under load, base Under load, head
create-objectstack (all 19) 19/19 files, 21 s 2/19 files fail (afterAll hook timeouts, 0/301 cases), 236 s 19/19 files, 20 s
cli (the 15 organization-ownership-* files) 232/232, 68 s 145/232 cases time out, 7 files, 1,809 s 232/232, 59 s
runtime (51 files using SQLite under os.tmpdir()) 684/684, 102 s 25/684 time out, 7 files (package revert, uninstall, duplicate-adopt, list-commits, audit-meta-item), 501 s 684/684, 110 s
driver-turso (14 files using os.tmpdir()) 502/502, 17 s 21/502 time out, 4 files (inherited-members, external-object-parity, drift-detection, migration-entries), 211 s 502/502, 17 s
driver-sql (23 files using os.tmpdir()) 192/192, 28 s 3/192 time out (posture conformance, reclaim-space, declared-index retired keys), 98 s 192/192, 28 s
service-package (2 files) 11/11, slowest case 0.17 s 11/11 green, slowest case 3.04 s 11/11, slowest case 0.15 s
service-automation (4 files) 86/86, slowest case 0.31 s 86/86 green, slowest case 4.35 s of its 5 s budget 86/86, slowest case 0.34 s

Every failure under load on the base is Test timed out or Hook timed out. None is an assertion failure, and none fails idle. service-package and service-automation stayed green in this load run (the card's survey had 5 of 11 and 1 of 8 failing). They are treated because the card lists them as exposed and the readings put them at 61% and 87% of budget for no change in code.

Full package suites on the head: each affected package's own suite, idle, on the final head 110f05aa (after merging origin/main), unless noted:

  • cli unit layer (vitest run --project unit): 346/346 files, 5,032/5,032 tests. The integration layer is CI's; its 14 measured organization-ownership-* integration files are in the table above.
  • runtime (pnpm test): 471 files, 7,668 passed and 19 skipped.
  • On fb2d18d7, before the merge of main, which touched no file of these five: driver-turso 95 files, 2,492 passed and 34 skipped; driver-sql 236 files passed and 12 skipped, 3,847 tests passed and 214 skipped; service-package 10/10 files, 127/127; service-automation 217/217 files, 2,768/2,768; create-objectstack 19/19 files, 301/301; driver-sqlite-wasm 39/39 files, 746/746.

Acceptance notes

  • service-print (the card's Chromium-profile exception) and the other fsyncing packages in the card's survey (dogfood, plugin-auth, verify, service-datasource, plugin-security, plugin-pinyin-search, rest) are not touched. The card's own table measured the last four of those green under load, and dogfood, verify and rest were not in its exposure table.
  • Some cli tests deliberately scaffold under packages/cli/node_modules/… or packages/cli/tmp (they need the workspace's module resolution) and are not moved by TMPDIR. They were not in the measured failing family, and this PR leaves them alone.
  • The survey's evidence file (pm-orders/server/evidence/27076/fsync-survey.md) was not reachable from this account, so every reading above was re-measured here.
  • No changeset: the diff touches only vitest configs and a root test helper, none of which is in any package's published files. Check Changeset reports whatever it reports, and the seat decides on the label.

Verification

All on the final head 110f05aa.

Derived gate families: 45 derived, 45 run, all exit 0

node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 45 families from the 9 changed paths. Each was run and its exit code recorded, then reconciled with --ran: ✓ dispatch-gates --ran: 45 derived famil(ies) accounted for — 45 run, 0 NOT-MEASURED. Two notes. check-plugin-teardown-shape.mjs --self-test first exited 3 on a shallow clone (its pinned fixture commit was unreachable) and exited 0 after git fetch --unshallow. check:dts-closure and check:dual-build-cjs-loads read built output, so they were run after a full turbo run build.

Lint

eslint --no-inline-config over the nine touched files: exit 0. The repo-wide pnpm lint is CI's.

How the load was made

Four loops of dd if=/dev/zero of=FILE bs=1M count=256 conv=fsync on the same disk as /tmp, started 3 s before the suite and stopped after it. Each base/head pair used the same file list and --maxWorkers=2. The per-file and per-case durations come from vitest's JSON reporter.

Human Minimum

  • 1. Schemas start as Zod; packages/spec holds no runtime logic. (not touched)
  • 2. Every name I added uses the casing for its kind.
  • 3. No formatter ran; pnpm lint passes. (eslint on the nine touched files, exit 0; the repo-wide run is CI's)
  • 4. One issue, one branch off an up-to-date main, one pull request.
  • 5. A change that publishes carries a changeset, and both declaration lines are filled in here and in the changeset. (publishes nothing)
  • 6. packages/spec touched: its generated artifacts are regenerated and committed. (not touched)
  • 7. No hand edits to content/docs/references/, packages/*/CHANGELOG.md or content/docs/releases/.
  • 8. Title, body and comments are in English.
  • The Before Submitting list in CONTRIBUTING.md is done. (the local subset is above; the full farm is CI's)

Generated by Claude Code

…les on a memory-backed TMPDIR

Claude-Session: https://claude.ai/code/session_01Utp6CZiAsVSvj5E1XZbWrG
Co-authored-by: Claude <noreply@anthropic.com>
…elper; readings in each config

Claude-Session: https://claude.ai/code/session_01Utp6CZiAsVSvj5E1XZbWrG
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

2 anchor(s) derived from 8 changed package(s); no hand-written page names any of them. ⚠️ 7 changed file(s) yielded no anchor (packages/cli/vitest.config.ts, packages/create-objectstack/vitest.config.ts, packages/drivers/driver-sql/vitest.config.ts, …), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files.

What this run could not see
  • 7 changed file(s) yielded no anchor (packages/cli/vitest.config.ts, packages/create-objectstack/vitest.config.ts, packages/drivers/driver-sql/vitest.config.ts, …) — pages documenting those are invisible to this run
  • the SDK route bridge reached 58 of 210 client-bound route-ledger rows — the other 152 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 152: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 55 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 97 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 63 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 7e200b4a68c242afc9f7caf0289e985eff3fcac6 → packageMentionDocs.

Which tree this was computed on

This run read content/docs from ba1cf2ea549be224cd9c7c2c975c1f42f11e9014 — the merge of head 51e902259e987d5b89f4d339069fada235579e55 into base 7e200b4a68c242afc9f7caf0289e985eff3fcac6, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin ba1cf2ea549be224cd9c7c2c975c1f42f11e9014 && git checkout ba1cf2ea549be224cd9c7c2c975c1f42f11e9014
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 7e200b4a68c242afc9f7caf0289e985eff3fcac6 51e902259e987d5b89f4d339069fada235579e55 && git checkout -B drift-repro 7e200b4a68c242afc9f7caf0289e985eff3fcac6 && git merge --no-ff 51e902259e987d5b89f4d339069fada235579e55

node scripts/docs-audit/affected-docs.mjs --json 7e200b4a68c242afc9f7caf0289e985eff3fcac6

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Oct 29, 2026
…mp.mjs with a declaration

A package tsconfig.test.json type-checks its vitest.config.ts, where a .mts
import path is TS5097. The helper follows the tsup-drop-sources-content.mjs
shape: an .mjs module with a hand-written .d.mts that check:declaration-mirrors
holds in step.

Claude-Session: https://claude.ai/code/session_01Utp6CZiAsVSvj5E1XZbWrG
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:server#3 · os-bill · session_01Utp6CXc5hequf76uJfzrdK

席位核对 — ACCEPT · domain:server#3 · session_01Utp6CXc5hequf76uJfzrdK · head 51e90225 · 2026-10-29T05:02Z

  • Shape: 10 files, vitest configs only. A new helper, scripts/vitest-memory-tmp.mjs (a .mjs with a hand-written .d.mts beside it, after tsup-drop-sources-content.mjs; the round-2 fix for the TS5097 that check:test-typecheck caught in packages/cli/vitest.config.ts at 110f05aa), carries memoryBackedTmpEnv(): it sets TMPDIR to /dev/shm when that directory is writable, and sets nothing otherwise. The helper is lifted verbatim from driver-sqlite-wasm's inline copy (4-hourly full run: red on main (CI) #27076), which now imports it. The other seven configs spread it into their test.env:

    • create-objectstack, cli and runtime, in both of their projects;
    • driver-turso and driver-sql;
    • service-package and service-automation.

    Not touched: no source, no assertion, no budget, no packages/spec, no governed surface.

  • Existing env keys are kept. OS_REGISTRY_LOG: 'warn' is spread beside the new key in every config that had it. Per-project env is restated in cli and runtime because a root value is inert under projects.

  • driver-turso moves from a bare preset re-export to its own defineConfig. It restates disableConsoleIntercept: true with the finding: any late console.* in a vitest worker can fail a fully green suite — the #9371 amplifier is upstream and still live #10374 note, which is the shape check-console-intercept-disarm judges, and it leaves every other key on vitest's defaults, the same as the re-export.

  • What it measures, as stated per config. Each config compares the base and the head, idle and beside four dd … conv=fsync writers. The base reds or nears its budget on Test/Hook timeouts only. The head stays at its idle times.

    • create-objectstack is stated as the dispatch asked. The mechanism is metadata I/O (unlinks and rmdirs), not fsync. The CI failing case itself is NOT MEASURED: the signature matches, but nothing proves it is the same case.
  • Read for side effects:

    • Child processes inherit TMPDIR, which is the intent.
    • A path built from the package or repo root does not follow TMPDIR. The helper's header says so.
    • Hosts without /dev/shm (macOS, Windows) keep their own temp directory.
    • tmpfs holds what the suites leave behind in RAM. The suites mkdtemp and remove their trees, and the leftover report on Test Core counts repo paths. Accepted.
  • Declaration: Clause-②: no, Metadata-protocol: none. The diff publishes nothing, so the seat applied skip-changeset (no .changeset row is added or changed). Review face TIER_DEFAULT, hits empty, so no contract review is owed.

  • Gates: all 50 check-runs on 51e90225 completed with no failure (Check Changeset skipped under the label).

  • Landing: ready → auto-merge through the queue. On merge, pm:dispatched comes off tests: SQLite-backed suites in cli, runtime, driver-turso, driver-sql and service-package time out under shard disk load (fsync); give them the #27076 TMPDIR treatment #27306.


Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 29, 2026 05:03
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 29, 2026
Merged via the queue into main with commit cf218ee Oct 29, 2026
55 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/project-thread-qe3lcv branch October 29, 2026 05:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/m skip-changeset PR has no user-facing published change; bypasses the changeset gate tests

Projects

None yet

2 participants