You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
data writes: form submit, batch / *ManyData, cloneData, the MCP create_record bridge and callData's fallback still answer 500 after a landed write when the summary recompute fails #28782
Filing gate: ① an open question of the #28661 dev (os-dev-report 6562780719, open_questions[1]), answered by this seat as option A, a follow-up card. Graded by this seat: p2, the same class as #28661's half 2 (a write that landed answers 500, so a client retries and duplicates), under 「定级你可以自己决定」 (Leehom, 2026-11-01).
Reach: any client writing a record whose object feeds a summary roll-up, through any door other than the REST and dispatcher single-record POST/PATCH/DELETE that PR #28781 fixes.
Reader who acts: a domain:server seat (packages/rest, packages/runtime, the MCP bridge).
What happens
ERR_SUMMARY_RECOMPUTE is thrown after the triggering write is stored (import-runner.ts and seed-loader.ts already read it as "the record WAS written"). PR #28781 makes the REST and dispatcher single-record doors answer their normal success body in that case. These doors still answer 500 INTERNAL_ERROR for a write that landed:
form submit (form-routes.ts);
the batch and *ManyData routes;
cloneData;
the MCP create_record bridge;
callData's ObjectQL fallback.
A roll-up stored before #28781's save-door gate, or any other recompute failure, still reaches them.
Claim: PM loop round 1 · card thread · 2026-11-01T21:19Z
Session: session_01FEkQ5oc56xChD6Wrc4cGSt (the seat); the card thread is session_01FEkQ5kV6ptpTnU6Hjb2mE4 (the #28661 dev thread, continuing)
Account: os-project-manager (the seat's linked user; the card's assignee)
Branch: claude/project-thread-1minft (the card thread's harness-pinned branch, restarted from origin/main after PR #28781's squash merge deleted it; it names no issue, so this claim is the identity record)
Worktree: the card thread's own container checkout
Domain: domain:server
Seat: domain:server#5
Ruling-ref: 「定级你可以自己决定」 (Leehom, 2026-11-01T12:11Z) with this seat's grade as filed (p2) and the seat's rulings in the order; pick announced to seats 1-3 (seat 3 confirmed; seats 1 and 2 silent past the window, neither holds it).
File surface: packages/rest/src/ (form and batch routes), packages/runtime/src/ (domains/data.ts *ManyData / cloneData, action-execution.ts callData), the MCP data bridge(s), their tests, changesets; packages/types/src/summary-recompute-answer.ts only for an additive helper. ⛔ No packages/spec/**, ⛔ no ui/**.
Container & model: M, mode:thread, model and effort as the thread was opened
Clause-②: no
Metadata-protocol: none
Responsibility: the code is the remaining data write doors' error path after a stored write · a write that landed answers 500 when the summary recompute fails, so a client retry duplicates it · reached by any write through form submit, batch / *ManyData, cloneData, MCP create_record or callData's fallback on an object feeding a roll-up
Thread-read: 6563870244
Premise: holds (read at origin/mainc9a9981da, which contains PR #287811617b7fb91: only the REST and dispatcher single-record doors read the carrier)
Serial constraints cleared: none needed.
Resume-from: none — fresh from origin/main
State: pm:queue → pm:dispatched, assigned to os-project-manager, recorded by this claim. Order: pm-orders/server/order-28782.md in the project.
{
"issue": 28782,
"status": "done",
"branch": "claude/project-thread-1minft",
"pr": "https://github.com/objectstack-ai/objectstack/pull/28843",
"session": "session_01FEkQ5kV6ptpTnU6Hjb2mE4",
"premise_still_valid": true,
"summary": "Every remaining write door answers a write that landed under a failing roll-up (ERR_SUMMARY_RECOMPUTE carrying written) with its own existing success answer, through the #28781 carrier and its log line; no new code, member, status, header or carrier, and @objectstack/types is untouched. Producers attach the earned answer and rethrow (protocol createManyData and cloneData, runtime callData ObjectQL fallback create/update/delete, MCP stdio bridge create); doors read it (REST form submit, createMany, clone via a new earnedAnswerLogged helper; MCP create_record tool for both bridges). The non-atomic per-row loops (batchData, updateManyData, deleteManyData) turn a stored row into a success row built from written and continue; atomic batches and the cross-object POST /batch are unchanged because the refusal is raised inside the transaction and the rollback answer is the truth. Pre-write refusals, import-runner, seed-loader and insertManyData are untouched; no packages/spec edit.",
"tests": "Red on origin/main c9a9981da (impl reverted on disk, metadata-protocol rebuilt), green on head: rest data-write-summary-recompute-other-doors.test.ts 9/9 (base 7 red: form/createMany/clone 500, batch/updateMany/deleteMany success:false + NOT_ATTEMPTED; 2 guards green: atomic rollback, pre-write refusal); runtime domains/data-write-summary-recompute-fallback.test.ts 5/5 (base 4 red, the refusal left dispatch()); mcp mcp-create-record-stale-summary.test.ts 4/4 (base 3 red, isError). Ablations (on disk, restored, git diff HEAD empty): form 1 red, createMany 1 red, clone 1 red, bulk-loop helper (mp rebuilt) 3 red, createManyData 1 red, cloneData 1 red, callData fallback 4 red, MCP tool 3 red, stdio bridge 1 red. Suites on 6e3035f3: metadata-protocol 22074 passed, rest 7217 passed, runtime 9242 passed, mcp 635/635. Live probe base vs head (fresh showcase, lint roll-up runtime entry off to store sum(memo)): batch 200 row0 ERR_SUMMARY_RECOMPUTE + row1 NOT_ATTEMPTED with b1 stored -> 200 succeeded 2, both stored once; createMany 500 (row stored) -> 201; clone 500 (row stored) -> 201; form submit 400 reference_not_found pre-write on both (see deviations).",
"gates": "dispatch-gates --commands --repo objectstack-ai/objectstack derived 71 (63 before the engine-double ledger widened it); all 71 exit 0 after fixing check:engine-double-contract (exit 1 on the new MCP double: routed through assertEngine*Dispatch, --write); --ran: 71 derived, 71 run, 0 NOT-MEASURED. spec check:error-code-provenance exit 0. Scoped eslint over 12 changed .ts exit 0. check:nul-bytes exit 0. tsc --noEmit metadata-protocol/rest/runtime/mcp exit 0. After the final main merge (a4d7f538): engine-double-contract and error-code-provenance exit 0, closures rebuilt, door files green (rest 14, runtime 9, mcp 36), mp tsc 0. PR check-runs were queued at report time; not re-run locally.",
"dogfood_battery": "6e3035f3 (before the final main merge to a4d7f538) · os-verify-lock: VERDICT batch-last-exit 0 (the dogfood was the last part) · Test Files 380 passed, 3 skipped (383) · Tests 3114 passed, 28 skipped (3142) · no failures",
"line_budget": "+758 / -27 across 14 files (PR #28843 as GitHub counts it)",
"files_changed": [
".changeset/28782-stale-summary-remaining-doors.md",
"packages/mcp/src/mcp-create-record-stale-summary.test.ts",
"packages/mcp/src/mcp-http-tools.ts",
"packages/mcp/src/stdio-data-bridge.ts",
"packages/metadata-protocol/src/protocol-batch-data.ts",
"packages/metadata-protocol/src/protocol.ts",
"packages/rest/src/batch-routes.ts",
"packages/rest/src/data-action-routes.ts",
"packages/rest/src/data-write-summary-recompute-other-doors.test.ts",
"packages/rest/src/form-routes.ts",
"packages/rest/src/stale-summary-answer.ts",
"packages/runtime/src/action-execution.ts",
"packages/runtime/src/domains/data-write-summary-recompute-fallback.test.ts",
"scripts/engine-double-contract.pinned.json"
],
"deviations": [
"Live probe of the public form door did not reach the post-write path: the door runs as the anonymous caller even with a session cookie, and the reference check refuses the master-detail parent before the write (400 reference_not_found) on base and head alike; its post-write answer is pinned on a real store by the REST test instead.",
"Full dogfood ran on 6e3035f3; the final merge of main (a4d7f538, unrelated main changes in metadata-protocol/runtime) was followed by rebuilt closures, the door files and the two touched gates, not a second full dogfood.",
"Two existing tests surfaced in the package suites and were fixed in the implementation, not the tests: metadata-protocol bracketed-refusal-opener test (log tag now [Protocol]) and mcp stdio-data-bridge.exposure (bare vi.fn insert double: the stdio bridge now uses try/catch)."
],
"mcp_calls": "3 — mcp__github__issue_read get (#28782), mcp__github__issue_read get_comments (#28782), mcp__github__pull_request_read get (#28843); no write tool",
"api_writes": "2 — relay pr_create via scripts/pm/fleet-write/dispatch.mjs (POST /repos/objectstack-ai/objectstack/pulls, #28843, read-back identical, assignees none); this report via scripts/pm/post-stamped.mjs (POST /repos/objectstack-ai/objectstack/issues/28782/comments)",
"open_questions": [
{
"question": "MCP update_record and delete_record reach callData('update'/'delete') the same way and still answer a landed write under a failing roll-up as an isError result; the card named only create_record. Follow up?",
"options": [
"A a follow-up card applying the same tool-side earnedAnswerOf reading (runtime bridge) plus a stdio-bridge carrier",
"B leave them; #28781's save gate stops new bad roll-ups"
],
"recommendation": "A, because an agent that reads the error retries an update or delete that landed, and the carrier and the tool-side reading already exist"
}
],
"out_of_scope_findings": [
"class: b · reach: MCP update_record / delete_record answer isError for a landed write when the roll-up recompute fails · evidence: same callData path as create_record, unwired · dedupe words: mcp update_record delete_record summary recompute",
"carrier: PR #28843 Acceptance notes · noted, not filed"
]
}
ACCEPT → PR #28843 comment 6565651976 · head a4d7f538 · 2026-11-01T23:43Z. No contract review owed. Landing: pr_ready + automerge_enable through the relay; the merge queue closes this card. The MCP update_record / delete_record gap is #28844, unblocked when this lands.
Activity
objectstack-fleet commentedon Nov 1, 2026
domain:server#5 · os-project-manager · session_01FEkQ5oc56xChD6Wrc4cGSt
Unblocked ·
pm:queue⛔ Not a claim.
Blocked-by: #28661— closed as completed via PR fix(lint,metadata-protocol,rest,runtime): refuse a sum/avg roll-up the engine cannot recompute, and answer a landed child write's success #28781 (1617b7fb91), which added the@objectstack/typescarrier (isSummaryRecomputeRefusal/ the earned-write answer) and the REST and dispatcher single-record reading this card applies to the remaining doors.pm:blocked→pm:queuein one label write; grade unchanged, no assignee.objectstack-fleet commentedon Nov 1, 2026
domain:server#5 · os-project-manager · session_01FEkQ5oc56xChD6Wrc4cGSt
Claim: PM loop round 1 · card thread · 2026-11-01T21:19Z
Session:
session_01FEkQ5oc56xChD6Wrc4cGSt(the seat); the card thread issession_01FEkQ5kV6ptpTnU6Hjb2mE4(the #28661 dev thread, continuing)Account:
os-project-manager(the seat's linked user; the card's assignee)Branch:
claude/project-thread-1minft(the card thread's harness-pinned branch, restarted fromorigin/mainafter PR #28781's squash merge deleted it; it names no issue, so this claim is the identity record)Worktree: the card thread's own container checkout
Domain:
domain:serverSeat:
domain:server#5Ruling-ref: 「定级你可以自己决定」 (Leehom, 2026-11-01T12:11Z) with this seat's grade as filed (p2) and the seat's rulings in the order; pick announced to seats 1-3 (seat 3 confirmed; seats 1 and 2 silent past the window, neither holds it).
File surface:
packages/rest/src/(form and batch routes),packages/runtime/src/(domains/data.ts*ManyData / cloneData,action-execution.tscallData), the MCP data bridge(s), their tests, changesets;packages/types/src/summary-recompute-answer.tsonly for an additive helper. ⛔ Nopackages/spec/**, ⛔ noui/**.Container & model:
M,mode:thread, model and effort as the thread was openedClause-②: no
Metadata-protocol: none
Responsibility: the code is the remaining data write doors' error path after a stored write · a write that landed answers 500 when the summary recompute fails, so a client retry duplicates it · reached by any write through form submit, batch / *ManyData, cloneData, MCP create_record or callData's fallback on an object feeding a roll-up
Thread-read: 6563870244
Premise: holds (read at
origin/mainc9a9981da, which contains PR #287811617b7fb91: only the REST and dispatcher single-record doors read the carrier)Serial constraints cleared: none needed.
Resume-from: none — fresh from
origin/mainState:
pm:queue→pm:dispatched, assigned toos-project-manager, recorded by this claim. Order:pm-orders/server/order-28782.mdin the project.objectstack-fleet commentedon Nov 1, 2026
domain:server#5 · os-project-manager · session_01FEkQ5kV6ptpTnU6Hjb2mE4
os-dev-report
{ "issue": 28782, "status": "done", "branch": "claude/project-thread-1minft", "pr": "https://github.com/objectstack-ai/objectstack/pull/28843", "session": "session_01FEkQ5kV6ptpTnU6Hjb2mE4", "premise_still_valid": true, "summary": "Every remaining write door answers a write that landed under a failing roll-up (ERR_SUMMARY_RECOMPUTE carrying written) with its own existing success answer, through the #28781 carrier and its log line; no new code, member, status, header or carrier, and @objectstack/types is untouched. Producers attach the earned answer and rethrow (protocol createManyData and cloneData, runtime callData ObjectQL fallback create/update/delete, MCP stdio bridge create); doors read it (REST form submit, createMany, clone via a new earnedAnswerLogged helper; MCP create_record tool for both bridges). The non-atomic per-row loops (batchData, updateManyData, deleteManyData) turn a stored row into a success row built from written and continue; atomic batches and the cross-object POST /batch are unchanged because the refusal is raised inside the transaction and the rollback answer is the truth. Pre-write refusals, import-runner, seed-loader and insertManyData are untouched; no packages/spec edit.", "tests": "Red on origin/main c9a9981da (impl reverted on disk, metadata-protocol rebuilt), green on head: rest data-write-summary-recompute-other-doors.test.ts 9/9 (base 7 red: form/createMany/clone 500, batch/updateMany/deleteMany success:false + NOT_ATTEMPTED; 2 guards green: atomic rollback, pre-write refusal); runtime domains/data-write-summary-recompute-fallback.test.ts 5/5 (base 4 red, the refusal left dispatch()); mcp mcp-create-record-stale-summary.test.ts 4/4 (base 3 red, isError). Ablations (on disk, restored, git diff HEAD empty): form 1 red, createMany 1 red, clone 1 red, bulk-loop helper (mp rebuilt) 3 red, createManyData 1 red, cloneData 1 red, callData fallback 4 red, MCP tool 3 red, stdio bridge 1 red. Suites on 6e3035f3: metadata-protocol 22074 passed, rest 7217 passed, runtime 9242 passed, mcp 635/635. Live probe base vs head (fresh showcase, lint roll-up runtime entry off to store sum(memo)): batch 200 row0 ERR_SUMMARY_RECOMPUTE + row1 NOT_ATTEMPTED with b1 stored -> 200 succeeded 2, both stored once; createMany 500 (row stored) -> 201; clone 500 (row stored) -> 201; form submit 400 reference_not_found pre-write on both (see deviations).", "gates": "dispatch-gates --commands --repo objectstack-ai/objectstack derived 71 (63 before the engine-double ledger widened it); all 71 exit 0 after fixing check:engine-double-contract (exit 1 on the new MCP double: routed through assertEngine*Dispatch, --write); --ran: 71 derived, 71 run, 0 NOT-MEASURED. spec check:error-code-provenance exit 0. Scoped eslint over 12 changed .ts exit 0. check:nul-bytes exit 0. tsc --noEmit metadata-protocol/rest/runtime/mcp exit 0. After the final main merge (a4d7f538): engine-double-contract and error-code-provenance exit 0, closures rebuilt, door files green (rest 14, runtime 9, mcp 36), mp tsc 0. PR check-runs were queued at report time; not re-run locally.", "dogfood_battery": "6e3035f3 (before the final main merge to a4d7f538) · os-verify-lock: VERDICT batch-last-exit 0 (the dogfood was the last part) · Test Files 380 passed, 3 skipped (383) · Tests 3114 passed, 28 skipped (3142) · no failures", "line_budget": "+758 / -27 across 14 files (PR #28843 as GitHub counts it)", "files_changed": [ ".changeset/28782-stale-summary-remaining-doors.md", "packages/mcp/src/mcp-create-record-stale-summary.test.ts", "packages/mcp/src/mcp-http-tools.ts", "packages/mcp/src/stdio-data-bridge.ts", "packages/metadata-protocol/src/protocol-batch-data.ts", "packages/metadata-protocol/src/protocol.ts", "packages/rest/src/batch-routes.ts", "packages/rest/src/data-action-routes.ts", "packages/rest/src/data-write-summary-recompute-other-doors.test.ts", "packages/rest/src/form-routes.ts", "packages/rest/src/stale-summary-answer.ts", "packages/runtime/src/action-execution.ts", "packages/runtime/src/domains/data-write-summary-recompute-fallback.test.ts", "scripts/engine-double-contract.pinned.json" ], "deviations": [ "Live probe of the public form door did not reach the post-write path: the door runs as the anonymous caller even with a session cookie, and the reference check refuses the master-detail parent before the write (400 reference_not_found) on base and head alike; its post-write answer is pinned on a real store by the REST test instead.", "Full dogfood ran on 6e3035f3; the final merge of main (a4d7f538, unrelated main changes in metadata-protocol/runtime) was followed by rebuilt closures, the door files and the two touched gates, not a second full dogfood.", "Two existing tests surfaced in the package suites and were fixed in the implementation, not the tests: metadata-protocol bracketed-refusal-opener test (log tag now [Protocol]) and mcp stdio-data-bridge.exposure (bare vi.fn insert double: the stdio bridge now uses try/catch)." ], "mcp_calls": "3 — mcp__github__issue_read get (#28782), mcp__github__issue_read get_comments (#28782), mcp__github__pull_request_read get (#28843); no write tool", "api_writes": "2 — relay pr_create via scripts/pm/fleet-write/dispatch.mjs (POST /repos/objectstack-ai/objectstack/pulls, #28843, read-back identical, assignees none); this report via scripts/pm/post-stamped.mjs (POST /repos/objectstack-ai/objectstack/issues/28782/comments)", "open_questions": [ { "question": "MCP update_record and delete_record reach callData('update'/'delete') the same way and still answer a landed write under a failing roll-up as an isError result; the card named only create_record. Follow up?", "options": [ "A a follow-up card applying the same tool-side earnedAnswerOf reading (runtime bridge) plus a stdio-bridge carrier", "B leave them; #28781's save gate stops new bad roll-ups" ], "recommendation": "A, because an agent that reads the error retries an update or delete that landed, and the carrier and the tool-side reading already exist" } ], "out_of_scope_findings": [ "class: b · reach: MCP update_record / delete_record answer isError for a landed write when the roll-up recompute fails · evidence: same callData path as create_record, unwired · dedupe words: mcp update_record delete_record summary recompute", "carrier: PR #28843 Acceptance notes · noted, not filed" ] }Generated by Claude Code
objectstack-fleet commentedon Nov 1, 2026
domain:server#5 · os-project-manager · session_01FEkQ5oc56xChD6Wrc4cGSt
ACCEPT → PR #28843 comment 6565651976 · head
a4d7f538· 2026-11-01T23:43Z. No contract review owed. Landing:pr_ready+automerge_enablethrough the relay; the merge queue closes this card. The MCPupdate_record/delete_recordgap is #28844, unblocked when this lands.objectstack-fleet commentedon Nov 2, 2026
domain:server#5 · os-project-manager · session_01FEkQ5oc56xChD6Wrc4cGSt
Landed · 2026-11-02T00:33Z · PR #28843 merged through the merge queue as
b95a856e33; this card closed as completed by itsFixesline.b95a856e33pm:dispatchedremoved and the seat unassigned in this stroke,domain:*/area:*keptThe MCP
update_record/delete_recordgap is #28844, unblocked in the same round.