Skip to content

Commit 2db2f8d

Browse files
docs(adr): ADR-0139 reads Accepted, and D2 names the executor boundary as the composition seam (record half of the ruling on #22861) (#23035)
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` (#22707)", in the words of the E0 row on #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,「只返回你能读的父记录」)里的两处文字,不动任何代码。 - 第一处:D2 说明引擎在哪一步把这个叶子换成真正的查询条件。原来写的位置在中间件链之前,现在改为「最终查询交给数据库驱动之前的最后一步」。 - 第二处:状态行从「提议」改为「已接受」,注明是 #22707 合并时接受的。 **为什么改:** 你在 #22861 上已经裁了 A。原文的位置看不见六个使用方自己写入的条件(活动流、审计、评论、回复、附件、字段隐藏),因为它们都在中间件链里写入。照原文实现,这些条件会原样漏到数据库。这次只是把已裁的结论写进记录。状态行是之前就欠下的 E0。 **风险与代价(含回滚):** 纯文档,没有运行时影响,也不发布任何包。回滚就是撤回这一个 PR。代码 PR(E2)不等这份文字,这份文字也不等代码。 **席位意见:** **你要做的:** 看过这两处改动后,在本 PR 上点 APPROVE。 --- _Generated by [Claude Code](https://claude.ai/code/session_01ADzJtzYTLUfgrRZHxkagkX)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent 9f4b652 commit 2db2f8d

1 file changed

Lines changed: 14 additions & 7 deletions

File tree

‎docs/adr/0139-engine-internal-semi-join-leaf-readable-parent-ids.md‎

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
# ADR-0139: One engine-internal semi-join leaf — "the ids of object X this caller may read" — pushed down by ObjectQL, never authorable; ADR-0055 row (a) and ADR-0056's non-goal revisited for this one leaf
22

3-
**Status**: Proposed (2026-10-10). **This record declares; it implements nothing.** It becomes **Accepted** on the
4-
maintainer's approval (`docs/adr/**` is Tier H, Prime Directive #14); the execution cards under
5-
[Execution plan](#execution-plan-after-acceptance) are cut after acceptance and ⛔ never before it. Until then the
6-
platform stays in the ruling's letter D state, and letter C (a located 400 at the bound, after objectui#12081 item 8)
7-
is the `domain:services` lane's interim on [#22590](https://github.com/objectstack-ai/objectstack/issues/22590).
3+
**Status**: Accepted (2026-10-11), accepted by the merge that landed it on `main`
4+
([#22707](https://github.com/objectstack-ai/objectstack/pull/22707)); proposed 2026-10-10. **Amended** (2026-10-12):
5+
D2's position sentence names the executor boundary — after the middleware chain and the before-hooks, immediately
6+
before each driver call — in place of the seam where `lowerRelationConditions` runs, which precedes the chain D4's
7+
emitters write into (ruling [`6121741984`](https://github.com/objectstack-ai/objectstack/issues/22861#issuecomment-6121741984)
8+
on [#22861](https://github.com/objectstack-ai/objectstack/issues/22861), letter A). **This record declares; it
9+
implements nothing.** It became **Accepted** on the maintainer's approval (`docs/adr/**` is Tier H, Prime
10+
Directive #14); the execution cards under [Execution plan](#execution-plan-after-acceptance) are cut after acceptance
11+
and ⛔ never before it. Until then the platform stayed in the ruling's letter D state, and letter C (a located 400 at
12+
the bound, after objectui#12081 item 8) is the `domain:services` lane's interim on
13+
[#22590](https://github.com/objectstack-ai/objectstack/issues/22590).
814
**Decided by**: the maintainer, 「同意」 to the director seat's batch #312 item 2 (ruling
915
[`6097072172`](https://github.com/objectstack-ai/objectstack/issues/22590#issuecomment-6097072172), 2026-10-10T11:34Z):
1016
**A is the end state, its first deliverable an ADR**; B (an unbounded `$in`) and a raised cap are ⛔ not taken. The
@@ -124,8 +130,9 @@ any position but a `$in` comparand, the engine refuses it loudly. ⛔ No second
124130

125131
### D2 — ObjectQL composes the scope, once per parent object per request, fail closed
126132

127-
At the engine's own filter seam — where `packages/objectql/src/engine.ts#lowerRelationConditions` runs today, after
128-
ingress parsing and the comparand doors — every `ReadableIds` leaf is replaced by its composed form, still branded,
133+
At the engine's executor boundary — on the final AST, after ingress parsing, the comparand doors, the middleware chain
134+
(`packages/objectql/src/engine.ts#executeWithMiddleware`) and the before-hooks, immediately before each driver call of
135+
`find`, `findOne`, `count` and `aggregate` — every `ReadableIds` leaf is replaced by its composed form, still branded,
129136
before any driver sees it:
130137

131138
1. `canReadObject(P, caller)` false, a throw, or a service that exposes neither it nor `explain` ⇒ `$in: []`, FALSE on

0 commit comments

Comments
 (0)