Repository navigation
Description
domain:devx#2 · marchtian · session_017ihL2ebbZkr2QAEG1x7UC8
Filing gate: ① defect class with a measured reproduction. Out-of-scope finding of the measurement for #30901 (PR #30919, dev report 6683692239), from the Actions API over main push and merge-group CI runs on 2026-11-03..06, plus local idle timings. ⛔ Not a claim. Triage sets the grade and the lane.
Business reason. Test Core turns main and queue entries red when a case on the vitest 5 s default runs long under load. #30901 fixed the formula case, #30785 fixed the cli parity case, and #30873 holds the rest case. These nine are the next in line: they already reach 50-85% of the budget in CI, so a slow runner can tip any of them over.
The two drain cases look like a product issue, not load
Both are in packages/plugins/plugin-hono-server. Each takes the same time on an idle machine as in CI, so the wait is built in:
| Case | CI (n, median, max) | Local idle |
|---|---|---|
src/adapter-tls-listener.test.ts › drains on close exactly as the plain listener does |
n=2, 4228 ms, 4239 ms | 4209 ms ×2 |
src/adapter-drain.test.ts › lets an in-flight request complete instead of aborting it |
n=2, 3303 ms, 3321 ms | 3230 ms ×2 |
A guess, not measured: close() calls closeIdleConnections() while the request is still in flight. The socket that goes idle afterwards then waits for the client's keep-alive to end. If so, a real server's shutdown waits the same keep-alive window per open connection.
The other seven (2.5-3.4 s max in CI, a sample)
clientsrc/auth-rotated-session-token.test.ts› login → enable → verifyTotp → disable → deleteUser: n=5, median 1424 ms, max 3427 msclisrc/utils/unmanaged-tables.integration.test.ts› the boot this sweep reads from really did compose the deployment: n=5, median 2892 ms, max 3295 msmetadata-protocolsrc/reference-sites.derivation.test.ts› two derivations of the same schemas agree exactly: n=2, median 2548 ms, max 3210 msplugin-securitysrc/org-admin-assignment-boundary.posture.test.ts› posture single/isolated/group column cases: n=3, median 1989-2228 ms, max 2554-2949 msclitest/released-port-production-spawn.pin.test.ts› the census reaches the live tree: n=6, median 2301 ms, max 2629 msplugin-sharingsrc/share-link-password.test.ts› a refused upgrade write does not block the read: n=4, median 2078 ms, max 2605 msdriver-sqlsrc/logger-receiver-detach.test.ts› sql-driver.ts and the modules split out of it contain none of them: n=2, median 2470 ms, max 2499 ms
Wanted
- Drain cases: find why
close()waits 3-4 s with a request in flight. If it is the keep-alive wait, fix it in the adapter so shutdown finishes when the in-flight request ends. The two cases then run in milliseconds. - The seven: for each, cut the heavy work, or set a per-case timeout sized at 3x the measured max, with its reason in a comment (the rule ci(test-core): three different cases hit the vitest 5 s default timeout under load in 24 h; measure the shards and fix the timeout class, not one case at a time #30901 applied). ⛔ No global timeout raise, no skip, no retry.
Level: tests, plus the adapter if the drain guess holds. Clause-②: no, Metadata-protocol: none.
Dedupe (open and closed): "plugin-hono-server drain closeIdleConnections" (only #30901); "hono drain test slow" (#23181, the cli wall-time budget, which is a different package and class). New.
Related: #30901, PR #30919, #30785, #30873, #25870.
Reader: triage. The drain half is packages/plugins/plugin-hono-server (server). The seven are spread over their packages' lanes.
Activity
objectstack-fleet commentedon Nov 6, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: audit · p2 ·
domain:devx· 2026-11-06T12:20Z⛔ Not a claim.
findingis removed.Generated by Claude Code
objectstack-fleet commentedon Nov 7, 2026
domain:devx#2 · marchtian · session_017ihL2ebbZkr2QAEG1x7UC8
Claim: PM loop round 1
Session:
session_017ihL2ebbZkr2QAEG1x7UC8Account:
marchtianBranch:
claude/issue-30920-test-core-slow-casesWorktree:
objectstack-issue-30920Domain:
domain:devxSeat:
domain:devx#2File surface:
packages/plugins/plugin-hono-server/src/adapter.ts(theclose()drain path nearcloseIdleConnections(),:1854-1864), together withadapter-drain.test.tsandadapter-tls-listener.test.ts. This applies only if the measured cause is the keep-alive wait; otherwise only the two tests change.clientauth-rotated-session-token.test.ts;cliunmanaged-tables.integration.test.tsandreleased-port-production-spawn.pin.test.ts;metadata-protocolreference-sites.derivation.test.ts;plugin-securityorg-admin-assignment-boundary.posture.test.ts;plugin-sharingshare-link-password.test.ts;driver-sqllogger-receiver-detach.test.ts. In each, the heavy work is cut or a per-case timeout is set at 3× the measured max, with its reason.Container & model:
M,mode:subagentClause-②: no
Metadata-protocol: none
Responsibility: n/a — tests, plus a server shutdown fix if measured; independent contract review before ACCEPT
Thread-read: none
Premise: holds. At
origin/mainaf3451b08b:adapter-drain.test.ts:14);close()still callscloseIdleConnections()(adapter.ts:1863-1864);Serial constraints cleared: no open PR touches any file in the surface.
objectstack-fleet commentedon Nov 7, 2026
domain:devx#2 · marchtian · session_017ihL2ebbZkr2QAEG1x7UC8
os-dev-report
{ "pr": "https://github.com/objectstack-ai/objectstack/pull/31189", "head": "2ff6bb07351d65bccdad23a3eb3249b082200a2b", "branch": "claude/issue-30920-test-core-slow-cases", "change": "plugin-hono-server close(): during a drain, a response whose headers are not yet written goes out with Connection: close (Node ends the socket after it), and a response whose keep-alive headers were already sent releases its socket through closeIdleConnections() once it ends; in-flight requests still complete, the drain-window force-close is unchanged; patch changeset. Two new pins in adapter-drain.test.ts (Connection: close on the in-flight case; a streamed response sent before close() releases its connection within 1000 ms of its body ending), each arm ablated red. Seven other cases: two cut (metadata-protocol, client), four given a per-case budget of 3x the CI max (driver-sql, plugin-security, plugin-sharing, cli census), one left unchanged on measurement (cli unmanaged-tables).", "drain_cause": "Confirmed by a timing and socket-state trace (tsx script against src/adapter.ts, one GET sleeping 200 ms, close() at ~55 ms). Before: closeIdleConnections() at drain start skips the active connection; the response finishes at 219 ms with shouldKeepAlive=true and Keep-Alive: timeout=5; the detached server socket waits with a 6000 ms timer; close() resolves only when the CLIENT sends FIN: 3232 ms with fetch (undici: hint 5 s minus its 2 s margin), 4216 ms with the node:http agent keepAlive (hint minus 1 s). Control: agent:false (no keep-alive) resolves close() at 215 ms. After the fix: Connection: close sent, _last=true, close() resolves at 214-228 ms for all three clients. The card guess holds; the wait is the client keep-alive window, bounded by the server 6 s keep-alive timer when a client never closes.", "per_case": [ "plugin-hono-server adapter-tls-listener drains on close exactly as the plain listener does: 4209 ms -> 214 ms; work cut (product fix), no timeout", "plugin-hono-server adapter-drain lets an in-flight request complete instead of aborting it: 3233 ms -> 268 ms (ablated arms: 249 ms red on Connection header); work cut (product fix), no timeout", "client auth-rotated-session-token login -> enable -> verifyTotp -> disable -> deleteUser: 729/800/743 -> 566/583/558 ms; cut: the shared server and its better-auth instance are built at module scope, out of the first case clock; no timeout because the file header forbids answering it with a timeout and pin 4 refuses a numeric per-case timeout (3x would be 3 x 3427 = 10281 -> 11000, not set; see open_questions)", "cli unmanaged-tables.integration the boot this sweep reads from really did compose the deployment: 10222/11341/10996 ms local (box shared with other builds), not changed: instrumented trace shows body 1-2 ms, afterEach 3 ms, beforeEach 10038-10378 ms (first bootSchemaStack of the worker) under its own 180_000 hook timeout; the 5 s testTimeout clocks only the 2 ms body, so it cannot time out on the default and a per-case timeout would be a no-op", "metadata-protocol reference-sites.derivation two derivations of the same schemas agree exactly: 743/844/775 -> 353/372/410 ms; cut: one on-demand derivation compared with the module-load singleton (plus a not-the-same-object assertion) instead of two on-demand derivations; no timeout", "plugin-security org-admin-assignment-boundary.posture hidden-column cases (single/group/isolated): 624-694 -> 489-669 ms; timeout 9000 (3 x 2949 = 8847, rounded up to the next second)", "cli released-port-production-spawn.pin the census reaches the live tree: 1291/1243/1102 -> 1117/1234/1217 ms; timeout 8000 (3 x 2629 = 7887)", "plugin-sharing share-link-password a refused upgrade write does not block the read: 545/458/689 -> 499/398/474 ms; timeout 8000 (3 x 2605 = 7815)", "driver-sql logger-receiver-detach sql-driver.ts and the modules split out of it contain none of them: 469/442 -> 433/313/432 ms; timeout 8000 (3 x 2499 = 7497)" ], "gates": { "derived_on": "2ff6bb0735 (objectstack-ai/objectstack, after merging origin/main 8ef4d30905)", "commands": [ "node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0", "node scripts/check-adr-0087-registration.mjs --self-test :: exit 0", "node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0", "node scripts/check-closing-keyword-parity.mjs :: exit 0", "node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0", "node scripts/check-comment-mask-adoption.mjs :: exit 0", "node scripts/check-comment-mask-adoption.mjs --self-test :: exit 0", "node scripts/check-comment-mask-corpus.mjs :: exit 0", "node scripts/check-dts-emitted.mjs --self-test :: exit 0", "node scripts/check-empty-changeset.mjs --base origin/main :: exit 0", "node scripts/check-empty-changeset.mjs --self-test :: exit 0", "node scripts/check-issue-citations.mjs :: exit 0", "node scripts/check-plugin-teardown-shape.mjs :: exit 0", "node scripts/check-plugin-teardown-shape.mjs --self-test :: exit 0", "node scripts/check-tenant-audit-census.mjs :: exit 0", "node scripts/check-tenant-audit-census.mjs --self-test :: exit 0", "node scripts/ci/assert-turbo-remote-cache.mjs --self-test :: exit 0", "node scripts/ci/plan-test-core-shards.mjs --self-test :: exit 0", "node scripts/ci/prune-turbo-cache.mjs --self-test :: exit 0", "node scripts/ci/snapshot-next.mjs --self-test :: exit 0", "node scripts/docs-audit/check-affected-docs.mjs :: exit 0", "node scripts/docs-audit/check-drift-comment.mjs :: exit 0", "node scripts/pm/release-rehearsal-clone.mjs --self-test :: exit 0", "node scripts/release-pending-publish.mjs --self-test :: exit 0", "pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0", "pnpm --filter @objectstack/spec run check:skill-examples :: exit 0", "pnpm check:changeset-gate-self-tests :: exit 0", "pnpm check:ci-filter-parity :: exit 0", "pnpm check:cli-test-child-env :: exit 0", "pnpm check:closed-ceremony-text :: exit 0", "pnpm check:cross-package-test-inputs :: exit 0", "pnpm check:dispatcher-error-vocabulary :: exit 0", "pnpm check:doc-authoring :: exit 0", "pnpm check:driver-conformance :: exit 0", "pnpm check:driver-memory-census :: exit 0", "pnpm check:dts-closure :: exit 0", "pnpm check:dual-build-cjs-loads :: exit 0", "pnpm check:durability-log-level :: exit 0", "pnpm check:engine-double-contract :: exit 0", "pnpm check:error-status-conformance :: exit 0", "pnpm check:gitlink-declared :: exit 0", "pnpm check:i18n :: exit 0", "pnpm check:i18n-stale-fill :: exit 0", "pnpm check:issue-citations :: exit 0", "pnpm check:keyed-text-bounds :: exit 0", "pnpm check:lean-entry-closure :: exit 0", "pnpm check:logger-receiver-detach :: exit 0", "pnpm check:nul-bytes :: exit 0", "pnpm check:objectql-double-limit :: exit 0", "pnpm check:org-identifier :: exit 0", "pnpm check:page-declaration-shape :: exit 0", "pnpm check:platform-object-tenancy-census :: exit 0", "pnpm check:published-files :: exit 0", "pnpm check:query-options-erasure :: exit 0", "pnpm check:refd-timer-probe :: exit 0", "pnpm check:registry-log-declared :: exit 0", "pnpm check:rest-log-spy-declared :: exit 0", "pnpm check:route-envelope :: exit 0", "pnpm check:slot-lookup :: exit 0", "pnpm check:sourcemap-no-sources-content :: exit 0", "pnpm check:system-context-census :: exit 0", "pnpm check:test-source-alias :: exit 0", "pnpm check:tier-file-adoption :: exit 0", "pnpm check:type-check-coverage :: exit 0", "pnpm check:type-check-debt :: exit 0", "pnpm check:undeclared-dep-imports :: exit 0", "pnpm check:vouch-for-reference-callers :: exit 0", "pnpm check:watch-hint-literal :: exit 0", "pnpm check:where-matcher :: exit 0" ], "reruns": [ "pnpm --filter @objectstack/spec run check:skill-examples :: exit 3 (PREREQUISITE: client-react had no dist) -> built -> exit 0", "pnpm check:dual-build-cjs-loads :: exit 3 (PREREQUISITE: eleven packages had no dist) -> built -> exit 0" ], "ran_reconciliation": "node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --ran FILE :: exit 0 -- 69 derived, 69 run, 0 NOT-MEASURED, 0 UNRUN (a DERIVED zero, all 69 recorded an exit code)", "package_checks": [ "typecheck plugin-hono-server, client, metadata-protocol, plugin-security, plugin-sharing, driver-sql, cli :: exit 0 each", "pnpm --filter @objectstack/plugin-hono-server test :: exit 0 (478/478)", "pnpm --filter @objectstack/client test :: exit 0 (712/712)", "pnpm --filter @objectstack/metadata-protocol test :: exit 0 (22525 passed, 26 skipped)", "pnpm --filter @objectstack/plugin-security test :: exit 0 (5820 passed, 45 skipped)", "pnpm --filter @objectstack/plugin-sharing test :: exit 0 (1445/1445)", "pnpm --filter @objectstack/driver-sql test :: exit 0 (3867 passed, 218 skipped)", "pnpm --filter @objectstack/cli exec vitest run --project unit :: exit 0 (5603/5603); cli integration layer declared to CI" ], "ci": "in_progress at report time; not awaited", "changeset_label": "none written. The diff is not scripts/ci-only: it changes a published package source (plugin-hono-server adapter.ts), so the house rule (AGENTS.md Post-Task Checklist step 3) is a patch changeset, which the PR carries, and never skip-changeset. The six test-only packages publish nothing." }, "files_changed": [ ".changeset/30920-hono-drain-closes-connections.md", "packages/plugins/plugin-hono-server/src/adapter.ts", "packages/plugins/plugin-hono-server/src/adapter-drain.test.ts", "packages/client/src/auth-rotated-session-token.test.ts", "packages/metadata-protocol/src/reference-sites.derivation.test.ts", "packages/drivers/driver-sql/src/logger-receiver-detach.test.ts", "packages/plugins/plugin-security/src/org-admin-assignment-boundary.posture.test.ts", "packages/plugins/plugin-sharing/src/share-link-password.test.ts", "packages/cli/test/released-port-production-spawn.pin.test.ts" ], "deviations": [ "Branch: the order names claude/issue-30920-skill-md-runs-console-pin; the newest Claim and the provisioned worktree name claude/issue-30920-test-core-slow-cases, which was used. Read as a template slip in the order, not a claim mismatch.", "adapter-tls-listener.test.ts is unchanged: its drain case is fixed by the adapter change and needed no edit.", "cli unmanaged-tables case not changed (measured; see per_case). The order asked for a cut or a timeout on each of the seven.", "client case: cut only, no budget, because the file own rule and pin 4 forbid a timeout (open_questions).", "Local verification narrowed to the seven touched packages (cli at --project unit); the repo-wide suite is left to CI.", "After-timings of the seven were taken on 1f14604b4f, before merging origin/main; the package suites were rerun on the merged head.", "The merge commit carries git default message without the trailer pair; the pre-push trailer check passed.", "pr_create carries assignees [marchtian] per the order, os-dev.md and pm-dispatch SKILL.md; AGENTS.md (claim section) still says pr_create carries none." ], "open_questions": [ { "question": "The client probe case (CI max 3427 ms) keeps no budget, because its file forbids answering a recurrence with a timeout and pin 4 refuses one. The cut took about 25% off locally. Is that enough?", "options": [ "A: accept the cut; if CI reds it, cut the probe work further, as the file says", "B: override the file rule: budget 11000 (3 x 3427 = 10281) and amend the header and pin 4 in this PR" ], "recommendation": "A, because the file rule is a recorded decision and B reverses it in a test-speed card" } ], "out_of_scope_findings": [ "class: none (observation) · cli src/utils/unmanaged-tables.integration.test.ts pays the worker first bootSchemaStack inside beforeEach under a 180_000 hook timeout: 10.0-10.4 s locally on a shared box, file wall about 11 s (CI reading on the card 3295 ms for the case). AGENTS.md: clocked windows measure behaviour, never loading. carrier: seat (cli lane), noted, not filed", "class: none (doc drift) · AGENTS.md claim paragraph says pr_create carries no assignee, while pm-dispatch SKILL.md and os-dev.md say pr_create assigns the claim Account. carrier: seat, noted, not filed", "class: none (order template) · order branch name and the scripts/ci-only changeset-label phrasing do not match this card. carrier: seat" ], "mcp_calls": "0 MCP GitHub calls", "api_writes": "2 relay strokes: (1) fleet-write dispatch fw-20261107T164540Z-d41894 (POST /repos/objectstack-ai/objectstack/dispatches) executing POST /repos/objectstack-ai/objectstack/pulls (draft #31189) + POST /repos/objectstack-ai/objectstack/issues/31189/assignees [marchtian]; (2) this os-dev-report comment via post-stamped.mjs (POST /repos/objectstack-ai/objectstack/issues/30920/comments). Plus git push of the branch (not a REST write).", "filed_issues": "none", "security_findings": "none" }objectstack-fleet commentedon Nov 7, 2026
domain:devx#2 · marchtian · session_017ihL2ebbZkr2QAEG1x7UC8
os-dev-report
{ "round": 2, "pr": "https://github.com/objectstack-ai/objectstack/pull/31189", "head": "586338ffbd", "change": "M1: a keep-alive response that ends during a drain now destroySoon()s only its own connection, once it has finished and no other response on that connection is pending; the server-wide closeIdleConnections() per response is gone. M2: drain bookkeeping is a Map from connection to the responses it owes (named type OwedResponses), and a connection entry is dropped on the connection close, so a pipelined response on a dead connection is not held. S1: a raw-socket case pins the request-time Connection: close line. S2: the driver-sql budget comment states the over-half-the-default threshold and why a 2499 ms reading (1 ms under it) keeps its budget (kept, not dropped). JSDoc and changeset claims corrected; corrected PR body written for the seat.", "pins_and_ablations": [ "slow reader, 32 MiB ended and still flushing (asserted) while another stream ends: whole body arrives. Ablated to the round-1 sweep: red, expected 3919730 to be 33554432", "four pipelined requests, connection destroyed: 0 retained. Ablated (no drop on connection close): red, expected 3 to be +0", "headers finish after close() began: Connection: close. Ablated (request-time line removed): red, expected keep-alive to be close", "new test file against the round-1 adapter.ts (2ff6bb0735): slow-reader red (3919730 of 33554432 bytes), pipelined red (NaN against 4: the round-1 Set holds responses), late-headers green (round 1 had that line)", "all ablations through scripts/ablation-replace.mjs on 586338ffbd; each restore verified blob == HEAD, git diff HEAD empty" ], "gates": [ "node scripts/pm/dispatch-gates.mjs --commands on 586338ffbd: 69 derived, 69 run, all exit 0; --ran: 0 NOT-MEASURED, 0 UNRUN (derived zero)", "node scripts/check-tenant-audit-census.mjs :: exit 1 on e0d0358b3f (untyped receiver owed.delete) -> set given a declared named type -> exit 0", "pnpm check:dts-closure :: exit 1, pnpm check:dual-build-cjs-loads :: exit 1 -- read a dist being rebuilt mid-run (files present minutes later) -> rerun :: exit 0 both", "pnpm --filter @objectstack/plugin-hono-server typecheck :: exit 0; test :: exit 0 (481/481)", "pnpm --filter @objectstack/driver-sql typecheck :: exit 0; logger-receiver-detach.test.ts :: exit 0 (12/12)", "dispatch-gates warned the tree is 11 commits behind origin/main with ci.yml and two gate scripts changed there; origin/main was not merged again this round (merge-once rule)" ], "files_changed": [ "packages/plugins/plugin-hono-server/src/adapter.ts", "packages/plugins/plugin-hono-server/src/adapter-drain.test.ts", "packages/drivers/driver-sql/src/logger-receiver-detach.test.ts", ".changeset/30920-hono-drain-closes-connections.md" ], "deviations": [ "The M1 pin makes the big response call end() AFTER close() starts. Ending it before close() also truncates it, through Node own server.close() sweep at drain start, which this PR does not change (see out_of_scope_findings)." ], "out_of_scope_findings": [ "class: a · reach: HonoHttpServer.close() with a slow-reading client; repro: the slow-reader pin reordered so the 32 MiB response calls end() before close() -> expected 3919702 to be 33554432 bytes on this branch; the drain-start path (server.close() plus closeIdleConnections()) is unchanged from main · a response ended but still flushing when close() starts is destroyed mid-body, because Node treats an ended response as idle before its bytes flush · dedupe: hono close truncates flushing response, closeIdleConnections ended response, graceful drain slow client truncated · for the seat to file" ], "pr_body": "not patched; corrected body at /tmp/claude-0/-home-claude-objectstack/1677a8af-195d-5c45-a899-c3b41d538f0a/scratchpad/issue-30920/pr-body-r2.md for the seat", "mcp_calls": "0", "api_writes": "1 relay stroke: this comment via post-stamped.mjs (POST /repos/objectstack-ai/objectstack/issues/30920/comments); plus git push x2", "filed_issues": "none" }objectstack-fleet commentedon Nov 7, 2026
domain:devx#2 · marchtian · session_017ihL2ebbZkr2QAEG1x7UC8
Landed · #30920 · PR #31189
b48490e6d2(auto-merge, non-governed).Connection: close.'finish'.beforeEachwith its own limit;close()starts is still cut short. This is the same onmain.