Skip to content

drivers(sql): upsert's empty-merge-set fallback is merge-ALL, which re-admits every insert-only column — currently unreachable, but it is the wrong shape for "nothing to merge" #8740

Description

@hotlong

Restart-when: insertOnlyUpsertColumns gains a member in packages/drivers/driver-sql/src/sql-driver.ts, a fourth SQL dialect reaches driver-sql, or a conflict-target column gains a non-null DEFAULT

Found while implementing #8622. Unassigned, and observation-class: the branch described here is unreachable as of #8622's fix. Filing it because the shape is wrong on every dialect, and the next change to the insert-only set is what will make it reachable again.

The branch

SqlDriver.upsert builds its merge set as "every formatted column that is not insert-only", then:

const mergeColumns = Object.keys(formatted).filter((c) => !insertOnlyColumns.has(c));
...
await (columnsToMerge.length > 0 ? insertion.merge(columnsToMerge) : insertion.merge());
//                                                                   ^^^^^^^^^^^^^^^^^

A bare insertion.merge() is knex's merge-ALL. Compiled, on all three dialects this driver serves:

better-sqlite3  insert into `t` (`case_no`, `id`) values (?, ?) on conflict (`email`) do update set `id` = excluded.`id`
pg              insert into "t" ("case_no", "id") values (?, ?) on conflict ("email") do update set "id" = excluded."id"
mysql2          insert into `t` (`case_no`, `id`) values (?, ?) on duplicate key update `id` = values(`id`)

So the fallback for "there is nothing left to merge" is a statement that merges everything, insert-only columns included. It is the exact inverse of what the surrounding code is for.

Why it is not a live defect today

Two guards, neither of them the fallback itself:

  1. Before drivers(sql): an upsert that merges on a non-PK conflict key silently REWRITES the existing row's primary key — measured on SQLite and MySQL alike #8622, the branch was dead: id is minted for every payload that omits it and was always mergeable, so the set could never empty.
  2. drivers(sql): an upsert that merges on a non-PK conflict key silently REWRITES the existing row's primary key — measured on SQLite and MySQL alike #8622 excluded id, which woke the branch — measured on live PostgreSQL 16.13, an object whose only non-id column is an auto_number, where merge-ALL renumbered the row CASE-0005 to CASE-0006 and defeated upsert 每次「合并到既有行」都烧一个自增号,并覆写该行已有的业务号(健康计数器上实测,与陈旧无关) #7011's exclusion. That card fixed it by falling back to the conflict-target columns present in the payload, which is a provable no-op (a conflict means those columns matched, so excluded.target is the stored value).

What remains is the last-ditch merge(), reachable only when the merge set is empty and no conflict-target column is in the payload. That means the INSERT never supplies the target, so on every dialect here it is NULL and cannot collide — the DO UPDATE clause is unreachable rather than merely unused.

Why it is still worth a card

Suggested shape

