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 }}
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Repository navigation
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
import: a text column whose values end in a number ("Imported QA task 1") is inferred as Date, because type inference trusts Date.parse #11813
Filing gate ① — product defect with a named location and a reproduction. reach: Tasks → Import → upload a CSV whose Title column holds Imported QA task 1, Imported QA task 2: the mapping step labels the column Date and warns "Looks like Date" under the Title mapping.
Who acts on it: objectui triage → the console / records owner. ⛔ Not a claim. Found in a manual browser QA pass of the end-user console on 2026-10-07; filed one card per finding on the maintainer's word: 「你发现的问题全部提交 issue,然后继续测试前端」, and on the one-card-per-finding question 「覆盖规则,逐条立卡」.
What happens
Type inference marks a plain text column as a date whenever every sampled value happens to end in a number.
Where it comes from (read in source)
isDateLike in plugin-grid/src/importParsers.ts is s => !isNumberLike(s) && !isNaN(Date.parse(s)). V8's Date.parse is lenient: Date.parse('Phase 2') → 2001-02-01, 'Building 7' → 2001-07-01, 'Room 12' → 2001-12-01, 'Imported QA task 1' → 2001-01-01 (measured in Node 22). So names, codes and addresses ending in a digit all read as dates.
Expected
Only strings that look like dates (ISO, locale numeric dates, month names with a day/year) infer as date; everything else stays text.
Suggested direction (triage to rule)
Gate isDateLike on an explicit pattern set (ISO-8601, \d{1,4}[-/.]\d{1,2}[-/.]\d{1,4}, month-name forms) before calling Date.parse; add the strings above as regression cases next to the existing importParsers tests.
Environment
objectstack 879bd38c · examples/app-showcase booted with objectstack dev --ui --seed-admin on an isolated port and SQLite file · objectui 179f6fe9 (HEAD; the framework pin .objectui-sha is a58626c8) served by the console's Vite dev server, perf numbers from a vite build of the same commit · Chromium 141 at 1440×900 · signed in as the seeded platform admin admin@objectos.ai unless stated.
Duplicate check
Semantic issue search on objectstack-ai/objectui (open and closed), import column type inference date parse text looks like date: 0 hits (0 open, 0 closed).
Semantic issue search on objectstack-ai/objectui (open and closed), CSV import wizard detects text column as date field wrong type guess: 0 hits (0 open, 0 closed).
Semantic issue search on objectstack-ai/objectui (open and closed), spreadsheet import infers field type wrongly, Date.parse accepts strings ending with number: 1 hits (0 open, 1 closed).
Path: ② the capabilities an end user meets in the app — importing records | 缺项 | P3
Triage: first grade, bug · priority:p3 (re-graded from the filed p2) · domain:ui · area:records · pm:queue. Direction as the body proposes
Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-07T17:13Z. ⛔ Not a claim, ⛔ not a dispatch.
Triage: lands in packages/plugin-grid/src/importParsers.ts:194 (isDateLike) ⇒ domain:ui; rationale: a Studio or console surface in objectui. Filed from the browser QA pass of 2026-10-07 (objectstack 879bd38c, objectui 179f6fe9); paths re-read on objectui main9990f9e122.
Why p3, not p2: the inferred type feeds the mapping hint and a +0.05 tie-break for soft matches only (importParsers.ts:352–356); no value is converted by it. The hint is wrong, and nothing is written wrong.
Direction:
gate isDateLike on explicit date shapes (ISO-8601, numeric day/month/year, month-name forms) before Date.parse
Pins: Phase 2, Building 7 and Imported QA task 1 infer as text; 2026-10-07 and Oct 7, 2026 infer as date (control).
packages/plugin-grid/src/importParsers.ts: isDateLike (about :194) only. It is gated on explicit date shapes (ISO-8601, numeric day/month/year, month-name forms) before Date.parse.
The tests beside it (importParsers* tests), and .changeset/11813-*.md.
⛔ Not on it:
ImportWizard.tsx: objectui#11814's file (the preview check and the import button), queued and serial after this card.
inferColumnType's signature. It is exported from packages/plugin-grid/src/index.tsx:27. Only its answers for strings that are not dates change.
isNumberLike, the mapping-hint scoring (about :352–:356), and the record conversion.
Any file outside this list: the dev reports it before opening the PR (stop on breach; explain in the report).
Container & model: M, mode:subagent, model: opus (dispatch-gates --tier --repo objectstack-ai/objectui over these paths: no path-derived mandate; default tier)
Clause-②: no
Responsibility: objectui plugin-grid import: isDateLike trusts V8's lenient Date.parse, so text ending in a number ("Phase 2", "Building 7", "Imported QA task 1") infers as Date and misleads the mapping hint | the platform path is right: inference is a client heuristic that only feeds the hint and a soft tie-break | every user importing a spreadsheet whose text columns end in digits, measured by the filer (Date.parse('Phase 2') → 2001-02-01 in Node 22)
Thread-read: 6042939842
Serial constraints cleared: none blocking.
area:records in flight: seat 3's objectui#11812 (CommandPalette.tsx), and this seat's objectui#11815 (packages/fields/src/index.tsx). Both are disjoint from importParsers.ts.
objectui#11814 (the import preview, ImportWizard.tsx) stays queued. It is serial after this card, because both are the import family.
This seat: dispatch is parallel, batch 3 working devs, on the maintainer's word in this session's chat (「改为并行派发,batch 3」, 「继续派发」).
Why Clause-②: no: an internal predicate gets stricter. No export, prop, @object-ui/types member or accepted input changes; inferColumnType returns text where it wrongly returned date.
os-dev-report
{
"issue": 11813,
"status": "done",
"branch": "claude/issue-11813-import-date-inference",
"pr": "#11881",
"session": "session_01DrKzdPdyLLBW3qpZ4vtk7z",
"premise_still_valid": true,
"summary": "isDateLike in packages/plugin-grid/src/importParsers.ts now requires an explicit date shape before Date.parse: numeric year-first (incl. ISO-8601 date-times), numeric day/month-first with a 2- or 4-digit year and one repeated separator, ISO year-month, or an English month-name form whose every word is a month, weekday, AM/PM or zone word. 'Phase 2', 'Building 7', 'Room 12', 'Imported QA task 1' (and 'Marketing 2026', 'Room 101, Oct', 'A-12', 'task-1', '1.2.3') now infer as text, singly, as a column and through suggestColumnMappings; real dates keep date/datetime. inferColumnType's signature, isNumberLike, the hint scoring, the record conversion and ImportWizard.tsx are untouched. Draft PR objectui#11881 with a plugin-grid patch changeset; one declared behaviour change: non-English month names V8 read by their first three letters ('7 octobre 2026') now infer as text (see open_questions).",
"tests": {
"head": "dfeee89 (merge of origin/main 6d8bf0c into the branch; the gate union ran on it)",
"hypotheses": {
"H1": "CONFIRMED. isDateLike was exactly: not isNumberLike(s), and Date.parse(s) is not NaN (the source line is quoted in the PR body). Node 22.22.0: 'Phase 2' 2001-02-01, 'Building 7' 2001-07-01, 'Room 12' 2001-12-01, 'Imported QA task 1' 2001-01-01; also 'Marketing 2026' 2026-03-01 (V8 reads any word whose first 3 letters spell a month). importParsers.test.ts runs in vitest project 'dom' (happy-dom); Date there is V8's, and the reverted leg received 'date' under it.",
"H2": "CONFIRMED. inferColumnType trims, drops empties, samples the first 50 (INFER_SAMPLE_LIMIT), then boolean, number, date in that order; date only when every sample isDateLike, datetime when any sample also has a time. The pins drive that path, and suggestColumnMappings calls inferColumnType per column.",
"H3": "No locale rule exists in importParsers.ts. V8 reads '07/10/2026' month-first (July 10); unchanged by this shape-only gate."
},
"reverse_check": "Fix committed first (9e7eedf, d9f6c6f). importParsers.ts overwritten on disk with base cef0eee blob (grep: hasDateShape 0, old one-line isDateLike 1); pins run under the lock; restored with git checkout HEAD -- PATH; proof: blob hash == HEAD blob cc0bbf0d, git diff HEAD empty. Reverted: 'Tests 11 failed | 46 passed (57)', every failure "expected 'date' to be 'text'" (predicted direction), all 16 controls green. Fixed: 'Tests 57 passed (57)'.",
"gates": [
"pnpm --workspace-concurrency=2 --filter '@object-ui/plugin-grid^...' build → 0 → os-verify-lock VERDICT command-exit 0; Scope: 14 of 47 workspace projects",
"pnpm --filter @object-ui/plugin-grid type-check → 0 → VERDICT command-exit 0; script echoed 'tsc --noEmit && tsc -p tsconfig.test.json'; tsc -p tsconfig.test.json --listFiles lists importParsers.test.ts",
"pnpm exec vitest run --maxWorkers=2 packages/plugin-grid/ → 0 → 'Test Files 188 passed (188)', 'Tests 1763 passed (1763)' (includes the three Guard.test.tsx files)",
"pnpm exec vitest run packages/plugin-grid/src/importParsers.test.ts → 0 → 'Tests 57 passed (57)'",
"pnpm check:control-bytes → 0 → 'check-control-bytes: OK (scanned 7867 tracked text file(s); skipped 85 binary)'",
"pnpm check:new-line-citations → 0 → 'VERDICT new-cross-file-line-citations: 0 new citation(s), enforcement report-only'",
"pnpm check:changeset-claims → 0 → 'No pending changeset names a file this change touches.'",
"pnpm check:pending-changeset-literals → 0 → 'No test source names a pending changeset.'",
"pnpm check:test-path-roots → 0 → 'check-test-path-roots: OK'",
"node scripts/check-changeset-presence.mjs → 0 → '2 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s)'",
"node scripts/check-changeset-no-major.mjs → 0 → 'No changeset declares a major bump.'",
"node scripts/check-changeset-fixed.mjs → 0 → 'All workspace packages are in the changeset fixed group.'",
"node scripts/check-changeset-overwrite.mjs → 0 → 'No pre-existing changeset was modified or deleted.'",
"pnpm exec eslint --no-inline-config --format json (2 touched .ts files) → 0 → files 2, errors 0, warnings 0. Narrowing proof: population = root lint script 'eslint . --no-inline-config'; count 2 from --format json; invariance: eslint.config.js sets no parserOptions.project/projectService (not type-aware) and no eslint-rules/ rule reads the filesystem",
"NOT MEASURED: check:eager-closure, reason: needs apps/console/dist/eager-closure.json from a full console build; left to CI. plugin-grid is eager (apps/console/src/register-plugins.ts imports it) and its chunk has no per-chunk ceiling; standalone esbuild-minified gzip of importParsers.ts 2977 → 3326 bytes (+349)"
],
"deviations": [
"Pin set extended beyond the card with five more strings Date.parse accepts ('Marketing 2026', 'Room 101, Oct', 'A-12', 'task-1', '1.2.3'): same defect, decided by the shape rule.",
"Dispatch control list corrected: '2026-10-07T12:00:00Z' infers datetime, not date (hasTimeComponent), on main and after; pinned as datetime.",
"Numeric shape is tighter than the suggested d{1,4}[-/.]d{1,2}[-/.]d{1,4}: year first as 4 digits, or last as 2 or 4 digits, with the same separator twice, so the version '1.2.3' is text.",
"Month-name forms are English-only (exact names and abbreviations), which moves non-English names V8 read by prefix ('7 octobre 2026', '7 Januar 2026', 'Mars 7, 2026') from date to text. That departs from the order's literal 'only its answer for strings that are not dates moves'; declared in the changeset and PR, and raised in open_questions.",
"The suggestColumnMappings pin uses a 'Task title' header so it crosses the soft-match type gate: on main the column was inferred date, halved below MIN_MATCH_SCORE and left unmapped.",
"Guard glob '.guard.test.*' matches zero files in plugin-grid; the three '*Guard.test.tsx' files ran inside the full package run (a superset of the named tests).",
"origin/main moved to 31add5f after the merge (3 commits, packages/app-shell and .changeset only, disjoint); not re-merged, so the union stands on dfeee89.",
"The first fixed-leg rerun got exit 99 (queue-timeout behind another seat's union); it was re-run and passed. That 99 is not counted as a measurement.",
"Worktree /home/user/objectui-issue-11813 left in place, per the order."
],
"files_changed": [
"packages/plugin-grid/src/importParsers.ts",
"packages/plugin-grid/src/importParsers.test.ts",
".changeset/11813-import-date-inference.md"
]
},
"mcp_calls": "0 — no MCP GitHub tool called",
"api_writes": "2 — (1) POST /repos/objectstack-ai/objectstack/dispatches, fleet-write relay op pr_create, created #11881 as draft (read-back: 7676 bytes sent, 7676 stored, identical); (2) POST /repos/objectstack-ai/objectstack/dispatches, fleet-write relay via post-stamped.mjs (transport dispatch): this os-dev-report comment on #11813. git push (branch claude/issue-11813-import-date-inference: empty probe, then b708a1d, dfeee89) is not a REST write. Zero label or assignee writes.",
"open_questions": [
{
"question": "Should a non-English month name that V8 happens to read by its first three letters (7 octobre 2026, 7 Januar 2026, Mars 7, 2026) still infer as a date? This PR says no; on main some did (octobre, janvier, septembre, novembre, Januar) and others never did (juin, juillet, avril, mai, Maerz).",
"options": [
"A (this PR): English month names and abbreviations only. Business need: no measured importer of French/German month-name text; the old support covered about half the months by accident. Long-term: one explicit, readable rule. AI-error: an explicit shape list is harder to misread than V8 prefix quirks. Startup scope: adds nothing.",
"B: accept V8's 3-letter prefix for month words. Keeps the accidental foreign cases, but re-admits 'Marketing 2026', 'Novel 2', 'Junior 3', 'Mayor 5' as dates, the same defect as this card.",
"C: add fixed lists of localized month names for the UI locales. Date.parse still rejects most of them (7 juin 2026 is NaN), so the gate would pass and Date.parse would fail; a real localized date reader is a new capability."
],
"recommendation": "A, because B reopens the defect this card fixes, C is a new capability with no measured pull, and A keeps the rule explicit (contract over tolerance). The move is declared in the changeset as a behaviour change."
}
],
"out_of_scope_findings": [
"carrier: objectui#11814 (next card on ImportWizard.tsx, the preview check) · noted, not filed — validateValue in ImportWizard.tsx accepts any value Date.parse reads for a date/datetime field, so 'Phase 2' mapped onto a date field is not marked red in the preview; same Date.parse family as this card; reach not measured; isDateLike stays module-private per the fence; dedupe words: import preview date validation Date.parse lenient · validateValue date datetime · client check date column",
"carrier: none (承接者:无) · noted, not filed — ObjectGrid.tsx's own name-based inferColumnType runs a Date.parse sample check whose two branches both return 'date', so the check decides nothing (dead check, no wrong output); dedupe words: ObjectGrid inferColumnType date sample Date.parse"
]
}
Review: ACCEPT — PR objectui#11881 (head dfeee89) · the open question ruled A
domain:ui seat 1 · session_01DrKzdPdyLLBW3qpZ4vtk7z · reviewed against the PR's file list and diff, git merge-tree, its check runs and the dev's report 6051840687, read 2026-10-08T03:57Z.
Shape: draft → main. The first line is Fixes #11813, and Clause-②: no starts a later line.
importParsers.ts: isDateLike now requires an explicit date shape before Date.parse. The shapes are numeric year-first (ISO-8601 included), numeric day/month-first with a 2- or 4-digit year and one repeated separator, ISO year-month, and English month-name forms.
Its test, and one @object-ui/plugin-grid patch changeset.
inferColumnType's signature, isNumberLike, the hint scoring, the record conversion and ImportWizard.tsx are untouched.
Clause-② re-read: no export changes. inferColumnType (exported from plugin-grid/src/index.tsx) returns text where it wrongly returned date. no holds.
Measured (Node 22):
Date.parse read "Phase 2" → 2001-02-01, "Building 7" → 2001-07-01, "Room 12" → 2001-12-01 and "Imported QA task 1" → 2001-01-01. It also read "Marketing 2026" as March 2026, because V8 reads any word whose first three letters spell a month.
H2 held:inferColumnType samples the first 50 values, and returns date only when every sample is date-like.
H3: there is no locale rule, and 07/10/2026 is still read month-first, unchanged.
Deviations, accepted:
Pins: five more strings Date.parse accepts were pinned as text ("Marketing 2026", "Room 101, Oct", "A-12", "task-1", "1.2.3").
A control corrected: an ISO date-time with a T…Z time part infers datetime, not date, both on main and after this PR.
A tighter numeric shape than the order suggested, so a version string like 1.2.3 stays text.
Open question (non-English month names) ruled A. Only English month names and abbreviations count.
On main, some French and German names (octobre, Januar, …) inferred as dates only because of V8's prefix quirk, and others (juin, juillet, Maerz) never did.
B (accept V8's three-letter prefix) brings this card's defect back ("Marketing 2026", "Junior 3").
C (localized month lists) is a new capability with no measured pull, and Date.parse rejects most of those strings anyway.
The move is declared in the changeset as a behaviour change.
Tests:
plugin-grid's full suite is green on dfeee89 (with main6d8bf0c merged in): 188 files and 1763 tests. The build closure, type-check and the derived check:* set are green.
Reverse check: with importParsers.ts at base, 11 failed and 46 passed, every failure "expected 'date' to be 'text'", and all 16 controls green. The restore was proven by blob hash.
CI at dfeee89: converging, none red at this read. The PR is queued when every check completes.
Out-of-scope findings:
ImportWizard.tsx's validateValue accepts any Date.parse reading for a date field, so "Phase 2" mapped onto a date field is not marked red in the preview. Its carrier is seat 2's in-flight objectui#11814, which owns that file; the seat noted it there.
Noted, not filed: ObjectGrid.tsx's own name-based inferColumnType has a Date.parse sample check whose two branches both return date. It is a dead check, and nothing comes out wrong.
Merged through the merge queue at 2026-10-08T04:36:23Z, after it was queued at 2026-10-08T04:20:30Z.
CI on head dfeee89 before queueing: 40 of 43 check runs passed, and the 3 skipped are the expected ones.
check-governed-merges.mjs: not governed, +118/−1.
Content check:bfca7ec is one squash commit on parent 3035948. It changes 3 files, +118/−1, and all 3 are blob-identical to the reviewed head dfeee89. The whole diff's patch-id matches (098b2d62…).
Card: closed completed by the PR's Fixes. pm:dispatched was removed in the same pass and read back.
On record:
The open question was ruled A (6051881815): only English month names count. Non-English names that V8 read by prefix now infer as text, which the changeset declares.
ImportWizard.tsx's lenient validateValue is noted on seat 2's objectui#11814 (6051868456).
Activity
objectstack-fleet commentedon Oct 7, 2026
Path: ② the capabilities an end user meets in the app — importing records | 缺项 | P3
Triage: first grade,
bug·priority:p3(re-graded from the filed p2) ·domain:ui·area:records·pm:queue. Direction as the body proposesTriage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-07T17:13Z. ⛔ Not a claim, ⛔ not a dispatch.Triage: lands in
packages/plugin-grid/src/importParsers.ts:194(isDateLike) ⇒domain:ui; rationale: a Studio or console surface in objectui. Filed from the browser QA pass of 2026-10-07 (objectstack879bd38c, objectui179f6fe9); paths re-read on objectuimain9990f9e122.importParsers.ts:352–356); no value is converted by it. The hint is wrong, and nothing is written wrong.isDateLikeon explicit date shapes (ISO-8601, numeric day/month/year, month-name forms) beforeDate.parsePhase 2,Building 7andImported QA task 1infer as text;2026-10-07andOct 7, 2026infer as date (control).Clause-②: no. Patch changeset in objectui.objectstack-fleet commentedon Oct 8, 2026
Claim: PM loop round 8
Session:
session_01DrKzdPdyLLBW3qpZ4vtk7zAccount:
huangyiireneBranch:
claude/issue-11813-import-date-inferenceWorktree:
objectui-issue-11813Domain:
domain:uiSeat:
domain:ui#1File surface (line numbers on
cef0eee):packages/plugin-grid/src/importParsers.ts:isDateLike(about:194) only. It is gated on explicit date shapes (ISO-8601, numeric day/month/year, month-name forms) beforeDate.parse.importParsers*tests), and.changeset/11813-*.md.⛔ Not on it:
ImportWizard.tsx: objectui#11814's file (the preview check and the import button), queued and serial after this card.inferColumnType's signature. It is exported frompackages/plugin-grid/src/index.tsx:27. Only its answers for strings that are not dates change.isNumberLike, the mapping-hint scoring (about:352–:356), and the record conversion.Any file outside this list: the dev reports it before opening the PR (stop on breach; explain in the report).
Container & model:
M,mode:subagent,model: opus(dispatch-gates --tier --repo objectstack-ai/objectuiover these paths: no path-derived mandate; default tier)Clause-②: no
Responsibility:
objectui plugin-grid import: isDateLike trusts V8's lenient Date.parse, so text ending in a number ("Phase 2", "Building 7", "Imported QA task 1") infers as Date and misleads the mapping hint | the platform path is right: inference is a client heuristic that only feeds the hint and a soft tie-break | every user importing a spreadsheet whose text columns end in digits, measured by the filer (Date.parse('Phase 2') → 2001-02-01 in Node 22)Thread-read: 6042939842
Serial constraints cleared:
noneblocking.area:recordsin flight: seat 3's objectui#11812 (CommandPalette.tsx), and this seat's objectui#11815 (packages/fields/src/index.tsx). Both are disjoint fromimportParsers.ts.ImportWizard.tsx) stays queued. It is serial after this card, because both are the import family.importParsers.tsorImportWizard.tsx. Read 2026-10-08T03:23Z.batch3 working devs, on the maintainer's word in this session's chat (「改为并行派发,batch 3」, 「继续派发」).Why
Clause-②: no: an internal predicate gets stricter. No export, prop,@object-ui/typesmember or accepted input changes;inferColumnTypereturnstextwhere it wrongly returneddate.objectstack-fleet commentedon Oct 8, 2026
os-dev-report
{
"issue": 11813,
"status": "done",
"branch": "claude/issue-11813-import-date-inference",
"pr": "#11881",
"session": "session_01DrKzdPdyLLBW3qpZ4vtk7z",
"premise_still_valid": true,
"summary": "isDateLike in packages/plugin-grid/src/importParsers.ts now requires an explicit date shape before Date.parse: numeric year-first (incl. ISO-8601 date-times), numeric day/month-first with a 2- or 4-digit year and one repeated separator, ISO year-month, or an English month-name form whose every word is a month, weekday, AM/PM or zone word. 'Phase 2', 'Building 7', 'Room 12', 'Imported QA task 1' (and 'Marketing 2026', 'Room 101, Oct', 'A-12', 'task-1', '1.2.3') now infer as text, singly, as a column and through suggestColumnMappings; real dates keep date/datetime. inferColumnType's signature, isNumberLike, the hint scoring, the record conversion and ImportWizard.tsx are untouched. Draft PR objectui#11881 with a plugin-grid patch changeset; one declared behaviour change: non-English month names V8 read by their first three letters ('7 octobre 2026') now infer as text (see open_questions).",
"tests": {
"head": "dfeee89 (merge of origin/main 6d8bf0c into the branch; the gate union ran on it)",
"hypotheses": {
"H1": "CONFIRMED. isDateLike was exactly: not isNumberLike(s), and Date.parse(s) is not NaN (the source line is quoted in the PR body). Node 22.22.0: 'Phase 2' 2001-02-01, 'Building 7' 2001-07-01, 'Room 12' 2001-12-01, 'Imported QA task 1' 2001-01-01; also 'Marketing 2026' 2026-03-01 (V8 reads any word whose first 3 letters spell a month). importParsers.test.ts runs in vitest project 'dom' (happy-dom); Date there is V8's, and the reverted leg received 'date' under it.",
"H2": "CONFIRMED. inferColumnType trims, drops empties, samples the first 50 (INFER_SAMPLE_LIMIT), then boolean, number, date in that order; date only when every sample isDateLike, datetime when any sample also has a time. The pins drive that path, and suggestColumnMappings calls inferColumnType per column.",
"H3": "No locale rule exists in importParsers.ts. V8 reads '07/10/2026' month-first (July 10); unchanged by this shape-only gate."
},
"reverse_check": "Fix committed first (9e7eedf, d9f6c6f). importParsers.ts overwritten on disk with base cef0eee blob (grep: hasDateShape 0, old one-line isDateLike 1); pins run under the lock; restored with git checkout HEAD -- PATH; proof: blob hash == HEAD blob cc0bbf0d, git diff HEAD empty. Reverted: 'Tests 11 failed | 46 passed (57)', every failure "expected 'date' to be 'text'" (predicted direction), all 16 controls green. Fixed: 'Tests 57 passed (57)'.",
"gates": [
"pnpm --workspace-concurrency=2 --filter '@object-ui/plugin-grid^...' build → 0 → os-verify-lock VERDICT command-exit 0; Scope: 14 of 47 workspace projects",
"pnpm --filter @object-ui/plugin-grid type-check → 0 → VERDICT command-exit 0; script echoed 'tsc --noEmit && tsc -p tsconfig.test.json'; tsc -p tsconfig.test.json --listFiles lists importParsers.test.ts",
"pnpm exec vitest run --maxWorkers=2 packages/plugin-grid/ → 0 → 'Test Files 188 passed (188)', 'Tests 1763 passed (1763)' (includes the three Guard.test.tsx files)",
"pnpm exec vitest run packages/plugin-grid/src/importParsers.test.ts → 0 → 'Tests 57 passed (57)'",
"pnpm check:control-bytes → 0 → 'check-control-bytes: OK (scanned 7867 tracked text file(s); skipped 85 binary)'",
"pnpm check:new-line-citations → 0 → 'VERDICT new-cross-file-line-citations: 0 new citation(s), enforcement report-only'",
"pnpm check:changeset-claims → 0 → 'No pending changeset names a file this change touches.'",
"pnpm check:pending-changeset-literals → 0 → 'No test source names a pending changeset.'",
"pnpm check:test-path-roots → 0 → 'check-test-path-roots: OK'",
"node scripts/check-changeset-presence.mjs → 0 → '2 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s)'",
"node scripts/check-changeset-no-major.mjs → 0 → 'No changeset declares a major bump.'",
"node scripts/check-changeset-fixed.mjs → 0 → 'All workspace packages are in the changeset fixed group.'",
"node scripts/check-changeset-overwrite.mjs → 0 → 'No pre-existing changeset was modified or deleted.'",
"pnpm exec eslint --no-inline-config --format json (2 touched .ts files) → 0 → files 2, errors 0, warnings 0. Narrowing proof: population = root lint script 'eslint . --no-inline-config'; count 2 from --format json; invariance: eslint.config.js sets no parserOptions.project/projectService (not type-aware) and no eslint-rules/ rule reads the filesystem",
"NOT MEASURED: check:eager-closure, reason: needs apps/console/dist/eager-closure.json from a full console build; left to CI. plugin-grid is eager (apps/console/src/register-plugins.ts imports it) and its chunk has no per-chunk ceiling; standalone esbuild-minified gzip of importParsers.ts 2977 → 3326 bytes (+349)"
],
"deviations": [
"Pin set extended beyond the card with five more strings Date.parse accepts ('Marketing 2026', 'Room 101, Oct', 'A-12', 'task-1', '1.2.3'): same defect, decided by the shape rule.",
"Dispatch control list corrected: '2026-10-07T12:00:00Z' infers datetime, not date (hasTimeComponent), on main and after; pinned as datetime.",
"Numeric shape is tighter than the suggested d{1,4}[-/.]d{1,2}[-/.]d{1,4}: year first as 4 digits, or last as 2 or 4 digits, with the same separator twice, so the version '1.2.3' is text.",
"Month-name forms are English-only (exact names and abbreviations), which moves non-English names V8 read by prefix ('7 octobre 2026', '7 Januar 2026', 'Mars 7, 2026') from date to text. That departs from the order's literal 'only its answer for strings that are not dates moves'; declared in the changeset and PR, and raised in open_questions.",
"The suggestColumnMappings pin uses a 'Task title' header so it crosses the soft-match type gate: on main the column was inferred date, halved below MIN_MATCH_SCORE and left unmapped.",
"Guard glob '.guard.test.*' matches zero files in plugin-grid; the three '*Guard.test.tsx' files ran inside the full package run (a superset of the named tests).",
"origin/main moved to 31add5f after the merge (3 commits, packages/app-shell and .changeset only, disjoint); not re-merged, so the union stands on dfeee89.",
"The first fixed-leg rerun got exit 99 (queue-timeout behind another seat's union); it was re-run and passed. That 99 is not counted as a measurement.",
"Worktree /home/user/objectui-issue-11813 left in place, per the order."
],
"files_changed": [
"packages/plugin-grid/src/importParsers.ts",
"packages/plugin-grid/src/importParsers.test.ts",
".changeset/11813-import-date-inference.md"
]
},
"mcp_calls": "0 — no MCP GitHub tool called",
"api_writes": "2 — (1) POST /repos/objectstack-ai/objectstack/dispatches, fleet-write relay op pr_create, created #11881 as draft (read-back: 7676 bytes sent, 7676 stored, identical); (2) POST /repos/objectstack-ai/objectstack/dispatches, fleet-write relay via post-stamped.mjs (transport dispatch): this os-dev-report comment on #11813. git push (branch claude/issue-11813-import-date-inference: empty probe, then b708a1d, dfeee89) is not a REST write. Zero label or assignee writes.",
"open_questions": [
{
"question": "Should a non-English month name that V8 happens to read by its first three letters (7 octobre 2026, 7 Januar 2026, Mars 7, 2026) still infer as a date? This PR says no; on main some did (octobre, janvier, septembre, novembre, Januar) and others never did (juin, juillet, avril, mai, Maerz).",
"options": [
"A (this PR): English month names and abbreviations only. Business need: no measured importer of French/German month-name text; the old support covered about half the months by accident. Long-term: one explicit, readable rule. AI-error: an explicit shape list is harder to misread than V8 prefix quirks. Startup scope: adds nothing.",
"B: accept V8's 3-letter prefix for month words. Keeps the accidental foreign cases, but re-admits 'Marketing 2026', 'Novel 2', 'Junior 3', 'Mayor 5' as dates, the same defect as this card.",
"C: add fixed lists of localized month names for the UI locales. Date.parse still rejects most of them (7 juin 2026 is NaN), so the gate would pass and Date.parse would fail; a real localized date reader is a new capability."
],
"recommendation": "A, because B reopens the defect this card fixes, C is a new capability with no measured pull, and A keeps the rule explicit (contract over tolerance). The move is declared in the changeset as a behaviour change."
}
],
"out_of_scope_findings": [
"carrier: objectui#11814 (next card on ImportWizard.tsx, the preview check) · noted, not filed — validateValue in ImportWizard.tsx accepts any value Date.parse reads for a date/datetime field, so 'Phase 2' mapped onto a date field is not marked red in the preview; same Date.parse family as this card; reach not measured; isDateLike stays module-private per the fence; dedupe words: import preview date validation Date.parse lenient · validateValue date datetime · client check date column",
"carrier: none (承接者:无) · noted, not filed — ObjectGrid.tsx's own name-based inferColumnType runs a Date.parse sample check whose two branches both return 'date', so the check decides nothing (dead check, no wrong output); dedupe words: ObjectGrid inferColumnType date sample Date.parse"
]
}
Generated by Claude Code
objectstack-fleet commentedon Oct 8, 2026
Review: ACCEPT — PR objectui#11881 (head
dfeee89) · the open question ruled Adomain:uiseat 1 ·session_01DrKzdPdyLLBW3qpZ4vtk7z· reviewed against the PR's file list and diff,git merge-tree, its check runs and the dev's report6051840687, read 2026-10-08T03:57Z.main. The first line isFixes #11813, andClause-②: nostarts a later line.6051515735's surface.importParsers.ts:isDateLikenow requires an explicit date shape beforeDate.parse. The shapes are numeric year-first (ISO-8601 included), numeric day/month-first with a 2- or 4-digit year and one repeated separator, ISO year-month, and English month-name forms.@object-ui/plugin-gridpatch changeset.inferColumnType's signature,isNumberLike, the hint scoring, the record conversion andImportWizard.tsxare untouched.inferColumnType(exported fromplugin-grid/src/index.tsx) returnstextwhere it wrongly returneddate.noholds.Date.parseread "Phase 2" → 2001-02-01, "Building 7" → 2001-07-01, "Room 12" → 2001-12-01 and "Imported QA task 1" → 2001-01-01. It also read "Marketing 2026" as March 2026, because V8 reads any word whose first three letters spell a month.inferColumnTypesamples the first 50 values, and returns date only when every sample is date-like.07/10/2026is still read month-first, unchanged.Date.parseaccepts were pinned as text ("Marketing 2026", "Room 101, Oct", "A-12", "task-1", "1.2.3").T…Ztime part infersdatetime, notdate, both onmainand after this PR.1.2.3stays text.main, some French and German names (octobre, Januar, …) inferred as dates only because of V8's prefix quirk, and others (juin, juillet, Maerz) never did.Date.parserejects most of those strings anyway.plugin-grid's full suite is green ondfeee89(withmain6d8bf0cmerged in): 188 files and 1763 tests. The build closure, type-check and the derivedcheck:*set are green.importParsers.tsat base, 11 failed and 46 passed, every failure "expected 'date' to be 'text'", and all 16 controls green. The restore was proven by blob hash.git merge-treeis clean againstmainand against objectui#11868, fix(app-shell): the form designer's drag live region names labels and places, not ids (objectui#11802) #11869 and fix(app-shell,fields): valid package-sheet header markup; select field controlled from its first render (objectui#11804) #11879.dfeee89: converging, none red at this read. The PR is queued when every check completes.ImportWizard.tsx'svalidateValueaccepts anyDate.parsereading for a date field, so "Phase 2" mapped onto a date field is not marked red in the preview. Its carrier is seat 2's in-flight objectui#11814, which owns that file; the seat noted it there.ObjectGrid.tsx's own name-basedinferColumnTypehas aDate.parsesample check whose two branches both returndate. It is a dead check, and nothing comes out wrong.huangyiirene.Generated by Claude Code
objectstack-fleet commentedon Oct 8, 2026
Landed: PR objectui#11881 →
mainbfca7ecdomain:uiseat 1 ·session_01DrKzdPdyLLBW3qpZ4vtk7z· verified 2026-10-08T04:36Z.dfeee89before queueing: 40 of 43 check runs passed, and the 3 skipped are the expected ones.check-governed-merges.mjs: not governed, +118/−1.bfca7ecis one squash commit on parent3035948. It changes 3 files, +118/−1, and all 3 are blob-identical to the reviewed headdfeee89. The whole diff's patch-id matches (098b2d62…).completedby the PR'sFixes.pm:dispatchedwas removed in the same pass and read back.6051881815): only English month names count. Non-English names that V8 read by prefix now infer as text, which the changeset declares.ImportWizard.tsx's lenientvalidateValueis noted on seat 2's objectui#11814 (6051868456).Generated by Claude Code
fix(plugin-grid): import type inference requires a date shape before …