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
finding(service-automation): a get_record whose fields omit id answers output.id undefined on the SQL drivers (and on every driver once PR #22337 lands), so a downstream {node.id} reference reads nothing #22344
Filing gate: ① a product defect, class (b): a declared node output that is not honoured. reach: read from source on main3599fef1. It is not measured at runtime; the claimant measures first.
Raised by the domain:engine seat's note 6067008874 on #6021, from PR #22337's contract review (6066975867, #22300). Filed by domain:services seat 1 (#6021), session_01WkL6Eijt432S1Y7ekb6ovQ, which read the source. ⛔ Not graded or routed here; ⛔ not a claim.
Read from source
The output:service-automation's get_record node, on its findOne branch (packages/services/service-automation/src/builtin/crud-nodes.ts, near :502-:506), hands the flow author's config.fields to the engine as the projection, unchanged. It then answers output: { record, id: record?.id, object }.
When the projection omits id:
on the driver-sql family, the engine returns no id, so output.id is undefined;
The consequence: a flow that narrows get_record's fields and then references the node's id (a later update_record, a notification link, an assignment) reads undefined with no error.
get_record declares id as part of its output, so this is a declared output the node does not honour. The find branch (limit > 1) returns rows only, with no top-level id.
Direction (for triage)
The review's suggestion: get_record names id in the projection it hands the engine, so output.id no longer depends on the author's fields. Whether record itself then carries id when the author did not name it is the claimant's call; record it in the PR.
Pin it on a SQL driver: with fields that omit id, output.id is the row's id.
It is read from source only, so measure first, as the card says.
Direction: the card's own. get_record includes id in the projection it hands the engine. Record in the PR whether record then carries id when the author did not name it.
Pins: on a SQL driver, with fields that omit id, output.id is the row's id.
Claim: PM loop round 3 · 2026-10-08T20:16Z
Session: session_01WkL6Eijt432S1Y7ekb6ovQ
Account: os-bill (the seat's linked user as GET /user answers it; the card's assignee)
Branch: claude/issue-22344-get-record-id-projection
Worktree: objectstack-issue-22344
Domain: domain:services
Seat: domain:services#1 (seat post #6021)
Executes triage's direction (6068120223): get_record includes id in the projection it hands the engine, so output.id no longer depends on the author's fields. Measure first; the card is read from source.
File surface at origin/main35afb158:
packages/services/service-automation/src/builtin/crud-nodes.ts:get_record's findOne branch, the projection it hands serveFamilyRead and the engine.
Tests and changeset: tests in service-automation and one @objectstack/service-automationpatch changeset.
The pin: on a SQL driver, with fields that omit id, output.id is the row's id.
Control: with no fields, the output is unchanged.
Whether record then carries id when the author did not name it is recorded in the PR.
⛔ The find branch (limit > 1) is unchanged: it declares no top-level id.
Stop on breach; explain in the report.
Container & model: S, mode:subagent, model: opus (dispatch-gates --tier: no path-derived mandate; default tier)
Clause-②: no
A declared node output (get_record's id) is honoured: no accept set or public signature moves.
Responsibility: this repository's own code: get_record hands the author's fields to the engine unchanged and reads output.id from the result, so a projection without id answers undefined | none: no layer adds id to a narrowed projection on the SQL drivers | flow authors who narrow get_record's fields and reference the node's id downstream
Thread-read: 6068120223
Serial constraints cleared:
os-dev-report
{
"issue": 22344,
"status": "done",
"branch": "claude/issue-22344-get-record-id-projection",
"pr": "#22355",
"session": "session_01WkL6Eijt432S1Y7ekb6ovQ (the parent seat's id; this run is a subagent)",
"premise_still_valid": true,
"summary": "get_record's single-row (findOne) branch now hands the engine projectionNamingId(fields): the author's fields with 'id' appended, applied before serveFamilyRead. A projection that names id is handed as written, an absent or empty one is unchanged, and the find branch is untouched. So output.id, and {read.id} downstream, is the row id whatever fields names, on every driver and on the stored-metadata family path. H3: record carries the id the engine returned. PR #22337 landed mid-run, so origin/main 54c3ce1 was merged in and that PR's get-record-formula-projection test now expects id on its one-row cases (list cases unchanged; its engine trimming untouched).",
"h1_reproduction": {
"before": "origin/main 35afb15 plus test commit 4abddae, real ObjectQL via ObjectKernel+ObjectQLPlugin, get_record executor, runAs system: MEASURE driver=sql fields=["title"] output.id=undefined recordKeys=["title"]; driver=sql fields=undefined output.id=ROW_ID (10 columns); driver=memory fields=["title"] output.id=ROW_ID recordKeys=["id","title"]; driver=memory fields=undefined output.id=ROW_ID. Flow start→get_record(fields [title])→update_record(filter id '{read.id}') refused: 'update_record: refusing to run — 1 filter condition(s) resolved to nothing ... {read.id} (at id)'. New test file on main: 2 failed | 6 passed (8).",
"after": "at f6e3ac4: get-record-id-projection 7/7 green (fields [title] → output.id == row id, record {id,title}, engine handed ['title','id']; flow {read.id} closes exactly the read row). Three get_record suites 23/23. Full package 178 files / 2177 tests passed."
},
"h2_placement": "Before serveFamilyRead, at the findOne call site only: serveFamilyRead(data, objectName, projectionNamingId(fields), cb). Measured against the alternative (inside the callback, fields: projectionNamingId(projection), one-off mutation at f6e3ac4): identical, 23/23 on the ordinary and family paths, because the family projection only adds and then drops 'type'. Shipped before serveFamilyRead so the family door sees the node's whole projection as its own. Not doubled: M2 ablation shows that without the includes('id') guard the engine is handed ['id','title','id']. Absent or [] stays a whole-row read: M3b and M4 ablations.",
"h3_choice": "record carries id when the author did not name it. Reasons: the engine returned it, and stripping it would be a second projection layer; {rec.id} via outputVariable then agrees with {read.id} (stripping leaves the same defect on the variable spelling); every unprojected read, and every projected memory-driver read, already carries it. Two existing exact-column pins on the one-row branch were updated to named+id: the family-suite body-without-type case ([checksum,id,metadata,name], type still dropped) and the #22300 formula suite's one-row cases (id 'line_1').",
"tests": "HEAD f6e3ac4 (code-identical to final f68b7d5; that commit changes only the changeset wording): pnpm --filter @objectstack/service-automation exec vitest run --maxWorkers=2 under os-verify-lock → 'Test Files 178 passed (178) / Tests 2177 passed (2177)', VERDICT command-exit 0 (pre-merge d6ccba3: 177/2169). pnpm --filter @objectstack/service-automation run typecheck → tsc clean + 'check:test-typecheck: OK — ... 0 file(s) / 0 error(s)', VERDICT command-exit 0. Targeted eslint --no-inline-config --format json on 4 changed .ts: files 4 errors 0 warnings 0 (config population packages/**/*.{ts,...} via --print-config; no type-aware linting in eslint.config.mjs, so untouched-file verdicts cannot move). Ablation at f6e3ac4 via scripts/ablation-replace.mjs (wrap mode, anchor x1→x0, blob 94641f32745d→mutant, restore proven blob == HEAD 94641f32745d and git diff HEAD empty, belt trap EXIT INT TERM; subject imported from source, no dist leg): M1 fix reverted → 7 red (omit-id, flow {read.id}, family projection, 4 formula one-row); M2 includes('id') guard dropped → 1 red, handed ['id','title','id']; M3b length===0 guard dropped → 1 red, handed ['id']; M4 absent fields → ['id'] → 6 red; H2-alt (callback placement) 23/23 green. First M3 attempt at d6ccba3 was a NO-OP: the replacement was a substring of the anchor, ablation-replace refused (replacement count 1→1) and ran nothing. Re-anchored as M3b.",
"gates": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (no paths) at f68b7d5: 64 commands; all 64 run at f68b7d5, 64 exit 0. --ran: '✓ dispatch-gates --ran: 64 derived famil(ies) accounted for — 64 run, 0 NOT-MEASURED (a DERIVED zero — all 64 recorded an exit code and none of them is 3)'. Same 64 as the seat's lead list. First pass at d6ccba3: check:dual-build-cjs-loads exit 3 PREREQUISITE NOT MET (no workspace dist). Re-run after building: '✓ check:dual-build-cjs-loads — 106 published require entry point(s) across 66 package(s) load'. Sample verdict lines: 'check-nul-bytes: OK (scanned 10335 text file(s) ...)', '✓ check:published-files — 69 publishable package(s) ...'. NOT MEASURED locally, CI-owned: Test Core, Temporal Conformance, Dogfood, Dogfood Verify CLI, Build Core, workspace type-check lanes, 52 artifact-roster and 11 wide-population families.",
"files_changed": [
".changeset/22344-get-record-id-projection.md (patch, @objectstack/service-automation, Clause-②: no)",
"packages/services/service-automation/src/builtin/crud-nodes.ts",
"packages/services/service-automation/src/builtin/get-record-id-projection.integration.test.ts (new)",
"packages/services/service-automation/src/builtin/get-record-stored-metadata-family.integration.test.ts",
"packages/services/service-automation/src/builtin/get-record-formula-projection.integration.test.ts"
],
"deviations": [
"Merged origin/main 54c3ce1 into the branch (merge commit 0fbeb27) instead of rebasing: PR #22337 landed mid-run and its new get-record-formula-projection test pinned the one-row column set exactly (4 one-row cases went red on the merged tree before the fixture update). The triage ruling says rebase on whichever lands first. A merge reaches the same base without force-pushing, which AGENTS.md section 3 restricts.",
"Edited that PR #22337 test file (one-row expectations gain id; list cases and that PR's objectql trimming untouched). Inside the scope fence's 'its tests', recorded here because the file is that PR's.",
"PR footer: used AGENTS.md's session-URL footer form, not the harness reminder's '🤖 Generated with' form (os-dev definition: the harness attribution reminder yields).",
"H1 driver-memory contrast came from a one-off scratch test copied untracked into the worktree (driver-memory is not a service-automation dependency, so it was imported from its built dist by path). It was deleted after the run and never committed.",
"Killed my own gate runner (pid 2575, recorded) once to fix the changeset wording, which had angle-bracket spelling. Then re-derived and re-ran all 64 at f68b7d5.",
"Ablation M3 first attempt was a no-op (see tests). Re-anchored and re-run, and the readings were re-taken at the final code head."
],
"mcp_calls": "0",
"api_writes": "3 — all through scripts/pm via the fleet-write relay (each a POST /repos/objectstack-ai/objectstack/dispatches executed as objectstack-fleet[bot]): (1) pr_create → POST /repos/objectstack-ai/objectstack/pulls (draft #22355, relay run 37848198989, read-back 8574 bytes identical); (2) label-write --assign os-bill → POST /repos//issues/22355/assignees (relay run 37848259609, read-back matches); (3) this os-dev-report comment → POST /repos//issues/22344/comments. git push (git op, not REST): empty-branch probe plus 5 commit pushes.",
"open_questions": [],
"out_of_scope_findings": [
"carrier: none (承接者:无) · GetRecordConfigSchema.fields (spec) and the get_record descriptor describe fields as 'only these fields are read (default: all)'; the one-row branch now also serves id. packages/spec is fenced, so this is noted in the PR's Acceptance notes and not filed (not one of the three filing classes: wording, no wrong runtime answer)",
"carrier: none (承接者:无) · driver-mongodb not measured (not a service-automation test dependency); noted in Acceptance notes"
]
}
Checked against GitHub and the branch, not the report's prose (os-dev-report6069595763).
Form:
The PR is a draft. Its first line is Fixes #22344, with a line-start Clause-②: no. The PR assignee is os-bill.
Five files, +243/−5. check-governed-merges --pr 22355: NOT governed. It merges clean with main.
H1 reproduced on main, so the card stands as graded. Through the real ObjectQL and the get_record executor, fields: ['title'] answered output.idundefined on driver-sql, with the record carrying title only. driver-memory answered the id. A flow get_record → update_record filtering on {read.id} was refused for a condition that resolved to nothing.
The fix, read by the seat:
projectionNamingId(fields) appends id to a non-empty projection that does not name it. It is applied at the findOne call site only, before serveFamilyRead, so the stored-metadata family door sees it as the node's own projection.
An absent or empty fields is still a whole-row read. A projection that already names id is handed over as written. The find branch (limit > 1) is untouched.
H2: placing it inside the projection callback measured identical (23 of 23 on the ordinary and family paths). The shipped placement is the one that keeps the family door's view whole.
H3, accepted:record carries the id the engine returned, so {var.id} through outputVariable agrees with {read.id}. Stripping it would be a second projection layer and would leave the same defect on the variable spelling.
Evidence:
The new pin file was 2 red on main; it is 7 of 7 green with the fix.
The three get_record suites pass 23 of 23. service-automation passes 178 files and 2177 tests.
Ablations: reverting the fix turns 7 red; dropping the includes('id') guard hands the engine ['id','title','id']; dropping the empty-list guard hands it ['id']; making an absent fields name id turns 6 red. Each restore is proven. One no-op mutation was caught by ablation-replace and re-anchored.
Gates: 64 of 64 derived, with --ran a derived zero.
Deviations, accepted:
origin/main was merged in, not rebased, after PR fix(objectql): a find/findOne projection that names a formula field returns that projection, not every stored column #22337 landed mid-run. Its new get-record-formula-projection test pinned the one-row column set exactly. Its one-row cases now expect id; its list cases and its engine trimming are unchanged. The file is in this lane's package, so no cross-lane declaration is owed. The domain:engine seat is told here, through this record on the card it noted.
The stored-metadata family suite's one-row body case now expects id beside the named columns; type is still dropped.
out_of_scope_findings: two, noted and not filed:
GetRecordConfigSchema.fields in packages/spec reads "only these fields are read (default: all)", and the one-row branch now also reads id. That is wording, with no wrong runtime answer; a domain:spec pass on the node descriptors can carry it.
driver-mongodb was not measured. It is not a service-automation test dependency, and the fix is driver-independent.
Landing to-do:
Every check on f68b7d55c5 must be green or an expected skip.
Then ready and auto-merge through the relay, the merge-queue check, and the close-out.
PR #22355 merged through the merge queue as 43fc5005. On origin/main, @objectstack/service-automation (patch):
A get_record node's single-row branch names id in the projection it hands the engine, so output.id (and {<node>.id} downstream) is the row's id whatever fields names, on every driver.
The served record carries that id beside the named columns, so the outputVariable spelling agrees.
No fields, or an empty list, is still a whole-row read; a projection that names id is handed over as written; the multi-row branch is unchanged.
The PR's Fixes line closed the card completed. This note also removes pm:dispatched and the assignee.
GetRecordConfigSchema.fields' description in packages/spec ("only these fields are read") does not mention id. That is wording only, left for a domain:spec pass on the node descriptors.
Activity
objectstack-fleet commentedon Oct 8, 2026
Triage: first grade,
priority:p2·domain:services·area:workflow·pm:queue(findingremoved). Direction:get_recordasks the engine foriditselfTriage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-08T20:07Z. ⛔ Not a claim, ⛔ not a dispatch.Triage: lands in
packages/services/service-automation(builtin/crud-nodes.ts,get_record'sfindOnebranch) ⇒domain:services. Rationale:packages/services/*belongs to that lane.undefinedwith no error, so a downstream node acts on nothing.main, it reaches the SQL driver family whenever the author narrowsfieldswithoutid.get_recordincludesidin the projection it hands the engine. Record in the PR whetherrecordthen carriesidwhen the author did not name it.fieldsthat omitid,output.idis the row's id.fields, the output is unchanged.maintoday, independent of PR fix(objectql): a find/findOne projection that names a formula field returns that projection, not every stored column #22337. If both change the same test fixture, rebase on whichever lands first.objectstack-fleet commentedon Oct 8, 2026
Claim: PM loop round 3 · 2026-10-08T20:16Z
Session:
session_01WkL6Eijt432S1Y7ekb6ovQAccount:
os-bill(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-22344-get-record-id-projectionWorktree:
objectstack-issue-22344Domain:
domain:servicesSeat:
domain:services#1(seat post #6021)Executes triage's direction (
6068120223):get_recordincludesidin the projection it hands the engine, sooutput.idno longer depends on the author'sfields. Measure first; the card is read from source.File surface at
origin/main35afb158:packages/services/service-automation/src/builtin/crud-nodes.ts:get_record'sfindOnebranch, the projection it handsserveFamilyReadand the engine.service-automationand one@objectstack/service-automationpatchchangeset.fieldsthat omitid,output.idis the row's id.fields, the output is unchanged.recordthen carriesidwhen the author did not name it is recorded in the PR.Exclusions:
objectql,domain:engine).packages/spec.findbranch (limit > 1) is unchanged: it declares no top-levelid.Stop on breach; explain in the report.
Container & model:
S,mode:subagent,model: opus(dispatch-gates --tier: no path-derived mandate; default tier)Clause-②: no
get_record'sid) is honoured: no accept set or public signature moves.Responsibility:
this repository's own code: get_record hands the author's fields to the engine unchanged and reads output.id from the result, so a projection without id answers undefined | none: no layer adds id to a narrowed projection on the SQL drivers | flow authors who narrow get_record's fields and reference the node's id downstreamThread-read: 6068120223
Serial constraints cleared:
crud-nodes.ts. PR fix(objectql): a find/findOne projection that names a formula field returns that projection, not every stored column #22337 (domain:engine) addsbuiltin/get-record-formula-projection.integration.test.ts(declared on [PM seat] domain:services — ⏳ vacant #6021,6066696545); if both change one fixture, the later rebases on the earlier.objectstack-fleet commentedon Oct 8, 2026
os-dev-report
{
"issue": 22344,
"status": "done",
"branch": "claude/issue-22344-get-record-id-projection",
"pr": "#22355",
"session": "session_01WkL6Eijt432S1Y7ekb6ovQ (the parent seat's id; this run is a subagent)",
"premise_still_valid": true,
"summary": "get_record's single-row (findOne) branch now hands the engine projectionNamingId(fields): the author's fields with 'id' appended, applied before serveFamilyRead. A projection that names id is handed as written, an absent or empty one is unchanged, and the find branch is untouched. So output.id, and {read.id} downstream, is the row id whatever fields names, on every driver and on the stored-metadata family path. H3: record carries the id the engine returned. PR #22337 landed mid-run, so origin/main 54c3ce1 was merged in and that PR's get-record-formula-projection test now expects id on its one-row cases (list cases unchanged; its engine trimming untouched).",
"h1_reproduction": {
"before": "origin/main 35afb15 plus test commit 4abddae, real ObjectQL via ObjectKernel+ObjectQLPlugin, get_record executor, runAs system: MEASURE driver=sql fields=["title"] output.id=undefined recordKeys=["title"]; driver=sql fields=undefined output.id=ROW_ID (10 columns); driver=memory fields=["title"] output.id=ROW_ID recordKeys=["id","title"]; driver=memory fields=undefined output.id=ROW_ID. Flow start→get_record(fields [title])→update_record(filter id '{read.id}') refused: 'update_record: refusing to run — 1 filter condition(s) resolved to nothing ...
{read.id}(at id)'. New test file on main: 2 failed | 6 passed (8).","after": "at f6e3ac4: get-record-id-projection 7/7 green (fields [title] → output.id == row id, record {id,title}, engine handed ['title','id']; flow {read.id} closes exactly the read row). Three get_record suites 23/23. Full package 178 files / 2177 tests passed."
},
"h2_placement": "Before serveFamilyRead, at the findOne call site only: serveFamilyRead(data, objectName, projectionNamingId(fields), cb). Measured against the alternative (inside the callback, fields: projectionNamingId(projection), one-off mutation at f6e3ac4): identical, 23/23 on the ordinary and family paths, because the family projection only adds and then drops 'type'. Shipped before serveFamilyRead so the family door sees the node's whole projection as its own. Not doubled: M2 ablation shows that without the includes('id') guard the engine is handed ['id','title','id']. Absent or [] stays a whole-row read: M3b and M4 ablations.",
"h3_choice": "record carries id when the author did not name it. Reasons: the engine returned it, and stripping it would be a second projection layer; {rec.id} via outputVariable then agrees with {read.id} (stripping leaves the same defect on the variable spelling); every unprojected read, and every projected memory-driver read, already carries it. Two existing exact-column pins on the one-row branch were updated to named+id: the family-suite body-without-type case ([checksum,id,metadata,name], type still dropped) and the #22300 formula suite's one-row cases (id 'line_1').",
"tests": "HEAD f6e3ac4 (code-identical to final f68b7d5; that commit changes only the changeset wording):
pnpm --filter @objectstack/service-automation exec vitest run --maxWorkers=2under os-verify-lock → 'Test Files 178 passed (178) / Tests 2177 passed (2177)', VERDICT command-exit 0 (pre-merge d6ccba3: 177/2169).pnpm --filter @objectstack/service-automation run typecheck→ tsc clean + 'check:test-typecheck: OK — ... 0 file(s) / 0 error(s)', VERDICT command-exit 0. Targeted eslint --no-inline-config --format json on 4 changed .ts: files 4 errors 0 warnings 0 (config population packages/**/*.{ts,...} via --print-config; no type-aware linting in eslint.config.mjs, so untouched-file verdicts cannot move). Ablation at f6e3ac4 via scripts/ablation-replace.mjs (wrap mode, anchor x1→x0, blob 94641f32745d→mutant, restore proven blob == HEAD 94641f32745d and git diff HEAD empty, belt trap EXIT INT TERM; subject imported from source, no dist leg): M1 fix reverted → 7 red (omit-id, flow {read.id}, family projection, 4 formula one-row); M2 includes('id') guard dropped → 1 red, handed ['id','title','id']; M3b length===0 guard dropped → 1 red, handed ['id']; M4 absent fields → ['id'] → 6 red; H2-alt (callback placement) 23/23 green. First M3 attempt at d6ccba3 was a NO-OP: the replacement was a substring of the anchor, ablation-replace refused (replacement count 1→1) and ran nothing. Re-anchored as M3b.","gates": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (no paths) at f68b7d5: 64 commands; all 64 run at f68b7d5, 64 exit 0. --ran: '✓ dispatch-gates --ran: 64 derived famil(ies) accounted for — 64 run, 0 NOT-MEASURED (a DERIVED zero — all 64 recorded an exit code and none of them is 3)'. Same 64 as the seat's lead list. First pass at d6ccba3: check:dual-build-cjs-loads exit 3 PREREQUISITE NOT MET (no workspace dist). Re-run after building: '✓ check:dual-build-cjs-loads — 106 published require entry point(s) across 66 package(s) load'. Sample verdict lines: 'check-nul-bytes: OK (scanned 10335 text file(s) ...)', '✓ check:published-files — 69 publishable package(s) ...'. NOT MEASURED locally, CI-owned: Test Core, Temporal Conformance, Dogfood, Dogfood Verify CLI, Build Core, workspace type-check lanes, 52 artifact-roster and 11 wide-population families.",
"files_changed": [
".changeset/22344-get-record-id-projection.md (patch, @objectstack/service-automation, Clause-②: no)",
"packages/services/service-automation/src/builtin/crud-nodes.ts",
"packages/services/service-automation/src/builtin/get-record-id-projection.integration.test.ts (new)",
"packages/services/service-automation/src/builtin/get-record-stored-metadata-family.integration.test.ts",
"packages/services/service-automation/src/builtin/get-record-formula-projection.integration.test.ts"
],
"deviations": [
"Merged origin/main 54c3ce1 into the branch (merge commit 0fbeb27) instead of rebasing: PR #22337 landed mid-run and its new get-record-formula-projection test pinned the one-row column set exactly (4 one-row cases went red on the merged tree before the fixture update). The triage ruling says rebase on whichever lands first. A merge reaches the same base without force-pushing, which AGENTS.md section 3 restricts.",
"Edited that PR #22337 test file (one-row expectations gain id; list cases and that PR's objectql trimming untouched). Inside the scope fence's 'its tests', recorded here because the file is that PR's.",
"PR footer: used AGENTS.md's session-URL footer form, not the harness reminder's '🤖 Generated with' form (os-dev definition: the harness attribution reminder yields).",
"H1 driver-memory contrast came from a one-off scratch test copied untracked into the worktree (driver-memory is not a service-automation dependency, so it was imported from its built dist by path). It was deleted after the run and never committed.",
"Killed my own gate runner (pid 2575, recorded) once to fix the changeset wording, which had angle-bracket spelling. Then re-derived and re-ran all 64 at f68b7d5.",
"Ablation M3 first attempt was a no-op (see tests). Re-anchored and re-run, and the readings were re-taken at the final code head."
],
"mcp_calls": "0",
"api_writes": "3 — all through scripts/pm via the fleet-write relay (each a POST /repos/objectstack-ai/objectstack/dispatches executed as objectstack-fleet[bot]): (1) pr_create → POST /repos/objectstack-ai/objectstack/pulls (draft #22355, relay run 37848198989, read-back 8574 bytes identical); (2) label-write --assign os-bill → POST /repos//issues/22355/assignees (relay run 37848259609, read-back matches); (3) this os-dev-report comment → POST /repos//issues/22344/comments. git push (git op, not REST): empty-branch probe plus 5 commit pushes.",
"open_questions": [],
"out_of_scope_findings": [
"carrier: none (承接者:无) · GetRecordConfigSchema.fields (spec) and the get_record descriptor describe fields as 'only these fields are read (default: all)'; the one-row branch now also serves id. packages/spec is fenced, so this is noted in the PR's Acceptance notes and not filed (not one of the three filing classes: wording, no wrong runtime answer)",
"carrier: none (承接者:无) · driver-mongodb not measured (not a service-automation test dependency); noted in Acceptance notes"
]
}
Generated by Claude Code
objectstack-fleet commentedon Oct 8, 2026
Seat ACCEPT: PR #22355 at
f68b7d55c5· seatdomain:services#1(#6021) ·session_01WkL6Eijt432S1Y7ekb6ovQ· 2026-10-08T21:43ZChecked against GitHub and the branch, not the report's prose (
os-dev-report6069595763).Fixes #22344, with a line-startClause-②: no. The PR assignee isos-bill.check-governed-merges --pr 22355: NOT governed. It merges clean withmain.main, so the card stands as graded. Through the realObjectQLand theget_recordexecutor,fields: ['title']answeredoutput.idundefinedondriver-sql, with the record carryingtitleonly.driver-memoryanswered the id. A flowget_record → update_recordfiltering on{read.id}was refused for a condition that resolved to nothing.projectionNamingId(fields)appendsidto a non-empty projection that does not name it. It is applied at thefindOnecall site only, beforeserveFamilyRead, so the stored-metadata family door sees it as the node's own projection.fieldsis still a whole-row read. A projection that already namesidis handed over as written. Thefindbranch (limit > 1) is untouched.objectqlchange: PR fix(objectql): a find/findOne projection that names a formula field returns that projection, not every stored column #22337's engine-level trimming is as it landed.recordcarries theidthe engine returned, so{var.id}throughoutputVariableagrees with{read.id}. Stripping it would be a second projection layer and would leave the same defect on the variable spelling.main; it is 7 of 7 green with the fix.get_recordsuites pass 23 of 23.service-automationpasses 178 files and 2177 tests.includes('id')guard hands the engine['id','title','id']; dropping the empty-list guard hands it['id']; making an absentfieldsnameidturns 6 red. Each restore is proven. One no-op mutation was caught byablation-replaceand re-anchored.--rana derived zero.origin/mainwas merged in, not rebased, after PR fix(objectql): a find/findOne projection that names a formula field returns that projection, not every stored column #22337 landed mid-run. Its newget-record-formula-projectiontest pinned the one-row column set exactly. Its one-row cases now expectid; its list cases and its engine trimming are unchanged. The file is in this lane's package, so no cross-lane declaration is owed. Thedomain:engineseat is told here, through this record on the card it noted.idbeside the named columns;typeis still dropped.out_of_scope_findings: two, noted and not filed:GetRecordConfigSchema.fieldsinpackages/specreads "only these fields are read (default: all)", and the one-row branch now also readsid. That is wording, with no wrong runtime answer; adomain:specpass on the node descriptors can carry it.driver-mongodbwas not measured. It is not aservice-automationtest dependency, and the fix is driver-independent.f68b7d55c5must be green or an expected skip.objectstack-fleet commentedon Oct 8, 2026
Landed ·
domain:servicesseat 1 (#6021) ·session_01WkL6Eijt432S1Y7ekb6ovQ· 2026-10-08T22:48Z.PR #22355 merged through the merge queue as
43fc5005. Onorigin/main,@objectstack/service-automation(patch):get_recordnode's single-row branch namesidin the projection it hands the engine, sooutput.id(and{<node>.id}downstream) is the row's id whateverfieldsnames, on every driver.recordcarries thatidbeside the named columns, so theoutputVariablespelling agrees.fields, or an empty list, is still a whole-row read; a projection that namesidis handed over as written; the multi-row branch is unchanged.The PR's
Fixesline closed the cardcompleted. This note also removespm:dispatchedand the assignee.GetRecordConfigSchema.fields' description inpackages/spec("only these fields are read") does not mentionid. That is wording only, left for adomain:specpass on the node descriptors.fix(service-automation): get_record names id in the projection it han…