Repository navigation
Description
Filed by the domain:services PM seat (#6021) as a cross-lane finding — the defect is in packages/drivers/driver-sql, which is domain:engine's surface, not mine. Unassigned: recording only.
What was measured
Temporal Conformance (live PG + MySQL) failed on PR #13685 — a PR whose entire diff is packages/plugins/plugin-auth/** + one changeset + one content/docs/permissions/*.mdx page. It touches no driver, no SQL, no schema-sync path.
Job 99403609711, @objectstack/driver-sql:
Test Files 1 failed | 155 passed (156)
FAIL src/sql-driver-13056-orphan-shadow-column-cleanup.test.ts
> a retired shadow-carried UNIQUE leaves no column behind (#13056)
> drops the orphaned generated column, and keeps the one still carrying a constraint
> converges — a second detect finds neither the index nor an orphan column
Error: Test timed out in 5000ms.
Both failures are timeouts, not assertion failures. Nothing in the service-container logs shows a MySQL error for these tables — the DDL that did run succeeded.
Root cause (this is not "a flake")
The two tests live in a declareDialectCell(MYSQL_CELL, …) block and each drives three to four full new SqlDriver(...) → initObjects(...) → disconnect() cycles against the live MySQL container — the positive control alone (sql-driver-13056-orphan-shadow-column-cleanup.test.ts:499 onward) costs two of them before the first "it is gone" assertion is reached.
They declare no per-test timeout, and packages/drivers/driver-sql/vitest.config.ts sets no global testTimeout — so vitest's default 5000ms applies to a multi-round-trip live-DDL test.
That is out of line with how every other multi-round-trip live test in this same package is budgeted:
| file | budget |
|---|---|
sql-driver-12380-json-roundtrip.test.ts:215,336 |
60_000 |
sql-driver-12380-json-roundtrip.test.ts:509 |
120_000 |
sql-driver-connect-bound.test.ts:224 |
40_000 |
sql-driver-diagnostic-value-probe.test.ts:357 |
60_000 |
sql-driver-value-roundtrip-conformance.test.ts:62 |
60_000 |
sql-driver-13056-orphan-shadow-column-cleanup.test.ts (both MySQL-cell tests) |
default 5000ms |
Four files in the package carry explicit budgets; this one shipped with #13056's fix without one. Under normal runner load it passes; under contention it does not, and it reddens whichever PR happens to be running — which is why it surfaced on a plugin-auth-only diff.
Proposed patch (small, matches the existing convention)
Give both MySQL-cell tests an explicit budget in the same shape the four sibling files use:
- });
+ }, 60_000);on each of the two it(...) blocks in the orphan shadow column cleanup (#13056) cell.
⛔ What this card is NOT asking for
- Not skip /
.skip/ quarantine. The tests are correct and their positive controls are the reason they are worth keeping — they read physical truth frominformation_schema, never from the DDL emitted. - Not a blanket global
testTimeoutfor the package. That would silently re-budget the 150+ tests that legitimately want the fast default; the four sibling files show the repo's answer is per-test.
Acceptance
- Both tests carry an explicit budget in line with the sibling live-DDL files.
- A control that the budget is what was missing: the same two tests, run against the live MySQL cell, pass; and the change touches no assertion, no control, and no production code (
git diffonpackages/drivers/driver-sql/src/*.tsexcluding the one test file is empty).
Activity
zhuangjianguo commentedon Aug 31, 2026
CLAIMED + dispatch order — #13688
session_01F3jdziLbAPGeceVNmSox5L· Branch:claude/issue-13688-orphan-shadow-test-budget· Worktree:../objectstack-13688-shadow-budget, offorigin/mainpm:queue→pm:dispatchedpackages/drivers/driver-sql/src/*.tsother than the one test file, that is STOP condition 1.Zone 1 — binding
1.1 — ⛔⛔ This is NOT "raise a timeout to make a slow test pass." Get that distinction right or the fix is worthless.
The card already did the work that separates the two, and it is the whole justification:
new SqlDriver(...)→initObjects(...)→disconnect()cycles against the live MySQL container; the positive control alone costs two before the first assertion.60_000,120_000,40_000,60_000. This file shipped with driver-sql: dropping an orphaned hash-shadow-carried index leaves its generated column behind forever, contradicting the cleanup contract isHashShadowColumn states #13056's fix without one.⇒ The 5000ms was inherited, never chosen. ⭐ This lane has already fixed this exact defect shape once this session (#13645 / PR #13656,
authz-store-unavailable.test.ts), and the lesson there is the one to carry: a budget is not an assertion about speed. Setting it close to observed cost buys nothing and re-files the card on a slower runner; a generous budget costs nothing when the test passes.1.2 — ⛔ Three things the card explicitly does NOT ask for. Do none of them.
.skip/ quarantine. The tests are correct, and their positive controls are why they are worth keeping — they read physical truth frominformation_schema, never from the emitted DDL.testTimeoutfor the package. That would silently re-budget the 150+ tests that legitimately want the fast default. The four sibling files show the repo's answer is per-test.git diffonpackages/drivers/driver-sql/src/*.tsexcluding the one test file is empty.1.3 — Match the existing convention, don't invent one. Per-⚠️ If you find a reason to differ, state it — ⛔ do not silently pick a different number.
itbudget, same shape as the four siblings. The card proposes60_000; that is in line with three of the four.Zone 2 — measure these; ⭐ falsifying one is a reportable success
A2.1 — ⭐ THE ACCEPTANCE CONTROL, and the one that makes this a fix rather than a guess. "The missing budget is what was failing." The card demands a control that the budget is what was missing. Establish the tests' actual cost — how long do those 3–4 round trips really take against the live cell?⚠️ If the honest answer is "I cannot run live MySQL here," say so as NOT MEASURED and lean on the structural argument (timeout not assertion, no DB error, four siblings budgeted) — ⛔ but do not claim a measurement you did not take.
A2.2 — "Only these two tests lack a budget." The card names two⚠️ widen only if they are in this same file, otherwise file a finding).
it(...)blocks in theorphan shadow column cleanup (#13056)cell. Sweep the file — and ideally the package — for other live-DDL tests still on the inherited default. ⭐ If there are more, they are the same defect and reddening the same PRs; report them (A2.3 — "
vitest.config.tsreally sets no globaltestTimeout." The card says so. Verify — if a global exists after all, the diagnosis changes.A2.4 — ⛔ Re-find both
it(...)blocks by quoted source, never by line number. The card citessql-driver-13056-orphan-shadow-column-cleanup.test.ts:499. This lane measured a ~4,600-line drift in anotherdriver-sqlfile today; report any drift.Zone 3 — advisory
plugin-auth-only diff. That is the cost being paid, and it is a repo-wide throughput tax, not a local annoyance.content/docs/releases/. ⛔ Nevergit stash. Worktree-first.STOP conditions
packages/drivers/driver-sql/src/other than the one test file.testTimeoutdoes exist ⇒ the root cause is different; report.packages/drivers/driver-sqlis currently free — no open PR or live seat touches it (measure: census the dependents of the SQL driver's orWhereNull tenant-wall carve-out before deciding its future (NULL org_id rows are globally visible on shared-DB walled deployments) #13564's census there is finished and was read-only). Live elsewhere: rest/meta: getViewsByObject / GET /meta/view?object= omits a runtime-authored view CONTAINER — #7163/#7736 expansion fix does not cover this path #13407 and fix(metadata-protocol): refuse the quoted-empty If-Match entity-tag at ingress (#13576) #13870 (packages/metadata-protocol), Refuse an undeclared field a before-hook writes — the post-hook half of the declared-field door, one envelope on every driver #13864 (packages/objectql), Give the driver registry an eviction door, so a deleted datasource stops draining /ready #13829 (resolving a conflict). If you somehow land outsidedriver-sql, STOP.Verification expected
The A2.1 cost measurement or an honest NOT MEASURED with the structural argument; the A2.2 sweep result; re-located anchors with drift reported;
pnpm --filter @objectstack/driver-sql test(noting which cells can and cannot run without the live containers, and saying which); the gate family fromnode scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack; a changeset or a justifiedskip-changeset(test-only publishes nothing). ⛔ No ablation is meaningful here — there is no behaviour to neuter; say so rather than fabricating one. ⛔ Report anything unmeasured as NOT MEASURED. ⛔ No test skipped, disabled, quarantined, allow-listed, deleted or re-baselined.Generated by Claude Code
test(driver-sql): budget the #13056 live-MySQL orphan-shadow tests (#…
zhuangjianguo commentedon Aug 31, 2026
os-dev-report
{ "issue": 13688, "status": "done", "branch": "claude/issue-13688-orphan-shadow-test-budget", "pr": "https://github.com/objectstack-ai/objectstack/pull/13908", "premise_still_valid": true, "summary": "Gave the two MySQL-cell it() blocks in sql-driver-13056-orphan-shadow-column-cleanup.test.ts (lines 499 and 555, no drift from the card's :499 citation) an explicit 60_000ms budget each, matching 3 of the 4 sibling budgets in the package, with a one-line comment naming why (2-3 live connect/DDL/disconnect cycles against MySQL). No production code touched: git diff on packages/drivers/driver-sql/src/*.ts excluding the one test file is empty. vitest.config.ts confirmed to carry no global testTimeout, so the diagnosis (inherited 5000ms default, not a chosen budget) holds. A package-wide sweep for the same shape (STOP condition 3) found 9 more files / 37 more it() blocks with the identical gap; filed as #13902 rather than folded into this fix, per the dispatch order.", "tests": "pnpm --filter @objectstack/driver-sql typecheck: PASS (exit 0). pnpm --filter @objectstack/driver-sql exec vitest run --maxWorkers=2 at HEAD fcc9ce8034: PASS, 147 passed | 9 skipped test files (156), 2252 passed | 132 skipped tests (2384). Target file alone (--reporter=verbose): 12 passed | 1 skipped -- the live-MySQL describe block collapses to one named-skip test since no live MySQL/PG container is reachable here (docker daemon not running; no OS_TEST_MYSQL_URL/OS_TEST_POSTGRES_URL; nothing listening on 3306/5432), so the two edited it() blocks did not execute -- A2.1 (actual cost against live MySQL) is honestly NOT MEASURED, leaning on the structural argument (timeout not assertion, no DB error, four sibling files already budgeted). Gate family via node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack, re-derived at HEAD fcc9ce8034 after git fetch origin main: 26 relevant families (22 path-matched + 4 from the 'edits a test file' convention trigger) -- 23 PASS, 3 NOT MEASURED (check:dual-build-cjs-loads and check:type-check-debt need the full 78-package workspace built, which is CI's own Build-Core/debt-ledger scope; check:test-completeness by its own design needs a saved turbo-run-test log that only CI produces). No ablation attempted or claimed -- there is no behaviour to neuter, per the dispatch order.", "mcp_calls": "6", "open_questions": [], "out_of_scope_findings": [ "filed as #13902: driver-sql package-wide sweep found 9 more files / 37 more it() blocks doing live MySQL/PG round trips inside declareDialectCell() with no explicit timeout, the same inherited-5000ms-default shape this card fixed for its one file -- reported per STOP condition 3 rather than widened into this PR" ] }Generated by Claude Code
test(driver-sql): budget the objectstack-ai#13056 live-MySQL orphan-s…