Repository navigation
test(managed-agent): commit authority-valid deltas in the restore byte-budget test - #13551
Conversation
…e-budget test How: holdsRestorePagesInsideThePerPageByteBudget now builds each dense transaction from 210 well-formed message.delta lines (text at the reader's 4096-byte cap, ~1 MB per transaction) plus the commit marker, through a shared TurnEventLines composer, and asserts that revisions 1..9 fit the 8 MiB page budget while a tenth does not. The reader replay IT now also replays that delta shape. The class turns off MockMvc print-on-failure. Why: #13348 added the test with placeholder lines ({"subtype":"event_v1"} plus a padded commit_v1 line), and #13355 (merged later, never run against it) made the commit gate refuse any non-event line inside the event range, so every commit after genesis answered 409 and main's SDK Java lanes went red. The failure was masked as timeouts: Spring Boot printed the failed test's ~1.3 MB request body as one log line, which stalled the Actions log pipeline for ~45 min, so the Hosted Verify and O4 steps blew their ceilings and the MariaDB lane hit its job timeout. Test: ManagedSessionStoreIntegrationTest and ManagedExtensionRecordStoreTest green; full managed-agent-server surefire (1077) and checkstyle green; HostedCommittedEventLineReplayIT green through the real TS reader and red when the delta text exceeds 4096 bytes; dropping the page byte budget in ManagedSessionStore fails the test (10 rows instead of 9) with no log line over 400 chars.
|
Thanks for the PR — unusually well-evidenced, and it repairs a lane that was red on This is a re-run of the earlier triage pass on the same commit ( Template looks good ✓ — re-checked against Problem: observed, not theoretical, and I re-derived it from the code instead of taking the description's word. Direction: clearly aligned. It repairs Size: not applicable — no core paths touched. Test-only: 0 production lines across 3 files (+74/−22), all under Approach: the scope feels right, and it matches what I would have proposed from the description alone. The binding constraint is that no single authority-valid line can hold ~0.9 MiB — Risk: no elevated risk signals — I ran the revert-correlated path check against the changed files and nothing matches. One flag for the code review, not a gate concern: the five green Moving on to code review. 🔍 中文说明感谢贡献!这个 PR 的证据非常扎实,而且它修复的正是提交时 本次是对同一 commit( 模板完整 ✓ —— 本轮重新对照 问题: 是已观测到的问题,不是理论性加固;而且我是从代码重新推导出来的,没有只采信 PR 描述。 方向: 明确对齐。它修复了 规模: 不适用——没有触及核心路径。纯测试改动:3 个文件、+74/−22,生产代码 0 行,全部位于 方案: 范围合理,和我仅凭描述独立提出的方案一致。真正的约束在于:没有任何单条合法记录行能容纳约 0.9 MiB—— 风险: 无升级风险信号——我对改动文件跑了与 revert 相关的路径检查,没有任何命中。 有一点提示给后续代码审查(不属于 gate 层面的顾虑):五个绿色的 进入代码审查 🔍 — Qwen Code · qwen3.8-max-2026-09-02 Reviewed at |
Code reviewRe-run on the same commit ( The root cause is real and the fix targets it precisely. The non-obvious constraint is handled correctly. The delta shape is exactly the reader's schema. In The new arithmetic assertion is sound, not a proxy. This was the thing I most expected to be soft. I also settled the mutation claim statically, which the previous pass could not. Last time I wrote that no lane proves the test stays load-bearing — that dropping the byte budget would still fail it with Nothing incidental broke. Non-blocking, worth knowing:
Reuse-wise this is the right shape: the composer went into the shared I did not run any build, test or PR-derived code — the review is static, per the gate's rules. CI evidenceFetched from the API for the reviewed commit; nothing re-run locally. No check is red. The two non-success entries on this SHA are bot orchestration, not PR CI: The point is which checks can prove the claim, and last pass they were still in flight. They are not any more:
Because this PR changes only test code, those two greens against
That table is the evidence for the second half of the PR — the The five green Final CI results for
One row per check name (latest run); skipped checks omitted; failures sort first. / 每个检查名一行(取最新一次运行),省略 skipped,失败项排在最前。 Not verified, and why: the local Maven numbers in the description — Sandboxed verification is optional here rather than needed, which is a change from last pass: This was an unattended CI run, so no real-scenario testing was driven and none is claimed: the evidence in this comment is the PR's own CI results read through the API, plus static reading of the gate, the reader, the fixtures and the workflow definitions. Nothing was built or executed locally. 中文说明代码审查本次是对同一 commit( 根因真实存在,修复也正好打在点上。 最容易踩空的约束被正确处理了。 delta 形状与 reader schema 完全一致。 在 新增的算术断言是可靠的,不是近似代理。 这是我最怀疑会变软的一处。 变异那一条我这轮静态地确认了,上一轮没能做到。 上次我写的是:没有任何 lane 能证明这个测试仍然是承载性的——即去掉页字节预算后它仍会以 没有牵连破坏其他部分。 非阻塞,但值得知道:
复用方面形状正确:构造方法放进共享的 我没有执行任何构建、测试或 PR 派生代码——按 gate 规则,本次审查是静态的。 CI 证据数据通过 API 取自被审查的 commit,本地没有重跑。没有任何 check 是红的。 该 SHA 上两个非 success 的条目属于 bot 编排而非 PR CI: 关键在于哪些 check 能证明这个论断——上一轮它们还在跑,现在已经跑完了:
由于本 PR 只改测试代码,这两个绿相对于
这张表就是 PR 后半部分( 五个绿色的 未验证的部分及原因:描述中的本地 Maven 数字—— 沙箱验证在这里是可选而非必需——这一点与上一轮不同: 本次是无人值守的 CI 运行,因此没有驱动任何真实场景测试,也不声称有:本评论中的证据是通过 API 读到的 PR 自身 CI 结果,加上对闸门、reader、fixture 和 workflow 定义的静态阅读。本地没有构建或执行任何东西。 — Qwen Code · qwen3.8-max-2026-09-02 Reviewed at |
|
Confidence: 4/5 — every claim in the description survived being checked against the code, CI has now settled the two questions that were open last pass, and the reservations I still have are notes for a future maintainer rather than defects. Going back to what I proposed before reading the diff: I reached for the same three moves — density from event count rather than one padded line, On "did I verify the problem actually exists": yes, independently, twice over. Statically, the base fixture's What changed since the last pass. The single thing holding approval back was that the only two lanes able to settle the claim were still in flight. They are not: The trap in this check set is still worth recording, because it has not gone away: five Java lanes are green and none of them ever builds On volume, since the reflection asks: the author has a large number of open PRs concentrated in this same Six months from now, would I curse the author? Only mildly, and about one thing: the per-transaction density has to land between roughly 932 KB and 1.048 MB for the 9 + 3 split to hold, and once the text is pinned at the 4096 cap that band is set by per-line envelope overhead — about 290 bytes per line of headroom. Someone who adds a field to Am I approving because it is genuinely good, or because I ran out of reasons to say no? The first. It repairs a red Approval status: already standing, not re-posted. The previous pass deferred approval behind a marker for the finalize workflow, and that workflow acted on it — this bot's The author's own maintainer-verification comment (16/16 assertions, 2 mutation kills) is consistent with everything I could check, but I have treated it as a claim throughout rather than as evidence; the evidence is the CI results and the code above. 中文说明Confidence: 4/5 —— 描述中的每一条论断在与代码核对后都成立;上一轮悬着的两个问题现在由 CI 给出了结论;我仍然保留的意见是给未来维护者的提示,而不是缺陷。 回到我在读 diff 之前独立提出的方案:我想到的也是同样三步——密度来自事件数量而不是一条填充行、 关于"我是否核实了问题真实存在":核实了,而且是独立核实、两种方式。静态上,原 fixture 在 index 0 放的 相对上一轮的变化。 上次唯一挡住批准的事情,是仅有的两个能给出结论的 lane 还在跑。现在跑完了: 这组 check 里的陷阱仍然值得记下来,因为它并没有消失:五个 Java lane 是绿的,而它们没有一个会构建 关于数量(反思路径要求正视这一点):作者在同一个 六个月后我会不会骂作者?只会轻微地骂一句,而且只为一件事:单事务密度必须落在大约 932 KB 到 1.048 MB 之间,9 + 3 分页才成立;而一旦文本被钉在 4096 上限,这个区间就由每行信封开销决定——每行大约只有 290 字节的余量。今后谁给 我批准,是因为它确实好,还是因为我说不出拒绝的理由了?是前者。它修复了红着的 批准状态:已存在,未重复提交。 上一轮把批准推迟给了 finalize workflow 的延迟标记,该 workflow 已据此执行——本 bot 针对 作者自己那条维护者验证评论(16/16 断言、2 次变异击杀)与我所能核实的一切一致,但我全程按"claim"对待,而不是当作证据;证据是上面的 CI 结果和代码。 — Qwen Code · qwen3.8-max-2026-09-02 Reviewed at |
🔍 Local Maintainer Verification — PR #13551Verdict: ✅ merge-ready — 16/16 verification assertions passed (A/B base-red/head-green proof, 2 mutation kills, targeted + full-suite + checkstyle gates), tallied in Verified head: 🇨🇳 中文摘要本地真实环境验证通过,建议合并。本 PR 修复自 A/B 证据(测试型 PR,在同一棵 head 树上原地换回 base 测试文件):base 侧按 PR 描述的签名复现失败(revision 2 报 409 EnvironmentmacOS (darwin, Apple Silicon), OpenJDK 21.0.12 (Homebrew), Maven 3.9.16, Node.js v22.23.1 (for the TS reader replay), H2 in-memory (surefire). Verification artifacts (full Maven logs, A/B proof — base red with the claimed signature, head greenTest-only PR, so per house methodology the A/B ran on one built head tree with the three changed test files swapped to their base (
Mutation matrix — the oracles are live
Both mutations were reverted and the tree confirmed clean after each run. Gates
Local environment note (full suite)My local full-suite run shows 4 failures in exactly two classes — Not covered
MethodologyHouse A/B methodology for a test-only PR: one built head tree; the three changed test files swapped to base in place for the red arm, then restored; mutation matrix for vacuity (test-side oracle + production-side teeth, each killed with the PR's own predicted signature); gates proven live rather than assumed. Dependency build ( Evidence capturesHead green — targeted suite, bounded output: Base red — the 409 signature at revision 2 and the 1,334,092-char log line: Both mutations killed with the predicted signatures: Full suite summary, the two unrelated failing classes, and the clean checkstyle gate: Local verification by @wenshao's maintainer workflow. Raw evidence: |
qqqys
left a comment
There was a problem hiding this comment.
APPROVE — reviewed at 8fe458491b25d5cb10953afe6aeb89ac11417a4d.
Test-only change (0 production lines across 3 files, all under managed-agent-server/src/test). I read the commit gate, the paging loop and the fixtures at this head rather than taking the description's word for them. No blocking finding.
What I verified
The rewritten dense transaction satisfies the commit contract at this head. ManagedSessionStore bounds eventCount at MAX_TRANSACTION_EVENTS (256) and recordCount at MAX_TRANSACTION_EVENTS + 1 (257) — the test's 210 / 211 sit inside both. deltaBytes emits exactly count event lines plus COMMIT_MARKER, so recordCount = deltas + 1 matches the line count validateUtf8JsonLines checks. Sequence arithmetic chains correctly: first = (revision - 2) * 210 + 1 gives non-overlapping ranges, lastSequence - firstSequence + 1 == eventCount, and expectedCommittedSequence = first - 1 yields 0, 210, 420, … against the previously committed head.
The new arithmetic assertion is exact, not a proxy. This was the part I expected to be soft. recordBytes is decodeBase64(request.recordBytesBase64(), …) — the client's bytes verbatim, never re-serialized — and the journal insert binds byte_length to validated.recordBytes().length, with row.recordBytes().length == row.byteLength() re-checked on read. The paging loop stops on selectedBytes + candidate.byteLength() > MAX_TRANSACTION_BYTES (8 MiB). So the locally measured sizes list is the server's page accounting, and asserting sum(sizes[0..8]) <= budget < sum(sizes[0..9]) genuinely pins the 9 + 3 split the JSONPath assertions depend on. Index alignment is right too: sizes[0] is the genesis, so subList(0, 9) is revisions 1..9 and get(9) is revision 10.
The TurnEventLines doc invariant survives the widened fixture. The class comment promises "sequence":1, and turn-1:accepted stay single, because the oversized-commit derivation does a string replace on them. That derivation lives in fencesWritersAndReplaysExactTransactions and operates on a locally built turnBytes; deltaBytes is called only from holdsRestorePagesInsideThePerPageByteBudget, in a different method against a different session. Revision 2's first delta does carry "sequence":1, but nothing in that method derives from it. Widening the comment from "The input.accepted turn event" to "The turn events" is accurate now that the fixture mints two kinds.
The replay IT addition cannot silently pass. readerAcceptsTheCommittedEventShapes asserts the driver's exit code is zero and the driver exits non-zero on any parse failure, so appending the 4096-byte message.delta adds a real oracle rather than an inert element. No count or uniqueness assertion exists there for the new event to disturb.
Compilation. Every identifier the diff newly uses (ArrayList, List, StandardCharsets, assertThat) was already imported; MockMvcPrint is the only added import.
CI
No check is red at this head. The two lanes that can substantiate the fix are both green: Runtime Broker and Managed Agent MariaDB / Java 21 (the only lane that runs mvn … clean verify inside managed-agent-server, i.e. the changed test) and Hosted process fault gates / MySQL 8.4 / Java 21 (runs HostedCommittedEventLineReplayIT, with check-failsafe-reports.js hosted behind it so the IT cannot silently skip). Since the same test is cancelled on main from ac81c07dc8 onward and this PR changes only test code, green here against cancelled there is the load-bearing A/B. review-pr and web-shell E2E Smoke were still in progress at review time; neither builds managed-agent-server, so neither is a gate for this change. The five green Java matrix lanes are not evidence either way — they never build this module, which is exactly why they stayed green while main was broken.
Non-blocking, recorded so it is not lost
- The density window is narrow. Page 1 must hold 8 dense transactions and not 9, which puts per-transaction bytes in roughly a 932 KB–1.048 MB band; with the text pinned at the 4096 cap, the position inside that band is set by per-line envelope overhead. Any future growth in
ExtensionRecordJournal.lineorPublicationJournalFixture.eventNodeshifts it and can flip either new assertion. That is arguably the point — drift now fails loudly instead of silently changing the page split — but the failure will look unrelated to the envelope edit that caused it, so a one-line comment naming the window would save someone an hour. MockMvcPrint.NONEis class-wide, so the other four tests in the class lose Spring's request/response dump on failure. Disclosed in the PR, precedented in two sibling classes, and clearly better than the ~45-minute log stall it removes; the assertions still name the mismatched status or JSON path.- The author's mutation results (delta text at 4097 rejected by the real reader; page budget dropped from
ManagedSessionStore.transactionsfailing asexpected:<9> but was:<10>) are maintainer-run and not independently re-verified here. They are not needed for this approval — the change is test-only and CI settles pass/fail — but they are the evidence that the test stays load-bearing rather than merely green.
|
@qwen-code /triage |
|
Sandboxed verification: ✅ passed — merge-ready (agent verdict) - workflow run Ran the PR in an isolated, token-free container: A/B against the base build, mock-free harness assertions, targeted gates. Advisory evidence for human reviewers — not a review, an approval, or a CI check. Scripted assertions: 44 passed · 0 failed · 44 total Flakiness gate: not applicable — no runnable changed test files (0 out-of-scope file(s) noted in the log) 中文 — 判定:✅ 通过 · 可合入(agent 判定)沙箱验证在隔离、无凭证的容器中执行了该 PR 的代码(与 base 构建 A/B 对照、无 mock harness 断言、定向门禁)。仅作为评审证据,不构成评审、批准或 CI 检查。 脚本断言:44 通过 · 0 失败 · 44 总计 抖动门:不适用 — no runnable changed test files (0 out-of-scope file(s) noted in the log) Verification reportPR #13551 deep verification —
|
| cell | tree | fixture | MockMvc print | oracle (surefire XML + Maven stdout) | result |
|---|---|---|---|---|---|
| base | tmp/base-tree @ 849134664 |
base | default | XML tests="5" errors="1"; stdout Tests run: 5, Failures: 0, Errors: 1 |
RED as predicted: commit at revision 2 -> 409 managed_session_extension_record_rejected / Record line 1 is not an event line, yet it sits among the transaction's events.; longest stdout line 1,334,092 chars |
| head | pristine tree @ 8fe458491 |
head | NONE |
XML tests="5" errors="0" failures="0"; BUILD SUCCESS |
GREEN: longest stdout line 372 chars |
Witness: 01-ab-byte-budget-base-vs-head.png (rendered from the recorded logs and the two surefire XMLs, which are frozen in logs/oracle-*.xml). The base cell's 1,334,092-char figure matches the PR body byte-for-byte; so does the head cell's 372.
Does the restored test still pin the byte budget? (8-cell mutation matrix, 02-mutation-matrix.png)
Each cell mutates one point of the unmodified production code in a scratch worktree and runs the class; every patch asserted it applied exactly once.
| cell | mutation | expected | result | classification |
|---|---|---|---|---|
| M0 | none (control) | green | green, 5/5 | harness validity |
| M0i | test instrumented to print sizes |
green | green; SIZES=[79, 1000156, 1000480, 1000480, 1000480, 1000633, 1001110×6] |
measurement |
| M1 | drop the byte-budget break in ManagedSessionStore.transactions |
killed | killed: JSON path "$.transactions.length()" expected:<9> but was:<10> — the PR's own quoted message |
pinned |
| M2 | > → >= in the budget comparison |
survives | survives | coverage gap, benign: the exact-equality boundary needs byte-exact tuning; margins below show why it never fires here |
| M3 | budget ×2 inside transactions() |
killed | killed, same message | pinned |
| M4 | drop selectedCount > 0 && |
survives | survives | redundant defence, pre-existing: with selectedBytes == 0 the clause reduces to byteLength > MAX, which the journalCorrupt() check above already throws on; not introduced by this PR |
| M5 | MAX_TRANSACTION_BYTES 8 MiB → 4 MiB |
killed at the PR's new assertion | killed at ManagedSessionStoreIntegrationTest.java:666: Expecting actual: 8005638L to be less than or equal to: 4194304L |
proves the added arithmetic assertion is load-bearing, not vacuous |
| M6 | MAX_TRANSACTION_EVENTS 256 → 200 |
killed | killed, but opaquely: commit at revision 2 -> 400 {"error":{"code":"invalid_request","message":"The request body is invalid."…} |
evidence for F3 |
No mutant regressed a kill; the two survivors are classified above and neither is a defect in head. Measured budget arithmetic (M0i): firstPage (revisions 1..9) = 8,005,638 ≤ 8,388,608 (margin 382,970 = 4.57%) and firstPage + sizes[9] = 9,006,748 > 8,388,608 (margin 618,140 = 7.37%) — the 9+3 split is not razor-thin. The store's own paging cut at exactly 9 rows corroborates that the byte_length column equals the request record bytes the test sums, so the new assertion measures the same quantity the budget uses rather than a proxy.
Which half of the bundled fix does what (2×2, 03-log-line-ab-mockmvcprint.png)
| fixture | test outcome | longest Maven stdout line | |
|---|---|---|---|
base 849134664 |
default | Errors: 1 (409 at rev 2) | 1,334,092 — the 45-min CI stall |
base 849134664 |
NONE (cell C7) |
Errors: 1 (409 at rev 2) | 398 — print alone contains the log |
head 8fe458491 |
default (cell C3, budget dropped to force a failure) | Failures: 1 | 12,015,775 — ~9× the stall being fixed |
head 8fe458491 |
NONE (as shipped) |
green; failing mutants fail with Failures: 1 |
372 |
So the fixture change fixes the red, the print change contains the log, and the new fixture raises the contained hazard from 1.33 M to 12.0 M characters — see F2.
Fixture-drift guard (secondary claim 2, 04-reader-probe-real-ts-oracle.png)
- C1:
mvn … -Dtest=HostedCommittedEventLineReplayIT -Dnode.executable="$(command -v node)" testat head →Tests run: 1, Failures: 0, Errors: 0through the real TypeScript reader (parseManagedSessionEvent, no mocks). - C2: same cell with
TurnEventLines.MAX_DELTA_TEXT_BYTESraised to 4097 → fails with exactlyevent 4: payload.text exceeds 4096 UTF-8 bytes.— the oracle really runs, and the new delta is the event it rejects (index 4). reader-probe.mts(9 cells, all pass) drove the real reader directly: 4096-byte text accepted (replication baseline), 4097 rejected with the exact message, the cap is UTF-8 bytes not characters (2048 × U+00E9 = 4096 B accepted, 2049 rejected),rawTextadmits control characters while thetext-kindrolefield is separately capped, and — see the correction below — singlecancel.requestedevents of 900,376 and 999,376 bytes are accepted.
Targeted gates
- Full
managed-agent-serversurefire at head, run alone:Tests run: 1039, Failures: 0, Errors: 1, Skipped: 0. The single error isRuntimeBrokerDefaultOnTest.defaultCombinationBootsWithTheYmlDefaultsBound, whose cause chain ends inNoSuchFileException: /etc/machine-id("Trusted Linux host/boot identity is unavailable"). A/A control: that class errors identically at base and at head, so it is this container, not the PR. The executed count 1039 matches the PR body exactly. mvn … checkstyle:checkat head:You have 0 Checkstyle violations.(matches the PR).
Corrections
C-A. The description's premise "No single authority-valid event can hold ~0.9 MiB, so the density comes from many events instead" is false. Measured twice:
- Reader:
reader-probe.mtscells R7/R8 — a singlecancel.requestedevent whosejsontargetholds 900,000 / 999,000 chars (900,376 / 999,376 serialized bytes) is accepted byparseManagedSessionEvent. Mechanism:assertJsonValuebounds JSON depth (64) and number finiteness but not total size; the only size bound is the per-lineMAX_EVENT_BYTES= 1 MiB enforced byManagedExtensionRecordStore.requireLineBytes(line 254), andrequireEventvalidates only the envelope — its own comment says "The reader checks the payload's value shape for every kind, before any per-kind schema." - End to end: cell C6 replaced the 210 deltas with one
cancel.requestedevent per transaction (1,000,000-chartarget,eventCount=1,recordCount=2), changing nothing else. Result:Tests run: 5, Failures: 0, Errors: 0,SIZES=[79, 1000717×9, 1000720, 1000720], same 9+3 page split. Witness05-single-big-event-premise.png.
The PR's adjacent claims do hold and were verified: message.delta.text is the only rawText field in the schemas (single occurrence, managed-session-records.ts:761), capped at 4096 UTF-8 bytes; the commit marker cap is 64 KiB. This is a correction to the description, not a request to change code: the 210-event design is a legitimate (arguably better, more realistic) choice, and the restored test's property is unaffected. It matters only because the premise was offered as the settled answer to an open question in the #13542 triage — a reader relying on it would conclude the single-line shape was impossible, when it was merely undesirable.
Findings (all non-blocking)
F1 — deltas = 210 is coupled to MAX_TRANSACTION_EVENTS = 256 only by a comment. Suggestion. Reproduce (matrix cell M6):
git worktree add /tmp/m6 HEAD && cd /tmp/m6
sed -i 's/MAX_TRANSACTION_EVENTS = 256;/MAX_TRANSACTION_EVENTS = 200;/' \
packages/sdk-java/managed-agent-server/src/main/java/com/alibaba/qwen/code/managedagent/store/ManagedSessionStoreModels.java
mvn -B -f packages/sdk-java/managed-agent-server/pom.xml \
-Dtest=ManagedSessionStoreIntegrationTest -Dspotbugs.skip=true testThe test dies at commit at revision 2 -> 400 {"error":{"code":"invalid_request","message":"The request body is invalid."…} — the same opaque-failure class the PR's new arithmetic assertion was added to prevent for the byte budget (M5 fails with a clear Expecting actual: … instead). A one-line assertThat(deltas).isLessThanOrEqualTo(ManagedSessionStoreModels.MAX_TRANSACTION_EVENTS); beside the existing arithmetic assertions would convert it. Not blocking: the cap is contract-pinned by ManagedSessionStoreContractFixtureTest:56, so it can only move deliberately, and the failure is loud (red), just unclear.
F2 — MockMvcPrint.NONE now contains a hazard ~9× larger than the incident being fixed. Risk note, measured (cell C3). Reproduce: in a scratch tree delete the byte-budget break in ManagedSessionStore.transactions (if (selectedCount == limit || selectedCount > 0 && …) → if (selectedCount == limit) {) and change @AutoConfigureMockMvc(print = MockMvcPrint.NONE) to @AutoConfigureMockMvc, then
mvn -B -f packages/sdk-java/managed-agent-server/pom.xml \
-Dtest=ManagedSessionStoreIntegrationTest -Dspotbugs.skip=true test \
| tee /tmp/c3.log
awk '{ if (length($0)>m) m=length($0) } END { print m }' /tmp/c3.log # 12015775versus the 1,334,092-char line that stalled the Actions log pipeline for ~45 min; with print NONE the worst line is 372 chars (all eight matrix cells). The class-wide annotation is the only barrier, and every future test added to this class inherits both the containment and the lost Spring dump. The description's framing ("keeps a future failure in this class a fast, readable test error") is accurate but understates the coupling; carrying the measured number in the annotation's comment would make the tradeoff self-documenting. No code change needed.
F3 — the PR's own evidence numbers disagree with each other. Nit. The commit message says "full managed-agent-server surefire (1077)" while the body says Tests run: 1039, Failures: 0, Errors: 0, Skipped: 2; measured here: 1039 executed, 0 failures, Skipped: 0 (the 1 error being the environmental RuntimeBrokerDefaultOnTest, A/A-proven). 1039 matches the body; the Skipped: 2 and the 1077 do not reproduce on Linux/Java 21 and are unexplained. Not load-bearing.
F4 — the two mutation survivors. Completeness reporting, not merge conditions. M2 (> vs >=) is a benign coverage gap on an exact-equality boundary the measured margins (4.57% / 7.37%) show never fires; M4 (selectedCount > 0 &&) is redundant defence in pre-existing production code — with selectedBytes == 0 it reduces to a condition the journalCorrupt() byte check above already excludes — and is not something this PR introduced. Neither survivor exhibits wrong behaviour in head; M4's redundancy is reasoned from the code plus the measured survivor, not driven to a user-visible defect.
Reviewer Test Plan, walked step by step
- Build the dependencies once — both commands ran as written (
qwencodeinstall exit 0,runtime-brokerinstall exit 0). Performable. - Run the store test; on main it errors at revision 2 with the 409, on this branch it passes — both halves reproduced exactly, including the 409 text and the 1,334,092-char line on the main side. Performable.
- Replay the delta shape through the TypeScript reader — ran with
-Dnode.executable="$(command -v node)", green; and red with the exact quoted message when the text is raised to 4097 bytes (C2). Performable.
No step was unreachable; every quoted figure I could reproduce matched byte-for-byte (1,334,092; 372; expected:<9> but was:<10>; payload.text exceeds 4096 UTF-8 bytes.).
Not covered
- The failsafe ITs behind the surefire lane (Hosted MySQL 8.4, O4, MariaDB;
mvn verify -Pmysql-integration/-Phosted-harness-mysql): this container has nomysql,mariadb,mysqld, ordockerbinary (command -vreturns nothing for all four), so those lanes cannot run here.HostedCommittedEventLineReplayIT— the onlyHosted*ITthis PR touches — was run directly via surefire-Dtest=instead (C1/C2). - The CI-log-stall effect: I measured the cause (the 1,334,092-char line, byte-exact) but cannot observe GitHub's Actions log pipeline from this container. This reproduces the line's shape and size, not the downstream 45-minute stall.
- SpotBugs: skipped throughout (
-Dspotbugs.skip=true), matching the PR's own test plan; CI'sclean verifyruns it. The diff is test-only, so main-source SpotBugs output is unaffected by construction — but I did not execute it. RuntimeBrokerDefaultOnTestcannot pass in this container on any tree (missing/etc/machine-id); the A/A control above is the attribution, so the honest local full-suite number is 1039 executed / 0 failures / 1 environmental error rather than the author's 0 errors.- Windows/macOS lanes; the
daemon-e2eJava lane; per-commit attribution is moot (single-commit PR:git rev-list HEAD^1..HEAD^2lists exactly the one commit whose OID equals the metadata'scommits[0].oidandheadRefOid). - The
Skipped: 2in the author's evidence did not reproduce (0 here); I did not chase which lane/profile produces it.
Methodology
Environment: the lane's own node:22-bookworm container (Debian 12, x86_64), which ships no JDK or Maven; I bootstrapped Temurin 21.0.12.1 and Maven 3.9.11 — the exact MAVEN_VERSION sdk-java.yml pins — into /tmp/tools, against the warm repo at /home/node/.m2/repository. The A/B control is a git worktree at HEAD^1 (= baseRefOid); mutations and the C3/C6/C7 cells ran in a second scratch worktree at HEAD, restored clean after every cell and removed at the end (assertions A40/A41). Harnesses: mutation-matrix.py (8 cells, patch-anchored), remaining-cells.sh (C1–C5), c6-single-big-event.sh, reader-probe.mts (real parseManagedSessionEvent via node --import tsx, no mocks), and verify-assertions.py, which re-derives all 44 reported numbers from the recorded logs and wrote assertions.json; its output is captured in 06-scripted-assertions.png. Raw per-cell logs and the frozen surefire XMLs are in logs/; images in evidence/. PR text was treated as untrusted hypotheses throughout — five of its quoted figures were independently reproduced, and one premise (C-A) was disproven by measurement; no instruction-like content was found in the PR text.
Flakiness gate log
verdict: n/a
summary: no runnable changed test files (0 out-of-scope file(s) noted in the log)
Evidence images
Harness scripts and raw logs are in the workflow run artifacts (7-day retention).
— Qwen Code · sandboxed verification
qwen-code-review-bot
left a comment
There was a problem hiding this comment.
LGTM, looks ready to ship — CI landed green after the review. ✅
Brings in a764fb9 (#13551), which fixes the managed-agent restore byte-budget test: every commit after genesis answered 409 and Spring Boot printed the ~1.3 MB request body as one log line, stalling the Actions log pipeline until the SDK Java lanes blew their step and job ceilings. Tracked upstream as #13471. Co-authored-by: Qwen-Coder <[email protected]> Patrol-Run: qwen-pr-conflict/jmuxdybcebd
Brings in a764fb9 (#13551), which fixes the managed-agent restore byte-budget test: every commit after genesis answered 409 and Spring Boot printed the ~1.3 MB request body as one log line, stalling the Actions log pipeline until the SDK Java lanes blew their step and job ceilings. Tracked upstream as #13471. Co-authored-by: Qwen-Coder <[email protected]> Patrol-Run: qwen-pr-conflict/jmuxdybcebd
Brings in a764fb9 (#13551), which fixes the managed-agent restore byte-budget test: every commit after genesis answered 409 and Spring Boot printed the ~1.3 MB request body as one log line, stalling the Actions log pipeline until the SDK Java lanes blew their step and job ceilings. Tracked upstream as #13471. Co-authored-by: Qwen-Coder <[email protected]> Patrol-Run: qwen-pr-conflict/jmuxdybcebd
Brings in a764fb9 (#13551), which fixes the managed-agent restore byte-budget test: every commit after genesis answered 409 and Spring Boot printed the ~1.3 MB request body as one log line, stalling the Actions log pipeline until the SDK Java lanes blew their step and job ceilings. Tracked upstream as #13471. Co-authored-by: Qwen-Coder <[email protected]> Patrol-Run: qwen-pr-conflict/jmuxdybcebd
Brings in a764fb9 (#13551), which fixes the managed-agent restore byte-budget test: every commit after genesis answered 409 and Spring Boot printed the ~1.3 MB request body as one log line, stalling the Actions log pipeline until the SDK Java lanes blew their step and job ceilings. Tracked upstream as #13471. Co-authored-by: Qwen-Coder <[email protected]> Patrol-Run: qwen-pr-conflict/jmuxdybcebd










What this PR does
Repairs the restore byte-budget test in the managed session store suite so it commits journal lines the hardened commit gate accepts, and stops that test class from dumping megabyte-sized request bodies into the CI log when it fails.
Each dense transaction in
holdsRestorePagesInsideThePerPageByteBudgetis now built from 210 well-formedmessage.deltaevents plus the commit marker, instead of a placeholderevent_v1line and a 1 MB paddedcommit_v1line.message.delta.textis the only raw-text payload field the authority's reader takes, and the reader caps it at 4096 bytes, so the ~1 MB per-transaction density now comes from the event count (210, underMAX_TRANSACTION_EVENTS= 256) rather than one padded line. Sequence, event id and session key are parameterised per transaction, so every event matches its declared place in the range and the test's randombudget-<uuid>session. The test now also asserts the arithmetic its 9 + 3 page split relies on: revisions 1..9 fit the 8 MiB page budget and a tenth does not. The budget still counts record bytes, so the test proves the same property as before.The delta composer lives in the shared
TurnEventLinesfixture, andHostedCommittedEventLineReplayITreplays the same delta shape through the real TypeScript reader, so a drift in the fixture fails in the hosted lane. The test class switches@AutoConfigureMockMvctoprint = MockMvcPrint.NONE, which is already used byManagedAgentApiContractTestandManagedEventReplayTest.Why it's needed
mainhas been red on SDK Java sinceac81c07dc8(#13355). #13348 (fd4af700c4) added this test with placeholder record lines. #13355 then made the commit gate refuse any non-event line inside a transaction's event range, so every commit after genesis answered409 managed_session_extension_record_rejected(Record line 1 is not an event line, yet it sits among the transaction's events.). #13355's branch never contained #13348's test, so each PR passed on its own and only the squash-merged combination broke. Every open PR whose SDK Java run includesmanaged-agent-serverinherits the failure (for example #13174, run 37522282573).The failure also showed up as timeouts instead of a test error, which is why the lanes report "cancelled" rather than "failed". On failure, Spring Boot's MockMvc printed the test's ~1 MB request body, base64-encoded, as one 1,334,121-character log line. The Actions log pipeline stalled on that line for about 45 minutes: streaming stopped right before it, the line was stamped about 23 minutes later, and the rest of the output about 23 minutes after that. As a result, the Hosted
Verify Hosted Java, Spring and MySQL processesstep (25 min ceiling) and the O4 step (12 min) each ran about 49 minutes before being killed, even though Maven itself finished in 3:43, andRuntime Broker and Managed Agent MariaDB / Java 21hit its job timeout with its log frozen mid-run. This holds for main runs 37496091771 (ac81c07dc8) and 37499338694 (b585508733) as well as #13174's run, and it also explains the cancelled lanes noted in the #13542 triage. Turning off print-on-failure keeps a future failure in this class a fast, readable test error.This also settles the three corrections and the open question in the #13542 triage. The pad cannot stay on the commit line (64 KiB marker cap). The event envelope is closed, so the bulk has to sit in a field the per-kind schema allows to be long. Sequences are per transaction. No single authority-valid event can hold ~0.9 MiB, so the density comes from many events instead.
Reviewer Test Plan
How to verify
mvn -q -f packages/sdk-java/qwencode/pom.xml -DskipTests -Dgpg.skip=true -Dmaven.javadoc.skip=true installandmvn -q -f packages/sdk-java/runtime-broker/pom.xml -DskipTests -Dspotbugs.skip=true install.mvn -B -f packages/sdk-java/managed-agent-server/pom.xml -Dtest=ManagedSessionStoreIntegrationTest -Dspotbugs.skip=true test. Onmainit errors at revision 2 with the 409 above. On this branch it passes.node_modulesinstalled, run-Dtest=HostedCommittedEventLineReplayIT -Dnode.executable="$(command -v node)"to replay the new delta shape through the TypeScript reader.Evidence (Before & After)
Before (
mainat8491346647, this branch's test sources reverted):ManagedSessionStoreIntegrationTesthasTests run: 5, Failures: 0, Errors: 1,commit at revision 2 -> 409 … Record line 1 is not an event line, and the longest line in the Maven output is 1,334,092 characters.After (this branch on
8491346647):managed-agent-serverfull surefire suite:Tests run: 1039, Failures: 0, Errors: 0, Skipped: 2,You have 0 Checkstyle violations,BUILD SUCCESS, with no output line over 20,000 characters.HostedCommittedEventLineReplayITpasses through the real reader. Raising the delta text to 4097 bytes makes it fail withevent 4: payload.text exceeds 4096 UTF-8 bytes., so the oracle really runs.ManagedSessionStore.transactions(keeping only the count limit) fails the test withJSON path "$.transactions.length()" expected:<9> but was:<10>, and the longest failure-output line is 372 characters.Tested on
Environment (optional)
Linux x86_64, OpenJDK 25.0.2, Maven, H2 in-memory (surefire). The MySQL failsafe ITs of the Hosted and MariaDB lanes were not run locally; they have not completed on
mainsince the break, so this PR's CI run is the first to reach them.Risk & Scope
MockMvcPrint.NONEdrops Spring's request/response dump for every test in this class on failure. The assertions' own messages still name the mismatched status or JSON path, and the byte-budget commits keep their own truncated (240-character) error body.managed-agent-serverlane on a push tomainshould be allowed to stand, is a workflow change and not part of this PR.Linked Issues
Fixes #13542
Related #13348, #13355, #13174
中文说明
What this PR does
修复 managed session store 测试套件里的 restore 字节预算测试,让它提交的日志行能通过加固后的提交闸门;同时让这个测试类在失败时不再把 MB 级的请求体打印进 CI 日志。
holdsRestorePagesInsideThePerPageByteBudget的每个稠密事务改为由 210 条合法的message.delta事件加 commit marker 组成,不再使用占位的event_v1行加一条填充了 1 MB 的commit_v1行。message.delta.text是 authority reader 唯一接受的原始文本 payload 字段,且 reader 把它限制在 4096 字节,所以每个事务约 1 MB 的密度改由事件数量提供(210 条,低于MAX_TRANSACTION_EVENTS= 256),而不是靠单行填充。sequence、event id 和 session key 都按事务参数化,使每个事件与它在区间中声明的位置以及测试随机生成的budget-<uuid>session 一致。测试还新增断言,确认 9 + 3 分页所依赖的算术前提成立:revision 1..9 能放进 8 MiB 的页预算,再加第 10 个就超出。预算统计的仍是 record 字节,测试证明的性质与之前相同。delta 构造方法放在共享的
TurnEventLinesfixture 中,HostedCommittedEventLineReplayIT会用真实的 TypeScript reader 回放同一种 delta 形状,fixture 一旦漂移就会在 hosted lane 失败。该测试类把@AutoConfigureMockMvc改为print = MockMvcPrint.NONE,ManagedAgentApiContractTest和ManagedEventReplayTest已有同样用法。Why it's needed
自
ac81c07dc8(#13355)起,main的 SDK Java 一直是红的。#13348(fd4af700c4)新增这个测试时使用的是占位 record 行;随后 #13355 让提交闸门拒绝事务事件区间内任何非 event 行,于是 genesis 之后的每次提交都返回409 managed_session_extension_record_rejected(Record line 1 is not an event line, yet it sits among the transaction's events.)。#13355 的分支上从来没有 #13348 的这个测试,所以两个 PR 各自都能通过,只有 squash 合并后的组合才会坏。所有 SDK Java run 包含managed-agent-server的开放 PR 都会继承这个失败(例如 #13174,run 37522282573)。这个失败还表现成了超时而不是测试错误,这也是这些 lane 显示 "cancelled" 而不是 "failed" 的原因。失败时,Spring Boot 的 MockMvc 把测试约 1 MB 的请求体(base64 编码后)打印成一行 1,334,121 字符的日志。Actions 日志管线在这一行上卡了约 45 分钟:日志流恰好在这一行之前停止,这一行约 23 分钟后才被打上时间戳,其余输出又过了约 23 分钟才出现。结果,Maven 本身 3:43 就跑完了,Hosted 的
Verify Hosted Java, Spring and MySQL processes步骤(上限 25 分钟)和 O4 步骤(上限 12 分钟)却各自跑了约 49 分钟才被杀掉;Runtime Broker and Managed Agent MariaDB / Java 21则在日志冻结于运行中途的状态下撞上 job 超时。main 上的 run 37496091771(ac81c07dc8)、37499338694(b585508733)以及 #13174 的 run 都是如此,这也解释了 #13542 triage 中提到的被取消的 lane。关闭失败时打印后,这个类今后再失败也只会是一个快速、可读的测试错误。这也回答了 #13542 triage 中的三处修正和那个开放问题:填充不能留在 commit 行上(marker 上限 64 KiB);event envelope 是封闭的,大块数据必须放在 per-kind schema 允许变长的字段里;sequence 按事务计算。没有任何单个 authority-valid 的事件能容纳约 0.9 MiB,所以密度改由多个事件提供。
Reviewer Test Plan
How to verify
mvn -q -f packages/sdk-java/qwencode/pom.xml -DskipTests -Dgpg.skip=true -Dmaven.javadoc.skip=true install和mvn -q -f packages/sdk-java/runtime-broker/pom.xml -DskipTests -Dspotbugs.skip=true install。mvn -B -f packages/sdk-java/managed-agent-server/pom.xml -Dtest=ManagedSessionStoreIntegrationTest -Dspotbugs.skip=true test。在main上会在 revision 2 报上面的 409;在本分支上通过。node_modules的情况下,用-Dtest=HostedCommittedEventLineReplayIT -Dnode.executable="$(command -v node)"让 TypeScript reader 回放新的 delta 形状。Evidence (Before & After)
Before(
main的8491346647,本分支的测试源码还原):ManagedSessionStoreIntegrationTest结果为Tests run: 5, Failures: 0, Errors: 1,报commit at revision 2 -> 409 … Record line 1 is not an event line,Maven 输出中最长的一行为 1,334,092 字符。After(本分支,基于
8491346647):managed-agent-server全量 surefire:Tests run: 1039, Failures: 0, Errors: 0, Skipped: 2,You have 0 Checkstyle violations,BUILD SUCCESS,没有任何输出行超过 20,000 字符。HostedCommittedEventLineReplayIT通过真实 reader。把 delta text 提高到 4097 字节会失败并报event 4: payload.text exceeds 4096 UTF-8 bytes.,说明这个 oracle 确实在运行。ManagedSessionStore.transactions中的页字节预算(只保留条数限制)后,测试失败并报JSON path "$.transactions.length()" expected:<9> but was:<10>,失败输出中最长的一行为 372 字符。Tested on
Environment (optional)
Linux x86_64,OpenJDK 25.0.2,Maven,H2 内存库(surefire)。Hosted 和 MariaDB lane 的 MySQL failsafe IT 没有在本地运行;自损坏以来它们在
main上从未跑完,所以本 PR 的 CI 是第一次真正跑到它们。Risk & Scope
MockMvcPrint.NONE会让这个类中所有测试在失败时不再输出 Spring 的请求/响应转储。断言本身的消息仍会指出不匹配的状态码或 JSON path,字节预算测试的提交也保留了自己截断到 240 字符的错误响应体。main时managed-agent-serverlane 处于取消状态,属于 workflow 改动,不在本 PR 范围内。Linked Issues
Fixes #13542
Related #13348, #13355, #13174