Repository navigation
test(runtime): hold clock-derived header values fixed in the /meta action-entry wire comparison - #31195
Conversation
…ues held fixed The ADR-0106 D1 action-entry describe compared whole wire texts, including the Last-Modified header the protocol stamps with the time of the read at one-second precision. Two sequential reads that straddled a second differed there only and ejected unrelated PRs from the merge queue. wireText now reads a date-valued Last-Modified or Date header as a fixed token; status, body, ETag, every other header, and the clock header's presence are still compared. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017ihL2gH1g3Qk8UMKLnGKoq
📓 Docs Drift CheckNothing 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): |
|
domain:server#4 · marchtian · session_017ihL2dLQEXWGsE2SZ3Qn5F 席位核对 — ACCEPT · domain:server#4 · Head-sha:
|
⛔ merge queue 构建失败 — 先分诊,再决定要不要重排队列构建 42396875046 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集), 分类: 失败的 job(日志抽取,best effort):
跨 PR 相同签名(24h,按失败测试文件聚合):
历史信号:
分诊清单:
Generated by Claude Code · merge-queue-triage workflow (#4859) |
|
domain:server#4 · marchtian · session_017ihL2dLQEXWGsE2SZ3Qn5F Queue ejection read · build 42396875046 ·
|
Requested by 田騏 · project thread
Fixes #31171
Clause-②: no
Metadata-protocol: none
维护者速读
/meta动作条目对比测试在比较两次响应时,把Last-Modified(以及Date)头的日期值视为固定占位,其余字节照旧逐字比较。packages/runtime/src/domains/mcp-object-schema-mask.test.ts里新的CLOCK_HEADERS和wireText。pnpm --filter @objectstack/runtime exec vitest run src/domains/mcp-object-schema-mask.test.ts,预期 45 个用例全部通过。What changes
wireTextin the ADR-0106 D1 action-entry describe ofpackages/runtime/src/domains/mcp-object-schema-mask.test.tsserialised the whole/metawire (status, body, headers) and every comparison in that describe is an exact string equality over it. The REST cached arm sendsLast-Modified, and the protocol stamps it with the time of the read (packages/metadata-protocol/src/protocol-search-and-cache.ts,lastModified: new Date().toISOString()), rendered at one-second precision. Two sequential reads that straddle a second boundary therefore differ in that header only.wireTextnow reads the value of aLast-ModifiedorDateheader (case-insensitive) as the fixed tokenCLOCKwhen the value parses as a date. Everything else is compared exactly as before:ETag,Cache-Control,Varyand every other header, byte for byte;Last-Modifiedstill differs);Every
wireTextcaller in the describe (the absent-name equivalences, thelayers/legacyLayers/publishedreads, the member-vs-staff CONTROL, the exempt-vs-unsecured CONTROL and the conditional-read 404) still proves the same thing: none of them is about the time of the read.Both queue ejections were this header, read from the Test Core logs:
usr_system item st_ping),Last-Modified14:49:31 GMTvs14:49:30 GMT, every other byte equal.15:19:24 GMTvs15:19:23 GMT(diagnosis on the card).No nondeterminism in the projection itself was found: in both logs the body and the
ETagare equal and the header keys come in the same order.Tests
Ablation (one-time, the test file mutated through scripts/ablation-replace.mjs, restored to HEAD after each leg)
The member-vs-staff CONTROL assertion was replaced so that the staff read happens with the clock moved forward one second (
vi.useFakeTimers({ toFake: ['Date'] })+vi.setSystemTime(Date.now() + 1000)), with a precondition on the REST cached arm that the twoLast-Modifiedvalues really differ. Run with-t "CONTROL — a field-bound action"(3 tests: REST cached, REST uncached, dispatcher).wireText+ one-second skew: 3 passed.JSON.stringify) + one-second skew: REST cached arm FAILS onst_rename; the diff is"Last-Modified":"Sat, 07 Nov 2026 16:14:07 GMT"vs16:14:06 GMT. This reproduces the queue failure deterministically.wireText, no skew,Last-Modifieddeleted from the staff answer: REST cached arm FAILS ("Last-Modified":"CLOCK"against an answer without the header), so presence is still compared.Each leg:
ablation-replace: ok mutation landedbefore the run andok restored: blob == HEAD (784ab7096c9c) and git diff HEAD is emptyafter it. The test file runs from source, so nodist/is involved.Repeat runs
pnpm --filter @objectstack/runtime exec vitest run --maxWorkers=2 src/domains/mcp-object-schema-mask.test.ts, 15 runs in a loop on dbd57b6: 15 ×Tests 45 passed (45), every run exit 0.Acceptance notes
Last-Modifiedthe/metaitem door sends on its cached arm is the time of the read, not the time the item last changed (protocol-search-and-cache.tsstampsnew Date()), so it carries no information a client can use; freshness is gated by theETag. Noted, not filed: this PR does not change it and no test here depends on it.Last-Modified, so on those doors the comparison was already stable.Verification
Merged
origin/main(eb68b98) once before opening; the derived gate list was taken at fc6ee74.Derived gates (node scripts/pm/dispatch-gates.mjs --commands, 50 commands)
All on fc6ee74 (after the merge of origin/main):
node scripts/check-closing-keyword-parity.mjs :: exit 0node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0node scripts/check-comment-mask-adoption.mjs :: exit 0node scripts/check-comment-mask-adoption.mjs --self-test :: exit 0node scripts/check-comment-mask-corpus.mjs :: exit 0node scripts/check-dts-emitted.mjs --self-test :: exit 0node scripts/check-issue-citations.mjs :: exit 0node scripts/check-plugin-teardown-shape.mjs :: exit 0node scripts/check-plugin-teardown-shape.mjs --self-test :: exit 0node scripts/ci/assert-turbo-remote-cache.mjs --self-test :: exit 0node scripts/ci/plan-test-core-shards.mjs --self-test :: exit 0node scripts/ci/prune-turbo-cache.mjs --self-test :: exit 0node scripts/docs-audit/check-affected-docs.mjs :: exit 0node scripts/docs-audit/check-drift-comment.mjs :: exit 0pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0pnpm check:ci-filter-parity :: exit 0pnpm check:closed-ceremony-text :: exit 0pnpm check:cross-package-test-inputs :: exit 0pnpm check:doc-authoring :: exit 0pnpm check:driver-memory-census :: exit 0pnpm check:dts-closure :: exit 0pnpm check:dual-build-cjs-loads :: exit 0pnpm check:engine-double-contract :: exit 0pnpm check:gitlink-declared :: exit 0pnpm check:issue-citations :: exit 0pnpm check:keyed-text-bounds :: exit 0pnpm check:lean-entry-closure :: exit 0pnpm check:logger-receiver-detach :: exit 0pnpm check:nul-bytes :: exit 0pnpm check:objectql-double-limit :: exit 0pnpm check:org-identifier :: exit 0pnpm check:page-declaration-shape :: exit 0pnpm check:platform-object-tenancy-census :: exit 0pnpm check:published-files :: exit 0pnpm check:query-options-erasure :: exit 0pnpm check:refd-timer-probe :: exit 0pnpm check:registry-log-declared :: exit 0pnpm check:rest-log-spy-declared :: exit 0pnpm check:route-envelope :: exit 0pnpm check:slot-lookup :: exit 0pnpm check:sourcemap-no-sources-content :: exit 0pnpm check:system-context-census :: exit 0pnpm check:test-source-alias :: exit 0pnpm check:tier-file-adoption :: exit 0pnpm check:type-check-coverage :: exit 0pnpm check:type-check-debt :: exit 0pnpm check:undeclared-dep-imports :: exit 0pnpm check:vouch-for-reference-callers :: exit 0pnpm check:watch-hint-literal :: exit 0pnpm check:where-matcher :: exit 0Two first ran exit 3 and were rerun after building their prerequisite:
node scripts/check-plugin-teardown-shape.mjs --self-test(positive-control commit 621a487 not in the shallow clone; fetched it),pnpm check:dual-build-cjs-loads(no dist; fullturbo run build, 119/119 tasks). Reconciliation:node scripts/pm/dispatch-gates.mjs --ran→ 50 derived, 50 run, 0 NOT-MEASURED, 0 UNRUN.Package:
pnpm --filter @objectstack/runtime typecheckexit 0 (tsc + check:test-typecheck);pnpm --filter @objectstack/runtime testexit 0, Test Files 554 passed (554), Tests 8918 passed / 19 skipped; eslint over packages/runtime (--no-inline-config) exit 0.Human Minimum
packages/specholds no runtime logic.pnpm lintpasses.main, one pull request.@objectstack/runtimeshipsdistonly, so nothing publishes:skip-changeset.)packages/spectouched: its generated artifacts are regenerated and committed. (Not touched.)content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.Generated by Claude Code
🤖 Generated with Claude Code