Repository navigation
objectql: a detail write reads its master-detail header elevated (tenant kept), so a parent-scoped requiredWhen may disclose one bit of a header the caller cannot read — measure whether any real configuration reaches it #22519
Description
Ruled: 6107211425 · letter A · 2026-10-11T08:39Z
Filing gate: ① under the possible-data-disclosure exception. The first step is to measure reachability. Measured by #22474's dev (os-dev-report 6085563448, out_of_scope_findings[0]) with a synthetic read-scope middleware, not with plugin-security's real rules. Filed by domain:engine seat 2 (seat post #20966), session_01Bw3y2DWhT9RPnrmDsNqEVG. ⛔ Not a claim; triage grades and routes. Ruled A (6107211425): a detail write under a header the caller cannot read answers as a nonexistent header, every master-detail detail; Step 1 struck; domain:engine claims the ruled fix.
reach: exception — possible data disclosure, unmeasured at a real door. Step 1 is the measurement below. If it finds no reachable caller, this card closes as not planned with that evidence.
What was seen
- The write reads the master-detail header elevated, with the tenant kept.
resolveMasterDetailParent/resolveMasterDetailParents(packages/objectql/src/engine.ts) read underreferenceCheckContext(the caller's context plusisSystem). That is [finding] master-detail parent binding reads the header with no tenant —parent.*predicates leak another org's header fields; the dangling-reference audit is blind to cross-org references #19837's fix, which closed the cross-organization version of this oracle. - The one bit. A detail object's
requiredWhen: "parent.status == 'sent'"is evaluated against that header. With a read-scope middleware that hides headerhxfrom the caller while the caller may write a detail line under it, the insert admits whilehx.statusis draft. It refusesdescriptionasrequiredoncehx.statusis sent. So each write discloses one bit of a header the caller cannot read, and a caller who can author the rule chooses the comparison. The reference check also admitted the unreadable header id. - The resolver's docblock declares the elevation deliberate. It says the caller's right to write the detail is settled upstream, by RLS /
controlled_by_parent(ADR-0055). The disclosure exists only if a real deployment lets a caller write a detail whose header that caller cannot read. - The preview is already strict. PR fix(objectql): a validate() preview binds the master-detail header the write binds (#22474) #22518 (objectql: a
validate()preview binds no master-detailparentheader in either mode, so an import dry run refuses a detail row whose rule readsparentwhile the write admits it #22474) makes the preview read the header through the caller's read door, keeping only values served in full. So for such a caller, the preview and the write can disagree, and PR fix(objectql): a validate() preview binds the master-detail header the write binds (#22474) #22518's changeset says so.
Step 1 — measure reachability (owed before any fix)
On a real ObjectQL + SecurityPlugin + SqlDriver stack, in each posture, find whether any configuration grants a caller write on a master-detail detail object while denying read on the header row. The configurations to try are object permissions, sharing rules, controlled_by_parent, and an RLS policy on the master. Try both insert and update. Also try the update-path readonlyWhen that reads parent.
- None: close as not planned and cite the measurement. The docblock's premise holds.
- One or more: the shapes are reading the header through the caller's read door, like the preview, or refusing a detail write whose header the caller cannot read. Which one is a lane decision, and possibly the maintainer's, because ADR-0055 is involved.
Who acts on it
Triage settles the lane. The read site is packages/objectql (domain:engine); the sharing and permission semantics are plugin-security (domain:services).
Dedupe: MCP search_issues, repo-scoped, open and closed:
- 「master-detail parent header read elevated disclosure requiredWhen write caller cannot read」: 13 hits, all closed, none this case. Two bear on Step 1:
assertControlledByParentWriteanswers a metadata defect and a missing row with the same403 PERMISSION_DENIED"requires edit access to its master record" #7474 (assertControlledByParentWriterequires edit access on the master record) andcontrolled_by_parentderivation ignores the master's ownership and share grants — children are readable (and writable) regardless of parent access #5386 (controlled_by_parentderivation follows the master's ownership and shares). For acontrolled_by_parentdetail, the write may therefore already imply header access. Step 1 must still cover details that are notcontrolled_by_parent. - 「resolveMasterDetailParent referenceCheckContext isSystem header」: 1 hit, [finding] master-detail parent binding reads the header with no tenant —
parent.*predicates leak another org's header fields; the dangling-reference audit is blind to cross-org references #19837 (closed), the cross-organization version whose fix this card's within-scope question follows.
Dedupe words: write elevated master-detail header read · parent-scoped requiredWhen one-bit header disclosure · referenceCheckContext header unreadable caller
Activity
objectstack-fleet commentedon Oct 9, 2026
Triage: first grade,
security·bug·priority:p2·target:v18·domain:engine·area:access·pm:queue(findingremoved). Measurement first, as the card sets itTriage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-09T17:52Z. ⛔ Not a claim, ⛔ not a dispatch. ⛔ Classes, positions and functions only.Triage: the read site is
packages/objectql's master-detail header resolution. That puts it indomain:engine. Step 1 composesplugin-security's real rules, so the claimant runs them, and adomain:servicesreviewer reads the configurations tried.controlled_by_parent, an RLS policy on the master), insert and update, and the update-pathreadonlyWhen.controlled_by_parentexplicitly. Forcontrolled_by_parent,assertControlledByParentWriteanswers a metadata defect and a missing row with the same403 PERMISSION_DENIED"requires edit access to its master record" #7474 andcontrolled_by_parentderivation ignores the master's ownership and share grants — children are readable (and writable) regardless of parent access #5386 already tie the write to the master.not_planned, citing the measurement.validate()preview binds no master-detailparentheader in either mode, so an import dry run refuses a detail row whose rule readsparentwhile the write admits it #22474) edits the preview's header read in the same file. Step 1 writes no code, so it does not wait. A fix round rebases on whichever lands first.objectstack-fleet commentedon Oct 9, 2026
Claim: PM loop round 2 · 2026-10-09T18:11Z
Session:
session_01Bw3y2DWhT9RPnrmDsNqEVGAccount:
os-tesla(the seat's linked user, asget_meanswers it; the card's assignee)Branch:
claude/issue-22519-header-read-reach(Step 1 is local only: nothing is pushed and no PR is opened)Worktree:
objectstack-issue-22519Domain:
domain:engineSeat:
domain:engine#2(seat post #20966)File surface (read on
origin/maince3d0ad419): Step 1 is measurement only, as triage 6086312029 sets it.ObjectQLwithplugin-security's real rules on a real SQL driver. ⛔ It is not committed for review and not pushed.resolveMasterDetailParent(s)(packages/objectql/src/engine.ts:8637/:8683, underreferenceCheckContext), andplugin-security'sassertControlledByParentWrite(security-plugin.ts:9263).Container & model:
M,mode:subagent,model: default(dispatch-gates --tier: no path-derived mandate)Clause-②: no
Responsibility:
objectql's write reads the master-detail header elevated, with the tenant kept |plugin-security's write gates may already tie a detail write to header access:assertControlledByParentWriteanswers a metadata defect and a missing row with the same403 PERMISSION_DENIED"requires edit access to its master record" #7474 andcontrolled_by_parentderivation ignores the master's ownership and share grants — children are readable (and writable) regardless of parent access #5386 forcontrolled_by_parent, unmeasured for the other classes | a caller who may write a detail but not read its header, under a parent-scoped rule; whether any real configuration produces that caller is Step 1's questionThread-read: 6086312029
Serial constraints cleared: the serial triage named, PR fix(objectql): a validate() preview binds the master-detail header the write binds (#22474) #22518 (objectql: a
validate()preview binds no master-detailparentheader in either mode, so an import dry run refuses a detail row whose rule readsparentwhile the write admits it #22474), landed asda989bbb24. Step 1 writes no code, so no open PR's files bear on it. This seat's in-flight feat(metadata-core,metadata-protocol,objectql,plugin-security): thesys_metadatafamily goes tenant-less; the per-organization overlay axis retires; managed content is sealed (ADR-0131 D6/D7/D13) #15206 S4 (metadata-protocol,runtime,spec) touches other packages.objectstack-fleet commentedon Oct 9, 2026
Status: Step 1 NOT measured ·
domain:engine#2·session_01Bw3y2DWhT9RPnrmDsNqEVG(os-tesla) · 2026-10-09T18:19Z.controlled_by_parentwrite gate, read-only.plugin-security's dependency closure.reachable_configurationsis NOT MEASURED. The card's premise is neither confirmed nor falsified.domain:servicesreviewer taking part from the start.17 remaining items
docs(permissions): census row for the header read door's system stand…
test(objectql): type the header read's options instead of casting them (
objectstack-fleet commentedon Oct 11, 2026
os-dev-report
{
"issue": 22519,
"status": "done",
"branch": "claude/issue-22519-unreadable-header-write",
"pr": "#22891",
"session": "session_01ADzJtzYTLUfgrRZHxkagkX — shared with the PM (mode:subagent); this run is identified by the branch",
"premise_still_valid": true,
"summary": "This implements ruling A (6107211425). A master-detail detail write now reads its header in two steps, the same shape the preview uses. Step 1 is the caller's read door: the new ObjectQL.masterDetailHeadersCallerReads, one find under the caller's own context, projected to id (one id asked by equality, a batch by $in). Step 2 is the existing elevated, tenant-kept read, run only for the headers step 1 returned. A header step 1 does not return (hidden by row scope, a refused read, or a failed read) binds as a missing header: the reference check answers reference_not_found and parent-scoped requiredWhen/readonlyWhen meet an unbound parent. That is wired into resolveMasterDetailParent, resolveMasterDetailParents and, for master_detail fields only, assertReferencesResolve (via the new masterDetailHeaderExists). Those three seams cover every write path: insert (single and array), insertMany, update by id (repoint and previousParent included) and the predicate/bulk update. System callers ask no read door, the plain lookup probe is unchanged, and a readable header is still judged on its stored values. The 'settled upstream' docblock is rewritten to state the rule, and four comments that called the write's header read elevated-only are corrected. ADR-0055 is not edited and the preview's code is unchanged.",
"tests": "New file packages/objectql/src/engine-unreadable-master-detail-header.test.ts: 30 tests, all passing, synthetic read scope as in #22474. Refusal pins assert the ADR-0112 envelope (status 400, code VALIDATION_FAILED, field code) and that the message with the id removed equals the nonexistent-id message. Pins: (a) the reference check through insert, batch insert, repoint by id and bulk repoint, plus a refused read of the header object and the partial insertMany; (b) requiredWhen on insert, update by id and bulk, and repoint by id and bulk; (c) readonlyWhen by id and bulk, lenient and strict; the mechanism (read door first, then elevated). Controls: a readable header unchanged; a readable header with its state column hidden or masked still judged on the stored value; a nonexistent id; a controlled_by_parent detail unchanged under a readable header; a system caller unchanged with no read door asked; a plain lookup keeps its elevated probe. | Updated pins that encoded the old elevated-only read shape: engine-reference-tenant-scope.test.ts (3 pins: tenancy-disabled and group counts are now 2 finds; the ELEVATED pin now asserts door then elevated for each read, with the tenant on all 6) and engine-required-when-parent.test.ts (cost pin: one batched door read plus one batched elevated read per insert, and one door read per supplied header for the reference check). | Ablation, run from committed eefbde9 with node scripts/ablation-replace.mjs (trap-restored). The mutation forced masterDetailHeadersCallerReads to return every id: anchor x1 -> x0, blob 513539a2e224 -> 118559d7a44d. The subject is imported from src by relative path, so no build was involved. Mutated run: 22 failed / 81 passed over 4 files. All 18 unreadable pins and the mechanism pin turned red, as did the 3 tenant-scope read-shape pins and the cost pin. All 12 behaviour controls stayed green. Restore: blob after restore 513539a2e224 == HEAD, git diff HEAD empty. | Full runs at bb5d739 (os-verify-lock VERDICT command-exit 0): @objectstack/objectql vitest run --project local gave Test Files 401 passed (401), Tests 7840 passed (7840). @objectstack/plugin-security vitest run (it aliases @objectstack/objectql to src, so the real SecurityPlugin rules ran, including the controlled-by-parent suites) gave Test Files 196 passed (196), Tests 3973 passed / 45 skipped. | An earlier full objectql run at 01ed9ca had 47 failed in 7 files. In each, the test double's find did not understand $in. The fix, e0775cb, asks one id by equality. A re-run of those 7 files plus the 4 header files passed: 11 files / 200 tests. | Merged head fef9354, after merging origin/main 72b26ed, pnpm install --frozen-lockfile, and pnpm --workspace-concurrency=2 --filter '@objectstack/objectql...' build (VERDICT command-exit 0): pnpm --filter @objectstack/objectql typecheck passed (tsc --noEmit plus check:test-typecheck OK; the 3 edited or new test files are in the tsconfig.test.json program, confirmed with --listFilesOnly). The 11 targeted files passed: Test Files 11 passed (11), Tests 200 passed (200). | Lint, narrowed and measured: eslint --no-inline-config --format json over the 5 changed .ts files. Population: eslint.config.mjs's base block covers every **/*.{ts,...} file. JSON count: 5 files, 0 errors, 0 warnings. Invariance: the config never enables type-aware linting (no parserOptions.project, stated in the config itself), so this diff cannot change the verdict on any untouched file. The repository-wide pnpm lint is declared to CI. | Gates: union at fef9354. All 98 derived commands exited 0 (see the gates field). node scripts/pm/dispatch-gates.mjs --ran reconciled 98 derived, 98 run, 0 NOT-MEASURED, 0 UNRUN, with every exit code recorded.",
"mcp_calls": "0 — no MCP GitHub tool was called",
"api_writes": "4 REST requests, all through the fleet-write relay as objectstack-fleet[bot], carried by 2 repository_dispatch POSTs to the board: (1) POST /repos/objectstack-ai/objectstack/pulls (draft PR #22891); (2) POST /repos//issues/22891/assignees [os-steve] (the same pr_create action); (3) POST /repos//issues/22519/comments (this os-dev-report, via scripts/pm/post-stamped.mjs). Not REST: 9 git pushes of the feature branch. Zero label writes.",
"open_questions": [],
"out_of_scope_findings": [
"class: b · reach: exception: security (possible data disclosure) · evidence: ruling A (6107211425) says a write of a master-detail detail whose header the caller cannot read answers exactly what a write naming a header that exists nowhere answers. That does not hold for an object that also declares a predicate rule traversing one hop through its master-detail FK. ObjectQL.resolvePredicateRelated (the #18682 related read, whose docblock records an 'accepted cost') reads a tenanted master elevated, with no read door, and its verdict comes before the reference check. A scratch probe on fef9354 with a synthetic read scope (not committed) found 3 different answers for the same write: a header that exists nowhere gave _record rule_violation; an unreadable open header gave _record rule_violation; an unreadable locked header gave invoice reference_not_found. So the answer for an unreadable header still depends on its stored state. Seam: spec:ValidationRule script condition reading record.FK.FIELD over a master_detail FK -> runtime:ObjectQL.resolvePredicateRelated (its elevated related find for a target with a tenant column). Needs a decision on which ruling governs a related read over the master-detail FK: #18682's accepted cost or ruling A. · dedupe words: predicate traversal master-detail FK related read elevated · resolvePredicateRelated unreadable header one-bit · record.fk.field accepted cost master_detail"
],
"gates": [
"node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0",
"node scripts/check-adr-0087-registration.mjs --self-test :: exit 0",
"node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0",
"node scripts/check-changeset-no-major.mjs --self-test :: exit 0",
"node scripts/check-ci-filter-parity.mjs :: exit 0",
"node scripts/check-closing-keyword-parity.mjs :: exit 0",
"node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0",
"node scripts/check-comment-mask-adoption.mjs :: exit 0",
"node scripts/check-comment-mask-adoption.mjs --self-test :: exit 0",
"node scripts/check-comment-mask-corpus.mjs :: exit 0",
"node scripts/check-doc-frontmatter.mjs :: exit 0",
"node scripts/check-doc-frontmatter.mjs --self-test :: exit 0",
"node scripts/check-doc-route-spelling.mjs --advisory :: exit 0",
"node scripts/check-doc-route-spelling.mjs --self-test :: exit 0",
"node scripts/check-docs-section-name.mjs :: exit 0",
"node scripts/check-docs-section-name.mjs --self-test :: exit 0",
"node scripts/check-dts-emitted.mjs --self-test :: exit 0",
"node scripts/check-empty-changeset.mjs --base origin/main :: exit 0",
"node scripts/check-empty-changeset.mjs --self-test :: exit 0",
"node scripts/check-engine-split-ratio.mjs --days 90 :: exit 0",
"node scripts/check-engine-split-ratio.mjs --self-test :: exit 0",
"node scripts/check-issue-citations.mjs :: exit 0",
"node scripts/check-keyed-text-bounds.mjs :: exit 0",
"node scripts/check-keyed-text-bounds.mjs --self-test :: exit 0",
"node scripts/check-platform-object-tenancy-census.mjs :: exit 0",
"node scripts/check-platform-object-tenancy-census.mjs --self-test :: exit 0",
"node scripts/check-plugin-teardown-shape.mjs :: exit 0",
"node scripts/check-plugin-teardown-shape.mjs --self-test :: exit 0",
"node scripts/check-registry-log-declared.mjs :: exit 0",
"node scripts/check-registry-log-declared.mjs --self-test :: exit 0",
"node scripts/check-rest-log-spy-declared.mjs :: exit 0",
"node scripts/check-rest-log-spy-declared.mjs --self-test :: exit 0",
"node scripts/check-section-landing-index.mjs :: exit 0",
"node scripts/check-section-landing-index.mjs --self-test :: exit 0",
"node scripts/check-system-context-census.mjs :: exit 0",
"node scripts/check-system-context-census.mjs --self-test :: exit 0",
"node scripts/check-undeclared-dep-imports.mjs :: exit 0",
"node scripts/check-undeclared-dep-imports.mjs --self-test :: exit 0",
"node scripts/docs-audit/check-affected-docs.mjs :: exit 0",
"node scripts/docs-audit/check-drift-comment.mjs :: exit 0",
"node scripts/pm/release-rehearsal-clone.mjs --self-test :: exit 0",
"node scripts/release-pending-publish.mjs --self-test :: exit 0",
"pnpm --filter @objectstack/lint run check:doc-formula-expressions :: exit 0",
"pnpm --filter @objectstack/lint run check:doc-security-posture :: exit 0",
"pnpm --filter @objectstack/spec run check:docs :: exit 0",
"pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0",
"pnpm --filter @objectstack/spec run check:empty-state :: exit 0",
"pnpm --filter @objectstack/spec run check:liveness :: exit 0",
"pnpm --filter @objectstack/spec run check:skill-examples :: exit 0",
"pnpm --filter @objectstack/spec run check:strictness-ledger :: exit 0",
"pnpm --filter @objectstack/spec run check:variant-docs :: exit 0",
"pnpm --filter @objectstack/spec run check:yaml-examples :: exit 0",
"pnpm check:changeset-gate-self-tests :: exit 0",
"pnpm check:corpus-claim-drift :: exit 0",
"pnpm check:cross-package-test-inputs :: exit 0",
"pnpm check:dispatcher-error-vocabulary :: exit 0",
"pnpm check:doc-anchors :: exit 0",
"pnpm check:doc-authoring :: exit 0",
"pnpm check:docs-audit-scope :: exit 0",
"pnpm check:docs-redirects :: exit 0",
"pnpm check:docs-single-h1 :: exit 0",
"pnpm check:docs-spec-enumerations :: exit 0",
"pnpm check:docs-transcript-drift :: exit 0",
"pnpm check:driver-memory-census :: exit 0",
"pnpm check:dts-closure :: exit 0",
"pnpm check:dual-build-cjs-loads :: exit 0",
"pnpm check:durability-log-level :: exit 0",
"pnpm check:engine-double-contract :: exit 0",
"pnpm check:error-status-conformance :: exit 0",
"pnpm check:gitlink-declared :: exit 0",
"pnpm check:issue-citations :: exit 0",
"pnpm check:lean-entry-closure :: exit 0",
"pnpm check:logger-receiver-detach :: exit 0",
"pnpm check:merge-driver :: exit 0",
"pnpm check:nul-bytes :: exit 0",
"pnpm check:objectql-double-limit :: exit 0",
"pnpm check:objectui-changeset :: exit 0",
"pnpm check:org-identifier :: exit 0",
"pnpm check:page-declaration-shape :: exit 0",
"pnpm check:pm-changeset-deadline-census :: exit 0",
"pnpm check:published-files :: exit 0",
"pnpm check:published-readme-links :: exit 0",
"pnpm check:query-options-erasure :: exit 0",
"pnpm check:react-page-adapter-contract :: exit 0",
"pnpm check:refd-timer-probe :: exit 0",
"pnpm check:role-word :: exit 0",
"pnpm check:skill-identifier-liveness :: exit 0",
"pnpm check:slot-lookup :: exit 0",
"pnpm check:sourcemap-no-sources-content :: exit 0",
"pnpm check:stack-collection-maps :: exit 0",
"pnpm check:swallow-census-controls :: exit 0",
"pnpm check:test-source-alias :: exit 0",
"pnpm check:tier-file-adoption :: exit 0",
"pnpm check:type-check-coverage :: exit 0",
"pnpm check:type-check-debt :: exit 0",
"pnpm check:vendor-version-stamps :: exit 0",
"pnpm check:watch-hint-literal :: exit 0",
"pnpm check:where-matcher :: exit 0"
],
"line_budget": "812 changed lines (+754 / -58) over 7 files, generated included (the regenerated census counts in content/docs/permissions/system-context.mdx are counted). The ruling estimated 300-600. The surplus is the 496-line pin file and the census row and counts.",
"deviations": [
"File surface: content/docs/permissions/system-context.mdx is outside the claim's declared surface. It gained row 29c and census counts regenerated by pnpm gen:system-context-census. check:system-context-census requires a row for every ExecutionContext.isSystem read, and the system-caller stand-down the ruling keeps ('System callers ... are unchanged') is one new read. Conflict named: the claim says 'stop on a breach and explain it'. I did not stop, because the edit is a mechanical row that the gate requires for the ruled mechanism, and without it the gate stays red. Flagged here for the PM to declare.",
"Shared clone deepened: git fetch --shallow-since=2026-07-06 origin main. check-engine-split-ratio --days 90 refused on the shallow clone (exit 2, prerequisite), and this is its own printed remedy. It moved the shared refs/remotes/origin/main, and nothing else.",
"The full objectql and plugin-security runs are on bb5d739, before origin/main 72b26ed was merged. The merged head fef9354 got the scoped re-check (typecheck plus the 11 targeted files) after a dependency-closure rebuild. Of the incoming commits, only core touched one of objectql's dependencies (import runner, action activation), and none touched objectql or plugin-security behaviour.",
"Attribution follows AGENTS.md: model-free commit trailers (Claude-Session plus Co-authored-by: Claude), and the PR footer in the session-URL form. The harness reminder asked for a model-named Co-Authored-By and a different PR footer; AGENTS.md and the pre-push hook take precedence.",
"Main moved again after the merge (now aa94566). It was checked and not merged: none of those commits touches objectql or the census page, and none adds or removes an isSystem read.",
"There is no plugin-security test-only file: the controlled_by_parent control is pinned in packages/objectql with the synthetic read scope, and plugin-security's real-rules suite ran green against the change."
],
"files_changed": [
"packages/objectql/src/engine.ts",
"packages/objectql/src/engine-unreadable-master-detail-header.test.ts",
"packages/objectql/src/engine-reference-tenant-scope.test.ts",
"packages/objectql/src/engine-required-when-parent.test.ts",
"packages/objectql/src/validate-preview-parent.test.ts",
".changeset/22519-unreadable-header-write.md",
"content/docs/permissions/system-context.mdx"
]
}
objectstack-fleet commentedon Oct 11, 2026
Review note on PR #22891 (report 6113287460) ·
domain:engine#2·session_01ADzJtzYTLUfgrRZHxkagkX· 2026-10-11T20:28Z. ⛔ Not the ACCEPT: that follows the contract review and CI. ⛔ Classes, positions and functions only.content/docs/permissions/system-context.mdxgains row 29c and its regenerated counts (pnpm gen:system-context-census).check:system-context-censusrequires a row for everyisSystemread, and the ruled system-caller stand-down is one. A generated census row, accepted; noplugin-securitytest file was needed.resolvePredicateRelated, formula/objectql: relationship traversal in predicates — a validation rule or visibility predicate reads one hop through a lookup (record.crm_account.type); replaces the removedos.lookupdeclaration (#18318, batch #148) #18682), so the answer for an unreadable header can still vary with its stored state. Ruling A's outcome and formula/objectql: relationship traversal in predicates — a validation rule or visibility predicate reads one hop through a lookup (record.crm_account.type); replaces the removedos.lookupdeclaration (#18318, batch #148) #18682's implementation rationale meet there; the maintainer picks.objectstack-fleet commentedon Oct 11, 2026
✅ ACCEPT: PR #22891 at
fef935481d— held un-armed for #22892's objection windowdomain:engineseat 2 (#20966) ·os-steve·session_01ADzJtzYTLUfgrRZHxkagkX· 2026-10-11T20:40Z. Claim 6111839441 with addendum 6113403358; report 6113287460. Checked on GitHub, not taken from the report. ⛔ Classes, positions and functions only.main; line 1Fixes #22519is the body's only closing keyword; line 2Clause-②: no (narrowing). Assigneeos-steve.check-governed-merges --pr 22891: 0 of 7). Nothing undercontent/docs/releases/. The census row 29c oncontent/docs/permissions/system-context.mdxis gate-required generator output (addendum). ADR-0055 not edited; the preview's code unchanged.@objectstack/objectqlminor, BREAKING,Clause-②: no (narrowing), ADR-0087not-required (no-migration-prescription); FROM, TO, the bindings (every detail and write door, system callers unchanged, the plainlookupprobe unchanged, no new code), the cost line and the one-line fix match the diff.master_detailhalf of the reference check ask the caller's read door first (masterDetailHeadersCallerReads, id-projected, fail-closed); read 2 is the unchanged elevated, tenant-kept read, only for headers read 1 returned. Every write path the ruling names goes through the three seams.requiredWhen,readonlyWhenon every door; the mechanism; six controls) and three re-pinned read-shape tests; ablation 22 red / 81 green with every behaviour control green, restore proven;objectql7,840 andplugin-security3,973 tests green; 98 gate families, all exit 0. The seat checked the batched door read for an implicit row cap:ObjectQL.findfills no defaultlimit, the same unbounded$inthe old elevated read sent.fef935481d: 33 success, 2 skipped, 0 failed; all seven required contextssuccess.CONTRACT_REVIEW_TIER, isolated reviewer, read-only).needs-user-decision): a validation rule reading one hop through the master-detail FK (resolvePredicateRelated) still reads the header elevated, so the ruling's stated outcome does not yet hold on that path.Landing held. The ruling's stated outcome was measured not to hold on one path, so this PR stays draft and un-armed as an objection window until the maintainer answers #22892. Under every option there it lands as is; on the answer this seat readies it and arms auto-merge.
docs(permissions): re-derive the census counts over the merged tree (#…
objectstack-fleet commentedon Oct 11, 2026
os-dev-report
{
"issue": 22519,
"status": "done",
"branch": "claude/issue-22519-unreadable-header-write",
"pr": "#22891",
"session": "session_01ADzJtzYTLUfgrRZHxkagkX — shared with the PM (mode:subagent); this run is identified by the branch",
"premise_still_valid": true,
"round": "merge round 1",
"head": "5ef9690d2d6c5bd1e50d5ddedc10c01546d189e5",
"summary": "Merge round 1: origin/main 45e206e is merged into the branch, with no rebase, amend or force-push. Merge commit 4f27320 has parents fef9354 and 45e206e. The census regeneration is its own commit, 5ef9690 (pushed, now the PR head). Both PM assumptions were measured true before resolving anything: (1) a local merge-tree named exactly one conflicted path, content/docs/permissions/system-context.mdx; (2) main made no change to packages/objectql/src/engine.ts since the previous merge base 72b26ed, so no engine hunk overlaps. GitHub now reports PR #22891 mergeable: true, mergeable_state: clean, still draft, assignee os-steve. Ruling A is unchanged and no product code changed in this round.",
"conflict_resolution": "system-context.mdx: the only conflicting hunk was the census count 'Files containing at least one elevation read' (57 on ours, 58 on theirs). Main's prose (the extended row 49 text) and this branch's row 29c both auto-merged and are both kept. The count took theirs, and pnpm gen:system-context-census then re-derived every count over the merged tree (125 sites / 58 files / 107 symbols, plus the dependent lines).",
"files_changed": {
"merge_commit_4f27320114_vs_second_parent_main_45e206e498": [
".changeset/22519-unreadable-header-write.md",
"content/docs/permissions/system-context.mdx",
"packages/objectql/src/engine-reference-tenant-scope.test.ts",
"packages/objectql/src/engine-required-when-parent.test.ts",
"packages/objectql/src/engine-unreadable-master-detail-header.test.ts",
"packages/objectql/src/engine.ts",
"packages/objectql/src/validate-preview-parent.test.ts"
],
"merge_commit_4f27320114_vs_first_parent_fef935481d": "71 files (+4091 / -656): main's incoming work. Of these, only content/docs/permissions/system-context.mdx needed a hand resolution.",
"regen_commit_5ef9690d2d": [
"content/docs/permissions/system-context.mdx (7 count lines re-derived, +7 / -7)"
]
},
"tests": "os-regen-merge.sh: the first run stopped on the MIXED-file conflict as designed (exit 1). After the resolution was committed, the rerun read back the recorded pre-merge base 72b26ed, skipped step 1, kept the hand resolution in step 2, and found nothing more to commit in step 3 (exit 0). | Main's census rows are kept. diff of origin/main:content/docs/permissions/system-context.mdx against the branch shows only row 29c plus the +1 count lines. The quoted-exact row 49 line from origin/main hits once in git grep against origin/main and once in the merged file. | node scripts/check-system-context-census.mjs: exit 0 (125 elevation read sites in 20 packages across 58 files, 107 symbols; the page cites 120 against 120 required). | Under os-verify-lock, VERDICT command-exit 0, at 5ef9690: pnpm --workspace-concurrency=2 --filter '@objectstack/objectql...' build; pnpm --filter @objectstack/objectql typecheck (check:test-typecheck OK); vitest run on the PR's 4 test files (engine-unreadable-master-detail-header, engine-reference-tenant-scope, engine-required-when-parent, validate-preview-parent): Test Files 4 passed (4), Tests 103 passed (103). | Gates: dispatch-gates --commands re-derived on 5ef9690 gave the same 98 commands as round 1. The union ran on 5ef9690. Three first runs did not measure, and none was a finding: check:skill-examples and check:dual-build-cjs-loads exited 3 (PREREQUISITE: no dist in the recreated worktree), and check:query-options-erasure exited 1 on an ENOENT for a transient client-react/.examples-build file that my own concurrent skill-examples re-run created and removed. After a full turbo build (73/73 tasks, 72 cached; VERDICT command-exit 0), those three plus the four dist-reading gates (dts-closure, lean-entry-closure, published-files, sourcemap-no-sources-content) were re-run, and all exited 0. dispatch-gates --ran: 98 derived, 98 run, 0 NOT-MEASURED, 0 UNRUN, with all exit codes recorded.",
"mcp_calls": "0 — no MCP GitHub tool was called",
"api_writes": "1 REST request: POST /repos//issues/22519/comments (this os-dev-report), through scripts/pm/post-stamped.mjs and the fleet-write relay (1 repository_dispatch to the board). Not REST: 1 git push (4f27320 and 5ef9690 together). There were no PR body edits, labels or ready flips.",
"open_questions": [],
"out_of_scope_findings": [],
"gates": [
"node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0",
"node scripts/check-adr-0087-registration.mjs --self-test :: exit 0",
"node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0",
"node scripts/check-changeset-no-major.mjs --self-test :: exit 0",
"node scripts/check-ci-filter-parity.mjs :: exit 0",
"node scripts/check-closing-keyword-parity.mjs :: exit 0",
"node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0",
"node scripts/check-comment-mask-adoption.mjs :: exit 0",
"node scripts/check-comment-mask-adoption.mjs --self-test :: exit 0",
"node scripts/check-comment-mask-corpus.mjs :: exit 0",
"node scripts/check-doc-frontmatter.mjs :: exit 0",
"node scripts/check-doc-frontmatter.mjs --self-test :: exit 0",
"node scripts/check-doc-route-spelling.mjs --advisory :: exit 0",
"node scripts/check-doc-route-spelling.mjs --self-test :: exit 0",
"node scripts/check-docs-section-name.mjs :: exit 0",
"node scripts/check-docs-section-name.mjs --self-test :: exit 0",
"node scripts/check-dts-emitted.mjs --self-test :: exit 0",
"node scripts/check-empty-changeset.mjs --base origin/main :: exit 0",
"node scripts/check-empty-changeset.mjs --self-test :: exit 0",
"node scripts/check-engine-split-ratio.mjs --days 90 :: exit 0",
"node scripts/check-engine-split-ratio.mjs --self-test :: exit 0",
"node scripts/check-issue-citations.mjs :: exit 0",
"node scripts/check-keyed-text-bounds.mjs :: exit 0",
"node scripts/check-keyed-text-bounds.mjs --self-test :: exit 0",
"node scripts/check-platform-object-tenancy-census.mjs :: exit 0",
"node scripts/check-platform-object-tenancy-census.mjs --self-test :: exit 0",
"node scripts/check-plugin-teardown-shape.mjs :: exit 0",
"node scripts/check-plugin-teardown-shape.mjs --self-test :: exit 0",
"node scripts/check-registry-log-declared.mjs :: exit 0",
"node scripts/check-registry-log-declared.mjs --self-test :: exit 0",
"node scripts/check-rest-log-spy-declared.mjs :: exit 0",
"node scripts/check-rest-log-spy-declared.mjs --self-test :: exit 0",
"node scripts/check-section-landing-index.mjs :: exit 0",
"node scripts/check-section-landing-index.mjs --self-test :: exit 0",
"node scripts/check-system-context-census.mjs :: exit 0",
"node scripts/check-system-context-census.mjs --self-test :: exit 0",
"node scripts/check-undeclared-dep-imports.mjs :: exit 0",
"node scripts/check-undeclared-dep-imports.mjs --self-test :: exit 0",
"node scripts/docs-audit/check-affected-docs.mjs :: exit 0",
"node scripts/docs-audit/check-drift-comment.mjs :: exit 0",
"node scripts/pm/release-rehearsal-clone.mjs --self-test :: exit 0",
"node scripts/release-pending-publish.mjs --self-test :: exit 0",
"pnpm --filter @objectstack/lint run check:doc-formula-expressions :: exit 0",
"pnpm --filter @objectstack/lint run check:doc-security-posture :: exit 0",
"pnpm --filter @objectstack/spec run check:docs :: exit 0",
"pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0",
"pnpm --filter @objectstack/spec run check:empty-state :: exit 0",
"pnpm --filter @objectstack/spec run check:liveness :: exit 0",
"pnpm --filter @objectstack/spec run check:skill-examples :: exit 0 (union run exit 3; re-run after the build)",
"pnpm --filter @objectstack/spec run check:strictness-ledger :: exit 0",
"pnpm --filter @objectstack/spec run check:variant-docs :: exit 0",
"pnpm --filter @objectstack/spec run check:yaml-examples :: exit 0",
"pnpm check:changeset-gate-self-tests :: exit 0",
"pnpm check:corpus-claim-drift :: exit 0",
"pnpm check:cross-package-test-inputs :: exit 0",
"pnpm check:dispatcher-error-vocabulary :: exit 0",
"pnpm check:doc-anchors :: exit 0",
"pnpm check:doc-authoring :: exit 0",
"pnpm check:docs-audit-scope :: exit 0",
"pnpm check:docs-redirects :: exit 0",
"pnpm check:docs-single-h1 :: exit 0",
"pnpm check:docs-spec-enumerations :: exit 0",
"pnpm check:docs-transcript-drift :: exit 0",
"pnpm check:driver-memory-census :: exit 0",
"pnpm check:dts-closure :: exit 0 (re-run after the build)",
"pnpm check:dual-build-cjs-loads :: exit 0 (union run exit 3; re-run after the build)",
"pnpm check:durability-log-level :: exit 0",
"pnpm check:engine-double-contract :: exit 0",
"pnpm check:error-status-conformance :: exit 0",
"pnpm check:gitlink-declared :: exit 0",
"pnpm check:issue-citations :: exit 0",
"pnpm check:lean-entry-closure :: exit 0 (re-run after the build)",
"pnpm check:logger-receiver-detach :: exit 0",
"pnpm check:merge-driver :: exit 0",
"pnpm check:nul-bytes :: exit 0",
"pnpm check:objectql-double-limit :: exit 0",
"pnpm check:objectui-changeset :: exit 0",
"pnpm check:org-identifier :: exit 0",
"pnpm check:page-declaration-shape :: exit 0",
"pnpm check:pm-changeset-deadline-census :: exit 0",
"pnpm check:published-files :: exit 0 (re-run after the build)",
"pnpm check:published-readme-links :: exit 0",
"pnpm check:query-options-erasure :: exit 0 (union run exit 1; re-run after the build)",
"pnpm check:react-page-adapter-contract :: exit 0",
"pnpm check:refd-timer-probe :: exit 0",
"pnpm check:role-word :: exit 0",
"pnpm check:skill-identifier-liveness :: exit 0",
"pnpm check:slot-lookup :: exit 0",
"pnpm check:sourcemap-no-sources-content :: exit 0 (re-run after the build)",
"pnpm check:stack-collection-maps :: exit 0",
"pnpm check:swallow-census-controls :: exit 0",
"pnpm check:test-source-alias :: exit 0",
"pnpm check:tier-file-adoption :: exit 0",
"pnpm check:type-check-coverage :: exit 0",
"pnpm check:type-check-debt :: exit 0",
"pnpm check:vendor-version-stamps :: exit 0",
"pnpm check:watch-hint-literal :: exit 0",
"pnpm check:where-matcher :: exit 0"
],
"line_budget": "The PR's net against origin/main 45e206e after the merge: +754 / -58 over 7 files (git diff --shortstat origin/main...HEAD; dispatch-gates also reads 812 changed lines). This is identical to the pre-merge +754 / -58. The census count lines moved by value (124 -> 125, and so on) but not in number, so there is no line-count difference to name.",
"deviations": [
"The worktree had to be recreated. I removed it at the end of the previous round, as the role file's cleanup step says. For this round it was re-added on the existing local branch, whose head matched the remote head fef9354, and pnpm install --frozen-lockfile was re-run.",
"A full turbo build was needed: the recreated worktree had no dist for the packages two gates read. The first attempt failed in metadata-protocol's dts step, a missing declaration for @objectstack/metadata/errors while metadata's dist was being restored concurrently. The immediate retry succeeded (73/73, 72 cached). This is environment state and not this diff.",
"The push carried the regeneration commit together with the merge commit (one git push), not the merge commit alone.",
"origin/main moved to 20028df (#22893) after the merge. I checked it and did not merge it: it touches neither objectql nor the census page, and in non-test code it rewrites one isSystem read within runtime's callData (one removed, one added in the same symbol). GitHub reports PR #22891 mergeable: clean against current main."
]
}
objectstack-fleet commentedon Oct 11, 2026
Head moved: PR #22891
fef935481d→5ef9690d2d(merge ofmain), ACCEPT unchanged and still held ·domain:engineseat 2 ·session_01ADzJtzYTLUfgrRZHxkagkX· 2026-10-11T22:04Zdirtyagainstmain, with one conflict incontent/docs/permissions/system-context.mdx. Merge round 1 (report 6114315611) mergedorigin/main45e206e498as4f27320114(no rebase, no force-push), then regenerated the census in its own commit,5ef9690d2d. The PR is nowmergeable: clean.mainis the same 7 files, +754 / −58. Diffed against the reviewed net diff atfef935481d, the only differences are seven generated count values on the census page (each one higher, becausemaingained a read site). No product code, test or changeset line moved. Main's new census prose and this PR's row 29c are both present.5ef9690d2d: 33 success, 2 skipped, 0 failed.mergeable_stateand CI on the head of that moment.objectstack-fleet commentedon Oct 12, 2026
The objection window PR #22891 was held for is closed: #22892 is ruled A (comment 6115662038, batch #318 item 3, the maintainer's word verbatim 「其他同意?」), and the card went to
pm:queueas the execution card forresolvePredicateRelatedover amaster_detailFK. Nothing in that ruling changes PR #22891; thedomain:engineseat arms it for the queue on its ACCEPT (6113521641, head5ef9690d2d). Director seat, summon #37,session_01LqNgdPZB2Jnr5HpGbaqLeB, 2026-10-12T00:35Z. ⛔ Not a claim.docs(permissions): re-derive the census counts over the merged tree (#…
objectstack-fleet commentedon Oct 12, 2026
Landing armed: PR #22891 at
8d99c119d5·domain:engineseat 2 ·session_01ADzJtzYTLUfgrRZHxkagkX· 2026-10-12T01:41ZresolvePredicateRelated) is [Decision] security(objectql): a validation rule that reads one hop through a master-detail FK still reads the header elevated, so an unreadable header's answer varies with its stored state after ruling A #22892's own PR, not this one.main: merge round 2 (5ef9690d2d→8d99c119d5; one census conflict onsystem-context.mdx, counts re-derived bypnpm gen:system-context-census). Checked by this seat on GitHub's objects: the net diff againstmainis the same 7 files, +754 / −58. Against the reviewed net diff, the only differences are generated count values on the census page.mergeable_stateisclean.8d99c119d5: 35 runs, 33 success, 2 skipped, 0 failed; all seven required contexts aresuccess.ReadableIdsleaf once per parent object, fail closed, refuses it on write verbs and for D5's three classes, and marks the scope'policy'(D2, D5) #22861 (same file, serial).objectstack-fleet commentedon Oct 12, 2026
os-dev-report
{
"issue": 22519,
"status": "done",
"branch": "claude/issue-22519-unreadable-header-write",
"pr": "#22891",
"session": "session_01ADzJtzYTLUfgrRZHxkagkX — shared with the PM (mode:subagent); this run is identified by the branch",
"premise_still_valid": true,
"round": "merge round 2",
"head": "8d99c119d5833083858e9f36ca3ff1579641043a",
"summary": "Merge round 2: origin/main 7de0265 is merged into the branch, with no rebase, amend or force-push. Merge commit 2e8697b has parents 5ef9690 and 7de0265. The census regeneration is its own commit, 8d99c11 (pushed, now the PR head). Both checks were verified before resolving anything: (1) a local merge-tree named exactly one conflicted path, content/docs/permissions/system-context.mdx; (2) packages/objectql/src/engine.ts auto-merged with no overlap. Against merge base 45e206e, this branch's hunks sit at old lines 8550-9019, 13560 and 13844; main's single engine.ts commit 6373952 (#22894, transaction handle) sits at 4132-6109 and from 19520 on. GitHub reports PR #22891 mergeable: true, mergeable_state: clean. The ruled resolvePredicateRelated extension is not in this round. No product code changed.",
"conflict_resolution": "system-context.mdx: the only conflicting hunk was the census decomposition counts (property reads, unrelated-field reads, ExecutionContext.isSystem reads, behaviour-bearing). Main's prose (the changed row 58 text) and this branch's row 29c both auto-merged and are both kept. The counts took main's side, and pnpm gen:system-context-census then re-derived every count over the merged tree (125 sites / 58 files / 107 symbols; unrelated-field reads 5).",
"files_changed": {
"merge_commit_2e8697b10e_vs_main_7de0265fc7": [
".changeset/22519-unreadable-header-write.md",
"content/docs/permissions/system-context.mdx",
"packages/objectql/src/engine-reference-tenant-scope.test.ts",
"packages/objectql/src/engine-required-when-parent.test.ts",
"packages/objectql/src/engine-unreadable-master-detail-header.test.ts",
"packages/objectql/src/engine.ts",
"packages/objectql/src/validate-preview-parent.test.ts"
],
"merge_commit_2e8697b10e_vs_first_parent_5ef9690d2d": "222 files (+5777 / -4470): main's incoming work. Only content/docs/permissions/system-context.mdx needed a hand resolution, and engine.ts auto-merged.",
"regen_commit_8d99c119d5": [
"content/docs/permissions/system-context.mdx (3 count lines re-derived, +3 / -3)"
]
},
"tests": "os-regen-merge.sh: the first run stopped on the MIXED-file conflict as designed (exit 1). After the resolution was committed, the rerun read back the recorded base, skipped step 1, kept the hand resolution in step 2, and found nothing more to commit in step 3 (exit 0). | Main's census rows are kept. diff of origin/main:content/docs/permissions/system-context.mdx against the branch shows only row 29c plus the +1 count lines. The quoted-exact row 58 line from origin/main hits once in git grep against origin/main and once in the merged file. | node scripts/check-system-context-census.mjs: exit 0 (125 elevation read sites in 20 packages across 58 files, 107 symbols; the page cites 120 against 120 required). | Full turbo build at 8d99c11: the first attempt was cut by the foreground cap at 67/69 tasks (exit 124; main moved, so the cache missed). The background rerun finished 73/73 tasks, 67 cached (VERDICT command-exit 0). | Under os-verify-lock, VERDICT command-exit 0, at 8d99c11: pnpm --filter @objectstack/objectql typecheck (check:test-typecheck OK); vitest run on the PR's 4 test files: Test Files 4 passed (4), Tests 103 passed (103). | Gates: dispatch-gates --commands re-derived on 8d99c11 gave the same 98 commands as round 1. The union ran on 8d99c11 and all 98 exited 0 on the first run, with no re-runs. dispatch-gates --ran: 98 derived, 98 run, 0 NOT-MEASURED, 0 UNRUN, with all exit codes recorded.",
"mcp_calls": "0 — no MCP GitHub tool was called",
"api_writes": "1 REST request: POST /repos//issues/22519/comments (this os-dev-report), through scripts/pm/post-stamped.mjs and the fleet-write relay (1 repository_dispatch to the board). Not REST: 1 git push (2e8697b and 8d99c11 together). There were no PR body edits, labels, ready flips or auto-merge actions.",
"open_questions": [],
"out_of_scope_findings": [],
"gates": [
"node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0",
"node scripts/check-adr-0087-registration.mjs --self-test :: exit 0",
"node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0",
"node scripts/check-changeset-no-major.mjs --self-test :: exit 0",
"node scripts/check-ci-filter-parity.mjs :: exit 0",
"node scripts/check-closing-keyword-parity.mjs :: exit 0",
"node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0",
"node scripts/check-comment-mask-adoption.mjs :: exit 0",
"node scripts/check-comment-mask-adoption.mjs --self-test :: exit 0",
"node scripts/check-comment-mask-corpus.mjs :: exit 0",
"node scripts/check-doc-frontmatter.mjs :: exit 0",
"node scripts/check-doc-frontmatter.mjs --self-test :: exit 0",
"node scripts/check-doc-route-spelling.mjs --advisory :: exit 0",
"node scripts/check-doc-route-spelling.mjs --self-test :: exit 0",
"node scripts/check-docs-section-name.mjs :: exit 0",
"node scripts/check-docs-section-name.mjs --self-test :: exit 0",
"node scripts/check-dts-emitted.mjs --self-test :: exit 0",
"node scripts/check-empty-changeset.mjs --base origin/main :: exit 0",
"node scripts/check-empty-changeset.mjs --self-test :: exit 0",
"node scripts/check-engine-split-ratio.mjs --days 90 :: exit 0",
"node scripts/check-engine-split-ratio.mjs --self-test :: exit 0",
"node scripts/check-issue-citations.mjs :: exit 0",
"node scripts/check-keyed-text-bounds.mjs :: exit 0",
"node scripts/check-keyed-text-bounds.mjs --self-test :: exit 0",
"node scripts/check-platform-object-tenancy-census.mjs :: exit 0",
"node scripts/check-platform-object-tenancy-census.mjs --self-test :: exit 0",
"node scripts/check-plugin-teardown-shape.mjs :: exit 0",
"node scripts/check-plugin-teardown-shape.mjs --self-test :: exit 0",
"node scripts/check-registry-log-declared.mjs :: exit 0",
"node scripts/check-registry-log-declared.mjs --self-test :: exit 0",
"node scripts/check-rest-log-spy-declared.mjs :: exit 0",
"node scripts/check-rest-log-spy-declared.mjs --self-test :: exit 0",
"node scripts/check-section-landing-index.mjs :: exit 0",
"node scripts/check-section-landing-index.mjs --self-test :: exit 0",
"node scripts/check-system-context-census.mjs :: exit 0",
"node scripts/check-system-context-census.mjs --self-test :: exit 0",
"node scripts/check-undeclared-dep-imports.mjs :: exit 0",
"node scripts/check-undeclared-dep-imports.mjs --self-test :: exit 0",
"node scripts/docs-audit/check-affected-docs.mjs :: exit 0",
"node scripts/docs-audit/check-drift-comment.mjs :: exit 0",
"node scripts/pm/release-rehearsal-clone.mjs --self-test :: exit 0",
"node scripts/release-pending-publish.mjs --self-test :: exit 0",
"pnpm --filter @objectstack/lint run check:doc-formula-expressions :: exit 0",
"pnpm --filter @objectstack/lint run check:doc-security-posture :: exit 0",
"pnpm --filter @objectstack/spec run check:docs :: exit 0",
"pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0",
"pnpm --filter @objectstack/spec run check:empty-state :: exit 0",
"pnpm --filter @objectstack/spec run check:liveness :: exit 0",
"pnpm --filter @objectstack/spec run check:skill-examples :: exit 0",
"pnpm --filter @objectstack/spec run check:strictness-ledger :: exit 0",
"pnpm --filter @objectstack/spec run check:variant-docs :: exit 0",
"pnpm --filter @objectstack/spec run check:yaml-examples :: exit 0",
"pnpm check:changeset-gate-self-tests :: exit 0",
"pnpm check:corpus-claim-drift :: exit 0",
"pnpm check:cross-package-test-inputs :: exit 0",
"pnpm check:dispatcher-error-vocabulary :: exit 0",
"pnpm check:doc-anchors :: exit 0",
"pnpm check:doc-authoring :: exit 0",
"pnpm check:docs-audit-scope :: exit 0",
"pnpm check:docs-redirects :: exit 0",
"pnpm check:docs-single-h1 :: exit 0",
"pnpm check:docs-spec-enumerations :: exit 0",
"pnpm check:docs-transcript-drift :: exit 0",
"pnpm check:driver-memory-census :: exit 0",
"pnpm check:dts-closure :: exit 0",
"pnpm check:dual-build-cjs-loads :: exit 0",
"pnpm check:durability-log-level :: exit 0",
"pnpm check:engine-double-contract :: exit 0",
"pnpm check:error-status-conformance :: exit 0",
"pnpm check:gitlink-declared :: exit 0",
"pnpm check:issue-citations :: exit 0",
"pnpm check:lean-entry-closure :: exit 0",
"pnpm check:logger-receiver-detach :: exit 0",
"pnpm check:merge-driver :: exit 0",
"pnpm check:nul-bytes :: exit 0",
"pnpm check:objectql-double-limit :: exit 0",
"pnpm check:objectui-changeset :: exit 0",
"pnpm check:org-identifier :: exit 0",
"pnpm check:page-declaration-shape :: exit 0",
"pnpm check:pm-changeset-deadline-census :: exit 0",
"pnpm check:published-files :: exit 0",
"pnpm check:published-readme-links :: exit 0",
"pnpm check:query-options-erasure :: exit 0",
"pnpm check:react-page-adapter-contract :: exit 0",
"pnpm check:refd-timer-probe :: exit 0",
"pnpm check:role-word :: exit 0",
"pnpm check:skill-identifier-liveness :: exit 0",
"pnpm check:slot-lookup :: exit 0",
"pnpm check:sourcemap-no-sources-content :: exit 0",
"pnpm check:stack-collection-maps :: exit 0",
"pnpm check:swallow-census-controls :: exit 0",
"pnpm check:test-source-alias :: exit 0",
"pnpm check:tier-file-adoption :: exit 0",
"pnpm check:type-check-coverage :: exit 0",
"pnpm check:type-check-debt :: exit 0",
"pnpm check:vendor-version-stamps :: exit 0",
"pnpm check:watch-hint-literal :: exit 0",
"pnpm check:where-matcher :: exit 0"
],
"line_budget": "The PR's net against origin/main 7de0265 after the merge: +754 / -58 over 7 files (git diff --shortstat origin/main...HEAD; dispatch-gates also reads 812 changed lines). This matches the expected +754 / -58, with no difference: the census counts moved by value, not by line count.",
"deviations": [
"The worktree had to be recreated at the remote head 5ef9690, since it was removed after round 1, and pnpm install --frozen-lockfile was re-run. It was removed again after this round's push and report.",
"The first full-build attempt ran in the foreground and hit the 10-minute cap at 67/69 tasks (exit 124). The rerun ran in the background and was waited on with tail --pid; it finished 73/73 (67 cached).",
"The push carried the regeneration commit together with the merge commit (one git push).",
"PR state set by another actor, not changed by me: PR #22891 now reads draft: false, with auto_merge not armed. I did not flip it and did not touch it.",
"origin/main moved to 7dbb89d (#22909, lint only) after the merge. I checked it and did not merge it: it touches neither objectql nor the census page and changes no non-test isSystem read. GitHub reports mergeable: clean."
]
}
objectstack-fleet commentedon Oct 12, 2026
Landed: PR #22891 →
018b077fbf·domain:engineseat 2 ·session_01ADzJtzYTLUfgrRZHxkagkX· 2026-10-12T02:31Z018b077fbf8876c0fd5f46e66dcc551a4e74c895(one parent). ACCEPT 6113521641, contract review PASS 6113514249, arming note 6116255683.mainat that commit: six of the seven paths are byte-identical to the head8d99c119d5. The seventh isengine.ts, which also carries PR fix(objectql)!: an after* hook carrying a condition rolls its write back when the condition cannot be evaluated #22906 (merged a minute earlier, in a disjoint region); this PR's hunk landed identical.completedby the PR'sFixes #22519;pm:dispatchedcomes off in this act.