Skip to content

docs(adr): ADR-0139 reads Accepted, and D2 names the executor boundary as the composition seam (record half of the ruling on #22861) - #23035

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-22861-adr-0139-d2-executor-boundary
Oct 12, 2026
Merged

os-zhuang merged 1 commit into
mainfrom
claude/issue-22861-adr-0139-d2-executor-boundary

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Part of #22861
Clause-②: no

Tier H, draft only. The diff touches docs/adr/**, a governed surface (Prime Directive #14). This PR lands only on an APPROVED review by an account in GOVERNED_APPROVERS. ⛔ No seat readies it, queues it or arms auto-merge on it.

This is the record half of the ruling 6121741984 on #22861 (letter A, maintainer 「22861 objectui#12191 同意。」). It is docs only, one file: docs/adr/0139-engine-internal-semi-join-leaf-readable-parent-ids.md, +14 / -7. E2's code PR does not wait for this text, and this text does not wait for the code.

What changes

  1. D2's position sentence. The text that sat at lines 127-129 on main named the seam "where lowerRelationConditions runs today, after ingress parsing and the comparand doors". Per the ruling, it now names the executor boundary: on the final AST, after ingress parsing, the comparand doors, the middleware chain (packages/objectql/src/engine.ts#executeWithMiddleware) and the before-hooks, immediately before each driver call of find, findOne, count and aggregate. The rest of D2 is unchanged: steps 1 to 3, the composed form, and the uncomposed refusal at the driver.
  2. E0's status line. The record read "Proposed (2026-10-10)". It now reads "Accepted (2026-10-11), accepted by the merge that landed it on main (docs(adr): ADR-0139 — one engine-internal semi-join leaf, "the ids of object X this caller may read" (ruling A on #22590 item 3) #22707)", in the words of the E0 row on ADR-0139 execution: the engine-internal semi-join leaf across spec, engine, drivers and consumers (E0–E7 coordination) #22788. The approving review on that PR was submitted 2026-10-11T06:02Z, and the merge followed at 06:38Z (a2e94c2a05). One Amended (2026-10-12) note names the D2 change and the ruling. Two verbs in the same paragraph move to the past tense ("becomes" to "became", "stays" to "stayed"), because the paragraph described the time before acceptance.

Nothing else in the record moves.

Why

The old position ran before the middleware chain. All six D4 consumers write their leaf inside that chain (object-scoped middlewares writing ctx.ast.where), and beforeFind hooks rewrite the AST inside the executor. So a seam at the old position could never see a D4 leaf. The previous dev measured this on 246edf5b39 (os-dev-report 6119740461). The director seat re-read it on 74c4b3435e4d for the ruling. On 9432bac077 the positions are unchanged: find calls resolveWhereTokens at engine.ts line 13160, the chain at 13162, beforeFind at 13174 and driver.find at 13178.

Gates

node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derives 19 families on this diff, and all 19 were run at d43e9a99ed. Exit codes were captured before any pipe.

  • Exit 0: check-adr-links (and --self-test), check-adr-symbol-anchors (and --self-test; its verdict line reads "2317 anchors across 142 records resolve"), check-ci-filter-parity, check-closing-keyword-parity (and --self-test), check-comment-mask-corpus, check:adr-anchors, check:cross-package-test-inputs, check:doc-authoring, check:driver-memory-census, check:gitlink-declared, check:nul-bytes, check:pm-governed-merges, check:pm-prior-rulings, check:refd-timer-probe and check:watch-hint-literal.
  • @objectstack/lint check:doc-formula-expressions: the first run exited 3 (PREREQUISITE NOT MET, lint was not built), so it measured nothing. After turbo run build --filter=@objectstack/formula --filter=@objectstack/lint (under os-verify-lock, VERDICT command-exit 0), the rerun exited 0.
  • Reconciliation: dispatch-gates --ran reports "19 derived famil(ies) accounted for — 19 run, 0 NOT-MEASURED (a DERIVED zero)".

Changeset: none. docs/adr/** publishes nothing from any package. The dispatch forbids label writes, so skip-changeset is not applied here. The seat applies it, or Check Changeset stays red; it is not one of the seven required contexts.

维护者速读(草稿)

改了什么: 只改一份 ADR(ADR-0139,「只返回你能读的父记录」)里的两处文字,不动任何代码。

为什么改: 你在 #22861 上已经裁了 A。原文的位置看不见六个使用方自己写入的条件(活动流、审计、评论、回复、附件、字段隐藏),因为它们都在中间件链里写入。照原文实现,这些条件会原样漏到数据库。这次只是把已裁的结论写进记录。状态行是之前就欠下的 E0。

风险与代价(含回滚): 纯文档,没有运行时影响,也不发布任何包。回滚就是撤回这一个 PR。代码 PR(E2)不等这份文字,这份文字也不等代码。

席位意见:

你要做的: 看过这两处改动后,在本 PR 上点 APPROVE。


Generated by Claude Code

…y as the composition seam

The status line reads Accepted (2026-10-11), accepted by the merge that
landed the record on main, with an Amended note for D2. D2's position
sentence now names the executor boundary: on the final AST, after the
middleware chain and the before-hooks, immediately before each driver
call of find, findOne, count and aggregate. The seam it named before
(where lowerRelationConditions runs) precedes the middleware chain that
D4's emitters write into, so no D4 leaf could reach it.

Claude-Session: https://claude.ai/code/session_01ADzJtzYTLUfgrRZHxkagkX
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: d43e9a99ed85c9daa44c871ca75e91b2368279af
Local-runs: none

Read-only review of the one-file diff origin/main...refs/review/pr-23035 (merge-base 3071d3e989; origin/main at edecd44851 at the final read; the ADR is unchanged on main since the merge-base), the PR body, labels and its empty comment and review lists, the head's check-runs, the card's ruling 6121741984 (letter A and "The record" paragraph), the decision analysis 6119820661, the dev report 6123413708, the seat answer 6123453723, card #22788's E0 row, PR #22707's reviews and merge data, and on origin/main the full ADR-0139 and packages/objectql/src/engine.ts around executeWithMiddleware, find, findOne, count and aggregate. GOVERNED_APPROVERS was read from scripts/pm/check-governed-queue-guard.mjs on origin/main.

① Derived judgments

The diff. One file, docs/adr/0139-engine-internal-semi-join-leaf-readable-parent-ids.md, +14 / -7, two hunks: the status paragraph (branch lines 3 to 13) and D2's position sentence (branch lines 133 to 136). The whitespace-insensitive diffstat is the same +14 / -7, git diff --check is clean, the final newline is kept, and the file goes from 285 to 292 lines. Nothing outside the two hunks moves.

D2's amended sentence says what the ruling orders. The ruling's letter A: "compose once on the final AST, at the executor boundary", composing "immediately before each driver call, after the middleware chain and the before-hooks" on find, findOne, count and aggregate; its "The record" paragraph: "the one position sentence at :127-129, naming the executor boundary after the before-hooks and immediately before each driver call". The branch's sentence (lines 133 to 136) reads: "At the engine's executor boundary — on the final AST, after ingress parsing, the comparand doors, the middleware chain (packages/objectql/src/engine.ts#executeWithMiddleware) and the before-hooks, immediately before each driver call of find, findOne, count and aggregate — every ReadableIds leaf is replaced by its composed form, still branded, before any driver sees it:". Every element the ruling names is present, the four verbs by name; "ingress parsing, the comparand doors" is carried over from the old sentence and is still true (both run in resolveWhereTokens, before the chain).

It names the real seam. Read on origin/main edecd44851: executeWithMiddleware (engine.ts:5870) runs the object's applicable middlewares and then the executor innermost. find: resolveWhereTokens at :13160 (which runs lowerRelationConditions through resolveRelateThenLowerWhere, :12750), then executeWithMiddleware :13162, beforeFind :13174, driver.find :13178. findOne: :13450, :13452, beforeFind :13468, driver.findOne :13471. count: :18971, :18983, driver.count :18986 (no before-hook runs; the fallback for a driver without count re-enters this.find, so it meets find's own boundary). aggregate: :19396 and :19430, then :19438, then drv.aggregate :19495 or driver.find :19539, two exclusive driver paths, both inside the executor, no before-hook. So the old seam, lowerRelationConditions, precedes the chain on every read verb, and the new sentence names the last engine position before each driver call. On count and aggregate "after the before-hooks" is vacuous, exactly as in the ruling's own wording; not a misstatement. These positions equal the dev's readings on 9432bac077.

The rest of D2 is unchanged. Steps 1 to 3 (lines 138 to 147), the composed form { object: P, scope } (line 146) and the uncomposed refusal at the driver (lines 149 to 152) are byte-identical to main; the second hunk replaces only main's lines 127 to 129.

No contradiction with D1, D4 or D5. D1 (lines 128 to 129) keeps the leaf legal on the same four verbs and refused on a write verb, in a having, or off a $in comparand; the new D2 names the same four verbs and moves no refusal. D4 (line 183) still has the consumers' branches "ANDed into the read's where as today", inside the middleware chain; with composition now after the chain, the D2/D4 contradiction the ruling names is gone. D5 (lines 201 to 220) names no position; its three refusal classes stand. lowerRelationConditions appears exactly once in the whole record, at line 6, as the seam replaced; E2's plan row (line 287) says "the engine seam composes the leaf", position-neutral. No sentence still places composition at lowerRelationConditions.

The status line is true. PR #22707 carries one review: os-zhuang, APPROVED, on 2026-10-11 at 06:02 UTC, on its head f87ef2345a; it was merged by os-zhuang on 2026-10-11 at 06:38 UTC as a2e94c2a05; os-zhuang is in GOVERNED_APPROVERS. "Accepted (2026-10-11), accepted by the merge that landed it on main (#22707)" is the E0 row's wording on #22788, with #22707 as a link; "proposed 2026-10-10" keeps the original date. The PR body's two times for #22707 match the review and merge data.

The Amended note is accurate and its link is right. "Amended (2026-10-12)": the ruling comment 6121741984 was posted on 2026-10-12 on issue #22861, letter A; the note's link issues/22861#issuecomment-6121741984 resolves to it. The note's description of the change, the executor boundary after the middleware chain and the before-hooks, immediately before each driver call, in place of the seam where lowerRelationConditions runs, "which precedes the chain D4's emitters write into", matches the engine reading above and the ruling's own reading.

The two tense changes are faithful. "becomes Accepted" to "became Accepted", and "stays in the ruling's letter D state" to "stayed": both sit in the paragraph the E0 row covers, both describe the pre-acceptance period as past, neither moves a decision. One residual reading: "Until then the platform stayed in the letter D state" can be read as the platform having left letter D at acceptance, which it has not (E2 onward are unlanded); that reading is inherited from the original "Until then", the next clause keeps letter C as the present interim, and the ruling's "E0's status line may ride in it" covers the paragraph. Not a defect of this diff.

Nothing else moves. Two hunks only; the head is one commit over the merge-base; mergeable_state is clean at the final read.

② Semver level

Docs only, under docs/adr/**; no package publishes. Clause-②: no is right and skip-changeset is the right disposition: no changeset is owed. At the final read the label is on the PR, and the newest Check Changeset run on the head is skipped (an earlier run, before the label, failed and is superseded).

③ Boundary flags

  • Tier H, stated. The PR body says: Tier H, draft only, lands only on an APPROVED review by an account in GOVERNED_APPROVERS, and no seat readies it, queues it or arms auto-merge on it. At the final read: draft, auto_merge null, no reviews, no comments, no requested reviewers; Governed Surface Queue Guard is success. This record does not lift the landing; the maintainer's APPROVED review does.
  • Dev deviations that concern this PR. (a) The tense change: declared in the dev report and in the PR body; judged faithful above. (b) skip-changeset left to the seat because the dispatch forbids label writes: present on the PR at the final read. (c) The code PR was not built (the case-set stop); by the ruling "E2's code PR does not wait for the text", and the seat answer puts the record PR on its own track, so it has no bearing on this verdict. (d) The commit carries the model-free trailer pair; the PR body carries the session-URL footer and Part of #22861 with no closing keyword, and the "Part-of PR must not also close its card" check is success.
  • Check-runs on the head. 43, all completed; none pending. Of the seven required contexts: Lint & Repo Gates, TypeScript Type Check, Test Core, Dogfood Regression Gate and Governed Surface Queue Guard are success; Build Core and Temporal Conformance (live PG + MySQL) are skipped on a docs-only diff.
  • Not in scope of this PR, carried by the seat answer: D2 step 2's lowering parenthetical, the deny sentinel's spread copies (spec: declare the RLS deny sentinel once in @objectstack/spec, imported by plugin-security and objectql (ADR-0139 D2 step 2; #22861 sub-question 2 ruled (i)) #23009), and the write refusal's position. The ruling amends only the position sentence, and the record text is otherwise untouched, which is the right scope.

Implemented-by: claude/issue-22861-adr-0139-d2-executor-boundary
Reviewed-by: session_01ADzJtzYTLUfgrRZHxkagkX

VERDICT: PASS

Adopted by domain:engine#2 (session_01ADzJtzYTLUfgrRZHxkagkX) at 2026-10-12T11:46Z. The record came from an isolated at-tier reviewer. Its transcript shows read-only tool use: REST reads, a fetch into a review ref and repository reads, and its only writes were its own scratch files. This record does not lift the landing. The PR is Tier H, stays a draft, and lands only on an APPROVED review by an account in GOVERNED_APPROVERS.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

维护者速读

改了什么: ADR-0139 里两处文字,只改文档,不动代码:

  1. D2 的「组合点」位置那一句,改成「在执行器边界:最终查询上,中间件链和前置钩子之后,每次真正查库之前」。这是你在 ADR-0139 E2: the engine composes the ReadableIds leaf 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 裁定的 A。
  2. 状态行从「Proposed」改成「Accepted (2026-10-11),由 docs(adr): ADR-0139 — one engine-internal semi-join leaf, "the ids of object X this caller may read" (ruling A on #22590 item 3) #22707 合入」,即 ADR-0139 execution: the engine-internal semi-join leaf across spec, engine, drivers and consumers (E0–E7 coordination) #22788 上一直欠着的 E0,顺带补一条 Amended (2026-10-12) 记录这次改动。

为什么改: 原文把组合点放在中间件链之前,可它自己点名的六个使用方(活动流、审计、评论等)都在中间件链里才写入叶子,原文自相矛盾。你已裁 A,代码按新位置实现,这份 ADR 要跟上,否则以后读 ADR 的 agent 会照旧位置写错。

风险与代价(含回滚): 纯文字,不影响运行时。契约复核 PASS:新句逐项对上裁决,其余段落一字未动,全文不再有把组合点放在旧位置的句子。回滚就是 revert 这一个文档提交。

席位意见: 建议批准。它只把你已裁的结论和早已成立的接受状态写进记录,没有新增任何决定。

你要做的: 在 PR #23035 上点 Approve。批准后席位负责落地。

@os-zhuang
os-zhuang marked this pull request as ready for review October 12, 2026 12:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/s skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants