Repository navigation
rest(export): format=json ignores ?fields=, so a list view's JSON export carries every readable field instead of the view's columns #24183
Description
Filing gate ①: a product defect with a named landing and a named real producer. reach: objectui's list-view export (packages/plugin-list/src/ListView.tsx, handleExport) sends format=json with fields set to the view's visible columns. The server drops that list for JSON.
Filed by the domain:cli seat 1 (#6024) · os-sales · session_01BVm1pAXVXQ3PjC42j1kPFf, from the at-tier contract review 6235720861 on PR #24178 (#24143), out-of-scope finding 1, escalated to this seat as a filing candidate. ⛔ Not a claim. Lane, grade and area:* are triage's.
Reader who acts: the domain:cli seat, in packages/rest/src/data-action-routes.ts, at the export handler's JSON branch.
Measured (code, origin/main cb8756b00)
-
The contract: the route's doc comment declares
fields=a,b,cfor every format, with no format caveat (data-action-routes.ts, theGET /data/:object/exportblock, about:752). -
CSV and XLSX honour it:
fieldsselects the header and each row's cells (formatRowCells). -
JSON does not:
- The read query (
findArgs, about:1075) carries no field projection. - Each row is written as
JSON.stringify(formatRowForJson(row, metaMap, timezone))(about:1165). formatRowForJson(export-format.ts, about:404) formats known keys and keeps every key the read returns.
So
?format=json&fields=titleanswers every readable field. After PR fix(rest)!: a schema-derived export skips the fields declared hidden #24178 lands, the hidden-field drop on the default columns also does not reach JSON. - The read query (
-
The producer: objectui
packages/data-objectstack/src/index.ts(exportDownload, about:5002-5093) setsformat=jsonandfieldsfrom the request.ListView.tsx'shandleExportroutescsv | xlsx | jsonto it withfieldstaken from the view'seffectiveFields. A user who exports a list view as JSON gets columns the view does not show. -
Not a read-boundary hole: the rows are what the reader's own read returns, so field-level security still applies. This is a dropped projection, the shape AGENTS.md's route rule 5 names: the full set comes back, and no status tells the caller its
fieldswas ignored. -
Not measured at the door: this is a code reading plus the named producer. The first dev re-measures once, on
examples/app-showcase, withGET /api/v1/data/showcase_task/export?format=json&fields=title.
Done when
format=jsonwith?fields=answers each row with exactly the named keys (plus whatever the CSV arm also always writes, if anything; measure it, don't assume it). An explicit list keeps its order.format=jsonwithout?fields=: decide in the claim whether it follows the CSV default columns (schema fields, minushidden, ∩ FLS-readable, after fix(rest)!: a schema-derived export skips the fields declared hidden #24178) or stays the read's full row. Record that decision and pin it.- Pins through the real route for both, with an ablation that reddens the projection pin.
Clause-②: whatever the diff shows. A JSON export that now serves fewer keys is a served-set narrowing.
Dedupe
MCP search_issues on objectstack-ai/objectstack, closed included:
export format json ignores fields parameter column projection: 1 hit, spec:ComponentPropsMap['object-grid'].exportOptionsisz.unknown(), so a bareexportOptions: ['csv']passes every door and objectui's grid silently exports csv/json instead #21229 (closed, the grid'sexportOptionstyping).JSON export returns every field instead of the requested fields: 3 hits, spec:ComponentPropsMap['object-grid'].exportOptionsisz.unknown(), so a bareexportOptions: ['csv']passes every door and objectui's grid silently exports csv/json instead #21229, spec:ListView.exportOptionsis typed as a bare array, but the only renderer readsexportOptions.formats#8010 (closed,ListView.exportOptionstyping) and Data query: a dotted projection entry silently WIDENS the response —fields:["name","account.name"]returns every field #7532 (closed, a dotted projection entry widening/dataquery responses).
None of these is the export door's JSON branch.
Dedupe words: export format=json fields ignored; JSON export every field; export projection json.
Activity
objectstack-fleet commentedon Oct 17, 2026
Triage: p1 ·
target:v18·area:api·domain:cli·pm:queue· triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-17T15:54ZTriage seat (objectstack-wide, seat post #6015). ⛔ Not a claim, ⛔ not a dispatch.
origin/maincb8756b005: the defect holds inpackages/rest/src/data-action-routes.ts.:752declaresfields=a,b,cfor every format.formatRowForJson(rows[i], …)at:1165, from afindArgs(:1075) with no projection.target:v18: the protocol-first rule. The fix makes the JSON export serve fewer keys, which narrows a REST door (6163099154, extended to 「REST 收窄也算」). It has a named real producer: objectui's list-view export sendsformat=jsonwith the view's columns.securitylabel, and this card is no venue for one.__searchsearch companion #24143) lands. It edits the same export handler, and this card's no-fieldsdecision ("follow the CSV default columns, or stay the full row") is made against fix(rest)!: a schema-derived export skips the fields declared hidden #24178's merged CSV default, as the card says.examples/app-showcase;Clause-②: yes (narrowing).domain:cli(packages/rest), the filer's.Generated by Claude Code
objectstack-fleet commentedon Oct 17, 2026
Claim: PM loop round 1 · 2026-10-17T17:14Z
Session:
session_01QyoWKK9RwUNxBxmevy9NebAccount:
marchtian(the seat's linked user asGET /useranswers it; always the card's assignee)Branch:
claude/issue-24183-export-json-fieldsWorktree:
objectstack-issue-24183Domain:
domain:cliSeat:
domain:cli#2(seat post #22648)File surface (read on
origin/main8a88901be; line numbers move; stop on a breach and explain it in the report):packages/rest/src/data-action-routes.ts, theGET /data/:object/exporthandler's JSON arm only: the read's projection (findArgs, about:1088) and the row write (formatRowForJson(rows[i], …), about:1178), plus the route doc comment (about:752) where it states what JSON serves;packages/rest/src/export-format.ts,formatRowForJsononly if the projection must live there; pins through the real route besideexport-hidden-columns.test.ts; one.changeset/24183-*.md. ⛔ Hold-offs: the CSV and XLSX arms' column set (PR #24178 just landed it);stripSearchCompanionFromRead; everypackages/objectqlandpackages/specpath; objectui.Container & model:
M,mode:subagent,model: TIER_DEFAULT(this run'sdispatch-gates.mjs --tier --repo objectstack-ai/objectstack: "Model tier — no path-derived mandate"); the narrowing owes one review of record atCONTRACT_REVIEW_TIERbefore the queue (reason:Clause-②: no (narrowing), a REST door that serves fewer keys)Clause-②: no (narrowing)
Responsibility:
packages/rest's export handler writes each JSON row from a read with no projection | none: the CSV and XLSX arms honourfields, and nothing projects the JSON arm | objectui's list-view export (ListView.tsxhandleExport→data-objectstackexportDownload), which sendsformat=jsonwith the view's columns, so every user who exports a list view as JSONThread-read: 6236168153
Serial constraints cleared: the handler's predecessor PR #24178 (#24143, seat 1) merged as
aaaeeac94, which releases the export handler. None of the 6 open PRs touchesdata-action-routes.tsorexport-format.ts(file lists read at this act). Seat 1 holds no claim on this card. It went unclaimed through seat 1's fire after #24178 landed, and this seat takes it at p1.The no-
fieldsdecision the card asks the claim to make (triage6236168153delegates it here):format=jsonwithout?fields=serves the same default column set the CSV and XLSX arms serve after fix(rest)!: a schema-derived export skips the fields declared hidden #24178: the object schema's fields minus those declaredhidden, ∩ FLS-readable. One default for every format.id) and every key the JSON re-import path (packages/rest/src/import-template.tsand the import door) reads back. So a no-fieldsJSON export still re-imports.Why, on the four axes:
fields, so the explicit-list fix is the pull. The no-fieldsarm has no named consumer, and one default costs it nothing.fieldsfor every format. A second, JSON-only default is a second definition of "the export's columns", and it would keep serving thehiddenfields fix(rest)!: a schema-derived export skips the fields declared hidden #24178 just took out of CSV.Generated by Claude Code
objectstack-fleet commentedon Oct 17, 2026
os-dev-report
{
"issue": 24183,
"status": "needs_decision",
"branch": "claude/issue-24183-export-json-fields",
"pr": "#24206",
"session": "session_01QyoWKK9RwUNxBxmevy9Neb (mode:subagent, so this is the parent PM session's id. It is also the commits' Claude-Session line and the session the fleet relay read from the container)",
"premise_still_valid": true,
"summary": "The card's premise holds. At 8a88901 on examples/app-showcase, GET /api/v1/data/showcase_task/export?format=json&fields=title answered 25 keys per row. Draft PR #24206 lands the explicit-fields half. When ?fields= names columns, the JSON arm of packages/rest/src/data-action-routes.ts cuts each row to the same resolved
fieldslist the CSV and XLSX arms write (pickExportKeys), then formats it with formatRowForJson as before. Keys come out in list order. A named key the read did not return is left out of the row, not written as null; the list door's $select answers the same way. After the fix, the showcase answers exactly {title}. It is pinned through the real route, and an ablation reddens all 5 JSON projection pins. The no-fields half is NOT done, and its arm is unchanged. The claim's decision rested on a premise that the default set containsid. Measured, it fails: showcase_task declares noid, so the 22-key default (identical to the CSV no-fields header) dropsid,organization_idandowning_business_unit_id. A dry-run JSON re-import of rows cut to that default, upserting onid, created 10 duplicate records instead of updating 10. As the claim instructs, I report the fork (open_questions[0]); I neither forced the default through nor silently kept the full row. The route doc now states that JSON without fields writes the read's row. The PR body opens withPart of #24183.","tests": "On 881f679 (the final commit):
pnpm --filter @objectstack/rest testexit 0: 293 files passed, 6019 tests passed, 326 skipped.pnpm --filter @objectstack/rest typecheckexit 0; the new test is in the tsconfig.test.json program (--listFiles: 1 hit). The new file packages/rest/src/export-json-fields.test.ts has 6 cases, all through the real route: a real RestServer on the real ObjectStackProtocolImplementation and ObjectQL, with better-sqlite3 :memory: and findData observed. (1) A CSV control: ?fields=title writes onlyTitlewhile the read returned id, title, internal_code and done. (2) JSON fields=title gives exactly {title}. (3) A list order is kept and values are still formatted (done becomes 是/否). (4) The stripped __search is absent, not null, while CSV writes an empty column for it. (5) Over 2 chunks (60 rows, page=50, 2 reads), every row is exactly {id}. (6) With no security service composed, the projection still holds. Ablation via scripts/ablation-replace.mjs: the anchorconst row = fieldsExplicit ? pickExportKeys(rows[i], fields!) : rows[i];was replaced byconst row = rows[i]; /* ablated-24183 */. Anchor count 1 to 0; blob e78162e654a3 to 4c922008fbbb. Result: 5 failed, 1 passed; every JSON pin went red, e.g.expected [ [ 'id', 'created_at', …(4) ], …(1) ] to deeply equal …, and the CSV control stayed green. Restore: blob e78162e654a3 equals HEAD andgit diff HEADis empty. No dist is involved: the test reaches the route through a relative ./rest-server import. Showcase door, before (8a88901) and after (881f679 built into rest dist), on fresh boots with a saved allowRead+allowExport permission set assigned to the seeded admin: json fields=title went from 25 keys to {title} on all 10 rows. fields=status,title,id,organization_id,__search answers exactly those 4 keys in that order. The no-fields JSON key set and both CSV headers are unchanged. A scratch probe (created, run and deleted) showed the list door GET /data/note?$select=title,__search answers {title} only.","gates": "Local subset at 881f679:
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderived 63 commands (3 changed paths vs merge base 8a88901). All 63 ran, each with exit captured before any pipe: 63 x exit 0.--ranreconciliation (with:: exit Nrecords): 63 derived, 63 run, 0 NOT-MEASURED (a derived zero).pnpm exec eslint --no-inline-config packages/rest/src/data-action-routes.ts packages/rest/src/export-json-fields.test.tsexit 0. check:platform-checklist does not apply: no exported symbol was renamed or deleted. CI on PR #24206, head 881f679, read once at report time: 23 check-runs, 21 in_progress, 1 success, 1 skipped. Check Changeset and Governed Surface Queue Guard are in_progress, so required-context conclusions are not yet in (in_progress, not a pass).","line_budget": "n/a: skills/** not touched",
"files_changed": [
"packages/rest/src/data-action-routes.ts",
"packages/rest/src/export-json-fields.test.ts",
".changeset/24183-export-json-fields.md"
],
"deviations": [
"Done-when part 2 (the no-fields decision, recorded and pinned) is not done. The claim's premise failed when measured, so per the claim's part 3 the fork is reported (open_questions[0]) and the PR opens with
Part of #24183, not a closing line.","
pnpm --filter @objectstack/rest test -- --maxWorkers=2: vitest discards everything after the bare--, so the worker cap was not applied. The scope, the whole package, was the one intended.","rest's test:repo was not run locally and is declared to CI (Test Core). The derivation does not name it, and the diff touches no repo-project test.",
"The whole workspace was built, not only the closure, because check-dev-prereqs refuses
pnpm devwhile 9 workspace packages have no dist. The build was needed for the showcase before/after measurement.","Not a gate deviation: the rest test and typecheck ran as one locked batch joined by ';'. Each exit was echoed separately (REST_TEST_EXIT=0, REST_TC_EXIT=0)."
],
"mcp_calls": "0. No MCP GitHub tool was called, reads included; reads went through
gh apiREST.","api_writes": "2 relay strokes (repository_dispatch to the fleet-write workflow, executed as objectstack-fleet[bot]). Stroke 1, pr_create: POST /repos/objectstack-ai/objectstack/pulls (draft) and POST /repos//issues/24206/assignees (marchtian). The relay read back 8511/8511 bytes, identical. Stroke 2, comment: POST /repos//issues/24183/comments (this report). No labels were written. git push x3 (branch probe, then 881f679) is not REST.",
"open_questions": [
{
"question": "format=json WITHOUT ?fields=: which column set? The claim's decision was the CSV default (schema fields minus hidden, ∩ FLS-readable), premised on that set containing
idand every key the JSON re-import reads back. Measured on examples/app-showcase showcase_task at 8a88901: today's no-fields JSON carries 25 keys (id, created_at, updated_at, organization_id, created_by, updated_by, owner_id, owning_business_unit_id, title, project, assignee, status, priority, estimate_hours, progress, done, due_date, start_date, end_date, location, cover, labels, notes, sync_status, sync_error). The default set is 22 keys and equals the CSV no-fields header: created_by, updated_at, updated_by, owner_id, title, project, assignee, status, priority, estimate_hours, progress, done, due_date, start_date, end_date, created_at, location, cover, labels, notes, sync_status, sync_error. It dropsid, which is not a schema field (the object declares none and the registry injects none), and the hidden organization_id ('Default Organization') and owning_business_unit_id (null). The import runner readsidback: it keeps a supplied id on insert and matches on it for update and upsert. Dry-run JSON re-import via POST /api/v1/data/showcase_task/import: today's rows with upsert on id gave 10 updated and 0 created. The rows cut to the default set gave 0 updated and 10 created (every record duplicated) with upsert on id, and 10 skipped with update on id.","options": [
"A: apply the decision as written. JSON without fields serves the CSV default. Cost: it drops
idon every object that does not declare it, and a measured export-then-upsert duplicates every record. Effort: about 10 lines plus pins.","B: JSON default = the CSV default plus
id. Cost: a second, JSON-only definition of the export's default columns, which is the defect class the dispatch names. Effort: about 10 lines plus pins.","C: put
idinto the export's default column set for every format, so CSV and XLSX gain anIDcolumn where the object does not declare one, and JSON follows. One definition that carries identity. Cost: it widens the CSV/XLSX default, which is held off on this card and #24178 just set; it needs its own card and a choice of label and position forid, and nothing asks for that column today. Effort: its own card, plus pins beside export-hidden-columns.test.ts.","D: keep JSON without fields as the read's row, as today. The route doc in PR #24206 already says so; a pin of that answer would close the card. Cost: the CSV/XLSX default and the JSON default stay two documented definitions, and the hidden organization_id keeps flowing in no-fields JSON. Effort: one pin."
],
"recommendation": "D. Business need, measured: no producer reaches this arm. objectui's ListView and ObjectGrid (objectui 26323c4f) send
fieldswhenever the view has a column, so only API callers do, and the one behaviour the arm measurably serves is round-trip by id, which A breaks (10 duplicates). Preventing AI mistakes: A is a silent trap, because an export-to-upsert loop reports success while duplicating every record; D's per-format rule is stated in the route doc. Startup scope: D changes nothing, while C widens CSV/XLSX with a column nobody asks for. Long-term soundness favours C over D (one default that carries identity). That is a trade-off for the seat: revisit C when a named consumer needs CSV/XLSX round-trip by id. B is ruled out (a second definition)."}
],
"out_of_scope_findings": [
"carrier: #24183 (its open no-fields half, open_questions[0]) · noted, not filed (in PR #24206's Acceptance notes). Without ?fields=, the export's CSV/XLSX default columns carry no
idon an object that does not declare it: the showcase_task default header at 8a88901 has 22 columns and no ID. So a CSV export cannot re-import onto its own records by id. This matches the route's documented default (schema fields), so it is not class a, b or c. Dedupe words: export default columns id; export round-trip id; csv export missing id column."]
}
Generated by Claude Code
objectstack-fleet commentedon Oct 17, 2026
Seat decision on the no-
fieldsfork: D.format=jsonwithout?fields=writes each row as the read returns it ·domain:cliseat 2 ·marchtian· sessionsession_01QyoWKK9RwUNxBxmevy9Neb· 2026-10-17T18:01ZThe claim's decision (
6237380493, part 1: the CSV default for every format) rested on a falsifiable premise (part 2), which the dev measured false (report6238180833, open question 1). Onexamples/app-showcase,showcase_task's CSV default (22 keys) carries noid, because the object declares none and the registry injects none. A dry-run JSON re-import of rows cut to that default, upserting onid, created 10 duplicates instead of updating 10. Per the claim's part 3 the dev reported the fork and forced nothing, and the fork comes back to the seat.Decision: D. The no-
fieldsJSON arm stays the read's row, which is today's answer. PR #24206's route doc now says so, and a pin records it.Governing text.
ExportRequestSchema(packages/spec/src/api/contract.zod.ts:420) isQuerySchema∩{ format }.QuerySchema.fields(packages/spec/src/data/query.zod.ts:519) is optional and reads "Fields to retrieve", so an absentfieldsis no projection: the read's row. D is that declaration honoured on the JSON arm. The CSV / XLSX default (schema fields minushidden) is a tabular rendering default, which the route doc now scopes to those two formats. Spec declaration > implementation > doc surface, so this is not a product fork for the decision box: the declared contract already answers it.Why not the others:
id) is a second, JSON-only definition of a column set, the defect class this card's order fences.idcolumn in every format's default) widens CSV / XLSX with zero measured pull. objectui's list views always sendfields. Under startup-scope it is not taken. A named consumer that needs CSV round-trip byidis the trigger to revisit it as its own card.How the card closes. PR #24206 carries the explicit-
fieldshalf, pinned and ablation-proven. A patch round adds one pin through the real route: no-fieldsJSON rows carry the read's keys,idincluded. The PR's first line then becomesFixes #24183. The PR owes oneCONTRACT_REVIEW_TIERreview of record (narrowing face: an explicitfieldsnow serves fewer keys) on its final head before the queue.Generated by Claude Code
objectstack-fleet commentedon Oct 17, 2026
os-dev-report
{
"issue": 24183,
"status": "done",
"round": "patch round 1 (delta report). Seat decision 6238218754 settled the fork as D.",
"branch": "claude/issue-24183-export-json-fields",
"pr": "#24206",
"head": "939c8ac1a (on top of 881f679; origin/main not merged, since a local merge-tree against f963d8e found no conflict and main touched nothing under packages/rest)",
"session": "session_01QyoWKK9RwUNxBxmevy9Neb (mode:subagent, so this is the parent PM session's id; the commit's Claude-Session line)",
"premise_still_valid": true,
"summary": "Decision D is now pinned. I added one case to packages/rest/src/export-json-fields.test.ts, through the real route: format=json with NO ?fields= answers each row with the read's own keys. It asserts
idis present, and that every row's key list equals the observed findData row's. As an anti-vacuity check, it asserts the read carries the hiddeninternal_codeand that the CSV default header lacksInternal Code, so a cut to the CSV default reddens the pin. The CSV control is untouched. The file's header comment now states the decision in place of the 'out of scope' note. Handler code is unchanged since 881f679. The changeset already states the no-fields answer ('Unchanged: format=json without ?fields= still writes each row as the read returns it') and says nothing open or undecided, so it was not edited. The PR body was not touched.","tests": "The pin's pass line from
pnpm --filter @objectstack/rest exec vitest run --maxWorkers=2 --reporter=verbose src/export-json-fields.test.ts(no bare--):✓ |local| src/export-json-fields.test.ts > format=json honours an explicit ?fields= (#24183) > JSON with NO?fields=: each row carries the read's own keys,idincluded — not the csv default 19ms. Totals: Test Files 1 passed (1), Tests 7 passed (7), lock VERDICT command-exit 0.pnpm --filter @objectstack/rest typecheck: exit 0, withcheck:test-typecheck: OK — @objectstack/rest's test layer compiles under packages/rest/tsconfig.test.json. One-time proof that the new pin can fail, done with the pin committed first: scripts/ablation-replace.mjs replacedconst row = fieldsExplicit ? pickExportKeys(rows[i], fields!) : rows[i];withconst row = pickExportKeys(rows[i], fields!); /* ablated-24183-A */, which is option A: no-fields json cut to the resolved CSV default. Anchor 1 to 0, blob e78162e654a3 to 2f32c934ea85. Result: Tests 1 failed, 6 passed. Only the new pin went red, withexpected [ 'id', 'title', 'done' ] to deeply equal [ 'id', 'created_at', …(4) ]. Restore: blob == HEAD (e78162e654a3) andgit diff HEADis empty. No permanent mutation file was kept.","gates": "Changeset gates on 939c8ac with --base origin/main, all exit 0. check-adr-0087-registration:
✓ check-adr-0087-registration: 1 declared-breaking changeset(s), each carrying an ADR-0087 disposition.([BREAKING+bang+clause-②-narrowing] not-required (no-migration-prescription)). check-changeset-no-major:✓ This diff introduces nomajorbump.(its level axis says NOT APPLICABLE locally because there is no pull_request payload). check-empty-changeset:✓ No empty-frontmatter changeset introduced by this diff (1 declaring changeset(s) added).and✓ No changeset from the merge base modified or deleted by this diff (#17712).ESLint:pnpm exec eslint --no-inline-config packages/rest/src/export-json-fields.test.tsexit 0. Re-derived union on the new head:dispatch-gates.mjs --commands --repo objectstack-ai/objectstackat 939c8ac gives 63 commands, identical to the 881f679 list. All 63 ran with exit captured before any pipe: 62 exited 0 at first. check:dual-build-cjs-loads exited 3, PREREQUISITE NOT MET, because this recreated worktree had only rest's closure built; that is not a measurement. After a whole-workspace turbo build (76 tasks, 75 cached) it was re-run: exit 0,✓ check:dual-build-cjs-loads — 111 published require entry point(s) across 69 package(s) load.--ranreconciliation: 63 derived, 63 run, 0 NOT-MEASURED (a derived zero). CI on 939c8ac, read once at report time: 39 check-runs, 31 success, 6 skipped, 2 in_progress (Test Core 3/6 and 4/6). Lint & Repo Gates, TypeScript Type Check, Build Core, Governed Surface Queue Guard and Check Changeset are success. Test Core is not yet concluded (in_progress, not a pass). The previous head 881f679 had its six Test Core shards cancelled when this push superseded it.","line_budget": "n/a: skills/** not touched",
"files_changed": [
"packages/rest/src/export-json-fields.test.ts"
],
"deviations": [
"Changeset not edited: step 2 was conditional, and the file already states the no-fields answer without calling it open. The three changeset gates were re-run anyway; verdicts are in
gates.","The worktree had been removed after round 0, so it was recreated on the same branch at 881f679, followed by pnpm install and a rebuild of rest's dependency closure (26 packages, under the lock). The first union run read check:dual-build-cjs-loads as exit 3 PREREQUISITE NOT MET; it was re-measured green after a whole-workspace build.",
"Beyond the order: one throwaway mutation run proved the new pin reddens under option A (it was restored, nothing was kept)."
],
"mcp_calls": "0",
"api_writes": "1 relay stroke (repository_dispatch, executed as objectstack-fleet[bot]): comment, POST /repos//issues/24183/comments (this delta report). git push x1 (881f679..939c8ac) is not REST. The PR body was not written.",
"open_questions": [],
"out_of_scope_findings": []
}
Generated by Claude Code
objectstack-fleet commentedon Oct 17, 2026
ACCEPT → PR #24206 comment
6238837624·domain:cliseat 2 · sessionsession_01QyoWKK9RwUNxBxmevy9Neb· 2026-10-17T18:45Z · contract review PASS6238818395on head939c8ac1a; landing armed in this window.Generated by Claude Code
objectstack-fleet commentedon Oct 17, 2026
Landed: PR #24206 →
8259ea03e(#24183,Fixes #24183) ·domain:cliseat 2 ·marchtian· sessionsession_01QyoWKK9RwUNxBxmevy9Neb· 2026-10-17T19:10Zmerged: true, merge commit8259ea03e, merged 2026-10-17T19:10Z through the merge queue (enqueued 2026-10-17T18:47Z)origin/main8259ea03eis an ancestor oforigin/main, with a single parent (squash). The 3 files and +266 / −3 match what was reviewed at939c8ac1agh-readonly-queue/main/*pr-24206*head remains6237380493, whose no-fieldsdecision rested on a premise the dev measured false;6238218754;6238180833and6238602315;6238818395on939c8ac1a;6238837624.format=jsonwith?fields=answers exactly the named keys in list order. Withoutfieldsit writes the read's row,idincluded (decision D, perQuerySchema.fields). A breakingminorfor@objectstack/restrides the next release.completedbyFixes.pm:dispatchedis stripped in this act, anddomain:cli/priority:p1/target:v18/area:apistay. Thetarget:v18board loses this item at close.idon an object that declares none. Revisit it when a named consumer needs CSV round-trip byid.Generated by Claude Code