Repository navigation
fix(e2e): root the live storage-state write and both storageState configs on their own file - #9631
os-try-charles wants to merge 1 commit into
Conversation
…igs on their own file objectui#9188 repaired the READ of `e2e/live/.auth/state.json`; the write in `e2e/live/global-setup.ts` and the `storageState` option in two Playwright configs still carried a bare relative path, so they took the ambient cwd. Measured on this tree, only the launch directory varying: a run started from `e2e/` really created `e2e/e2e/live/.auth/state.json`, and the repo-root-rooted read then found nothing. Playwright 1.62.1 resolves a relative `use.storageState` against the process cwd, not the config directory (probed both ways with a control), so the config half needed the same repair, and `playwright.import-console.config.ts` carried a third copy of the same string. All three now take the repository's one rooting spelling, bare `import.meta.url` taken apart by hand. A content pin holds the four ends of that path together, since a `global-setup.ts` and a `*.config.ts` match neither half of the path-roots gate's `TEST_FILE` population. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015h79niBMyoB1xcaQje3uiz
Superseded by PR #9636 — closing. ⛔ Nothing here was wrong; the branch was.
This PR's content is ACCEPTED and its review record stands on objectui#9519. The only thing wrong with it was one line of commit-message metadata — ⛔ My first instruction for fixing it was to force-push this branch. That instruction was wrong: So the route taken instead rewrites nothing: the amended commit went up as a new ref, which is an ordinary push. Verified in-seat before closing, ⛔ not on the dev's word
The tree-hash identity is what makes this cheap: every reading in the verification record — both ablation legs, the Playwright cwd-resolution probe with its two-direction control, the end-to-end doubled-path reproduction — was taken against tree ⇒ closing as superseded, not as rejected. Follow PR #9636. Generated by Claude Code |
…figs on their own file (objectstack-ai#9636) **Supersedes objectstack-ai#9631** — same commit content, one line of commit message different. That pull request's single commit carried a co-author trailer naming a model; this branch carries the repository's model-free spelling instead. Nothing in the tree moved: both commits hash the same tree, `55f8b4770b2682a6ba0f7ebcd28458f60d45c3e8`. A new branch rather than an amended one because `AGENTS.md` forbids force-pushing outright, and says in as many words that the ban is not graded by whether a branch has a single user. The superseded pull request is left for the dispatching seat to close. --- Fixes objectstack-ai#9519 ## The asymmetry this repairs objectui#9188 rooted the live storage-state **READ** on the spec's own file. The **WRITE**, and the `storageState` option that names the same file to Playwright, still carried a bare relative path — which names no root, so it takes the ambient cwd. | participant | before | after | |:--|:--|:--| | `e2e/live/global-setup.ts` (writes it) | `const STATE_PATH = 'e2e/live/.auth/state.json'` | `join(REPO_ROOT, 'e2e/live/.auth/state.json')`, REPO_ROOT from bare `import.meta.url` | | `playwright.live.config.ts` (names it) | `storageState: 'e2e/live/.auth/state.json'` | `storageState: STATE_PATH` (absolute, rooted on the config file) | | `playwright.import-console.config.ts` (names it) | same bare string — **a third instance**, see below | same repair | | `e2e/live/inline-edit-polish-2572.spec.ts` (reads it) | already repo-root rooted (objectui#9188) | unchanged | ## Measured, not inferred All three readings below come from real runs on this tree, with the **launch directory as the only variable**, a fake sign-in endpoint standing in for the backend, and the preinstalled Chromium. **1. The doubled path reproduces.** Real `playwright.live.config.ts` + real global setup, started from `e2e/`, before the repair: ``` [live-e2e] authenticated as admin@objectos.ai; storageState written to e2e/live/.auth/state.json PROBE cwd=/…/e2e configStorageState=e2e/live/.auth/state.json repoRootedExists=false Error: ENOENT (repo-root read): /…/e2e/live/.auth/state.json on disk: e2e/e2e/live/.auth/state.json ``` Same command from the repository root: green, file at `e2e/live/.auth/state.json` — so the instrument discriminates and the failure is the cwd, not the probe. **2. The config half was unmeasured; now it is measured, and it needed the repair.** Playwright 1.62.1 resolves a relative `use.storageState` against the **process cwd**, never the config directory. Probe with both copies present, run from a subdirectory of the config dir: the **cwd** copy won. Control, with only the config-dir copy on disk: `Error reading storage state from state/probe-state.json: ENOENT`. Two neighbouring options behave the other way and were left alone: `testDir` and `globalSetup` both resolved against the config directory in the same runs. **3. After the repair, from `e2e/`:** ``` [live-e2e] ... storageState written to /…/objectui-issue-9519/e2e/live/.auth/state.json PROBE cwd=/…/e2e configStorageState=/…/e2e/live/.auth/state.json repoRootedExists=true 1 passed ``` No `e2e/e2e/` tree is created. Control from the repository root: also green. **4. Ablation (one-shot, restored).** With the fix committed, `git checkout` of the base revision put the two bare strings back on disk (grep-confirmed before the run); the probe went red with the doubled path again, and the new content pin went `2 failed | 3 passed` — the two reverted files failing, `playwright.import-console.config.ts` still green because it was not reverted. Restored with `git checkout HEAD -- …`; `git diff HEAD` empty and both blob hashes equal to their HEAD blobs. ## The third instance (⭐ reported, and repaired here) `playwright.import-console.config.ts` carried a byte-identical `storageState: 'e2e/live/.auth/state.json'` and shares the same `globalSetup`. It is the same defect class, the same mechanical repair, and no open pull request holds that file (checked over all open PRs, 1765 filenames examined; positive control on the same instrument: `.github/workflows/ci.yml` is held by PR objectstack-ai#9584). Repairing the live config and leaving this one would have left the card reproducible one config over. ## What is NOT done here, deliberately The path-roots gate's population is `TEST_FILE` — `*.test.*` / `*.spec.*` — so a `global-setup.ts` and a `*.config.ts` match neither, which is how its registry could reach zero while these instances sat one directory away. **Widening that population is not in this pull request**: its pin test is held by PR objectstack-ai#9584, and the scope decision belongs on a card of its own. Instead, `scripts/__tests__/live-e2e-storage-state-roots-9519.test.ts` holds the four known ends of this one path together by content, and states in its header that the gate-population question is open. ## Verification - `pnpm exec vitest run scripts/__tests__/check-test-path-roots.test.ts scripts/__tests__/e2e-type-check.test.ts scripts/__tests__/live-e2e-storage-state-roots-9519.test.ts` — 3 files, 42 tests, passed. - `pnpm type-check:e2e` — exit 0 (this project compiles `e2e/**` and the root `playwright*.config.ts` files). - `pnpm lint:root` — exit 0 (32 pre-existing warnings, 0 errors); this task's scope covers `e2e/`, `scripts/` and the root configs. - `pnpm check:test-path-roots` — OK. `pnpm check:control-bytes` — OK. `pnpm check:new-line-citations` — 0 new citations. - `node scripts/check-changeset-presence.mjs` — exit 0, verdict line: "No source or published contract of a released package changed in this range, so no changeset is owed." (the diff touches no `packages/**` file.) - Not measured here: a full live run against a real backend and console — this branch changes only where the state file is rooted, and CI's live lane runs `pnpm test:e2e:live:ci` from the repository root, where the bare and the rooted spelling are the same file. ## Acceptance notes - Noted, not filed: `e2e/live/ci/better-auth-pin.mjs` resolves its app directory from a CLI argument with `path.resolve`. That is an explicit parameter, the documented behaviour of a CLI, and the gate names "a root that arrives as a function parameter" as a deliberate blind spot rather than this defect. Carrier if anyone revisits it: whoever next edits that script. - The seat asked for a third cwd-rooted path if one existed. It did — `playwright.import-console.config.ts`, repaired above rather than left for later. This work was generated by Claude Code in session `session_015h79niBMyoB1xcaQje3uiz`. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_015h79niBMyoB1xcaQje3uiz --- _Generated by [Claude Code](https://claude.ai/code/session_015h79niBMyoB1xcaQje3uiz)_ Co-authored-by: Claude <noreply@anthropic.com>
Fixes #9519
The asymmetry this repairs
objectui#9188 rooted the live storage-state READ on the spec's own file. The WRITE, and the
storageStateoption that names the same file to Playwright, still carried a bare relative path — which names no root, so it takes the ambient cwd.e2e/live/global-setup.ts(writes it)const STATE_PATH = 'e2e/live/.auth/state.json'join(REPO_ROOT, 'e2e/live/.auth/state.json'), REPO_ROOT from bareimport.meta.urlplaywright.live.config.ts(names it)storageState: 'e2e/live/.auth/state.json'storageState: STATE_PATH(absolute, rooted on the config file)playwright.import-console.config.ts(names it)e2e/live/inline-edit-polish-2572.spec.ts(reads it)Measured, not inferred
All three readings below come from real runs on this tree, with the launch directory as the only variable, a fake sign-in endpoint standing in for the backend, and the preinstalled Chromium.
1. The doubled path reproduces. Real
playwright.live.config.ts+ real global setup, started frome2e/, before the repair:Same command from the repository root: green, file at
e2e/live/.auth/state.json— so the instrument discriminates and the failure is the cwd, not the probe.2. The config half was unmeasured; now it is measured, and it needed the repair. Playwright 1.62.1 resolves a relative
use.storageStateagainst the process cwd, never the config directory. Probe with both copies present, run from a subdirectory of the config dir: the cwd copy won. Control, with only the config-dir copy on disk:Error reading storage state from state/probe-state.json: ENOENT. Two neighbouring options behave the other way and were left alone:testDirandglobalSetupboth resolved against the config directory in the same runs.3. After the repair, from
e2e/:No
e2e/e2e/tree is created. Control from the repository root: also green.4. Ablation (one-shot, restored). With the fix committed,
git checkoutof the base revision put the two bare strings back on disk (grep-confirmed before the run); the probe went red with the doubled path again, and the new content pin went2 failed | 3 passed— the two reverted files failing,playwright.import-console.config.tsstill green because it was not reverted. Restored withgit checkout HEAD -- …;git diff HEADempty and both blob hashes equal to their HEAD blobs.The third instance (⭐ reported, and repaired here)
playwright.import-console.config.tscarried a byte-identicalstorageState: 'e2e/live/.auth/state.json'and shares the sameglobalSetup. It is the same defect class, the same mechanical repair, and no open pull request holds that file (checked over all open PRs, 1765 filenames examined; positive control on the same instrument:.github/workflows/ci.ymlis held by PR #9584). Repairing the live config and leaving this one would have left the card reproducible one config over.What is NOT done here, deliberately
The path-roots gate's population is
TEST_FILE—*.test.*/*.spec.*— so aglobal-setup.tsand a*.config.tsmatch neither, which is how its registry could reach zero while these instances sat one directory away. Widening that population is not in this pull request: its pin test is held by PR #9584, and the scope decision belongs on a card of its own. Instead,scripts/__tests__/live-e2e-storage-state-roots-9519.test.tsholds the four known ends of this one path together by content, and states in its header that the gate-population question is open.Verification
pnpm exec vitest run scripts/__tests__/check-test-path-roots.test.ts scripts/__tests__/e2e-type-check.test.ts scripts/__tests__/live-e2e-storage-state-roots-9519.test.ts— 3 files, 42 tests, passed.pnpm type-check:e2e— exit 0 (this project compilese2e/**and the rootplaywright*.config.tsfiles).pnpm lint:root— exit 0 (32 pre-existing warnings, 0 errors); this task's scope coverse2e/,scripts/and the root configs.pnpm check:test-path-roots— OK.pnpm check:control-bytes— OK.pnpm check:new-line-citations— 0 new citations.node scripts/check-changeset-presence.mjs— exit 0, verdict line: "No source or published contract of a released package changed in this range, so no changeset is owed." (the diff touches nopackages/**file.)pnpm test:e2e:live:cifrom the repository root, where the bare and the rooted spelling are the same file.Acceptance notes
e2e/live/ci/better-auth-pin.mjsresolves its app directory from a CLI argument withpath.resolve. That is an explicit parameter, the documented behaviour of a CLI, and the gate names "a root that arrives as a function parameter" as a deliberate blind spot rather than this defect. Carrier if anyone revisits it: whoever next edits that script.playwright.import-console.config.ts, repaired above rather than left for later.This work was generated by Claude Code in session
session_015h79niBMyoB1xcaQje3uiz.🤖 Generated with Claude Code
https://claude.ai/code/session_015h79niBMyoB1xcaQje3uiz
Generated by Claude Code