Skip to content

docs(skills): previous is null on insert in objectstack-data and objectstack-formula, no longer unbound - #24174

Merged
os-zhuang merged 2 commits into
mainfrom
claude/issue-23983-previous-null-on-insert
Oct 17, 2026
Merged

os-zhuang merged 2 commits into
mainfrom
claude/issue-23983-previous-null-on-insert

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #23983
Clause-②: no

What changed

Two published skill files told authors that previous is unbound on insert events and that insert-event conditions must therefore be written over record alone. Since PR #23971 (the runtime change for card 23910, merged as b25d98a46f) @objectstack/objectql binds previous to null on insert in validation rules and in declarative hook conditions — the binding a flow's start condition already had — so that text was false. Both files now state the binding and the guard:

  • on insert, previous is null in validation, hook conditions and flows: previous == null || … judges an insert, previous != null && … skips one;
  • a column read off it on insert (previous.status, previous.done) still has no value and still fails the write — guard the read with previous != null &&, not the event;
  • a write to an existing row whose prior state is not in hand keeps previous unbound and fails closed, so previous == null never reads an update as an insert.

The old advice (write insert-event conditions over record alone) was still safe but is no longer the rule; it is replaced by the null guard, and the abort semantics for a typo'd key or a column read off null are kept. A hook's ctx.previous is unchanged and its row in the ctx.* table is untouched.

Files (text only; nothing an author writes changes):

  • skills/objectstack-data/references/data-hooks.md — the previous bullet (was 「previous is UNBOUND where there is no prior state … insert events … write those over record alone」), the abort warning's example (「a previous reference on an insert」 → a column read off previous on an insert), the load-bearing clause (「the unbound-previous and has(...) bullets」 → 「the previous-on-insert and has(...) bullets」) and the authoring consequence (「never on an insert event」 → read previous only against null on insert).
  • skills/objectstack-formula/SKILL.md — the §5 scope-table insert row (was 「unbound — there is no prior state」), a new row for the existing-row-not-in-hand case, the abort note under the table (was 「Referencing previous where it is unbound … So write insert-event conditions over record alone」) and the legacy-translation note under OLD.x / ISCHANGED(x) (was 「exists only where previous is bound … On an insert event it is not」).
  • .changeset/23983-previous-null-on-insert.md — '@objectstack/skills': patch, Clause-②: no (the catalog ships as packages/skills/dist).

