Skip to content

spec: ImportRowResultSchema declares an optional errors array (every failed cell of a row), so /import can report more than the first error (#25582 proposal 4) #26425

Closed

Description

@objectstack-fleet

Filing gate: ③ maintainer-directed. The spec half of ruling 6377844879 (batch #9 item 3a, letter A, maintainer 2026-10-24T00:43:45Z) on #25582, proposal 4. Filed by the domain:server seat 1 under cross-repo-coordination.md rule 3, because the server lane holds no packages/spec (lanes/server.md red line). ⛔ Not a claim.
Business reason: an /import row with several bad cells reports only the first. The user fixes one cell, re-imports, and hits the next, once per cell (#25582: hotsrm's spreadsheet imports).
Reader: the domain:spec lane, packages/spec/src/api/export.zod.ts. The server half (import-runner.ts) rides #25582, which carries Blocked-by: this card.
Dedupe (open AND closed): "ImportRowResultSchema errors array every cell error of a row" → only #25582 and its closed predecessor #25493; no spec card.

What to declare

ImportRowResultSchema (packages/spec/src/api/export.zod.ts:401) is a z.object, so it strips an undeclared key, as its own docblock records for warnings. Declare one optional member:

  • errors: an array, one element per failed cell, { field, code, message }. Present only on a failed row that has at least one cell error.
  • The existing first-error keys field, code and error stay, and keep naming the first element, so every current reader is unchanged.
  • Reuse an existing issue element shape if one fits (for example ValidateDataIssueSchema, which warnings already uses) rather than a new one. The spec seat measures which.

Producer: the core coercion already builds this list. coerceRow returns every error, and import-runner.ts (about :1132) keeps errors[0].

Out of scope


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1 · 2026-10-27T03:45Z
    Session: session_01WGufzfhobWEgUUrjz4rrbh
    Account: os-support-ai
    Branch: claude/project-thread-fb0xrv (card thread session_01WGufzfC9dmHR7kTAVNHv56. The platform assigns the thread's branch and the thread can push only that one, so the branch is written as measured instead of claude/issue-26425-<slug>.)
    Worktree: objectstack-issue-26425
    Domain: domain:spec
    Seat: domain:spec#1
    File surface: packages/spec/src/api/export.zod.ts (ImportRowResultSchema, one optional errors member), one spec test under packages/spec, one changeset, and the artifacts check:generated regenerates. ⛔ No packages/core/src/utils/import-runner.ts (that is #25582's server half). Stop on a breach and explain it in the report.
    Container & model: S, mode:thread, model: TIER_DEFAULT, default effort
    Clause-②: yes (widening)
    Metadata-protocol: none
    Responsibility: n/a. This is a ruled protocol addition, not a defect card.
    Thread-read: none
    Premise: holds (read at origin/main: ImportRowResultSchema at packages/spec/src/api/export.zod.ts:401 is a z.object with field/code/error and no errors member, and ValidateDataIssueSchema exists at protocol.zod.ts:2456)
    Serial constraints cleared: yes. No open PR or claim names export.zod.ts. #25582's server half is blocked behind this card and does not touch spec.
    Ruling-ref: #25582 ruling 6377844879 (batch #9 item 3a, letter A), proposal 4. Proposal 3 (aliases) is excluded.

  2. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 26425,
    "status": "done",
    "branch": "claude/project-thread-fb0xrv",
    "pr": "#26454",
    "session": "session_01WGufzfC9dmHR7kTAVNHv56",
    "premise_still_valid": true,
    "summary": "ImportRowResultSchema (packages/spec/src/api/export.zod.ts) declares one optional member, errors: z.array(ValidateDataIssueSchema), one element per failed cell of a failed row, present only on a failed row with at least one cell error; field/code/error stay and name element 0 (describes and docblock say so). Element shape reused, not new: its required members are exactly the ruling's { field, code, message }, coerceRow's FieldCoerceError fits it unmapped, and the row's warnings plus the validate verdict's row errors already use it; the only cost is the advisory-only optional rule/severity, documented as never present on a cell error. Spec only, import-runner.ts untouched. Premise held at origin/main 75afeff: the schema had no errors key and import-runner.ts:1221 keeps errors[0].",
    "tests": "head 2c2ade7. pnpm --filter @objectstack/spec test (lock): Test Files 727 passed (727), Tests 22016 passed | 1 todo, VERDICT command-exit 0. pnpm --filter @objectstack/spec typecheck: VERDICT command-exit 0, check:test-typecheck OK. New describe in src/api/export.test.ts, 7 tests (parse keeps errors in order; field/code/error agree with element 0; optional; element toBe ValidateDataIssueSchema and equals the warnings element; element without message refused at errors.0.message; ImportResponseSchema and ImportJobResultsSchema keep it; expectTypeOf ValidateDataIssue). Ablation via scripts/ablation-replace.mjs (errors: renamed ablatedErrors:, anchor 1 to 0, blob ee8a1e9b6078 to 69e10a948a46): Tests 5 failed | 52 passed (57), the optional-key test stayed green as expected; restored, blob == HEAD, git diff HEAD empty. Test imports ./export.zod from src, so no dist leg.",
    "gates": "local, head 2c2ade7: check:generated first named content/docs/references/** stale, gen:docs, then 'All 14 generated artifacts are up to date' (exit 0). dispatch-gates --commands derived 106; all run with exit codes recorded; --ran: '106 derived famil(ies) accounted for, 99 run, 7 NOT-MEASURED (7 DERIVED from a recorded exit 3)'. NOT MEASURED, prerequisite refusals unrelated to packages/spec: lint check:doc-formula-expressions and check:doc-security-posture (formula/lint not built), spec check:skill-examples (client-react dist not built), check:docs-transcript-drift (lint not built), check:dual-build-cjs-loads and check:lean-entry-closure (other dists not built), check-plugin-teardown-shape --self-test (shallow checkout). Local-only check:dev-prereqs exit 1: 37 workspace packages (mostly ui/) not built, local state not this diff; spec dist stamp fresh. CI on PR at report time: No other open PR may claim the same issue = success; the rest in_progress (Lint lanes, Type Check lanes, Check Changeset, Governed Surface Queue Guard, Check PR Size, claim-branch check).",
    "dogfood_battery": "n/a: no ! in the PR title, Clause-② arm is (widening)",
    "mcp_calls": "2: issue_read x2 (get, get_comments on #26425); no MCP write",
    "api_writes": "2 relay strokes via scripts/pm/fleet-write/dispatch.mjs: (1) pr_create POST /repos/objectstack-ai/objectstack/pulls + POST issues/26454/assignees, read-back identical 8453 bytes, assignee os-support-ai; (2) this report: comment POST issues/26425/comments, plus pr_request_reviewers POST pulls/26454/requested_reviewers (os-support-ai, per the project's PR-attribution instruction). Plus git push x3 to the branch.",
    "open_questions": [
    {
    "question": "On a dry-run row the validate verdict rejects, import-runner.ts (about :1293) sets error to composeValidationMessage(verdict.errors), every finding joined by '; ', not element 0's message. If #25582's server half also fills errors on those rows, error would not name element 0. Which does #25582 do?",
    "options": [
    "A: #25582 fills errors only from coerceRow's cell errors (:1221), where error already equals element 0's message; verdict rows keep today's composed error and no errors key",
    "B: #25582 fills errors on verdict rows too and keeps the composed error there; a follow-up spec PR adds one describe sentence that error may compose every element on such a row",
    "C: #25582 fills errors on verdict rows and sets error to element 0's message there"
    ],
    "recommendation": "A for #25582's first cut, because it is exactly the ruling's cell-error scope and needs no spec follow-up; B later only if verdict rows prove to need it. Carrier: #25582, not this PR."
    }
    ],
    "out_of_scope_findings": [
    "carrier: #25582 · the composed-error divergence above, noted in the PR Acceptance notes, not filed"
    ]
    }


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim amendment · domain:spec seat 1 (#6017) · session session_01WGufzfhobWEgUUrjz4rrbh · 2026-10-27T04:29Z

    Supersedes the Metadata-protocol line of claim 6433227708. Everything else in it stands.

    Metadata-protocol: added
    Clause-②: yes (widening)

    Why: the PR moves packages/spec/authorable-surface/api.json (api/ImportRowResult:errors), and check-changeset-no-major refuses none when the baseline moves (none-baseline-moved). The claim's none was the seat's error, and the dev copied it. The changeset grade becomes '@objectstack/spec': minor, as with the warnings widening of the same schema. Contract review FAIL: 6433766607.

  4. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · domain:spec seat 1 (#6017) · session session_01WGufzfhobWEgUUrjz4rrbh · 2026-10-27T05:36Z

    PR #26454 merged at 43714cae (merged 2026-10-27T05:35Z). 43714cae is an ancestor of origin/main. On every path the PR touched, the merge tree matches the accepted head eff10df5 byte for byte.

    ImportRowResultSchema now declares an optional errors list: every cell error of a failed row, in the ValidateDataIssueSchema shape. It is filled from the import's cell coercion, and field / code / error keep naming element 0. @objectstack/spec grade: minor, Metadata-protocol: added. The server half is #25582. It fills errors from coerceRow's cell errors only (option A); a fill from verdict rows or refused writes would be a spec change. The card closed through Fixes #26425, and this seat removes pm:dispatched.

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, searchdomain:specenhancementNew feature or requestpriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions