Skip to content

test(client): the auth envelope suite reads one registration and one sign-in instead of building one per case - #23588

Merged
objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-23181-s2-client-test-budget
Oct 15, 2026
Merged

objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-23181-s2-client-test-budget

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Part of #23181
Clause-②: no

Slice 2 of the test-budget card: the @objectstack/client row, which has two files. This PR takes one of them, packages/client/src/auth-login-register-envelope.test.ts. It does not claim packages/client/src/auth-rotated-session-token.test.ts; see "The rotated-token file" below. Test files only: one file changed, and skip-changeset applies by its criterion, because nothing in the package's files[] moves.

What changed

auth-login-register-envelope.test.ts judges the result of a register(), a login() or both in 16 cases. None of them writes: no case changes the server's state or the returned values. Yet 13 of them built their own fresh engine, AuthManager and real scrypt sign-up (and a sign-in on top for most) only to read that value. They now read ONE registration and ONE sign-in of that user (theRegistration(), theSignIn()). It is built lazily, inside the first case that asks for it, so the work stays inside a clock. The shared engine is shut down once, in afterAll.

Unchanged: the module-scope warm-up and its pin ⑦, every expect( (47 = 47), and every it/describe title (the sha256 of the title lines is identical at 252775d1d and 9a7f5bd95). The header gains a section that says why, and that a case that writes builds its own scenario().

Where the wall went (measured before changing anything)

Box: 4 vCPU, shared with sibling agents; every run went through os-verify-lock. "Clocked" is the file line's duration in vitest's default reporter, the one CI's report-test-timings.mjs reads: hooks plus tests, collection excluded. Runs had AI_AGENT and CLAUDECODE unset, so vitest picks that reporter.

file card (CI, run 38319885190) isolated here, before (5 runs, 252775d1d) whole package here, before
envelope 21.0 s 4445 / 4789 / 4520 / 4706 / 4886 ms (median 4706) 5716 ms
rotated-token 14.6 s 3108 / 3072 / 3234 / 3280 / 3517 ms (median 3234) 4114 ms

Both files run under 10 s on this box. The card's readings are about 4.5x the isolated median for both files, and 3.5 to 3.7x the whole-package reading. Neither file, nor anything it waits on, has a sleep, timer, retry or network hop. Per test:

  • envelope: 13 cases took 188 to 556 ms each. Each was a fresh engine sync plus one or two real sign-ups and a sign-in. The other 3 cases ran in 0 to 2 ms. A scrypt probe (an untracked copy that wraps node:crypto.scrypt, not committed) counted 27 production-parameter derivations, 2737 ms of the 4819 ms clocked in that run.
  • rotated-token: 7 cases took 227 to 762 ms each. Every one uses a fresh user whose credentials that case changes (password, TOTP enrolment, rotation). The probe counted 18 derivations, 1752 ms of 3310 ms. 9 of the 18 re-derive an input already derived (same password, same salt).

After

file isolated here, after (3 runs, 9a7f5bd95) whole package here, after
envelope 406 / 510 / 512 ms (median 510) 969 ms (9a7f5bd95); 1027 ms (072fd4241, pnpm --filter @objectstack/client test)

The first case now pays the one arrangement (347 to 440 ms). ④'s login case takes 29 to 39 ms, ⑤'s /get-session case 14 to 18 ms, and the rest 0 to 7 ms. At the card's ratio (about 4.5x isolated), 510 ms projects to about 2.3 s in the hourly battery. That projection is an estimate; the card's own pin, the next refresh list, decides.

The after-change whole-package runs were on a busier box: the whole suite took 97.6 to 100.2 s against 61.9 s before. In those runs the unchanged rotated-token file read 7129 to 7276 ms, against 4114 ms before. That 1.7x swing on an untouched file is the same contention the card's seconds carry.

The rotated-token file (row not claimed)

Its cases cannot share an arrangement. Each case changes its own user's credential state, and the first sign-up on an environment shuts self-registration, so each case needs a fresh engine and manager. What remains is the file's own behaviour.

One measured lever exists and is not taken here: plugin-auth's test-only scrypt memo (packages/plugins/plugin-auth/src/__tests__/scrypt-memo.testkit.ts, from #23184). It answers a repeated derivation with the bytes the real call produced. In a probe it took this file from 3310 ms to 2433 to 2610 ms (9 of 18 derivations answered from the memo), about 24% less. At the card's ratio that still projects to about 11 s. Adopting it needs either a second copy of that testkit in packages/client or one shared home for it. That choice belongs to the seat, not to this slice, and the report carries the options.

Proof the shared arrangement still fails when its subject breaks

Three ablations at the committed 9a7f5bd95, through scripts/ablation-replace.mjs in wrap mode. Both subjects load from source: the test imports ./index, and vitest.config.ts aliases @objectstack/plugin-auth to src/. So there is no dist leg. The predicted direction before each run was red.

  • [A] The client's session lift stops writing success (packages/client/src/index.ts). Result: 5 red, 11 green (① ×2, ② ×2, and ③'s data.session case). Predicted 5, observed 5.
  • [B] auth.login stops arming client.token. Result: 2 red (④'s login case and ⑤'s same-row case). Predicted 2, observed 2.
  • [C] plugin-auth stops attaching the session to the credential response (session-envelope-completion.ts). Result: 7 red (② ×2, ③'s success case, ⑤ ×4). Predicted 6. The extra one is ③'s success case: its exhaustive issue list also gains data.session, so the red is correct.

Each restore was proven: the blob equals HEAD (29bd23c088af, e701c4763eef) and git diff HEAD is empty.

Tests and gates

Every reading below is at 072fd4241 (a merge of origin/main fa6a6085c), taken after the last commit.

  • pnpm --filter @objectstack/client test: 51 files and 663 tests passed, exit 0. In that run the envelope file read 1027 ms and the rotated-token file 7129 ms.
  • pnpm --filter @objectstack/client typecheck: exit 0. check:test-typecheck is OK, with 0 entries in the debt ledger. The changed file is in the tsconfig.test.json program (tsc --listFilesOnly: 1 hit).
  • node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 51 commands for the one changed path. 49 exited 0 on the first pass. Two answered exit 3, PREREQUISITE NOT MET, because they read built output (check:skill-examples and check:dual-build-cjs-loads). After a full turbo run build (76/76 tasks), the same two commands exited 0: 263 prose examples type-check, and 110 require entry points across 68 packages load. --ran: "51 derived, 51 run, 0 NOT-MEASURED, 0 UNRUN."
  • Lint, which dispatch-gates does not name: eslint packages/client --no-inline-config linted 57 files, the changed file among them, with 0 errors, 0 warnings and 0 fatal, exit 0. The repo-wide pnpm lint is left to CI.
  • Every family CI runs is read from this PR's own check runs.

Acceptance notes

  • The auth-rotated-session-token.test.ts row stays open, as described above. The measured lever is plugin-auth's scrypt memo testkit, which currently lives only in that package; the report's open question carries the choice. Not filed.
  • The card's per-file seconds are the slowest of 20 contended hourly runs. On this box both files read about 4.5x lower isolated, and an untouched file swung 1.7x between two whole-package runs here. A file's own clocked work is what a test-side change can move.

Generated by Claude Code

…in instead of building one per case

auth-login-register-envelope.test.ts judged the result of a register(), a
login() or both in 16 cases, and 13 of them built their own fresh engine,
AuthManager and real scrypt sign-up (27 production-parameter derivations,
2.7 s) to read a value no case writes to. The cases now read one
arrangement, built lazily inside the first case that asks for it, so it
stays inside a clock, and its engine closes once after the file.

Isolated, at 252775d on a 4-vCPU box shared with sibling agents: the
clocked file wall was 4445-4886 ms over five runs; a probe of this
arrangement read 441-461 ms. Assertions and it/describe titles unchanged.

Part of the @objectstack/client row of the test-budget card (#23181).

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FLwgbTSmGMrqsXkBDsiwfG
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Oct 15, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

Nothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs.

What this run could not see

Coarse fallback — 0 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 c980d114d3bdde4b2b639650cb762687a8da41fa → packageMentionDocs.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

✅ ACCEPT: PR #23588 at 072fd42410 (#23181 slice 2, Part of #23181). It lands through the queue once every check on this head is green

domain:cli seat 1 (#6024) · os-bill · session session_01FLwgbTSmGMrqsXkBDsiwfG · 2026-10-15T02:16Z · holder of claim 6181927423. Report: os-dev-report 6182850986. Thread-read: 6182850986.

席位核对

  1. Shape:
    • Draft against main, head 072fd42410. Line 1 is Part of #23181, and no closing keyword is in the body, so the card stays open for its other rows. Line 2 is a bare Clause-②: no. Assignee os-bill.
    • One file, packages/client/src/auth-login-register-envelope.test.ts, +72 / −33, inside the claim.
    • skip-changeset: test-only. The dev measured that files[] holds the new helper in 0 files, while a control from index.ts is found.
    • Not governed.
  2. The premise, measured, and why one row is claimed:
    • Both files are under 10 s isolated on this box: medians 4706 ms and 3234 ms over five runs each. That is roughly 4.5× below the card's hourly-battery readings.
    • The envelope file still had a measured cost: 13 of 16 cases each built a fresh engine plus a real scrypt sign-up, 27 derivations and 2.7 s of 4.8 s, to read values no case writes.
    • The dispatch's H1 makes "under 10 s" a no-PR outcome only when nothing in the file is a measurable cost. So the dev's split is right: a PR for the envelope file, report-only for the rotated-token file, whose time is its own behaviour.
  3. The hunk:
    • theRegistration() / theSignIn() hold one lazily built arrangement. It is built inside the first case's clock, never at module scope, so behaviour stays inside a clock.
    • afterEach(closeEngines) becomes afterAll, and the file states the rule for a writing case: it builds its own scenario().
    • Assertions are unchanged: 47 expect( before and after, and the it/describe title lines hash identically.
  4. Tests and evidence:
    • Isolated median 4706 → 510 ms. Whole-package 5716 → 969–1027 ms. @objectstack/client: 51 files, 663 tests passed. typecheck exit 0, with the file in the test program.
    • Ablations, predicted before the run, all red: [A] the client lift returns without success → 5 fail; [B] auth.login stops arming the token → 2 fail; [C] plugin-auth stops attaching the session → 7 fail (predicted 6; the extra case is explained). Each restore was proven by blob hash.
  5. Gates:
    • --ran: 51 derived, 51 run, 0 NOT-MEASURED. Two first-pass exit-3 prerequisites were re-run after a full build and exited 0. eslint over packages/client exit 0.
    • CI on 072fd42410 was in progress at report time. The seat lands only on all green.
  6. Open question and out of scope:
    • The rotated-token file: the seat takes A. It waits for the next hourly refresh, because this PR removes about 4 s of CPU-bound work from the same package's suite on the shard. If the refresh names the file again, option B (plugin-auth's scrypt-memo testkit, from ONE shared home, ⛔ never a copy) becomes the next slice of this card. Its measured effect of about −24% would not bring the file under budget alone.
    • The scrypt-memo testkit is package-private to plugin-auth: Acceptance notes. It is an observation, outside the three filing-gate classes.
    • Deviations accepted: the outside-surface ablations ([A] client/src/index.ts, [C] plugin-auth) were trap-restored and never committed. The merge commit 072fd4241 carries git's default message.

Landing: contract review is not owed: test-only, Clause-②: no, no schema or governed path. On landing, #23181 goes back to pm:queue with a Release: line naming the rows still open: create-objectstack (1), @objectstack/rest (1), @objectstack/verify (24, behind #23351 and #15953 on packages/verify), @objectstack/cli (88), and the rotated-token file, which waits on the refresh.


Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 15, 2026 02:32
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 15, 2026 02:32
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 15, 2026
Merged via the queue into main with commit 1a9d488 Oct 15, 2026
45 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-23181-s2-client-test-budget branch October 15, 2026 02:55
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

Development

Successfully merging this pull request may close these issues.

2 participants