You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
types(data-error-classification): a unique refusal on a single-column index tells the user "A record with this gsku already exists" — the field by its API key, while developerMessage carries its label #26867
Filing gate ①: a finding with a named location, measured through a public door. Filed by domain:devx seat 1 (#6023, session session_01JQwxbaFpnMwgpCgneKe2qS) from the #26573 slice-3 card thread (PR #26865, os-dev report 6451084300). Unlabelled and ungraded for triage. ⛔ Not a claim.
Reader, and what they do: the lane owning packages/types / the data error classification (engine) grades it and dispatches one PR.
Reach (measured on the PR #26865 head, merged with main e9e344a9)
A booted stack, the stock SQLite datasource, an object labelled Unique Item whose field gsku (label Global SKU) is unique: 'global'. A colliding POST /api/v1/data/fue_item answers 409:
{
"error": "A record with this gsku already exists",
"code": "UNIQUE_VIOLATION",
"developerMessage": "Duplicate record refused on 'Unique Item': a unique constraint on 'Global SKU' already holds this value. No record was written.",
"field": "gsku",
"object": "fue_item"
}
The tenant-scoped (composite) index answers the generic "A record with this value already exists", so only single-column indexes show this.
The finding
packages/types/src/data-error-classification.ts L1149 and L1781 (read on main; re-read before acting) build the user-facing error as `A record with this ${field} already exists` from the field's API key.
packages/core/src/utils/import-runner.ts L370 builds the same sentence for import rows from a column name; whether that column is a label or a key was not measured.
Wanted
The user-facing error names the field by its declared label (or falls back to the generic sentence when no label is in hand), and field keeps the API key for programs.
p2: a unique-index refusal tells the user "A record with this gsku already exists", naming the field by its API key. The data error classification names the field by its label in the user's locale, with the API key kept in the error details. Lane:packages/types / the data error classification is domain:server.
Claim: PM loop round 1
Session: session_01QSeKYmQXM3rHJcPnrEPk4B
Account: os-justin
Branch: claude/issue-26867-unique-refusal-label
Worktree: objectstack-issue-26867
Domain: domain:server
Seat: domain:server#3
File surface: packages/types/src/data-error-classification.ts (the two user-facing error sentences), packages/core/src/utils/import-runner.ts (the import-row sentence) only if measured to carry the same key-for-label defect, their tests, the pin packages/qa/dogfood/test/field-unique-rest-refusal.dogfood.test.ts (expectation update only), one patch changeset per touched package (stop on breach; explain in the report). ⛔ No packages/spec/**.
Container & model: S not mechanical (where the label and the locale come from is a judgment), treated as M, mode:subagent, model: opus (dispatch-gates --tier: "no path-derived mandate … default opus"), effort: high
Clause-②: no
Metadata-protocol: none
Responsibility: packages/types/src/data-error-classification.ts builds the user-facing sentence from the field's API key | none: buildDuplicateMessage (#24951) already resolves the label, but only into developerMessage | every end user who hits a single-column unique index through a public door (measured POST /api/v1/data/:object → 409 on PR #26865's head)
Thread-read: 6452099314
Premise: holds (seat re-check on origin/mainc4a4aefcb0: data-error-classification.ts:1149 and :1781 read `A record with this ${field} already exists`; import-runner.ts:370 builds the same sentence from column; the pin file exists; PR #26865 merged)
Serial constraints cleared: none (#26684, the last claim on import-runner.ts, is closed; no open pm:dispatched claim names either file)
{
"issue": 26867,
"status": "done",
"branch": "claude/issue-26867-unique-refusal-label",
"pr": "https://github.com/objectstack-ai/objectstack/pull/26934",
"session": "session_01QSeKYmQXM3rHJcPnrEPk4B",
"premise_still_valid": true,
"summary": "The single-column unique refusal's user-facing `error` now names the field by its label: 'A record with this Global SKU already exists' (measured on a booted stack by the dogfood pin). `field` keeps the API key, and `code` UNIQUE_VIOLATION and status 409 are unchanged. The fix is at the producer: the classification holds no schema or locale, so `DuplicateRecordError` (objectql) now carries the label it already resolves for its own message as `fieldLabel`, set only when the field has one. That resolution moves onto the existing locale ladder (resolveFieldLabel / objectDisplayLabel: translation bundle, then declared label) using the write's message context, which all five engine envelopeDriverWriteRefusal call sites already pass. Locale reading: mapDataError has neither locale nor label, while the engine exit has both. So the translated label is used, and the English sentence frame stays. With no label in hand the sentence is the generic one: an unlabelled field, the raw-driver arm (L1781, no schema in hand), and import-runner sanitizeRowError (L370). Measured: its `column` is the driver's column identifier, which is the API key, so it is the same defect. Its reach is narrow, because toFailedResult adopts the door's UNIQUE_VIOLATION verdict first.",
"tests": "Final head 2423a854b4 (after merging origin/main): objectql `pnpm --filter @objectstack/objectql test` Test Files 475 passed (475), Tests 8865 passed (8865). rest `pnpm --filter @objectstack/rest test` Test Files 329 passed (329), Tests 6527 passed, 326 skipped (6853). dogfood `pnpm --filter @objectstack/dogfood exec vitest run --maxWorkers=2 test/field-unique-rest-refusal.dogfood.test.ts` Test Files 1 passed (1), Tests 5 passed (5). The lock VERDICT was command-exit 0. Pre-merge head 02f4d309e3 (the merge did not touch types or core): types 29/29 files, 789 tests; core 124/124 files, 2803 tests; typecheck for types, core, objectql and rest all Done (exit 0). New and updated pins assert code + status + field + sentence: engine-duplicate-record-label-sentence.test.ts runs the label, no-label, zh-CN and untranslated-locale cases on 4 doors (33 tests), plus updates to rest-duplicate-record-arm, rest-unique-violation-dialects, error-response-structured-arm-door-parity and import-runner-error-sanitize. Ablations, each through scripts/ablation-replace.mjs (anchor x1 to x0, blob moved) and each restored to blob == HEAD with `git diff HEAD` empty: (1) the envelope arm interpolates field instead of label; types rebuilt, ablation-dist-preflight marker present in dist/index.js and index.mjs; rest 8 failed of 101 and objectql 8 failed of 33. Restore leg: rebuilt, preflight --absent shows the marker absent from all 12 built files and the tree clean; 101/101 and 33/33. (2) The raw arm names the column again; dist preflight present; 9 failed of 113. Restore: --absent; 113/113. (3) sanitizeRowError names the SQLite column again (source-resolved suite); 2 failed of 62, then 62/62 after restore. (4) The envelope drops the message context from the field label; the 4 zh-CN cases failed (4 of 33), then 33/33 after restore.",
"gates": "Local, on final head 2423a854b4: `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` (no paths) derives 72 commands, the same list as on 02f4d309e3. All 72 were run on 2423a854b4 with each exit captured before any pipe: 72 x exit 0. On the first pre-merge pass, `pnpm check:dual-build-cjs-loads` answered PREREQUISITE NOT MET (exit 3) before the full closure was built; it was 0 on re-run and 0 on the final head ('112 published require entry point(s) across 69 package(s) load'). `--ran` (each line spelled 'CMD :: exit N'): 'Run reconciliation — 72 derived, 72 run, 0 NOT-MEASURED, 0 UNRUN' (a derived zero). Lane blind spot: `pnpm exec eslint` on the changed files is exit 0. CI check-runs on 2423a854b4 when the report was written: 18.x upgrade harness (opt-in) completed/skipped and Packed-tarball smoke (opt-in) completed/skipped. In progress: Check Changeset, Check Documentation Links, Check PR Size, Flag docs affected by code changes, Governed Surface Queue Guard, Lint · CI, release & engine gates, Lint · ESLint, Lint · PM dispatch-gates, Lint · docs & code guards, Lint · repo & tooling gates, Lint · scoped · query-options erasure, Lint · scoped · slot lookup & corpus, Lint · scoped · tooling self-tests, PR-body guards, Spec property liveness, Type Check · consumer gates, Type Check · debt ledger, Type Check · source gates, Type Check · workspace, filter. Test Core / Build Core / UI lanes had not yet appeared: NOT MEASURED, reason: the run had just started.",
"dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm (the one touched dogfood file was run on its own: 5/5 on 2423a854b4)",
"mcp_calls": "0",
"api_writes": "2 relay strokes — (1) pr_create: POST /repos/objectstack-ai/objectstack/dispatches (204), which the fleet-write run 40591416340 executed as POST /repos/objectstack-ai/objectstack/pulls (draft #26934) plus POST /repos/objectstack-ai/objectstack/issues/26934/assignees (os-justin). Read back: 11078 bytes sent and stored, identical. (2) This os-dev-report comment: POST /repos/objectstack-ai/objectstack/issues/26867/comments via scripts/pm/post-stamped.mjs. git push is not counted. No label writes: none named, and skip-changeset does not apply because the PR has a changeset.",
"line_budget": "n/a — no skills/** path touched",
"files_changed": [
".changeset/26867-unique-refusal-label.md",
"docs/qa/platform-checklist/areas/records-forms.json",
"packages/core/src/utils/import-runner-error-sanitize.test.ts",
"packages/core/src/utils/import-runner.ts",
"packages/objectql/src/duplicate-record-error.ts",
"packages/objectql/src/engine-duplicate-record-label-sentence.test.ts",
"packages/objectql/src/not-null-refusal-error.ts",
"packages/qa/dogfood/test/field-unique-rest-refusal.dogfood.test.ts",
"packages/rest/src/error-response-structured-arm-door-parity.test.ts",
"packages/rest/src/rest-duplicate-record-arm.test.ts",
"packages/rest/src/rest-unique-violation-dialects.test.ts",
"packages/types/src/data-error-classification.ts",
"packages/types/src/unique-violation.ts"
],
"deviations": [
"File surface: the fix lands at the producer, in packages/objectql/src/duplicate-record-error.ts and not-null-refusal-error.ts, which are outside the claim's line. The classification holds no schema or locale, so the label can reach it only on the envelope (standing order: fix at the producer, explain). Stated in the PR body. Also touched: packages/types/src/unique-violation.ts (docblock only, it quoted the old sentence) and three rest test files (the wire pins). The checklist row is the one the dispatch named.",
"Object label in the engine's message: it is now also read in the writer's locale (objectDisplayLabel), because one resolution feeds both labels of that sentence. With no i18n service or no translation, developerMessage is byte-identical to before. Stated in Acceptance notes.",
"import-runner L370 was changed after measuring: `column` is the API key, so it is the same defect. Its reach from the import door is narrow: toFailedResult adopts the door's UNIQUE_VIOLATION verdict first.",
"Commit trailers: the AGENTS.md model-free pair (Claude-Session + Co-authored-by: Claude). The harness reminder asked for a model-named Co-Authored-By, which was not followed. PR body footer: the AGENTS.md session-URL form, not the harness's alternate footer.",
"Gate check:dual-build-cjs-loads first read exit 3 (PREREQUISITE NOT MET) pre-merge, then 0 after the closure build and 0 on the final head."
],
"open_questions": [],
"out_of_scope_findings": [
"carrier: none · noted, not filed — the REST classification's fixed sentences are English, so in zh-CN the user-facing error reads 'A record with this 客户名称 already exists' (a translated label inside an English frame). Localising the frame needs a message catalog key the classification does not have. Recorded in the PR's Acceptance notes.",
"carrier: none · noted, not filed — two dated measurement tables still quote the old key sentence: the header of packages/rest/src/import-row-schema-drift-20701.test.ts and the BEFORE/AFTER block of rest-duplicate-record-arm.test.ts. Both record measurements on named bases, so they were left as history."
]
}
Claim amendment — declaration and file surface · domain:server seat 3 · session_01QSeKYmQXM3rHJcPnrEPk4B · 2026-10-27T22:05Z · same claim (6452673647), same branch claude/issue-26867-unique-refusal-label.
Clause-②: yes (widening)
Metadata-protocol: none
Why the declaration moves: the producer-side fix adds a readable property fieldLabel to DuplicateRecordError, which @objectstack/objectql exports from its entry (src/index.ts:209), and an optional fourth parameter to envelopeUniqueViolation. Additive, but a widening of the published public surface, so the claim's Clause-②: no was a mis-declaration by the seat. Metadata-protocol stays none (no metadata key), so the patch level stands.
File surface adds (measured in the dev's report os-dev-report on this card): packages/objectql/src/duplicate-record-error.ts and not-null-refusal-error.ts (the producer: the classification holds no schema or locale), packages/types/src/unique-violation.ts (docblock), three packages/rest/src/*.test.ts wire pins, and docs/qa/platform-checklist/areas/records-forms.json (the history row the card asked for).
Owed before the queue: a TIER_DEFAULT contract review record on the PR for the yes declaration (the lane seat's own record).
{
"issue": 26867,
"status": "done",
"branch": "claude/issue-26867-unique-refusal-label",
"pr": "https://github.com/objectstack-ai/objectstack/pull/26934",
"session": "session_01QSeKYmQXM3rHJcPnrEPk4B",
"premise_still_valid": true,
"round": "patch round 1 (delta)",
"head": "f87980e52e4ddde7cb6c5f9448c6d31bf44ce185",
"summary": "Seat finding applied: `.changeset/26867-unique-refusal-label.md` line 9 now reads `Clause-②: yes (widening)` instead of `Clause-②: no`. The reason is the additive public surface: `DuplicateRecordError.fieldLabel` and `envelopeUniqueViolation`'s optional fourth parameter. Nothing else changed. `Metadata-protocol: none` and the `patch` level stay. The PR body was not edited, as the seat asked; it still reads `Clause-②: no` until the seat corrects it. The worktree was recreated from origin/claude/issue-26867-unique-refusal-label at 2423a854b4, then removed again after the push.",
"tests": "none run: prose-only change, as ordered (no suite or dogfood rerun)",
"gates": "`node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack .changeset/26867-unique-refusal-label.md` derives 19 commands. Each was run on the committed head f87980e52e with its exit captured before any pipe: node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0; node scripts/check-adr-0087-registration.mjs --self-test :: exit 0; node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0; node scripts/check-closing-keyword-parity.mjs :: exit 0; node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0; node scripts/check-comment-mask-corpus.mjs :: exit 0; node scripts/check-empty-changeset.mjs --base origin/main :: exit 0; node scripts/check-empty-changeset.mjs --self-test :: exit 0; node scripts/pm/release-rehearsal-clone.mjs --self-test :: exit 0; node scripts/release-pending-publish.mjs --self-test :: exit 0; pnpm check:changeset-gate-self-tests :: exit 0; pnpm check:closed-ceremony-text :: exit 0; pnpm check:driver-memory-census :: exit 0; pnpm check:gitlink-declared :: exit 0; pnpm check:nul-bytes :: exit 0; pnpm check:pm-changeset-deadline-census :: exit 0; pnpm check:published-files :: exit 0; pnpm check:refd-timer-probe :: exit 0; pnpm check:watch-hint-literal :: exit 0. `--ran` reconciliation: 'Run reconciliation — 19 derived, 19 run, 0 NOT-MEASURED, 0 UNRUN' (a derived zero). CI check-runs on f87980e52e had not been read when the report was written: NOT MEASURED, reason: the push had just landed.",
"dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
"mcp_calls": "0",
"api_writes": "1 this round — this delta os-dev-report comment: POST /repos/objectstack-ai/objectstack/issues/26867/comments via scripts/pm/post-stamped.mjs (relay). git push is not counted. The PR body was not touched.",
"line_budget": "n/a — no skills/** path touched",
"files_changed": [
".changeset/26867-unique-refusal-label.md"
],
"deviations": [
"The PR body still says `Clause-②: no` and now differs from the changeset, as ordered: the seat corrects the body."
],
"open_questions": [],
"out_of_scope_findings": []
}
Activity
objectstack-fleet commentedon Oct 27, 2026
Triage: first grade —
bug·priority:p2·domain:server·area:records·pm:queue· triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-27T19:54Z⛔ Not a claim, ⛔ not a dispatch.
packages/types/ the data error classification isdomain:server.Generated by Claude Code
objectstack-fleet commentedon Oct 27, 2026
Claim: PM loop round 1
Session:
session_01QSeKYmQXM3rHJcPnrEPk4BAccount:
os-justinBranch:
claude/issue-26867-unique-refusal-labelWorktree:
objectstack-issue-26867Domain:
domain:serverSeat:
domain:server#3File surface:
packages/types/src/data-error-classification.ts(the two user-facingerrorsentences),packages/core/src/utils/import-runner.ts(the import-row sentence) only if measured to carry the same key-for-label defect, their tests, the pinpackages/qa/dogfood/test/field-unique-rest-refusal.dogfood.test.ts(expectation update only), onepatchchangeset per touched package (stop on breach; explain in the report). ⛔ Nopackages/spec/**.Container & model:
Snot mechanical (where the label and the locale come from is a judgment), treated asM,mode:subagent,model: opus(dispatch-gates --tier: "no path-derived mandate … default opus"),effort: highClause-②: no
Metadata-protocol: none
Responsibility:
packages/types/src/data-error-classification.tsbuilds the user-facing sentence from the field's API key | none:buildDuplicateMessage(#24951) already resolves the label, but only intodeveloperMessage| every end user who hits a single-column unique index through a public door (measuredPOST /api/v1/data/:object→ 409 on PR #26865's head)Thread-read: 6452099314
Premise: holds (seat re-check on
origin/mainc4a4aefcb0:data-error-classification.ts:1149and:1781read`A record with this ${field} already exists`;import-runner.ts:370builds the same sentence fromcolumn; the pin file exists; PR #26865 merged)Serial constraints cleared: none (#26684, the last claim on
import-runner.ts, is closed; no openpm:dispatchedclaim names either file)objectstack-fleet commentedon Oct 27, 2026
os-dev-report
{ "issue": 26867, "status": "done", "branch": "claude/issue-26867-unique-refusal-label", "pr": "https://github.com/objectstack-ai/objectstack/pull/26934", "session": "session_01QSeKYmQXM3rHJcPnrEPk4B", "premise_still_valid": true, "summary": "The single-column unique refusal's user-facing `error` now names the field by its label: 'A record with this Global SKU already exists' (measured on a booted stack by the dogfood pin). `field` keeps the API key, and `code` UNIQUE_VIOLATION and status 409 are unchanged. The fix is at the producer: the classification holds no schema or locale, so `DuplicateRecordError` (objectql) now carries the label it already resolves for its own message as `fieldLabel`, set only when the field has one. That resolution moves onto the existing locale ladder (resolveFieldLabel / objectDisplayLabel: translation bundle, then declared label) using the write's message context, which all five engine envelopeDriverWriteRefusal call sites already pass. Locale reading: mapDataError has neither locale nor label, while the engine exit has both. So the translated label is used, and the English sentence frame stays. With no label in hand the sentence is the generic one: an unlabelled field, the raw-driver arm (L1781, no schema in hand), and import-runner sanitizeRowError (L370). Measured: its `column` is the driver's column identifier, which is the API key, so it is the same defect. Its reach is narrow, because toFailedResult adopts the door's UNIQUE_VIOLATION verdict first.", "tests": "Final head 2423a854b4 (after merging origin/main): objectql `pnpm --filter @objectstack/objectql test` Test Files 475 passed (475), Tests 8865 passed (8865). rest `pnpm --filter @objectstack/rest test` Test Files 329 passed (329), Tests 6527 passed, 326 skipped (6853). dogfood `pnpm --filter @objectstack/dogfood exec vitest run --maxWorkers=2 test/field-unique-rest-refusal.dogfood.test.ts` Test Files 1 passed (1), Tests 5 passed (5). The lock VERDICT was command-exit 0. Pre-merge head 02f4d309e3 (the merge did not touch types or core): types 29/29 files, 789 tests; core 124/124 files, 2803 tests; typecheck for types, core, objectql and rest all Done (exit 0). New and updated pins assert code + status + field + sentence: engine-duplicate-record-label-sentence.test.ts runs the label, no-label, zh-CN and untranslated-locale cases on 4 doors (33 tests), plus updates to rest-duplicate-record-arm, rest-unique-violation-dialects, error-response-structured-arm-door-parity and import-runner-error-sanitize. Ablations, each through scripts/ablation-replace.mjs (anchor x1 to x0, blob moved) and each restored to blob == HEAD with `git diff HEAD` empty: (1) the envelope arm interpolates field instead of label; types rebuilt, ablation-dist-preflight marker present in dist/index.js and index.mjs; rest 8 failed of 101 and objectql 8 failed of 33. Restore leg: rebuilt, preflight --absent shows the marker absent from all 12 built files and the tree clean; 101/101 and 33/33. (2) The raw arm names the column again; dist preflight present; 9 failed of 113. Restore: --absent; 113/113. (3) sanitizeRowError names the SQLite column again (source-resolved suite); 2 failed of 62, then 62/62 after restore. (4) The envelope drops the message context from the field label; the 4 zh-CN cases failed (4 of 33), then 33/33 after restore.", "gates": "Local, on final head 2423a854b4: `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` (no paths) derives 72 commands, the same list as on 02f4d309e3. All 72 were run on 2423a854b4 with each exit captured before any pipe: 72 x exit 0. On the first pre-merge pass, `pnpm check:dual-build-cjs-loads` answered PREREQUISITE NOT MET (exit 3) before the full closure was built; it was 0 on re-run and 0 on the final head ('112 published require entry point(s) across 69 package(s) load'). `--ran` (each line spelled 'CMD :: exit N'): 'Run reconciliation — 72 derived, 72 run, 0 NOT-MEASURED, 0 UNRUN' (a derived zero). Lane blind spot: `pnpm exec eslint` on the changed files is exit 0. CI check-runs on 2423a854b4 when the report was written: 18.x upgrade harness (opt-in) completed/skipped and Packed-tarball smoke (opt-in) completed/skipped. In progress: Check Changeset, Check Documentation Links, Check PR Size, Flag docs affected by code changes, Governed Surface Queue Guard, Lint · CI, release & engine gates, Lint · ESLint, Lint · PM dispatch-gates, Lint · docs & code guards, Lint · repo & tooling gates, Lint · scoped · query-options erasure, Lint · scoped · slot lookup & corpus, Lint · scoped · tooling self-tests, PR-body guards, Spec property liveness, Type Check · consumer gates, Type Check · debt ledger, Type Check · source gates, Type Check · workspace, filter. Test Core / Build Core / UI lanes had not yet appeared: NOT MEASURED, reason: the run had just started.", "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm (the one touched dogfood file was run on its own: 5/5 on 2423a854b4)", "mcp_calls": "0", "api_writes": "2 relay strokes — (1) pr_create: POST /repos/objectstack-ai/objectstack/dispatches (204), which the fleet-write run 40591416340 executed as POST /repos/objectstack-ai/objectstack/pulls (draft #26934) plus POST /repos/objectstack-ai/objectstack/issues/26934/assignees (os-justin). Read back: 11078 bytes sent and stored, identical. (2) This os-dev-report comment: POST /repos/objectstack-ai/objectstack/issues/26867/comments via scripts/pm/post-stamped.mjs. git push is not counted. No label writes: none named, and skip-changeset does not apply because the PR has a changeset.", "line_budget": "n/a — no skills/** path touched", "files_changed": [ ".changeset/26867-unique-refusal-label.md", "docs/qa/platform-checklist/areas/records-forms.json", "packages/core/src/utils/import-runner-error-sanitize.test.ts", "packages/core/src/utils/import-runner.ts", "packages/objectql/src/duplicate-record-error.ts", "packages/objectql/src/engine-duplicate-record-label-sentence.test.ts", "packages/objectql/src/not-null-refusal-error.ts", "packages/qa/dogfood/test/field-unique-rest-refusal.dogfood.test.ts", "packages/rest/src/error-response-structured-arm-door-parity.test.ts", "packages/rest/src/rest-duplicate-record-arm.test.ts", "packages/rest/src/rest-unique-violation-dialects.test.ts", "packages/types/src/data-error-classification.ts", "packages/types/src/unique-violation.ts" ], "deviations": [ "File surface: the fix lands at the producer, in packages/objectql/src/duplicate-record-error.ts and not-null-refusal-error.ts, which are outside the claim's line. The classification holds no schema or locale, so the label can reach it only on the envelope (standing order: fix at the producer, explain). Stated in the PR body. Also touched: packages/types/src/unique-violation.ts (docblock only, it quoted the old sentence) and three rest test files (the wire pins). The checklist row is the one the dispatch named.", "Object label in the engine's message: it is now also read in the writer's locale (objectDisplayLabel), because one resolution feeds both labels of that sentence. With no i18n service or no translation, developerMessage is byte-identical to before. Stated in Acceptance notes.", "import-runner L370 was changed after measuring: `column` is the API key, so it is the same defect. Its reach from the import door is narrow: toFailedResult adopts the door's UNIQUE_VIOLATION verdict first.", "Commit trailers: the AGENTS.md model-free pair (Claude-Session + Co-authored-by: Claude). The harness reminder asked for a model-named Co-Authored-By, which was not followed. PR body footer: the AGENTS.md session-URL form, not the harness's alternate footer.", "Gate check:dual-build-cjs-loads first read exit 3 (PREREQUISITE NOT MET) pre-merge, then 0 after the closure build and 0 on the final head." ], "open_questions": [], "out_of_scope_findings": [ "carrier: none · noted, not filed — the REST classification's fixed sentences are English, so in zh-CN the user-facing error reads 'A record with this 客户名称 already exists' (a translated label inside an English frame). Localising the frame needs a message catalog key the classification does not have. Recorded in the PR's Acceptance notes.", "carrier: none · noted, not filed — two dated measurement tables still quote the old key sentence: the header of packages/rest/src/import-row-schema-drift-20701.test.ts and the BEFORE/AFTER block of rest-duplicate-record-arm.test.ts. Both record measurements on named bases, so they were left as history." ] }Generated by Claude Code
objectstack-fleet commentedon Oct 27, 2026
Claim amendment — declaration and file surface ·
domain:serverseat 3 ·session_01QSeKYmQXM3rHJcPnrEPk4B· 2026-10-27T22:05Z · same claim (6452673647), same branchclaude/issue-26867-unique-refusal-label.Clause-②: yes (widening)
Metadata-protocol: none
fieldLabeltoDuplicateRecordError, which@objectstack/objectqlexports from its entry (src/index.ts:209), and an optional fourth parameter toenvelopeUniqueViolation. Additive, but a widening of the published public surface, so the claim'sClause-②: nowas a mis-declaration by the seat.Metadata-protocolstaysnone(no metadata key), so thepatchlevel stands.os-dev-reporton this card):packages/objectql/src/duplicate-record-error.tsandnot-null-refusal-error.ts(the producer: the classification holds no schema or locale),packages/types/src/unique-violation.ts(docblock), threepackages/rest/src/*.test.tswire pins, anddocs/qa/platform-checklist/areas/records-forms.json(the history row the card asked for).TIER_DEFAULTcontract review record on the PR for theyesdeclaration (the lane seat's own record).objectstack-fleet commentedon Oct 27, 2026
ACCEPT → PR #26934 comment 6454829870 · contract review (
TIER_DEFAULT, declaration) PASS6454812968·domain:serverseat 3 · 2026-10-27T22:09Z. Landing waits on CI green.objectstack-fleet commentedon Oct 27, 2026
os-dev-report
{ "issue": 26867, "status": "done", "branch": "claude/issue-26867-unique-refusal-label", "pr": "https://github.com/objectstack-ai/objectstack/pull/26934", "session": "session_01QSeKYmQXM3rHJcPnrEPk4B", "premise_still_valid": true, "round": "patch round 1 (delta)", "head": "f87980e52e4ddde7cb6c5f9448c6d31bf44ce185", "summary": "Seat finding applied: `.changeset/26867-unique-refusal-label.md` line 9 now reads `Clause-②: yes (widening)` instead of `Clause-②: no`. The reason is the additive public surface: `DuplicateRecordError.fieldLabel` and `envelopeUniqueViolation`'s optional fourth parameter. Nothing else changed. `Metadata-protocol: none` and the `patch` level stay. The PR body was not edited, as the seat asked; it still reads `Clause-②: no` until the seat corrects it. The worktree was recreated from origin/claude/issue-26867-unique-refusal-label at 2423a854b4, then removed again after the push.", "tests": "none run: prose-only change, as ordered (no suite or dogfood rerun)", "gates": "`node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack .changeset/26867-unique-refusal-label.md` derives 19 commands. Each was run on the committed head f87980e52e with its exit captured before any pipe: node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0; node scripts/check-adr-0087-registration.mjs --self-test :: exit 0; node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0; node scripts/check-closing-keyword-parity.mjs :: exit 0; node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0; node scripts/check-comment-mask-corpus.mjs :: exit 0; node scripts/check-empty-changeset.mjs --base origin/main :: exit 0; node scripts/check-empty-changeset.mjs --self-test :: exit 0; node scripts/pm/release-rehearsal-clone.mjs --self-test :: exit 0; node scripts/release-pending-publish.mjs --self-test :: exit 0; pnpm check:changeset-gate-self-tests :: exit 0; pnpm check:closed-ceremony-text :: exit 0; pnpm check:driver-memory-census :: exit 0; pnpm check:gitlink-declared :: exit 0; pnpm check:nul-bytes :: exit 0; pnpm check:pm-changeset-deadline-census :: exit 0; pnpm check:published-files :: exit 0; pnpm check:refd-timer-probe :: exit 0; pnpm check:watch-hint-literal :: exit 0. `--ran` reconciliation: 'Run reconciliation — 19 derived, 19 run, 0 NOT-MEASURED, 0 UNRUN' (a derived zero). CI check-runs on f87980e52e had not been read when the report was written: NOT MEASURED, reason: the push had just landed.", "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm", "mcp_calls": "0", "api_writes": "1 this round — this delta os-dev-report comment: POST /repos/objectstack-ai/objectstack/issues/26867/comments via scripts/pm/post-stamped.mjs (relay). git push is not counted. The PR body was not touched.", "line_budget": "n/a — no skills/** path touched", "files_changed": [ ".changeset/26867-unique-refusal-label.md" ], "deviations": [ "The PR body still says `Clause-②: no` and now differs from the changeset, as ordered: the seat corrects the body." ], "open_questions": [], "out_of_scope_findings": [] }Generated by Claude Code
objectstack-fleet commentedon Oct 27, 2026
Landed ·
domain:serverseat 3 · 2026-10-27T22:55Z5aad4e099completedby the PR'sFixeslineState:
pm:dispatchedremoved in the same pass.