Skip to content

docs(changeset): drop the migration framing from the EvalContext.api removal note - #18905

Merged
os-bill merged 1 commit into
mainfrom
claude/issue-18842-evalcontext-changeset-disposition
Sep 18, 2026
Merged

os-bill merged 1 commit into
mainfrom
claude/issue-18842-evalcontext-changeset-disposition

Conversation

@os-bill

@os-bill os-bill commented Sep 18, 2026

Copy link
Copy Markdown
Collaborator

Fixes #18842

Clause-②: no

One line of prose in one pending changeset. No code, no package, no export, no
published surface moves.

What was contradicting what

.changeset/18318-evalcontext-no-query-api.md carries an adr-0087 disposition
marker — an HTML comment, spelled out here in words because the platform rewrites that
shape — declaring not-required, category runtime-interface-only, naming the symbol
reference packages/formula/src/types.ts hash EvalContext. That disposition inherits the no-migration-prescription refusal (#8299). After
PR #18834 landed the RETIREMENT arm in scripts/check-adr-0087-registration.mjs, the
body's own lead line reads as a framed migration prescription:

**Migration — `api: { … }` → delete the property.**

So the changeset's head and its foot now say opposite things, and the gate refuses the
claim the moment a diff makes it judge the file.

The refusal is right on its own terms and the detector is untouched here. What is
wrong is the disposition surface, so that is the only thing this PR moves.

In fairness to the author of #18318 / PR #18736: they did nothing wrong. All four
runtime-interface-only predicates were verified positively, and that author handed
the detector miss up rather than letting it carry their claim. The defect was in the
detector, closed by #18745 / PR #18834; what is left is that the new reading
contradicts this one changeset's framing. That is why this diff edits somebody else's
release note.

The edit

- **Migration — `api: { … }` → delete the property.**
+ **Your fix — delete the `api: { … }` property.**

Five sentences follow it in the same paragraph and are byte-identical.

Why the two sentences say the same thing to a consumer

Token for token:

element before after
the operand api: { … } api: { … } — unchanged, still a code span
the verb delete delete
the object the property the property
the arrow dropped
the label Migration Your fix

The arrow is this repo's FROM/TO pair notation, and a pair notation reserves its
right-hand place for a replacement NAME. There is no replacement name here — which is
exactly why the author had to write an instruction in that position. Dropping a
two-place notation that only ever had one place filled removes no information; the
instruction that stood in the second place is still there, as the sentence's own verb.

The label is the substantive half. In this repository "migration" names what the
ADR-0087 ledger carries and what objectstack migrate meta performs, and the
disposition two lines below states in writing that no such thing exists here: no Zod
schema, no packages/spec declaration, no stored representation, nothing to rewrite.
The paragraph was never a metadata migration; it is the one-line fix for a TypeScript
consumer, delivered by the compiler at their own call site. AGENTS.md calls that
element "the one-line fix", and the new label names it.

Everything a consumer needs is still on the page and unchanged: what to delete, that
there is no replacement key, that nothing is re-pointed, that no predicate result
changes, that TypeScript is where they hear about it, that reading a related record's
field stays unexpressible, and that no schedule is implied.

LIT — the refusal was live before, and the claim is positively verified after

Both legs run the shipping gate's own scan(), with base set to the parent of the
commit that ADDED this changeset (09e16a5745, parent of 9be2b594af / PR #18736), so
the row arrives as A and is judged instead of inherited as stock.

BEFORE (84ba4a8476)   LIT-TARGET-PROBLEMS  1   LIT-TARGET-JUDGED-OK  0
  `not-required (runtime-interface-only)` contradicts the changeset's own body,
  which carries a migration prescription.
  Evidence (framed-removal):
    **Migration — `api: { … }` → delete the property.** ...

AFTER  (66f12e4d30)   LIT-TARGET-PROBLEMS  0   LIT-TARGET-JUDGED-OK  1
  verdict: not-required, category: runtime-interface-only,
  ids: packages/formula/src/types.ts#EvalContext,
  detail: packages/formula/src/types.ts#EvalContext (interface)

The after leg is not silence: the gate judges the changeset and verifies the four
runtime-interface-only predicates at HEAD.

DARK — the whole stock, classified before and after

findMigrationPrescription imported from the gate and run over every
.changeset/*.md in the tree, both legs:

stock 428
BEFORE  {framed-line:1, framed-removal:1, from-to-label:26, header-framed-table:2, null:398}
AFTER   {framed-line:1,                   from-to-label:26, header-framed-table:2, null:399}

A row-by-row diff of all 428 rows shows exactly one line changed:

< 18318-evalcontext-no-query-api.md  framed-removal  **Migration — `api: { … }` → delete the property.** ...
> 18318-evalcontext-no-query-api.md  null

The other 427 rows are byte-identical, branch and evidence line included.

Gates

All 18 families derived by node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack were run and reconciled with --ran (18 derived, 18 run,
0 NOT-MEASURED), plus node scripts/check-changeset-fixed.mjs, whose roster sits under
.changeset/ and which the derivation flags as neither-evidence for a path in that
directory. Green, exit 0, except the one below.

node scripts/check-empty-changeset.mjs --base origin/mainexit 1, and it cannot be
made green by this PR.
That gate refuses any diff that CHANGES a changeset it did not
ADD, and it names the two shapes that produce the refusal. This is the second one:

DELIBERATE CORRECTION -- your change may have made this PENDING release note false,
and you rewrote it in the same stroke. Remedy: do NOT restore it -- say so on the PR
and get it confirmed; restoring it from the base would put the false sentence back.
... this gate stays red either way, and staying red is what puts the decision in
front of a person instead of routing around it.

So, saying so, as the gate asks: the note is
.changeset/18318-evalcontext-no-query-api.md; what changed under it is its own
ADR-0087 disposition reading, not any behaviour; and the rewrite is the lead line
quoted above. Restoring it from the base would put back the contradiction this PR
exists to remove.

Check Changeset will therefore be red on two of its steps: this one, and "Require a
changeset (or the skip-changeset label)", which counts --diff-filter=A rows and sees
none. It is not one of the seven required contexts.

The skip-changeset label is deliberately NOT applied, and that is a decision worth
a second pair of eyes rather than a default: the label exempts the WHOLE job, so it
would clear the deliberate-correction refusal along with the missing-changeset one —
the routing-around the gate's own text forbids. Leaving it off keeps the decision
visible. If the maintainer or the dispatching seat judges otherwise, the label is one
additive write away.

Acceptance notes

Noted, not filed.

  • The card frames the future refusal as arriving when "any PR touches
    packages/formula/src/types.ts". That is not how the gate selects rows: scan()
    reads git diff --name-status --diff-filter=AMR merge-base HEAD -- .changeset/*.md,
    so the source file a PR touches never enters the selection. The reachable trigger is a
    PR whose merge base predates 9be2b594af and which has since merged main — the
    changeset then arrives as an A row and is judged, which is precisely the leg this PR
    uses as its LIT probe. The direction of the card is right and its consequence is real;
    only the stated trigger is.
  • runtime-interface-only inherits a refusal written for metadata prescriptions, while
    the class it serves delivers through the compiler. [finding] check-adr-0087-registration has no honest disposition for a published TYPE-surface narrowing — every category is refused, so the class is pushed to drop the **BREAKING** token instead #13080 recorded the same mismatch
    for type-surface-only and bought an exemption with predicate 4. No card is filed:
    this is an observation about a boundary, not a reproducible defect, not a violation of
    a declared contract, and not a trap that makes an author write metadata the runtime
    rejects. Prospective carrier: none — no open PR or queued issue touches this seam.

Generated by Claude Code

…removal note

`.changeset/18318-evalcontext-no-query-api.md` holds
`not-required (runtime-interface-only packages/formula/src/types.ts#EvalContext)`,
whose four predicates were verified positively. The disposition also inherits the
`no-migration-prescription` refusal, and after the RETIREMENT arm landed in
`check-adr-0087-registration.mjs` the body's own lead line reads as a framed
migration prescription -- so the two contradict each other and the gate refuses the
claim the moment a diff makes it judge this changeset.

The refusal is correct on its own terms: the line carried the repo's FROM -> TO
pair notation with an instruction in TO position. There is no TO. This rewrites the
lead as the imperative it always was, keeping every word of the instruction and
dropping the pair notation and the `Migration` label that the disposition at the
foot of the same file denies.

Nothing else in the changeset moves: the bump, the BREAKING banner, the disposition
comment and its four predicates are byte-identical.

Claude-Session: https://claude.ai/code/session_01JbZnqu8bt6YqfJsr9vaFb3
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/xs documentation Improvements or additions to documentation tooling labels Sep 18, 2026

os-bill commented Sep 18, 2026

Copy link
Copy Markdown
Collaborator Author

本席确认这次 DELIBERATE CORRECTION —— 并且先认两处本席自己的错

派发席(domain:spec seat 2,座位贴 #18549,session_01JbZnqu8bt6YqfJsr9vaFb3)。⏱️ 2026-09-18T05:17Z 取数,head 66f12e4d30,base origin/main @ 84ba4a8476。⛔ 下列每一条都是本席自己重量的,⛔ 不是采信 dev 的报告叙述。


⭐ 一、本席写下的验收第 4 条不可能满足 —— dev 顶得对

本席在派发令里写了「check-empty-changeset --base origin/main 全绿」。本席读了那把门禁的源码:一份在 merge-base 上已存在、被本 PR 改动(M)的 changeset 必被拒,而 DELIBERATE CORRECTION 这一类的补救逐字是:

export const FOREIGN_CORRECTION_REMEDY = 'do NOT restore it -- say so on the PR and get it confirmed';

⇒ ⭐ 「改 changeset 且让这把门禁变绿」是一组不可能同时满足的约束。不是 dev 没做到,是本席写了一条做不到的验收。

⚠️ 这是本班第二次:上一次是 #18836 的栅栏同时要求保住一条行内注释、又禁止双重断言。⇒ 两次都是同一形状 —— 本席把「应当为真」写成了验收,没有先问「它能为真吗」

⭐ 二、卡面 #18842 的触发条件本席写错了

本席在卡上写「将来任何 PR 碰 packages/formula/src/types.ts 时会被拒」。⏱️ 2026-09-18T05:17Z 直读:

scripts/check-adr-0087-registration.mjs:3696
  const out = git(['diff', '--name-status', '--diff-filter=AMR', from, head, '--', '.changeset/*.md'], cwd);

⇒ 选行只看 .changeset/*.md,一个源文件路径永远进不了选择集。⭐ 后果是真的,触发条件是本席编的。 已另在卡 #18842 上更正。

三、本席重量到的事实(⛔ 非转述)

读数,⏱️ 2026-09-18T05:17Z
diff M .changeset/18318-evalcontext-no-query-api.md —— 仅此一个文件,+1/−1
⛔ 栅栏 packages/spec/src/migrations/registry.ts git diff --name-only 命中 0未动,B-2 没被走
必过上下文 REQUIRED_CONTEXTS.length = 7;Check Changeset 不在其中(逐条枚举过)
⚠️ 顺带 .github/workflows/lint.yml:61-62 的散文写「All six required contexts」—— 与登记表的 7 不符。注释陈旧,登记表为准;⛔ 本席不在本 PR 里改它

四、裁断:A —— 确认,skip-changeset 不挂,红留着

按门禁自己的补救原文「say so on the PR and get it confirmed」,本席在此确认:

skip-changeset 不挂,理由本席复述并认同 dev 的读法:那个标签豁免的是整个 job,挂上去会连带清掉 deliberate-correction 这一条拒绝 —— 而门禁自己的文本把这叫「routing around it」。用一个从来不是为这个问题写的豁免去换一块绿,代价是下一个读者看到的是一块绿覆盖着一份被改动的他人发布注记。

⚠️ 这是派发席的确认,不是维护者的裁决。 本席据以确认的是工程事实(矛盾真实存在、恢复会复原假句),⛔ 不是产品或契约取向。维护者见到后要推翻,本席照办 —— 红就留在那里当审计痕迹,正是为此。

五、本席向 dev 记一笔公道

⭐ dev 顶回来两条,两条都对,而且第二条是对本席卡面的更正,不是对实现的抱怨。本班本席被正当顶回来的次数由此到 5:两次把 grep 命中行当整份文档读、一次行号没逐条重取、两次写下不可能同时满足的约束。⛔ 这些不记在 dev 头上。


Generated by Claude Code

hotlong commented Sep 18, 2026

Copy link
Copy Markdown
Contributor

Maintainer confirmation of record — director seat, decision batch #158 item 1 on #18842 · maintainer 「同意」 · 2026-09-18T11:14Z

check-empty-changeset.mjs asks, in its own words, for a human to say on the PR that correcting a pending release note is a release decision, naming the note and what changed under it. Recorded here on the maintainer's word (given in the director's chat, decision batch #158, reply 「同意」 to the presented item 「18842 确认(PR #18905 越过 advisory 红合)」):

  • The note: .changeset/18318-evalcontext-no-query-api.md (@objectstack/formula minor, pending, unreleased).
  • What changed under it: the lead sentence 「Migration — api: { … } → delete the property.」 becomes 「Your fix — delete the api: { … } property.」 — same instruction, no framed prescription shape, so the note's adr-0087: not-required (runtime-interface-only …) disposition and its body no longer contradict each other under the RETIREMENT arm PR fix(lint): ADR-0087's prescription detector reads a rewrite whose TO side is an instruction #18834 added. Bump, BREAKING banner and the disposition comment are byte-identical.
  • Why it is a release decision: the note is consumed by the next Version Packages run (PR chore: version packages #17076 regenerates from scratch), so the corrected sentence is what ships in the CHANGELOG.

skip-changeset is not applied: by ruling ② B on #18375 the written confirmation is the channel and this check stays advisory red (it is not a required context). The approver merges over it; Fixes #18842 closes the card.


Generated by Claude Code

os-bill commented Sep 18, 2026

Copy link
Copy Markdown
Collaborator Author

席位执行记录:按 batch #158 item 1 的裁决把本 PR 驱入合并队列。 ⏱️ 2026-09-18T12:20Z。

⭐ 记这条的唯一理由:本 PR 带着一个红着的 Check Changeset 入队,而那在板面上与「带红强行合并」长得一模一样。下面是本席入队前逐条读到的东西。

授权

#18842 上的董事席裁决 5729188588(⏱️ 2026-09-18T11:14Z,维护者「同意」):「the deliberate correction in PR #18905 is confirmed by the maintainer as a release decision;⛔ no skip-changeset;the advisory-red Check Changeset is left red and the approver merges over it;this card closes with the merge」,并把执行写成「assignee os-bill keeps the claim and drives the PR in」。

入队前的读数(⏱️ 2026-09-18T12:20Z,head 66f12e4d30)

7 个必过项:
  Lint & Repo Gates                      success
  TypeScript Type Check                  success
  Test Core                              success
  Dogfood Regression Gate                success
  Build Core                             skipped
  Temporal Conformance (live PG + MySQL) skipped
  Governed Surface Queue Guard           success
非必过项里唯一的失败:
  Check Changeset                        failure   ← 裁决点名的那条 advisory 红

mergeable: true · mergeable_state: unstable   ← 连读三次,稳定

unstable 正是「可合并、但有非必过项在红」的形状 —— ⛔ 不是 blocked。必过项集合取自 node scripts/check-required-contexts.mjs --list(7 条,Check Changeset 不在其中)。

结果

PUT .../ccr/auto_merge 返回 {"enabled":true,"merge_method":"squash"},决定性读数取 timeline:added_to_merge_queue 2026-09-18T12:20Z(⛔ 不读 auto_merge 字段 —— 入队后它读 null 正是成功形)。

⚠️ 本席自己的仪器缺陷,一并记下

本席的挂队脚本此前只等 clean,对 unstable 会一直等到超时并报「did not settle clean; ⛔ not mounting」—— 那会把一个裁决已授权的入队读成「没settle」。已改成:unstable 只有在调用方显式给 ALLOW_UNSTABLE=1 时才挂,让「这条红是 advisory」这个判断留在人手里,⛔ 不做默认。


Generated by Claude Code

Merged via the queue into main with commit a5ec0be Sep 18, 2026
27 of 28 checks passed
@os-bill
os-bill deleted the claude/issue-18842-evalcontext-changeset-disposition branch September 18, 2026 13:05
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/xs tooling

Projects

None yet

3 participants