skills/** readings (lines and tokens, bd4276a91 → d0c7d6f13)

Token counts are the ratchet's own (node scripts/check-skills-token-ratchet.mjs, ceil(utf8 bytes / 4), release-stamp line excluded).

Reading before after ceiling
skills/objectstack-data/references/data-hooks.md lines 997 998 —
skills/objectstack-data/references/data-hooks.md tokens 10066 (headroom 0) 10059 (headroom 7) 10066
skills/objectstack-formula/SKILL.md lines 462 465 —
skills/objectstack-formula/SKILL.md tokens 5399 (headroom 598) 5511 (headroom 486) 5997
all skills/*/SKILL.md lines (sum of 10) 4389 4392 —
whole skills/** lines (65 files) 13332 13336 —
catalog authored tokens (ratcheted) 143907 144012 154888
bundle total tokens (whole shipped tree) 155093 155198 —

No ceiling moved. data-hooks.md sat at zero headroom, so the new sentences were paid for inside the file by deleting content, not by re-wrapping: the sentence 「Those are opposite failures, so "the condition said no" and "the platform could not work out what the condition says" are now different outcomes and the second one is loud」 restated what the paragraph's first sentence (does not degrade … it fails the write) and its protocol-17 history already say, and the four-line 「put a condition that reads previous on an update or delete event — either phase — never on an insert event」 rule is replaced by the shorter null-guard rule. Net −7 tokens on that file; objectstack-formula/SKILL.md spends 112 of its 598 headroom on the new row and the rewritten notes.

Verification (final head d0c7d6f13)

  • Derivation: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (no paths; change set from the merge base bd4276a91) → 44 families. Ran every one, exit code captured before any pipe; --ran reconciliation: 44 derived, 42 run (all exit 0), 2 NOT-MEASURED, 0 UNRUN.
    • NOT MEASURED locally (recorded exit 3, PREREQUISITE NOT MET — they load the built dist/ of 92 packages / @objectstack/objectql, which a three-text-file worktree does not build): pnpm check:dual-build-cjs-loads, pnpm check:lean-entry-closure. Both are whole-tree families named on every card; CI's Lint & Repo Gates builds first and runs them.
    • pnpm --filter @objectstack/lint run check:doc-formula-expressions first answered exit 3 (needs @objectstack/formula + @objectstack/lint built); after turbo run build --filter=@objectstack/formula --filter=@objectstack/lint it ran and exited 0 — that is the family that reads CEL expressions out of skills/**.
    • node scripts/check-skills-token-ratchet.mjs exit 0: 「54 authored bundle file(s) within their ceilings」 (the readings above).
    • pnpm check:role-word, pnpm check:corpus-claim-drift, pnpm check:skill-identifier-liveness, pnpm check:skill-compatibility, pnpm check:skill-frame-sync, pnpm check:doc-authoring, pnpm check:nul-bytes and the changeset gates (check-adr-0087-registration --base origin/main, check-changeset-no-major --base origin/main, check-empty-changeset --base origin/main, check:published-files, check:objectui-changeset, check:pm-changeset-deadline-census) all exit 0.
  • pnpm --filter @objectstack/spec build (under the shared verify lock, command-exit 0) then pnpm --filter @objectstack/spec check:generated → 「All 14 generated artifacts are up to date」; check:skill-docs ✓ and check:skill-refs ✓ — the SKILL.md change is body-only, so nothing was regenerated and no generated artifact is in this PR.
  • Ship-proof: pnpm --filter @objectstack/skills build → 「65 file(s) across 10 skill(s) copied from skills/** into dist/skills and read back byte-identical」; grep -rc "UNBOUND where there is no prior state" packages/skills/dist/ → 0 in every file; the new bullet is at packages/skills/dist/skills/objectstack-data/references/data-hooks.md:247 and the new table row at packages/skills/dist/skills/objectstack-formula/SKILL.md:307.
  • Control-character scan of the three changed files: none.
  • Premise re-checked on origin/main before editing: packages/objectql/src/validation/rule-validator.ts ruleScope() binds extra.previous = null when previous === null, and hook-wrappers.ts evaluates a declarative hook condition in that same scope (「previous is null on an insert event」); content/docs/data-modeling/formulas.mdx already states the null-on-insert row.

Acceptance notes

  • Round 2 (seat's claim amendment 6234558372, an in-place fix under the four conditions): skills/objectstack-formula/evals/cel-predicates-formulas.json line 27, eval case 3's expected_output, now says 「On insert previous is null: the previous.status read faults and aborts the write, so to run on inserts guard with previous != null &&.」 — the same statement this PR corrects, in a fixture that ships in the same package. Assertions untouched; 1046/1046 tokens, paid inside the same string; head 058737c52. (Round 1 had reported it as out of scope; the seat admitted it.)
  • Other unbound hits in skills/** are unrelated and still true: objectstack-formula/SKILL.md on a form-view visibleWhen's client-side unbound root falling back to true; objectstack-ai/SKILL.md and objectstack-query/rules/pagination.md use 「unbounded」 (numbers, queries).
  • data-hooks.md's ctx.previous row (「undefined on insert → use !ctx.previous」) is still true — only the CEL binding changed — and was left as is.
  • docs/adr/0058-expression-and-predicate-surface.md mentions bulk_write_previous_unbound as retired history; not published skill text, not touched.

维护者速读(草稿)

  • 改了什么:两份对外发布的 skill 文本(objectstack-data 的 data-hooks 参考页、objectstack-formula 的 SKILL.md)里「insert 时 previous 未绑定,只能用 record 写条件」的说法,改为运行时的真实行为:insert 时 previous 为 null,previous == null 判定 insert、previous != null && … 跳过 insert;insert 时读 previous.x 仍然报错拒写,要用 previous != null && 守住;只有「已存在的行但没拿到旧状态」才是未绑定。另附一份 @objectstack/skills patch changeset。
  • 为什么改:PR fix(objectql): bind previous to null on insert so a rule that reads it answers with its own message #23971 已把运行时改成 insert 时绑 null,这两处 skill 文本随之变假;按旧文本写的 AI 会绕开一个已不存在的错误,也写不出「只在 insert 时必填」这类规则。
  • 风险与代价(含回滚):纯文本,不改任何作者可写的键,也不改 hook 的 ctx.previous;token 棘轮 data-hooks 10066→10059(上限 10066 不动,靠删一句重复的解释句付账),formula SKILL.md 5399→5511(上限 5997)。回滚 = revert 这一个 commit。
  • 席位意见:
  • 你要做的:在此 PR 上给一个 APPROVED review;席位负责落地。

Generated by Claude Code

…objectstack-formula, no longer unbound

`data-hooks.md`'s `previous` bullet, abort note and authoring consequence, and
`objectstack-formula/SKILL.md`'s scope-table row, abort note and legacy-translation
note said `previous` is unbound on insert and told authors to write insert-event
conditions over `record` alone. The runtime binds it to `null` on insert in
validation rules and declarative hook conditions, so the text now states that
binding: `previous == null || …` judges an insert, `previous != null && …` skips
one, a column read off it on insert still faults, and only a write to an
existing row whose prior state is not in hand leaves `previous` unbound.

Token ratchet: data-hooks.md 10066 -> 10059 (ceiling 10066), formula SKILL.md
5399 -> 5511 (ceiling 5997); catalog authored total 143907 -> 144012.

Claude-Session: https://claude.ai/code/session_012PxNHU3dfov2hbpg9ycZ8q
Co-authored-by: Claude <noreply@anthropic.com>
…evious` is unbound on insert

Eval case 3's `expected_output` said the transition condition is 「Not usable on
insert events (unbound `previous` aborts the write)」. On insert `previous` is
`null`, so the sentence now says the `previous.status` read faults and aborts the
write and that a condition which must also run on inserts guards it with
`previous != null &&`. Assertions unchanged; the file stays at 1046/1046 tokens
(4184 -> 4181 bytes), paid by tightening the same sentence.

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

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 058737c52124fe32075f37f9f16f4a327ba7a890
Local-runs: none
Scope: skills/objectstack-data/references/data-hooks.md, skills/objectstack-formula/SKILL.md, skills/objectstack-formula/evals/cel-predicates-formulas.json + packages/objectql/src/validation/rule-validator.ts and packages/objectql/src/hook-wrappers.ts (the binding the text states; read at bd4276a91), the merged changeset b25d98a46:.changeset/23910-validation-previous-insert.md and packages/objectql/CHANGELOG.md L35–42 (the runtime truth), content/docs/data-modeling/formulas.mdx L211 (the docs row), .changeset/23983-previous-null-on-insert.md (the PR's own changeset)

Read 2026-10-17T13:53Z in seat by session_012PxNHU3dfov2hbpg9ycZ8q (marchtian, domain:skills#1), whose served model is the CONTRACT_REVIEW_TIER value (get_session last_served_model). Inputs: card #23983 (body + 7 comments: 6220637775, 6221580524, 6234215977, 6234266379, 6234524569, 6234558372, 6234675212), PR #24174 (body, 4-file list, diff +47/−34 against base bd4276a91, two rounds: d0c7d6f13 then the patch 058737c52), the head's check-runs at this write, origin/main bd4276a91. Read-only: nothing built, run or re-run; the dev's local gate runs and ship-proof are its evidence, not repeated.

① Derived judgments

The accept-set change: published skill text in three files of skills/** (shipped verbatim through @objectstack/skills dist), plus the owed changeset. No schema, no code. Each sentence judged against the runtime truth — the merged changeset of PR #23971: 「On insert, previous is now bound to null in validation rules and in declarative hook conditions … previous == null || … judges an insert, previous != null && … skips one. A column read off previous on insert (previous.stage) still has no value and still refuses the write … A write to an existing row whose prior state is not in hand keeps previous unbound and still fails closed」 — and formulas.mdx L211 (「null on insert … a column read off it there (previous.status) has no value and faults | validation, hook conditions and flows — null on insert」):

  • data-hooks.md, the previous bullet (L247–256 at the head). 「previous is null on insert … previous == null || … judges an insert and previous != null && … skips one; a column read off it there (previous.done) has no value and faults. previous is UNBOUND only for a write to an existing row whose prior state is not in hand, which fails closed rather than reading an update as an insert.」 — right on all three facts, in the changeset's own terms. The before*/multi: true sentence that followed is kept with its ADR-0058 Addendum II citation, re-anchored as 「not such a case」 (the unbound case) — right, the bulk dispatch binds previous per row.
  • data-hooks.md, the abort warning (L279–285). The example 「a previous reference on an insert」 becomes 「a column read off previous on an insert」 — right: a bare previous == null on insert now evaluates, only the column read faults. The dropped sentence 「Those are opposite failures, so "the condition said no" and "the platform could not work out what the condition says" are now different outcomes and the second one is loud」 restated what the paragraph's 「it fails the write」 already says; explanatory, not a rule — lossless for the rule set, and it pays the tokens (10066 → 10059, ceiling unmoved).
  • data-hooks.md, the authoring consequence (L287–290). 「on an insert event read previous only against null — a column read off it there is the mistake …」 — right, and it keeps the safety the old 「never on an insert event」 gave (the dispatch's 2(b): rewrite as the null guard, do not delete the safety).
  • objectstack-formula/SKILL.md §5 scope table (L306–307). The insert row: 「null — previous == null \|\| … judges an insert, previous != null && … skips one; a column read off it (previous.x) has no value and faults」 — right; the new row 「A write to an existing row whose prior state is not in hand | unbound — fails closed, so previous == null never reads an update as an insert」 — right, the changeset's last sentence. Table pipes inside the code span are escaped (\|\|), so the row parses.
  • §5 abort note (L311–318) and the legacy-translation note (L376–380). The first example becomes 「A column read off previous on an insert (previous.status, where previous is null)」 and the closing advice 「on an insert event read previous only against null, and put a column read off it behind previous != null &&」 — right. The OLD.x / ISCHANGED(x) note: 「has a value only where previous is a row … On an insert event previous is null, so the read … fails the write unless guarded by previous != null &&」 — right, and the card body named this note (「the note under the migration table restate it」), so it is in scope though the order enumerated only L306 and L312–314.
  • The eval fixture (round 2, cel-predicates-formulas.json case 3 expected_output). 「On insert previous is null: the previous.status read faults and aborts the write, so to run on inserts guard with previous != null &&.」 — right, and more exact than the seat's patch order: that case's own condition reads previous.status, so on an insert it IS the faulting shape; the order's 「aborts nothing」 held for a bare previous != null, not for this condition, and the dev reported the falsification instead of writing the order's sentence. The tightened wording elsewhere in the same string (「Writes it once as」, 「the post-write state (true on every later update too)」, 「per row on before*/after* update events, bulk too」, 「No ISCHANGED() function」) keeps every assertion-relevant token (previous.status, record.status, !=; none of ISCHANGED(, {previous.) and every fact; the assertions block is untouched; the file is valid JSON (json.load at the head), 55 lines before and after (the round-2 comment's 「69/69」 is a transcription slip the dev corrected in its terminal copy; the seat's own wc -l reads 55), 4184 → 4181 bytes, tokens 1046/1046 (ceiling unmoved).
  • Token ratchet (scripts/check-skills-token-ratchet.mjs, the dev's run at both heads, not re-run here): data-hooks.md 10066 → 10059 (ceiling 10066), formula SKILL.md 5399 → 5511 (ceiling 5997), the fixture 1046 → 1046 (ceiling 1046); no CEILINGS row moved; paid by deletion of restating text inside each file, not by re-wrap. Catalog: 13332 → 13336 lines across 65 files.
  • Other 「unbound」 hits in skills/** (the dev's grep, re-read by the seat's git grep -n unbound FETCH_HEAD -- skills): the form-view visibleWhen client-side unbound root, 「unbounded」 queries/numbers, and data-hooks.md's ctx.previous row (undefined on insert) — all still true; only the CEL binding changed. Right not to touch.
  • Main drift. Base bd4276a91 is origin/main's tip at this write; git merge-tree --write-tree origin/main FETCH_HEAD exits 0; the Version Packages PR's next re-stamp touches only the version: line of skills/*/SKILL.md.
  • Whole-package value density (read from an agent that loads either skill): the old text sent authors around a fault that no longer happens and hid the null idiom the runtime now offers; the new text gives the idiom, the one remaining fault and the one remaining unbound case, in the same number of bullets. Right.

Check-runs on 058737c52 at this write: 31 success, 6 skipped, 1 in_progress (Test Core (1/6)); none failed. Lint & Repo Gates, TypeScript Type Check, Build Core, Governed Surface Queue Guard, Check Changeset are success. Convergence is read at landing, not here.

② Semver level

  • .changeset/23983-previous-null-on-insert.md: '@objectstack/skills': patch, Clause-②: no with no arm, one summary line and one paragraph stating the binding and the null guard. @objectstack/skills is public (publishConfig.access: public; files[] = dist, built by packages/skills/scripts/sync-catalog.mjs copying skills/** byte for byte), so the changeset is owed and skip-changeset does not apply — right level, right clause; the PR body's line 2 Clause-②: no matches the claim (6234215977) and the changeset.
  • The changeset names the bullet, the scope-table row, the abort note and the legacy-translation note; it does not name the eval fixture sentence added in round 2. The fixture is the skill's own test data for the same statement, so the CHANGELOG entry stays true (nothing it says is false) and complete for an author; accepted as is, noted so the next changeset in this file's history reads it.
  • No model identifier in the PR title, body (one session-URL footer), the two commits (model-free trailer pairs) or any comment read.

③ Boundary flags

Dev reports 6234524569 (round 1) and 6234675212 (round 2): open_questions: [] both rounds; round-1 deviations D1–D7 and round-2 deviations, each answered:

  • R1-D1 base 697301491 → bd4276a91 at worktree creation; no conflict. Answered.
  • R1-D2 check:dual-build-cjs-loads and check:lean-entry-closure NOT MEASURED locally (exit 3, whole-tree builds); CI's Lint & Repo Gates runs them — success on this head. Answered.
  • R1-D3 the OLD.x / ISCHANGED(x) note rewritten beyond the order's enumeration — the card body names it; inside the declared file. Accepted.
  • R1-D4 shallow checkout, no ancestry claim made. n/a.
  • R1-D5 model-free trailers kept against the harness reminder. Right.
  • R1-D6 no label write (a changeset is owed). Right.
  • R1-D7 the round-1 report comment carries a literal angle-bracket email in a trailer quotation; read back byte-identical; not re-edited (a fifth write). Accepted; the os-dev-report marker and JSON are intact.
  • R1 OOS-1 the eval fixture sentence — absorbed by the patch round (claim amendment 6234558372) under the in-place fix's four conditions; no sub-issue.
  • R2 worktree recreated from the branch at d0c7d6f13 (Resume-from), nothing merged from main; the order's wording falsified for this fixture's own condition and the truth written instead (right, see ①); the round-2 comment's fixture line count 「69/69」 is wrong, 55/55 is right (seat-measured) — a record slip, not a diff defect; PR body not patched by the dev (⛔ per the order) — the seat patches the body's Acceptance notes in this act so the body no longer calls the fixture 「not changed here」.

Reviewer's own flags: none. mcp_calls 0 both rounds; api_writes three relay strokes in all (pr_create with the assignee, two report comments) plus three git push; no label write, no PATCH, no MCP write.

Implemented-by: claude/issue-23983-previous-null-on-insert
Reviewed-by: session_012PxNHU3dfov2hbpg9ycZ8q

VERDICT: PASS

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

维护者速读

改了什么:两个对外发布技能(objectstack-data、objectstack-formula)里说「previous 在 insert 上 unbound、insert 条件只能写 record」的四处文字,加 formula 技能 eval fixture 里同一句,改成运行时现状:insert 上 previous 为 null,previous == null || … 判 insert、previous != null && … 跳过 insert;只有读它的列(previous.status)才报错;只有「已存在行但旧值不在手」才 unbound 且失败关闭。附一个 @objectstack/skills patch changeset。token:data-hooks.md 10066→10059(顶 10066),formula SKILL.md 5399→5511(顶 5997),fixture 1046/1046;上限都没动。

为什么改:PR #23971(#23910,10-16 合并)把 insert 上的 previous 绑成 null,原技能文本随即为假;照旧文写元数据的 AI 会绕一个已不存在的故障,也用不上新的 null 写法。文档站 formulas.mdx 已先一步改了。

风险与代价(含回滚):纯文本 + changeset,不改任何键或行为;ctx.previous(hook 代码里的 undefined)那行有意不动,因为只有 CEL 绑定变了。回滚 = revert 本 PR 的两个 commit。

席位意见:ACCEPT。逐句对照 #23971 的 changeset 与 formulas.mdx L211 核过(见上方 ## Contract review PASS);dev 第 2 轮还纠正了席位补丁令里一处不准确的措辞(fixture 那条自身读列,insert 上会报错而非「无事」),写的是实测真相。

你要做的:对 PR #24174 给一个 APPROVED review(skills/** 是 Tier H)。批准后由席位落地(入队、合并),不需要其他动作。CI 在头 058737c52 上 31 绿 6 预期跳过,余 1 个分片收敛中,落地前席位再读一次。

席位核对

Seat domain:skills#1 · session_012PxNHU3dfov2hbpg9ycZ8q (marchtian) · read 2026-10-17T14:01Z · head 058737c52124fe32075f37f9f16f4a327ba7a890 · verdict: ACCEPT (Tier H — stays draft for an authorized approval; the seat lands after it)

Implemented-by: claude/issue-23983-previous-null-on-insert
Reviewed-by: session_012PxNHU3dfov2hbpg9ycZ8q

  1. Shape. Draft PR against main; body line 1 Fixes #23983, line 2 Clause-②: no (from claim 6234215977). The only closing keyword is the Fixes line; no other open card number sits beside a closing verb. Files: skills/objectstack-data/references/data-hooks.md (+22/−21), skills/objectstack-formula/SKILL.md (+15/−12), skills/objectstack-formula/evals/cel-predicates-formulas.json (+1/−1, round 2 under claim amendment 6234558372), .changeset/23983-previous-null-on-insert.md (new). Base bd4276a91 = origin/main tip; merge-tree exit 0. The seat patched the body's Acceptance notes in this act (the fixture bullet now records the round-2 fix).
  2. Premise and acceptance, read by the seat. Every rewritten sentence matches PR fix(objectql): bind previous to null on insert so a rule that reads it answers with its own message #23971's changeset and formulas.mdx L211 (contract review 6234710626 ①). The record-alone advice is kept as the null guard, not deleted. Token ceilings unmoved, paid by deletion inside each file; catalog 13332 → 13336 lines across 65 files (the two skills/** readings are in the PR body).
  3. Gates — check-runs pinned to head 058737c52 at this read: 31 success (Lint & Repo Gates, TypeScript Type Check, Build Core, Governed Surface Queue Guard, Check Changeset, every Lint · / Type Check · lane, Test Core 3–6/6, the three claim checks, Dogfood Regression Gate), 6 skipped, 1 in_progress (Test Core (1/6)), 0 failed; check-expected-skips.mjs --pr 24174 exits 3 while that shard runs (a reading of no reading) — re-read at landing. check-governed-merges.mjs --pr 24174: GOVERNED, Tier H (skills/** ×3), +47/−34 under the threshold.
  4. Changeset. @objectstack/skills patch, Clause-②: no, read sentence by sentence against the diff (contract review ②); Check Changeset success. No skip-changeset (rightly).
  5. Report hygiene. mcp_calls 0 both rounds; api_writes three relay strokes + three pushes; no PATCH by the dev; deviations answered in the contract review; the round-2 report's fixture line count 「69/69」 is a slip (55/55 measured by the seat).
  6. Out of scope. Round 1's finding was absorbed as the round-2 fix; the other unbound hits in skills/** are true and untouched; nothing filed.
  7. Landing (Tier H). In this act: needs-user-decision on the PR, review requested from os-zhuang and hotlong. Landing needs an authorized APPROVED review (the contract review PASS is on this head). Then the two pre-landing checks and the relay pr_ready + automerge_enable. subscribe_pr_activity live on this PR.

@os-zhuang
os-zhuang marked this pull request as ready for review October 17, 2026 14:06
@os-zhuang
os-zhuang added this pull request to the merge queue Oct 17, 2026
Merged via the queue into main with commit f1c0b57 Oct 17, 2026
51 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-23983-previous-null-on-insert branch October 17, 2026 14:22
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 tooling

Projects

None yet

3 participants