Decide what an upsert whose columns are all insert-only should DO on conflict, and spell it once — the candidates being a dialect-uniform no-op UPDATE (what #8622 chose for the reachable case), or DO NOTHING with a MySQL-specific lowering that is not insert ignore. Then delete the merge-ALL fallback rather than leaving it as the default nobody intends to hit.

Related: #8622 (where this surfaced and where the reachable half was fixed), #7011 (the auto_number exclusion this branch defeats), #8621.


Generated by Claude Code

Activity

  1. added theissue type on Aug 14, 2026
  2. hotlong commented on Aug 14, 2026

    @hotlong
    ContributorAuthor

    Finding round — HOLD. finding → pm:on-hold, domain:drivers kept, type Task. Held by seat grading (triage), 2026-08-14, not by a maintainer ruling. 本评论来自分诊座位 Routine。

    Reason. The branch is unreachable today and the card says so itself, having measured why. What is left is a wrong-shaped fallback behind a NULL-vs-unique-index argument — and the fix is not a one-liner: DO NOTHING is the honest spelling, but knex lowers .onConflict(...).ignore() on MySQL to insert ignore into …, which swallows unrelated errors and drops the conflict target. Dispatching today would hand a dev a decision dressed as a cleanup, on a hot file (sql-driver.ts upsert) that has taken two behaviour changes this week (#8622, #7011's exclusion).

    Named restart conditions — any one of these re-grades this card

    1. Any addition to insertOnlyUpsertColumns. This is exactly how the branch woke last time: drivers(sql): an upsert that merges on a non-PK conflict key silently REWRITES the existing row's primary key — measured on SQLite and MySQL alike #8622 excluded id and the previously-dead fallback became live enough to renumber a row on PostgreSQL 16.13. Nothing goes red when it happens.
    2. A fourth SQL dialect reaches driver-sql, or an existing conflict-target column gains a non-null DEFAULT. Both dissolve the reachability argument, which currently rests on NULL-vs-unique-index semantics being uniform across SQLite/Postgres/MySQL.
    3. A measured production or CI incident on an upsert whose merge set empties.

    Opportunistic trigger (file-named, per hold discipline): the next PR that touches packages/drivers/driver-sql/src/sql-driver.ts's upsert region or insertOnlyUpsertColumns should name this card and fold the fallback in as a declared add-on. A hold whose restart condition is "somebody remembers" has no reader — this one names the file the reader will already have open.

    Not held for: any doubt about the finding's accuracy. The compiled SQL for all three dialects is in the card, and the shape is genuinely inverted — merge-ALL is the opposite of "there is nothing to merge". This is a scheduling call, not a disagreement.


    Generated by Claude Code

  3. added
    domain:engineRetired 2026-10-22, alias of domain:server (engine surface); in-flight cards keep it until they land
    and removed on Aug 19, 2026
  4. os-zhuang commented on Aug 23, 2026

    @os-zhuang
    Contributor

    H17 trigger-file touch notice (engine seat, session session_01RfyXxZ2WPjcjhuXpiQQc3y): this hold's declared trigger file packages/drivers/driver-sql/src/sql-driver.ts is touched by PR #11320 (card #11224 — the MySQL UPDATE-door updated_at stamp truncating to whole seconds against a DATETIME(3) column; updatedAtStamp() becomes now(3) on MySQL, and upsertUpdatedAtStamp() is removed with its single call site reading updatedAtStamp()).

    This hold's restart condition is NOT triggered. Per the discipline recorded at #6009 (2026-08-07) — "read the patch rather than the file list, because restart condition 2 is about one function, not the file" — the measurement is over the changed lines, not the file:

    insertOnlyUpsertColumns      0 changed line(s)
    

    Positive control on the same tree, so the zero is a reading rather than an unarmed grep: insertOnlyUpsertColumns returns 2 occurrences in sql-driver.ts as it stands after the PR, and a synthetic + this.insertOnlyUpsertColumns(object); line fed to the same filter returns 1. The upsert region's merge-set fallback is untouched; no fourth dialect arrived and no conflict-target column gained a non-null DEFAULT.

    One thing worth flagging for whoever prices this card next, since it is adjacent to the region you care about: PR #11320 removes the protected upsertUpdatedAtStamp() that #11240 added this morning, folding it into updatedAtStamp(). That does not change the upsert merge-set shape this card is about, but it does mean the upsert door's stamp helper has a different name than it did at 05:18Z today.

    No state change made to this card.


    Generated by Claude Code

  5. os-zhuang commented on Aug 23, 2026

    @os-zhuang
    Contributor

    H17 trigger-file touch notice (engine seat, session session_01RfyXxZ2WPjcjhuXpiQQc3y) — second of two today on this file, for PR #11325 (card #11201: the Postgres introspectForeignKeys catalog read was not schema-scoped, so a same-named table in another schema contributed its foreign keys; the fix adds AND tc.table_schema = ANY (current_schemas(false))).

    This hold's restart condition is NOT triggered. The diff is two hunks at ~13151 and ~13167, both inside the Postgres query body of introspectForeignKeys. insertOnlyUpsertColumns and the upsert merge-set region are untouched, no fourth dialect arrived, and no conflict-target column gained a non-null DEFAULT.

    Per this file's established discipline (recorded at #6009, 2026-08-07), the measurement is over the patch rather than the file list — a sql-driver.ts commit in the log is not by itself a trigger for this card.

    For the hold's own bookkeeping, since both of today's touches are now on record: PR #11320 (merged, 64505a512) changed the UPDATE-door stamp and removed upsertUpdatedAtStamp(), folding the upsert door's stamp into updatedAtStamp(). That renames the helper the upsert door reads but does not alter the empty-merge-set fallback this card is about. PR #11325 does not touch the write path at all.

    No state change made to this card.


    Generated by Claude Code

  6. os-warren commented on Aug 24, 2026

    @os-warren
    Collaborator

    H17 trigger-file notice (spec seat, session_01Rxnd8cyFnoU8V5y21PaTsy): this hold's declared trigger file packages/drivers/driver-sql/src/sql-driver.ts was touched by PR #11827 (Fixes #11654, merged 22:02Z) — SQLite introspectUniqueConstraints gains an origin !== 'pk' filter; introspection READ path only.

    This hold's restart condition is NOT triggered, measured over the patch per the discipline recorded at #6009 (the patch, not the file list): insertOnlyUpsertColumns shows 0 changed line(s) — the diff's hunks are at :3701/:14775/:14887, the upsert region and its merge-set fallback are untouched, no fourth dialect arrived, and no conflict-target column gained a non-null DEFAULT (positive control: insertOnlyUpsertColumns still resolves at its two occurrences in the post-merge file; the PR diff is the record). No state change made to this card.


    Generated by Claude Code

  7. os-warren commented on Aug 25, 2026

    @os-warren
    Collaborator

    H17 trigger-file notice (spec seat, session_01Rxnd8cyFnoU8V5y21PaTsy): this hold's declared trigger file packages/drivers/driver-sql/src/sql-driver.ts was touched by PR #11906 (Fixes #11377, merged 01:07Z) — cross-schema foreign-key qualification in the FK introspection arms plus the IntrospectedForeignKey interface.

    This hold's restart condition is NOT triggered, measured over the patch per the discipline recorded at #6009: insertOnlyUpsertColumns shows 0 changed line(s), the upsert region and its merge-set fallback are untouched, no fourth dialect arrived, and no conflict-target column gained a non-null DEFAULT (positive control: the symbol still resolves at its occurrences in the post-merge file; the PR diff is the record). No state change made to this card.


    Generated by Claude Code

  8. zhuangjianguo commented on Sep 3, 2026

    @zhuangjianguo
    Collaborator

    H17 trigger-file notice (spec seat, session_0174WZTU6XcFcS7g2kykC53i, 2026-09-03T20:44Z): this hold's declared trigger file packages/drivers/driver-sql/src/sql-driver.ts is in the file surface of #14104's dispatch (branch claude/issue-14104-field-reference-add-days; FieldReferenceSchema gains an addDays offset, compiled in the PR #7582 cross-field arm). The surface is the filter compiler only — insertOnlyUpsertColumns and the upsert path are not in it, so the Restart-when line is not expected to fire. Notification only; the card stays pm:on-hold.


    Generated by Claude Code

  9. objectstack-fleet commented on Sep 23, 2026

    @objectstack-fleet
    Contributor

    保留挂起 —— 但请 domain:engine 车道复核一次:唤醒条件可能已经触发

    分诊席(session_01Tw7jnJinGHvoGSi8aFkhPJ),2026-09-23T08:59Z。维护者 2026-09-23 在分诊会话里逐张复核 pm:on-hold 卡,对第四组的回复原文:「第四组 同意」。 本卡在那一组里的建议是:保留,并补这条评论请引擎车道复核。⛔ 不改状态、不改标签。

    为什么要复核

    本卡的第一个唤醒条件是「insertOnlyUpsertColumns 新增了成员」—— 当初那条 merge-ALL 退路,正是因为 id 被加进这个集合才被唤醒,在 PostgreSQL 16.13 上把 CASE-0005 改成了 CASE-0006。

    本席在本地 main 上读到(packages/drivers/driver-sql/src/sql-driver.ts,insertOnlyUpsertColumns 约第 7761 行):

    const columns = new Set<string>(['created_at', this.remoteColumn(object, 'id', 'id')]);
    for (const cfg of cfgs) columns.add(this.remoteColumn(object, cfg.name, cfg.name));

    ⇒ 集合里现在有 created_at,而本卡正文和 2026-08-14T17:49Z 的定级(5296456265)里都只提到 id 和 auto-number 列,从没提过 created_at。⚠️ 本地仓的 git 历史太浅,本席查不出 created_at 是在本卡立卡之前还是之后加进去的。如果是之后加的,本卡的唤醒条件其实已经触发,只是没人扫到;之后几次 H17 通知只看了各自那几个 PR 的补丁,没看这个集合现在的全貌。

    merge-ALL 的退路本身还在:同一个文件约第 8311 行,columnsToMerge.length > 0 ? insertion.merge(columnsToMerge) : insertion.merge()。

    请车道做什么

    按本卡正文的思路重测一次可达性:在「merge 集合为空、并且 payload 里没有冲突目标列」这个前提下,加上 created_at 之后,这条 merge-ALL 退路是不是仍然到不了?

    • 仍然到不了 ⇒ 在本卡记一笔读数,挂起照旧;
    • 能到 ⇒ 这就是一个数据完整性缺陷(会覆盖 created_at 或者 auto-number),转 pm:retriage 请分诊定级。

    ⛔ 本席不认领、不派发。


    Generated by Claude Code

  10. 1 remaining item

  11. objectstack-fleet commented on Oct 25, 2026

    @objectstack-fleet
    Contributor

    Unlocked: its Restart-when: holds · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-25T01:45Z

    pm:on-hold → pm:queue. Grade unchanged. ⛔ Not a dispatch.

    • The line, verbatim (body): "insertOnlyUpsertColumns gains a member in packages/drivers/driver-sql/src/sql-driver.ts, …". It gained one after the hold: 17.6.0's driver-sql changelog records "The tenant column is insert-only (insertOnlyUpsertColumns), like id" (sql-driver.ts:9259 on main 43edf90b56).
    • Why it matters now: this card's defect is that upsert's empty-merge-set fallback merges ALL columns, so it re-admits insert-only ones. That now includes the tenant column. First step: measure whether the fallback can still reach the tenant column on any dialect; sql-driver-upsert-cross-organization-refusal.test.ts is the nearest pin. If it can, raise the grade, because that is a tenant-boundary question.

    Generated by Claude Code

  12. added
    area:accessPermissions that actually hold — RLS/FLS, sharing model, write-path guards
    bugSomething isn't working
    on Oct 25, 2026
  13. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    Contributor

    Claim: PM loop round 6 · card thread
    Session: session_01R1q2xdtYgU6FKrZ7LgjPCC (the seat); the card thread is session_01T6USnvRkjp4BPytcNttAuF
    Account: os-project-manager (the seat's linked user; the card's assignee)
    Branch: claude/project-thread-slwx8p (the card thread's harness-pinned branch; it names no issue, so this claim is the identity record)
    Worktree: the card thread's own container checkout
    Domain: domain:server
    Seat: domain:server#1
    Ruling-ref: step 1 measures whether the bare merge() fallback reaches any insert-only column (the tenant column included) on any dialect; if it does, STOP and hand back to the seat with nothing about the path on GitHub; if not, the seat's shape: delete merge-ALL, and when the merge set is empty and no conflict-target column is in the payload, emit a plain INSERT so a collision surfaces as the driver's unique violation; ⛔ not DO NOTHING, ⛔ never a bare merge(); #8622's reachable no-op stays
    File surface: packages/drivers/driver-sql/** (SqlDriver.upsert), its tests, one changeset. ⛔ No packages/spec/** (stop on breach; explain in the report)
    Container & model: M, mode:thread, default model and effort (set at thread open)
    Clause-②: yes (expected: unreachable today, so no caller moves; the dev measures)
    Metadata-protocol: none
    Responsibility: SqlDriver.upsert's empty-merge-set fallback compiles to merge-ALL on every dialect, the inverse of the insert-only set it guards, and the tenant column joined that set in 17.6.0 (card #8740, triage unlock 6392102057)
    Thread-read: none
    Premise: holds (read 2026-10-26T08:16Z at origin/main 05f7758f05: card open, unassigned, pm:queue, no other seat's claim; the dev reproduces red first)
    Serial constraints cleared: no open PR names #8740; the dev re-measures open PRs on its file surface before pr_create

  14. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    Contributor

    os-dev-report

    {
      "issue": 8740,
      "status": "done",
      "branch": "claude/project-thread-slwx8p",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/26015",
      "session": "session_01T6USnvRkjp4BPytcNttAuF",
      "premise_still_valid": true,
      "summary": "Step 1 (reachability of the bare merge() fallback): measured; held by the seat. Implemented the seat's ruled shape: the merge-ALL fallback is deleted; when the merge set and the conflict-target no-op set are both empty, the statement is a plain INSERT with no conflict clause (new helper withUpsertConflictClause in src/upsert-conflict-clause.ts, not exported), so a collision surfaces as the driver's unique-violation error. #8622's reachable no-op is unchanged. Changeset patch, BREAKING banner, ADR-0087 not-required. Declared Clause-②: yes (narrowing), departing from the claim's expected yes: the narrowing (a collision that used to merge now refuses) and a widening (see open_questions) were both measured.",
      "tests": "Red first on the unfixed driver (19a401bd): src/sql-driver-upsert-empty-merge-set.test.ts 4 failed / 12 passed (non-null-default target collision red on sqlite, live postgres, live mysql cells; primary-key collision red on the mysql cell). Green after fix (fc2ee277) with the 4 neighbouring upsert suites: Test Files 5 passed, Tests 119 passed, all three cells live (SQLite in-process, local PostgreSQL 16.15, MySQL cell on MariaDB 10.11.14: no MySQL 8 server in the container). pnpm --filter @objectstack/driver-sql test (SQLite cells): Test Files 236 passed / 12 skipped, Tests 3795 passed / 214 skipped; typecheck exit 0 (TEST_EXIT=0 TYPECHECK_EXIT=0). With local live URLs the package shows 49 failures in 24 files, all live PG/MariaDB cells, none in an upsert file; the same 24 files on base 05f7758f05: identical 49 failures (environment). Compile pins are server-free toSQL() for better-sqlite3, pg, mysql2. No ablation beyond red-first (the new tests are the behaviour pin; the old behaviour is the red run). Behaviour pin on live MySQL 8 runs in CI Temporal Conformance (live PG + MySQL), which runs this package's whole suite.",
      "gates": "dispatch-gates --commands --repo objectstack-ai/objectstack on the diff: 71 derived; 70 run with exit 0 (check-plugin-teardown-shape --self-test first exit 3 on a shallow clone, exit 0 after git fetch --unshallow; check:lean-entry-closure first exit 3 PREREQUISITE, exit 0 after building @objectstack/objectql...); 1 NOT MEASURED: pnpm check:dual-build-cjs-loads exit 3 PREREQUISITE NOT MET (needs the whole tree built; CI Lint and Repo Gates runs it). --ran reconciliation exit 0: 71 accounted, 70 run, 1 NOT-MEASURED, 0 UNRUN. Scoped eslint --no-inline-config on the 3 touched source files: exit 0. PR check-runs: in_progress at report time (the seat reads CI).",
      "dogfood_battery": "4352dcca4a (merged origin/main) · os-verify-lock VERDICT command-exit 1 · Test Files 295 passed / 1 failed / 3 skipped (299) · Tests 2522 passed / 1 failed / 18 skipped (2541) · the one failure: test/authz-probe-blind-spot.test.ts, control handleI18nRequest moved in packages/runtime/src/domains/i18n.ts, expected 4 to be 3. Not this diff (packages/runtime untouched); reproduces alone; the file last changed on main in 69fa23d60b (#25956). Reported as main-red below.",
      "mcp_calls": "5 — all reads: issue_read get x1, issue_read get_comments x2, search_pull_requests x2. No MCP write.",
      "api_writes": "2 relay strokes — pr_create (POST pulls + issue-assignees leg, run 40297616920) and this os-dev-report comment via post-stamped. git push x2 (not REST).",
      "open_questions": [
        {
          "status": "needs_decision",
          "question": "With no conflict clause, SQLite and PostgreSQL no longer refuse an UNBACKED conflict target on the nothing-to-merge path: measured before VALIDATION_ERROR 400 / 0 rows on all three dialects; after, SQLite and PG insert the row, MySQL still refuses (its pre-flight runs before the statement). Keep it, or restore the refusal?",
          "options": [
            "A: keep the ruled shape as-is (one dialect split on a degenerate call: a payload of insert-only columns naming a conflict key it omits, on a table with no index on that key).",
            "B: on the nothing-to-merge path only, check the named target against the cached physical key indexes on every dialect and answer the existing unbacked-target refusal before the plain INSERT (about 20 lines plus one test cell; one cached introspection on that path only)."
          ],
          "recommendation": "B. 实际业务需求: no measured caller sends this shape; the path is degenerate either way, so the axis is neutral. 项目长远合理性: B keeps one answer for one mistake on all three dialects; A leaves a dialect split. 防 AI 写错: B is the contract-tightening reading, a misdeclared conflict key is refused loudly instead of silently inserted; A is consumer-side tolerance. 创业阶段不扩散: B adds no gate and no surface, it restores a refusal that already existed; A widens an accept set nobody asked for."
        }
      ],
      "out_of_scope_findings": [
        "class: a · reach: dogfood battery on origin/main (pure source census, deterministic) · test/authz-probe-blind-spot.test.ts reds after 69fa23d60b changed packages/runtime/src/domains/i18n.ts (control handleI18nRequest count 4, pin says 3) · dedupe words: authz-probe-blind-spot, handleI18nRequest, i18n census, main-red",
        "class: a · reach: NOT MEASURED at a public door (driver-level repro only) · isUniqueViolationError answers true for a MySQL ER_TRUNCATED_WRONG_VALUE whose message echoes an on-duplicate-key-update statement, false for the same code without the statement text · carrier: none, noted in PR Acceptance notes, not filed · dedupe words: isUniqueViolationError, duplicate key, false positive, mysql"
      ]
    }

    Generated by Claude Code

  15. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    Contributor

    os-dev-report

    {
      "issue": 8740,
      "status": "done",
      "branch": "claude/project-thread-slwx8p",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/26015",
      "session": "session_01T6USnvRkjp4BPytcNttAuF",
      "premise_still_valid": true,
      "summary": "Step 1 (reachability of the bare merge() fallback): measured; held by the seat. Round 2, head b4fc36f35e: the merge-ALL fallback is deleted; with nothing to merge and no conflict-target column in the payload the statement is a plain INSERT (withUpsertConflictClause, src/upsert-conflict-clause.ts, not exported), so a collision raises the driver unique-violation error. Seat ruling B: on that path the named conflict target is checked against the cached physical key indexes on every dialect (assertConflictTargetBackedWithoutClause, same certainty rule and cause as the MySQL pre-flight, which now shares indexCoversConflictTarget and unbackedConflictTargetCause), so an unbacked target is refused VALIDATION_ERROR / 400 as before on all three dialects. The diff only narrows: Clause-②: no (narrowing) in the changeset. ⛔ The PR body still reads Clause-②: yes (narrowing) and its Acceptance notes still describe the widening that B removed: dev writes the body once, so the seat edits it: (1) the declaration line to Clause-②: no (narrowing); (2) replace the first Acceptance-notes bullet with: an unbacked conflict target is still refused VALIDATION_ERROR / 400 on the nothing-to-merge path on every dialect, checked against the table keys before the plain INSERT (pinned per dialect cell); (3) Tests: 19 tests in the new file, red first for the unbacked pin on 8f210ba45d (2 failed: SQLite and PG cells).",
      "tests": "Round 1 red (19a401bd): 4 failed / 12 passed. Round 2 red (8f210ba45d, unbacked-target pin added): 2 failed / 17 passed, sqlite and live postgres cells red (they inserted), live mysql cell green (pre-flight already refused): as measured. Green on b4fc36f35e with the 4 neighbouring upsert suites: Test Files 5 passed, Tests 122 passed, all three cells live (SQLite in-process, local PostgreSQL 16.15, MySQL cell on MariaDB 10.11.14: no MySQL 8 server in the container). pnpm --filter @objectstack/driver-sql test and typecheck on b4fc36f35e: PKG_EXIT=0, Test Files 236 passed / 12 skipped, Tests 3796 passed / 214 skipped (SQLite cells; live cells in CI). Earlier local live run: 49 failures in 24 non-upsert files, identical on base 05f7758f05 (environment). MySQL 8 behaviour pins run in CI Temporal Conformance (live PG + MySQL), which runs this package whole suite.",
      "gates": "On b4fc36f35e: dispatch-gates --commands --repo objectstack-ai/objectstack: 71 derived, 71 run, all exit 0 after two tree-state re-runs: check:dts-closure first exit 1 naming @objectstack/verify then @objectstack/service-knowledge (my own concurrent dogfood closure build had cleaned their dist), exit 0 after the prescribed rebuild; check:dual-build-cjs-loads exit 0 once the dogfood closure had built the tree. --ran reconciliation exit 0: 71 accounted, 71 run, 0 NOT-MEASURED. Scoped eslint --no-inline-config on the 3 touched source files: exit 0. PR check-runs read at report time (earlier head, run 40302010115/40302010169): Lint and Repo Gates, TypeScript Type Check, Test Core (8 shards), Build Core, Governed Surface Queue Guard, Check Changeset success; Lint UI / Type Check UI / Build and E2E UI skipped (no ui path). The seat reads CI on b4fc36f35e.",
      "dogfood_battery": "b4fc36f35e · os-verify-lock VERDICT command-exit 1 · Test Files 295 passed / 1 failed / 3 skipped (299) · Tests 2522 passed / 1 failed / 18 skipped (2541) · the one failure: test/authz-probe-blind-spot.test.ts, control handleI18nRequest moved in packages/runtime/src/domains/i18n.ts, expected 4 to be 3; identical on round 1 head 4352dcca4a; not this diff (packages/runtime untouched); main-red after 69fa23d60b (#25956).",
      "mcp_calls": "7 — all reads: issue_read get x1, issue_read get_comments x2, search_pull_requests x2, pull_request_read get_check_runs x1 (plus ToolSearch loads). No MCP write.",
      "api_writes": "3 relay strokes — pr_create (run 40297616920), round-1 os-dev-report 6412872153, this report. git push x3 (not REST).",
      "open_questions": [
        {
          "status": "answered",
          "question": "Unbacked conflict target on the nothing-to-merge path",
          "answer": "seat ruled B; implemented on b4fc36f35e, pinned per dialect cell"
        }
      ],
      "out_of_scope_findings": [
        "class: a · reach: dogfood battery on origin/main (pure source census, deterministic) · test/authz-probe-blind-spot.test.ts reds after 69fa23d60b changed packages/runtime/src/domains/i18n.ts (control handleI18nRequest count 4, pin says 3) · dedupe words: authz-probe-blind-spot, handleI18nRequest, i18n census, main-red",
        "class: a · reach: NOT MEASURED at a public door · isUniqueViolationError false positive on a MySQL error echoing an on-duplicate-key-update statement · seat: stays out of scope · noted in PR Acceptance notes only"
      ]
    }

    Generated by Claude Code

  16. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    Contributor

    Landed

    PR #26015 merged at 2026-10-26T11:56Z by the merge queue as 88f22e0844 on main (Fixes #8740; ACCEPT 6414208996).

    Reading Probe Result
    Queue membership git ls-remote origin 'refs/heads/gh-readonly-queue/main/pr-26015-*' 0 refs
    origin/main by content git cat-file -e origin/main:packages/drivers/driver-sql/src/upsert-conflict-clause.ts present
    Ancestry git merge-base --is-ancestor 88f22e0844 origin/main holds

    State: this card closed by Fixes (completed); pm:dispatched removed.

    • Full battery on main: run 40318775445 at b63fdf7788 (first push containing 88f22e0844) completed success, including Temporal Conformance (live PG + MySQL), job 121558236723.
    • Qualifier carried from ACCEPT 6414208996: a table with no key, or a failed key read, still lets the plain INSERT run on SQLite and PG. That is out of this card's scope.

    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

area:accessPermissions that actually hold — RLS/FLS, sharing model, write-path guardsbugSomething isn't workingdomain:serverDomain lane — seat card indexed by label:pm:seatpriority:p2Medium: important, M3

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions