Repository navigation
Commit 7d11067
fix(cloud-connection): stage the ledger adoption copy without mkdtempSync, so main's dispatch-gates lane is green again (#30487)
<!-- claude-projects-attribution: {"github_login":"os-bill"} -->
_Requested by **Bill** · [project
thread](https://claude.ai/code/project/chan_016iMXWSZDzqWRWvWzdNo8wg?thread=cmsg_016iMXWSZDzqWRWvWzdNo8wg9MmNtLnaKdSpq9S7Ah47uy)_
domain:server#3 · os-bill · session_01Utp6CZ9g1bEV7DPMneGKAx
Fixes #30467
Clause-②: no
Metadata-protocol: none
## 维护者速读
- **改了什么:** 本地安装账本首次从工作目录复制到 `OS_HOME` 时用的暂存目录,改用「随机名 + 独占
mkdirSync」创建,不再用 `mkdtempSync`。行为不变:仍是账本目录旁的唯一兄弟目录,复制完重命名到位,失败即删除。
- **为什么改:** PR #30351(#30217)落地后 `main` 的 `Lint · PM dispatch-gates`
一直红:dispatch-gates 自测要求每个 `mkdtempSync` 的基路径都能从源码读出,而这里的基路径是运行时才解析的账本位置。
- **风险与回滚:** 只改一处暂存目录的创建方式,另加一行 `node:crypto` 导入;名字碰撞时非递归 `mkdirSync` 抛
EEXIST,与 `mkdtempSync` 同样不复用已有目录。回滚即撤 PR(main 会再次变红)。
- **先看:** `packages/cloud-connection/src/local-manifest-source.ts` 的
`adoptLegacyEntries`(第 333 行起那段)。
- **两分钟验证:** `pnpm --filter @objectstack/cloud-connection exec vitest
run src/local-manifest-source.test.ts`,预期 adoptLegacyEntries
四个用例全过(含「失败不留账本目录」「不留暂存目录」)。
- **需要你做的:** 无,席位落地。
## What changes
`LocalManifestSource.adoptLegacyEntries()` (added by #30351, the
breaking commit `bc254be33e`) staged its copy with
`mkdtempSync(join(dirname(this.dir), ...))`. `this.dir` is the ledger
location resolved at run time (`OS_HOME`, or an explicit `storageDir`),
so the in-tree scratch scan in `scripts/pm/dispatch-gates.mjs` cannot
read that base. The scan holds `mkdtempSync` to completeness (an
unresolved base is a failure), so the dispatch-gates self-test case "no
mkdtempSync site in this tree takes a base the scan cannot read" has
been red on every `main` run since.
The staging directory is now spelled as an exclusive, non-recursive
`mkdirSync` of a randomly named sibling:
`.LEDGER_BASENAME.adopting-HEX12` (12 hex characters from
`randomBytes(6)`) under `dirname(this.dir)`. Why this spelling and not
one the scan resolves: no spelling of this base can be resolved from
source, because the base really is a run-time value (it may even land
inside a project checkout when `OS_HOME` points there). `mkdirSync` is
the shape the scan deliberately does not hold to completeness (see the
"In-tree scratch directories" block of `dispatch-gates.mjs`: runtime
bases are named in the report and not failed). The uniqueness guarantee
is kept: a non-recursive `mkdirSync` creates the directory atomically
and throws `EEXIST` rather than reuse one that is already there, as
`mkdtempSync` does. The rest is byte-for-byte unchanged: the files are
copied into the staging directory, it is renamed into place, and it is
removed if the copy fails.
`scripts/pm/dispatch-gates.mjs` and its self-test are not touched.
## Tests
No test changes. The four existing `adoptLegacyEntries` cases in
`packages/cloud-connection/src/local-manifest-source.test.ts` already
pin the behaviour this keeps: every file copied, no staging directory
left beside the ledger, nothing adopted once the ledger exists, and a
failed copy leaving neither a ledger nor a staging directory.
## Acceptance notes
- Ablation: not run. The diff changes how a directory is created, not a
tested behaviour; the existing cases above are the behaviour pins and
pass unchanged.
## Verification
All readings on head `c4fb1fe5`.
<details><summary>The failing self-test case, before and after</summary>
- CI, `main` at `c58008187` (run 42025638313, `Lint · PM
dispatch-gates`): `✗ no mkdtempSync site in this tree takes a base the
scan cannot read — UNRESOLVED:
packages/cloud-connection/src/local-manifest-source.ts:333 (a base this
scan cannot read: this.dir)`, then `✗ dispatch-gates self-test: 1 of
2234 case(s) failed.`
- The same scan (`exposedScratchDirs` from
`scripts/pm/dispatch-gates.mjs`), local: `origin/main f506b79:
mkdtempSync unresolved = 1
packages/cloud-connection/src/local-manifest-source.ts:333 (a base this
scan cannot read: this.dir)`; `head c4fb1fe: mkdtempSync unresolved = 0
; exposed = 0`.
- `node scripts/pm/check-dispatch-gates.mjs --slow` (both tiers, as
`main`'s push and schedule runs do) on head: `✓ no mkdtempSync site in
this tree takes a base the scan cannot read` and `✓ every in-tree
directory this tree's sources create is covered by a tracked ignore
rule, or is tracked itself`. The battery's total verdict line is quoted
in the os-dev-report on #30467.
- `pnpm check:pm-dispatch-gates` (fast tier, as PR and queue runs do) on
head: `✓ dispatch-gates self-test (fast tier): 1945 cases pass; 7 slow
section(s) deferred.`, exit 0. The case this PR fixes sits in a slow
section, so this PR's own CI does not run it; the first CI run that does
is `main`'s push battery after merge.
</details>
<details><summary>Package tests and type check</summary>
- `pnpm --filter '@objectstack/cloud-connection^...' build`: exit 0.
- `pnpm --filter @objectstack/cloud-connection test`: `Test Files 70
passed (70)`, `Tests 877 passed (877)`.
- `pnpm --filter @objectstack/cloud-connection typecheck`: exit 0.
</details>
<details><summary>Derived gates (dispatch-gates --commands, 51
commands)</summary>
`node scripts/pm/dispatch-gates.mjs --ran` on head: `✓ dispatch-gates
--ran: 51 derived famil(ies) accounted for — 49 run, 2 NOT-MEASURED (2
DERIVED from a recorded exit 3).` All 49 run exit 0. NOT MEASURED, left
to CI: `node scripts/check-plugin-teardown-shape.mjs --self-test`
(shallow clone cannot reach its pinned control commit) and `pnpm
check:dual-build-cjs-loads` (needs every package built).
</details>
---
_Generated by [Claude
Code](https://claude.ai/code/session_01Utp6CZ9g1bEV7DPMneGKAx)_
Co-authored-by: Claude <noreply@anthropic.com>1 parent 455b4f0 commit 7d11067
2 files changed
Lines changed: 18 additions & 3 deletions
File tree
- .changeset
- packages/cloud-connection/src
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
30 | 30 | | |
31 | 31 | | |
32 | 32 | | |
| 33 | + | |
33 | 34 | | |
34 | | - | |
35 | | - | |
| 35 | + | |
36 | 36 | | |
37 | 37 | | |
38 | 38 | | |
| |||
330 | 330 | | |
331 | 331 | | |
332 | 332 | | |
333 | | - | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
334 | 341 | | |
335 | 342 | | |
336 | 343 | | |
| |||
0 commit comments