diff --git a/.agents/skills/verify-dms-database/playground/src/bridge-schema.ts b/.agents/skills/verify-dms-database/playground/src/bridge-schema.ts index 8bf6a91..62ff187 100644 --- a/.agents/skills/verify-dms-database/playground/src/bridge-schema.ts +++ b/.agents/skills/verify-dms-database/playground/src/bridge-schema.ts @@ -102,5 +102,5 @@ export async function startBridgeSchemas(): Promise { const members = schema.instance().table("members"); if ((await members.count()) > 0) return; const row: MemberRow = { _id: "member_1", ["constructor"]: "ctor value", note: "plain column" }; - await members.insert([row]).run(); + await members.insert([row], { conflict: "update" }).run(); } diff --git a/.agents/skills/verify-dms-database/playground/src/browse-fixtures.ts b/.agents/skills/verify-dms-database/playground/src/browse-fixtures.ts index c064ac4..502a672 100644 --- a/.agents/skills/verify-dms-database/playground/src/browse-fixtures.ts +++ b/.agents/skills/verify-dms-database/playground/src/browse-fixtures.ts @@ -20,6 +20,6 @@ export async function seedBrowseFixtures(): Promise { .insert([ { _id: "acc_ada", handle: "ada", password: ACCOUNT_PASSWORD, card_number: ACCOUNT_CARD, display_name: ACCOUNT_NAME_LONG }, { _id: "acc_bob", handle: "bob", password: "$argon2id$v=19$stored-hash-of-bob", card_number: "enc:v1:stored-cipher-of-bob", display_name: "Bob" }, - ]) + ], { conflict: "update" }) .run(); } diff --git a/.agents/skills/verify-dms-database/playground/src/metrics-schema.ts b/.agents/skills/verify-dms-database/playground/src/metrics-schema.ts index 7b5b5d5..5724ba9 100644 --- a/.agents/skills/verify-dms-database/playground/src/metrics-schema.ts +++ b/.agents/skills/verify-dms-database/playground/src/metrics-schema.ts @@ -36,5 +36,5 @@ export async function seedMetrics(): Promise { band: `band-${(index % 5) + 1}`, value: (index * 7) % 101, })); - await readings.insert(rows).run(); + await readings.insert(rows, { conflict: "update" }).run(); } diff --git a/.agents/skills/verify-dms-database/playground/src/shop-schema.ts b/.agents/skills/verify-dms-database/playground/src/shop-schema.ts index e24eb0a..676bdf0 100644 --- a/.agents/skills/verify-dms-database/playground/src/shop-schema.ts +++ b/.agents/skills/verify-dms-database/playground/src/shop-schema.ts @@ -156,7 +156,7 @@ async function seedTable( ) { const target = schema.instance(region).table(table); if ((await target.count()) > 0) return; - await target.insert(rows).run(); + await target.insert(rows, { conflict: "update" }).run(); } /** Fills each region of the shop once, on a database that has none of it. */ diff --git a/.agents/skills/verify-dms-database/playground/src/vault-schema.ts b/.agents/skills/verify-dms-database/playground/src/vault-schema.ts index 3d97371..486dbab 100644 --- a/.agents/skills/verify-dms-database/playground/src/vault-schema.ts +++ b/.agents/skills/verify-dms-database/playground/src/vault-schema.ts @@ -81,8 +81,8 @@ export async function seedVault(): Promise { if (!schema) return; const notes = schema.instance().table("plain_notes"); if ((await notes.count()) > 0) return; - await notes.insert([{ _id: "note_1", body: "first note" }]).run(); - await schema.instance().table("parents_registry").insert([{ _id: "reg_1", label: "registry one" }]).run(); - await schema.instance().table("parents_links").insert([{ _id: "lnk_1", registry_id: "reg_1" }]).run(); - await schema.instance().table("wide_records").insert([{ _id: "wide_1", registry_id: "reg_1", c01: "a", tail_marker: "tail" }]).run(); + await notes.insert([{ _id: "note_1", body: "first note" }], { conflict: "update" }).run(); + await schema.instance().table("parents_registry").insert([{ _id: "reg_1", label: "registry one" }], { conflict: "update" }).run(); + await schema.instance().table("parents_links").insert([{ _id: "lnk_1", registry_id: "reg_1" }], { conflict: "update" }).run(); + await schema.instance().table("wide_records").insert([{ _id: "wide_1", registry_id: "reg_1", c01: "a", tail_marker: "tail" }], { conflict: "update" }).run(); } diff --git a/AGENTS.md b/AGENTS.md index d3c3b65..49f710d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -102,6 +102,7 @@ Verify a boundary against the imports a developer or agent would plausibly write | String-keyed object tables are read through own keys only | `antelopejs/no-inherited-key-lookup` | | A type guard checks each member it narrows to; keys with `Object.hasOwn` | `antelopejs/no-presence-only-type-guard` | | A type guard checks the nested elements and values it claims | review; no tool | +| A startup read does not decide an insert another replica can race | `antelopejs/no-read-then-insert` | | `Object.assign` writes no `unknown`, `any` or mistyped value over a field | `antelopejs/no-unsafe-object-assign` | | Every file type-aware lint reads is listed by a tsconfig | `antelopejs/require-tsconfig-include` | | Params ≤ 5, function ≤ 120 lines, file ≤ 500 lines, depth ≤ 4, complexity ≤ 20 | `eslint/max-*`, `eslint/complexity` | @@ -129,9 +130,9 @@ Verify a boundary against the imports a developer or agent would plausibly write | A CI gate reads `needs.` only of jobs in its `needs` | `antelopejs-sync --check` | | Entry-only rules exempt no tracked outsider | `antelopejs-sync --check` | | A DMS layer's `build/backend-boundary.ts` is the pack's plugin | `antelopejs-sync --check` | -| No `skipLibCheck` in the root tsconfig or one `typecheck` or `build` uses | Reported by `antelopejs-sync` (note only) | -| `build` skips the lib check only over what `typecheck` checks | Reported by `antelopejs-sync` (note only) | -| `release` runs `typecheck` | Reported by `antelopejs-sync` (note only) | +| No `skipLibCheck` in the root tsconfig or one `typecheck` or `build` uses | `antelopejs-sync --check` | +| `build` skips the lib check only over what `typecheck` checks | `antelopejs-sync --check` | +| `release` runs `typecheck` | `antelopejs-sync --check` | | A test names the wrong implementation it catches | review; no tool | diff --git a/package.json b/package.json index a7a7833..3994eef 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "@antelopejs/dms-frontend": ">=0.10.0 <0.11.0", "@antelopejs/interface-data-api": ">=0.6.1 <1.0.0", "@antelopejs/mongodb": "^1.6.2", - "@antelopejs/tooling-configs": "^0.5.0", + "@antelopejs/tooling-configs": "^0.5.1", "@types/chai": "^5.2.3", "@types/mocha": "^10.0.10", "@types/node": "^24.0.0", diff --git a/playground/src/shop-schema.ts b/playground/src/shop-schema.ts index e24eb0a..676bdf0 100644 --- a/playground/src/shop-schema.ts +++ b/playground/src/shop-schema.ts @@ -156,7 +156,7 @@ async function seedTable( ) { const target = schema.instance(region).table(table); if ((await target.count()) > 0) return; - await target.insert(rows).run(); + await target.insert(rows, { conflict: "update" }).run(); } /** Fills each region of the shop once, on a database that has none of it. */ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e214840..587c562 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -43,8 +43,8 @@ importers: specifier: ^1.6.2 version: 1.6.2(socks@2.8.8) '@antelopejs/tooling-configs': - specifier: ^0.5.0 - version: 0.5.0(knip@6.34.0)(oxfmt@0.66.0)(oxlint@1.81.0(oxlint-tsgolint@7.0.2001)) + specifier: ^0.5.1 + version: 0.5.1(knip@6.34.0)(oxfmt@0.66.0)(oxlint@1.81.0(oxlint-tsgolint@7.0.2001)) '@types/chai': specifier: ^5.2.3 version: 5.2.3 @@ -201,8 +201,8 @@ packages: '@antelopejs/mongodb@1.6.2': resolution: {integrity: sha512-+iMgHoA5Kj9rujlHKJmVHC82N38y/V7A5hgn4WAQU5vLfrKxBM6wSdrtvZDivY1Qt3OgRLwyBhj1+/YT13yyBw==} - '@antelopejs/tooling-configs@0.5.0': - resolution: {integrity: sha512-vTZyx0FpSzArjSdb119i+CTGPsYe903/D/JY+0KVUgBjdw/2+LTRt58NUinDtvnf9H18uAlF2xwWJXsSPTv/6A==} + '@antelopejs/tooling-configs@0.5.1': + resolution: {integrity: sha512-Q1JWAsMIDy8f6KaTFPAakT+ChWDhQCzJjdszFFam/pUFqBVMgY+Lp1I7bc8SwcWL3CMdHBzgUUEId2od2cB7hQ==} engines: {node: '>=22.18.0'} hasBin: true peerDependencies: @@ -3046,7 +3046,7 @@ snapshots: - snappy - socks - '@antelopejs/tooling-configs@0.5.0(knip@6.34.0)(oxfmt@0.66.0)(oxlint@1.81.0(oxlint-tsgolint@7.0.2001))': + '@antelopejs/tooling-configs@0.5.1(knip@6.34.0)(oxfmt@0.66.0)(oxlint@1.81.0(oxlint-tsgolint@7.0.2001))': dependencies: '@oxlint/plugins': 1.81.0 dts-bundle-generator: 9.5.1