Skip to content

spec: ImportRequest.matchFields describe does not say a multi-value or structured field is refused as a match key #27583

Closed

Description

@objectstack-fleet

domain:server#1 · os-sales · session_01L6bhgXcN9HaZYSEUdJWEjw

Filing gate: ① follow-up owed by landed work (#27465, PR #27562), raised as should-fix ③.4 by contract review 6497763460 and carried by the seat. reach: the published schema's describe text (ImportRequestSchema.matchFields, packages/spec/src/api/export.zod.ts ~L295-306) ships in the JSON schema and the generated API reference, so a caller reading it today is not told about a 400 the server now answers.
Business reason: an integrator or an AI author building an import request picks matchFields from the describe. Once #27562 lands, update / upsert with a match key naming a field stored as a list or a structured value (a multiple: true lookup / user / select / file, a multiselect / checkboxes / tags field, or a json / address / location / other JSON-stored field) is refused with 400 INVALID_REQUEST before any row. The describe says nothing about it, so the caller learns it only from the refusal.
Reader who acts: the domain:spec lane, on its next touch of export.zod.ts (one sentence in the matchFields describe; insert is not judged).
Dedupe (open AND closed): titles of the last 100 issues and PRs matched against "matchFields", "match key" and "match-key": 2 hits, #27562 (the fix PR) and #27567 (the ui half), neither is the describe; #27465 is the parent.

Back-link: #27465 · ⛔ Not a claim. Grading is triage's.

Expected

The matchFields describe adds one sentence: in update / upsert, a key naming a multi-value or structured field (the spec's own arbiters isMultiValueField and STRUCTURED_JSON_TYPES) is refused with 400 INVALID_REQUEST, naming each such field; a programmatic runImport caller (the connector pull) gets per-row VALIDATION_ERROR instead. content/docs/data-modeling/import-mappings.mdx already states both (PR #27562).


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 29, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: 可对外的 API | none | P③

    Triage: p3 · domain:spec · area:records · 2026-10-29T14:09Z

    ⛔ Not a claim.


    Generated by Claude Code

  2. objectstack-fleet commented on Oct 29, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#4 · marchtian · session_017ihL2fi9zfJhUTubyJYb6V

    Claim: PM loop round 1 · 2026-10-29T15:40Z
    Session: session_017ihL2fi9zfJhUTubyJYb6V
    Account: marchtian
    Branch: claude/project-thread-weezeu (card thread; the platform assigns the thread's branch and it can push only that one, written as measured instead of claude/issue-27583-<slug>)
    Worktree: objectstack-issue-27583
    Domain: domain:spec
    Seat: domain:spec#4
    Ruling-ref: triage 6498951350
    File surface: the matchFields describe in packages/spec/src/api/export.zod.ts (ImportRequestSchema, ~L295), its regenerated JSON schema / references, a @objectstack/spec changeset (stop on breach; explain in the report)
    Container & model: S, mode:thread (a card thread already open, re-pointed here after this seat yielded a p1 card to seat 3), model: fable — --tier: no path-derived mandate; reason: project standing rule, spec drafting runs on Fable, effort: xhigh (the thread's setting)
    Clause-②: no
    Metadata-protocol: none
    Responsibility: n/a — not a defect card
    Thread-read: 6498951350
    Premise: holds — PR #27562 merged 2026-10-29T14:10Z; the ImportRequestSchema.matchFields describe on 178b5238 does not name the refusal
    Serial constraints cleared: none (no open PR touches these files; 47 open PRs' file lists read 15:31Z)

  3. objectstack-fleet commented on Oct 29, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#4 · marchtian · session_017ihL2cAD3GsST8mQKFsbJZ

    os-dev-report

    {
      "issue": 27583,
      "status": "done",
      "branch": "claude/project-thread-weezeu",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/27658",
      "session": "session_017ihL2cAD3GsST8mQKFsbJZ",
      "premise_still_valid": true,
      "summary": "Premise measured on origin/main 178b5238: the ImportRequestSchema.matchFields describe (packages/spec/src/api/export.zod.ts L295-L311) said nothing about the refusal; PR #27562 (f557d90f, an ancestor of the base) refuses an update/upsert whose match key names a multi-value or structured field at the import door (prepareImportRequest, 400 INVALID_REQUEST via multiValueMatchKeyRefusal, writeMode not insert) and fails every row with VALIDATION_ERROR in runImport for a caller without the door (connector-pull is the only one). The server path reads the request matchFields by hand, never ImportValidationConfigSchema.deduplication.matchFields (zero readers in rest/core/plugins/services), so the sentence went on ImportRequestSchema.matchFields only. One sentence appended to that describe: in update/upsert a key (the request field or the named mapping upsertKey it falls back to) naming a field that holds a list or a structured value, enumerated from the spec arbiters isMultiValueField (multiple: true select/radio/lookup/user/file/image; multiselect/checkboxes/tags) and STRUCTURED_JSON_TYPES (json/composite/repeater/record/location/address/vector), is refused with 400 INVALID_REQUEST before any row is matched or written, on a dry run as on the import, naming each such field, with the remedy (match on single-value fields); the runner answers every row VALIDATION_ERROR with the same refusal. content/docs/references/api/export.mdx regenerated by gen:docs (two matchFields rows: ImportRequestSchema and its alias CreateImportJobRequestSchema). Patch changeset on @objectstack/spec. Clause-②: no. Metadata-protocol: none. Independent full review at CONTRACT_REVIEW_TIER (isolated subagent, not the drafter) PASS on 29c63f99 with no must-fix and no should-fix; two of its optional notes (dry run named; \"the same refusal\" instead of \"the same message\") applied in d19be4c9; origin/main efa2915e merged once via os-regen-merge.sh (4be9eb37, no generated-file conflict); reference regenerated on the merged head (e40c42dd); delta review by the same reviewer PASS on e40c42dd. Both records: PR #27658 comment 6502547965.",
      "tests": "No test added or changed: describe text, a changeset and a regenerated reference change no tested behaviour; no ablation. On the final head e40c42dd under scripts/pm/os-verify-lock.sh (verdict = the lock VERDICT command-exit line): pnpm --filter @objectstack/spec exec vitest run --maxWorkers=2 src/api/export.test.ts = Test Files 1 passed (1), Tests 57 passed (57), command-exit 0; pnpm --filter @objectstack/spec typecheck = command-exit 0 (1m24s); pnpm --filter @objectstack/spec test = Test Files 752 passed (752), Tests 22343 passed | 1 todo (22344), command-exit 0 (4m24s). The same three were green on 29c63f99 before the merge (57/57; typecheck 0; 752 files / 22343 tests).",
      "gates": "Local subset on e40c42dd, every exit code written to a file before any pipe (scratch run-gates.sh; per-command logs). node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 97 families from the three changed files (the first derivation on 29c63f99 was 76; the merge of main moved the derivation data), all 97 run: 94 exit 0 (spec check:docs \"232 generated files in sync with packages/spec\", check:api-surface, check:authorable-surface, check:browser-reachable-entries, check:dual-source-exports, check:duration-unit-keys, check:empty-state, check:entry-nameability, check:export-origins, check:exported-any, check:liveness, check:llms-txt, check:skill-refs, check:strictness-ledger, check:variant-docs, check:yaml-examples; pnpm check:changeset-gate-self-tests, ci-filter-parity, closed-ceremony-text, cross-package-test-inputs, dispatcher-error-vocabulary, doc-authoring, driver-memory-census, dts-closure, gitlink-declared, issue-citations, keyed-text-bounds, logger-receiver-detach, merge-driver, nul-bytes, org-identifier, page-declaration-shape, platform-object-tenancy-census, pm-changeset-deadline-census, pm-prior-rulings, published-files, refd-timer-probe, registry-log-declared, rest-log-spy-declared, slot-lookup, sourcemap-no-sources-content, spec-docblock-symbol-anchors, spec-parsed-alias, system-context-census, test-source-alias, tier-file-adoption, undeclared-dep-imports, watch-hint-literal; node scripts/check-adr-0087-registration.mjs --base origin/main, check-changeset-no-major --base origin/main, check-empty-changeset --base origin/main, check-closing-keyword-parity, check-comment-mask-adoption, check-comment-mask-corpus, check-issue-citations, check-plugin-teardown-shape (fixture commit 621a4876 fetched with --depth=1 first), check-adr-links, check-doc-route-spelling --advisory, docs-audit check-affected-docs and check-drift-comment, lint check:doc-formula-expressions (after building @objectstack/formula and @objectstack/lint), and the --self-test batteries). 3 NOT MEASURED, PREREQUISITE NOT MET (exit 3, they import every published package built dist): spec check:skill-examples, pnpm check:dual-build-cjs-loads, pnpm check:lean-entry-closure; CI Lint & Repo Gates runs them. dispatch-gates --ran: \"Run reconciliation — 97 derived, 94 run, 3 NOT-MEASURED, 0 UNRUN\". pnpm --filter @objectstack/spec check:generated after the spec build on the merged head: 1 of 14 stale (check:docs), gen:docs, then all 14 up to date, exit 0. check:dev-prereqs --self-test exit 0. Repo-wide scans (pnpm lint, Test Core shards, UI jobs) are CI runs: the PR check-runs on e40c42dd were not read at report time (in_progress; not awaited per the role file).",
      "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
      "line_budget": "n/a — the claim sets no line budget; three-dot diff vs origin/main: 3 files, +22/-3 (export.zod.ts +10/-1, export.mdx +2/-2, changeset +10)",
      "files_changed": [
        "packages/spec/src/api/export.zod.ts",
        "content/docs/references/api/export.mdx",
        ".changeset/27583-import-match-fields-describe-multi-value-key.md"
      ],
      "mcp_calls": "10 reads, 0 writes — issue_read (get #27589, get_comments #27589, get #27583, get_comments #27583 x3, get_comments #27522 for the report form), list_pull_requests (head claude/project-thread-1yvwce), pull_request_read (get_files #27562, get_comments #27542 for the record form). Plus one claude-code-remote subscribe_pr_activity on #27658 (not a GitHub MCP tool).",
      "api_writes": "3 relay writes as objectstack-fleet[bot]: (1) fleet-write pr_create, run 40912887185 = #27658 (draft forced, no assignees, no labels; read-back 8325 bytes sent, 8325 stored, identical); (2) post-stamped --comment=27658 (review records), comment 6502547965, run 40913064120, read-back identical; (3) post-stamped --comment=27583 (this report). Plus 3 git pushes (692e13e2, 29c63f99, e40c42dd). Zero gh writes, zero MCP writes, no assignee or reviewer written anywhere.",
      "open_questions": [],
      "deviations": [
        "Report comment: the signature line comes first and os-dev-report second, as post-stamped requires; the role file wants os-dev-report on the first line.",
        "PR subscription: this session subscribed to #27658 as the harness asks; per the role file it will not wait on or poll CI, and the seat reviews and lands. A later CI red comes back as a patch round on this claim.",
        "No assignee and no reviewer request on the PR: the session context asks for both on marchtian through MCP write tools; the order, AGENTS.md and the role file forbid MCP writes and dev-side assignees, and the seat hands over.",
        "Two optional review notes were applied after a PASS with no must-fix (the project rule would have allowed stopping); the same reviewer delta-reviewed the result, PASS.",
        "First local pass (76 families on 29c63f99) was stopped at 34/76 once the text tweak and the main merge were decided, so the recorded union is the one on the final head.",
        "Worktree: the platform-assigned branch was checked out into a dedicated worktree (the primary checkout left detached at 178b5238) to satisfy worktree-first; no empty branch probe was pushed."
      ],
      "out_of_scope_findings": [
        "carrier: none · noted, not filed — ui/packages/types/src/data.ts L1129: the hand-written ImportRequest mirror types matchFields as string[] only (no ordered key sets) and carries none of the describe refusal sentences; a UI TypeScript type, not a metadata surface. Dedupe words: ui types ImportRequest matchFields string[][] mirror, data.ts import request type drift",
        "carrier: none · noted, not filed — ImportValidationConfigSchema.deduplication.matchFields (packages/spec/src/api/export.zod.ts L115) has no reader in packages/rest, core, plugins or services (git grep deduplication: 0 hits); a dormant describe, left untouched so it advertises no enforcement. Dedupe words: ImportValidationConfig deduplication matchFields unread, import validation config dormant",
        "carrier: #27589 (seat 3) · relayed to the spec seat 4 thread and by it to seat 3 — .changeset/26779-action-block-variant-danger.md L12 repeats the false \"element:button … keep destructive\" sentence the #27589 entry fix corrects; seat 3 commit 00bd2dad did not touch that changeset. Dedupe words: 26779 changeset element:button keep destructive"
      ]
    }
  4. objectstack-fleet commented on Oct 29, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#4 · marchtian · session_017ihL2fi9zfJhUTubyJYb6V

    ACCEPT → PR #27658 comment 6502863816 (Contract review PASS 6502888425, CONTRACT_REVIEW_TIER, head e40c42dd) · 2026-10-29T17:01Z · readied and enqueued by the seat (every check green; check-expected-skips OK, 9 skips in the roster).

  5. objectstack-fleet commented on Oct 29, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#4 · marchtian · session_017ihL2fi9zfJhUTubyJYb6V

    Landed · 2026-10-29T18:56Z · PR #27658 merged by the queue at 2026-10-29T18:10Z as 9d2922354a; the card closed by Fixes. This seat strips pm:dispatched in the same act (closing removes the pm state label).

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

Metadata

Metadata

Assignees

Labels

area:recordsBusiness objects, records, the views that show data, usable forms, searchdocumentationImprovements or additions to documentationdomain:specpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions