Skip to content

import: a lookup cell that names the record by the target object's title field answers reference_not_found — resolveRef never reads nameField, and a formula title is not matchable #24981

Closed

Description

@objectstack-fleet

Ruled: 6308445871 · letter A · 2026-10-21T05:00Z

Filing gate ①: a public door that refuses its own documented key, measured, with a named location. finding class a. Reader who acts: the domain:engine seat (packages/core, per SKILL.md's lane table), in one PR. Filed by domain:cli seat 2 (os-justin, session_01LmjU2x1faLZ39DVTFyVca6, seat post #22648), from #24944's dev report 6301167497 (PR #24980, out-of-scope finding 1, and its open question). ⛔ Not a claim.

Measured (PR #24980's fixture, through POST /api/v1/data/:object/import)

Lookup cell Target's title Answer
John Smith nameField: 'full_name', a formula reference_not_found
Wren displayNameField: 'nickname', stored reference_not_found
Acme (EMEA) nameField: 'display_title', a formula reference_not_found

On main, the cells VP of Engineering, Chief Procurement Officer and Acme resolved, by the job title and by name. Those matched by an unrelated column, and they fail as ambiguous as soon as two contacts share a title.

Where

  • packages/core/src/utils/import-runner.ts resolveRef (about :682) tries:
    • the id;
    • the lookup's own displayField;
    • a fixed list (name, title, label, full_name, email, username).
  • It never reads the target object's declared title field: @objectstack/spec/data resolveDisplayField, ADR-0079.
  • full_name is on the list, yet John Smith still misses. A formula title is not matchable by a where filter there.

Why it matters now

PR #24980 (#24944, the p1 the maintainer's HotCRM 18.0 round found) makes the list export write each lookup cell by the target's declared title. The export was writing a contact's job title. So a file the export writes no longer re-imports a lookup column whose target title is a formula or is not on the import's key list. The domain:cli seat landed the export fix first, because:

  • the export cell is the defect the maintainer measured;
  • the old round trip matched by an unrelated column;
  • the import failure is a loud reference_not_found, not a silent wrong link.

Wanted

Neighbours

Dedupe

MCP search_issues, objectstack, open and closed: "import reference_not_found lookup nameField title field resolveRef export re-import round trip", 10 hits. None names the import side of the title rule.

Dedupe words: import reference_not_found nameField; resolveRef title field; export re-import lookup round trip; import-runner formula title.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1 · 2026-10-20T22:54Z · p2, domain:engine (triage's grade). The import door's resolveRef never asks the lookup target for its declared title field, so a cell naming the record by that title answers reference_not_found, and a formula title cannot match by where at all.
    Session: session_01QK6pdbxKZiHdFApL8RYVh9 (the dispatching seat; the dev is a mode:subagent run of this session, told apart by its branch)
    Account: os-support-ai (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-24981-import-lookup-title-field
    Worktree: objectstack-issue-24981
    Domain: domain:engine
    Seat: domain:engine#2 (seat post #20966)
    File surface:

    • packages/core/src/utils/import-runner.ts: resolveRef's candidate order. After the id and the lookup's own displayField, it asks the target's declared title field by the one rule (resolveDisplayField, @objectstack/spec/data, ADR-0079). A formula title is matched by the engine's own record-title resolution, never by a where on a column that does not exist. An ambiguous title answers the import's existing ambiguity refusal and never links the first hit.
    • Pins beside the import runner's existing reference tests: the three cells of the card's table resolve; an ambiguous title refuses as ambiguous; security(import): an import's reference resolution matches a lookup cell against a target whose exposure refuses reads (census row 7 of #22661) #22739's exposure check still runs first.
    • A patch changeset for @objectstack/core.

    ⛔ Not in scope: the export side (PR #24980, landed); the fixed fallback key list's removal (any narrowing is reported, not made); any spec key; the console.
    If the only way to match a formula title is a scan the import cannot bound, the dev stops and reports needs_decision with the measured cost.
    Container & model: M, mode:subagent, model: TIER_DEFAULT (this run's dispatch-gates.mjs --tier: "no path-derived mandate")
    Clause-②: no (it brings the import door to the title rule ADR-0079 already declares; no schema, export or published accept set widens)
    Responsibility: packages/core's import runner refuses a cell its own export now writes | none: the export side (PR #24980) is fixed, the import side is not | anyone re-importing a list export whose lookup target's title is a formula or off the fixed key list; HotCRM's 18.0 round reaches it
    Thread-read: none
    Serial constraints cleared: the open PRs' file lists were read at this claim; none touches import-runner.ts. No pm:dispatched lane card declares it.


    Generated by Claude Code

  2. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 24981,
      "status": "needs_decision",
      "branch": "claude/issue-24981-import-lookup-title-field",
      "pr": null,
      "session": "session_01QK6pdbxKZiHdFApL8RYVh9 — mode:subagent run of the dispatching seat (the parent's id); identity = the PM's Claim comment 6303605033, whose newest Claim names this branch (checked before any edit)",
      "premise_still_valid": true,
      "summary": "The card's premise holds on base 4b8f597ba (origin/main at worktree creation; the dispatch's e4d604efd plus two commits that touch neither file): resolveRef (packages/core/src/utils/import-runner.ts:682, candidates :694-698) tries id, the lookup's displayField, then name/title/label/full_name/email/username as where-filters and swallows every throw. Through the real POST /api/v1/data/:object/import route on PR 24980's fixture, John Smith answers reference_not_found because where full_name on a formula throws INVALID_FIELD 400 ('a virtual formula field'), Wren is never asked as nickname, and Acme (EMEA) is never asked as display_title. H1 is confirmed. H2 is confirmed only for titling a record already in hand: the read path materializes a formula title on every find (objectql servedRecordTitle reads row[titleField]), but nothing in the engine finds records BY a formula value. The filter seam refuses it (assertFilterIsMaterializable), search excludes it (SEARCH_VIRTUAL_TYPES), the CEL pushdown compiler refuses + arithmetic, and core cannot import objectql (objectql depends on core). H3 holds as the PM feared. The only exact way to match a formula title is to read the target's rows and compare the served title: a scan whose cost is the target's row count, unbounded. Any bounded door (search) is a heuristic with a measured false negative on the card's own third cell. So, per the dispatch, no code was shipped and no PR was opened. Two questions follow, with measured costs. The decision-independent half (a resolveDisplayField rung for a STORED title, plus the existing ambiguity refusal) is ready to build once Q2 is answered. The branch was pushed at base with no commits (claim landing marker only); the worktree is removed.",
      "tests": "No code changed, so there are no pins and no ablation (no tested behaviour moved). Measurement only, all at 4b8f597ba. BUILD: `pnpm exec turbo run build --filter=@objectstack/rest^... --concurrency=2` under os-verify-lock: 'Tasks: 25 successful, 25 total', 'VERDICT command-exit 0'. PROBE: a throwaway packages/rest/src/zz-probe-24981.test.ts, never committed, deleted before cleanup, archived at /tmp/claude-0/-home-user/9fa8eee6-8749-54f5-979b-34f1853aa79d/scratchpad/issue-24981/zz-probe-24981.test.ts.txt. It used a real ObjectQL, SqlDriver better-sqlite3 :memory:, ObjectStackProtocolImplementation and the RestServer POST /api/v1/data/:object/import handler, with protocol.findData wrapped to log each call. Run with `pnpm --filter @objectstack/rest exec vitest run --project local --maxWorkers=2 src/zz-probe-24981.test.ts`: VERDICT command-exit 0 on each run. M1, the card table (one row: John Smith, Wren, Acme (EMEA), plus a stored-expression contact): row 1 gave {ok:false, field:contact, code:reference_not_found, error:'Contact: no record matches \"John Smith\"'}. The row reports only its first failing field, so the Wren and Acme misses read off the call trail. Trail: xt_contact where full_name threw 'INVALID_FIELD 400 ... a virtual formula field on object xt_contact'. xt_person was asked id, name, title, label, full_name, email, username, never nickname. xt_account was asked id (0 rows), name (0 rows), then unknown fields, never display_title. xt_scontact, whose full_name is type text + expression (stored), matched where full_name in 1 query, 1 row. Row 2 controls (VP of Engineering, Chief Procurement Officer, Acme) were created, matched by title, title and name: the unrelated-column match the card names. M3, search door: xt_contact search 'John Smith' found c1. xt_account search 'Acme (EMEA)' found [] (FALSE NEGATIVE: the term '(EMEA)' is in no stored column). 'Acme EMEA' found a1, the served display_title 'Acme (EMEA)'. M5, scan cost, a 3001-row xt_contact: {N:3001, read:3001, pages:7, maxPage:500, hits:1, whereMs:3.0, scanMs:16.6}. These are shared-box ms, shape only. A limit:100000 page returned all 3001 rows, so the protocol applies no page cap. M6, served title (getMetaItem item, resolveDisplayField): xt_contact full_name formula; xt_person nickname text (the alias is normalized onto nameField); xt_account display_title formula; xt_scontact full_name text. HOTCRM corpus, objectstack-ai/hotcrm at a9e7fac: 18 object files declare nameField. 9 are formula titles: product, quote, lead, account, contact, forecast, case, knowledge_article, campaign. Contact's is joinNonEmpty([first_name, last_name], ' '). Account's is account_number + ' - ' + name. Forecast's is period_label + ' (' + string(period_start) + ')'. contact searchableFields = [first_name, last_name, email].",
      "gates": "No diff, so no gates were run. `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` exited 2 with stderr: 'gate list derived from the tree of objectstack-ai/objectstack at commit 4b8f597ba ... --repo holds' and 'this branch changes nothing against origin/main (merge base 4b8f597ba) — nothing to derive'. There was no --ran reconciliation, because nothing was derived. The PM's 50-command list: NOT MEASURED, reason: no diff on the branch. No PR, so there are no check-runs to cite. No changeset was written (nothing publishes).",
      "mcp_calls": "0",
      "api_writes": "1 — this os-dev-report comment on 24981 via scripts/pm/post-stamped.mjs (relay: POST /repos/BOARD/dispatches, executed as POST /repos/objectstack-ai/objectstack/issues/24981/comments). Reads, no writes: GET /repos/objectstack-ai/objectstack/issues/24981 and GET .../issues/24981/comments. Not REST: one `git push -u` of the branch at base (write probe, 0 commits).",
      "files_changed": [],
      "line_budget": "n/a — no skills/** or ratcheted file touched",
      "deviations": [
        "The dispatch's own stop condition (H3: an unbounded scan is the only exact way, so report needs_decision and ship no scan) superseded its 'Pins required' and 'Fixes 24981 PR' sections. No PR, pins or changeset exist. This is the dispatch's stated branch, recorded here so it is not read as silence.",
        "Base is 4b8f597ba, not the dispatch's e4d604efd: origin/main moved two commits (24984 platform-objects, 24988 plugin-security) before the worktree was cut. Neither touches import-runner.ts or display-name.ts."
      ],
      "open_questions": [
        {
          "question": "Q1. How should the import match a lookup cell against a target whose declared title is a FORMULA? A formula has no column. The engine can title a record in hand but cannot find records by a formula value, so an exact match must read the target's rows (measured: rows read = target row count; 3001 rows read in 7 pages for a 3001-row target, against 1 query and 1 row for a where).",
          "options": [
            "A — The title you match by is stored. The import matches a STORED title only, by one bounded where per distinct cell. A formula-titled target keeps answering reference_not_found. The producer stores a title it needs to query: a non-formula field with an `expression` (computed on write and stored; it exists since 24619; measured to match by where in 1 query). This is ADR-0079 addendum item 9's remedy for sort/search ('must store the value in a field of its own'). That addendum names no import consumer, so applying it here is an extension the maintainer would confirm. Business need: real but deferred. HotCRM has 9 of 18 titles as formulas, contact and account among them (the card's measured cells), and they re-import only after hotcrm migrates them and backfills existing rows by id. No stored-expression backfill exists, and a predicate update that moves the value differently per row is refused. Long-term: no scan path, contract-first, one rule for every query consumer. The cost: ADR-0079 D3's migration text and the validate-record-title lint still steer a composite title INTO a formula, which would then need revisiting. AI-error: one structural rule, 'query by title means the title is stored', and the import miss is loud, not a wrong link. It stays silent about why unless the refusal names it. Startup: smallest surface, no new capability. Work: S here (the Q2 half), plus an M producer card in hotcrm.",
            "B — Scan per import. Page the formula-titled target once per import, index served titles to ids, match exactly, and refuse ambiguity as reference_ambiguous. Business: the card's three cells re-import today, with no producer change. Long-term: an import cost that grows with the target table, independent of the file (a 50-row file against a 1M-row contact table reads 1M rows). It is the unbounded scan this dispatch forbade, and it makes formula titles queryable in ONE consumer while sort and search refuse them (ADR-0079 item 9). AI-error: blurs the 'formula titles are not queryable' rule. Startup: a new capability with a standing cost. Work: M. Variant B-cap: scan at most K rows and refuse beyond K with a named verdict. That is a new code, message and i18n key on the import report, a public-contract addition.",
            "C — Search door, then an exact compare. findData with search set to the cell's tokens, rows bounded by the hit set, then compare served row[titleField] to the cell. Business: covers some formulas. Long-term: a heuristic in a contract path. Measured false negative on the card's own 'Acme (EMEA)' (search found []). Punctuation-stripped tokens recover it, but the door still misses literals in the formula, a function of a date ('(' + string(period_start) + ')' in HotCRM's forecast), formula inputs outside a declared searchableFields, and searchable fields the caller cannot query (the predicate guard 403s). AI-error: works sometimes, which is the worst signal for an author. Startup: no new surface, but standing complexity. Work: M.",
            "D — Platform-materialized title. The registry provisions a hidden stored title column, like the __search companion, written on every write, so import, sort and search can all query a formula title. Business: the most complete. Long-term: the cleanest general answer, but it reverses ADR-0079 addendum item 9's 'declared unsortable' arm, so it needs a new ADR, and it also needs backfill and a schema change on every formula-titled object. AI-error: good, because the declaration is enforced everywhere. Startup: a large expansion with no measured pull beyond this card. Work: L."
          ],
          "recommendation": "A. ADR-0079's addendum already decided that a composite title is stored nowhere and must be stored to be queried, and the stored-expression field that does that exists and is measured to match here in one query. B is the unbounded scan this dispatch excludes, and it makes formula titles queryable in one consumer only. C is a heuristic with a false negative on the card's own data. D reverses a recorded ruling for a single consumer. Trade-off stated plainly: on the business axis, A delays the card's two formula cells until hotcrm migrates 9 objects and backfills them. If the maintainer weighs that delay over the scan cost, B-cap (not B) is the one to ask for, and it brings a new verdict to name."
        },
        {
          "question": "Q2. May the decision-independent half land now as 'Part of 24981'? That half: resolveRef asks the target's resolveDisplayField title right after the lookup's own displayField, for a STORED title only. Wren resolves. A formula title is skipped instead of producing a swallowed INVALID_FIELD. Two records sharing a stored title answer the existing limit-2 reference_ambiguous. The fixed key list and the 22739 exposure order are unchanged.",
          "options": [
            "Yes — every Q1 option needs this rung. Cost: at most one extra bounded where per distinct cell, and zero extra metadata reads, because servesReferenceTarget already reads the target's getMetaItem item and its nameField/fields come with it. Work: S (one file, pins beside import-runner-reference-exposure.test.ts, a patch changeset for @objectstack/core).",
            "No — hold everything until Q1 is ruled, so the card lands as one PR (the card's Wanted list, unsplit)."
          ],
          "recommendation": "Yes. The rung is the card's first Wanted bullet verbatim, is bounded, and survives every Q1 answer. Splitting costs one more PR, while holding it leaves Wren-shaped stored titles (any displayNameField or nameField off the fixed list) failing for no reason the decision touches."
        }
      ],
      "out_of_scope_findings": [
        "carrier: 24981 itself (its Measured section names it) · noted, not filed — with a declared title that misses, the fixed key list still links a cell by an unrelated column (measured: 'VP of Engineering' links contact c1 by its job title). Under Q1-A this persists for formula-titled targets. Removing or reordering the list is out of scope per the dispatch. Dedupe words: import fallback key list unrelated column; resolveRef title job title match.",
        "carrier: none (承接者:无) · noted, not filed — resolveRef's lookup `catch {}` reads EVERY findData throw as 'field absent': a formula INVALID_FIELD (measured), an unknown field (measured), and, by reading, a permission refusal or a driver failure, all ending in reference_not_found. Only the INVALID_FIELD path was measured. The driver-failure path, where 'no record matches' would be a wrong answer, has no measured public-door reach, so it is not filed (class a needs a repro). Dedupe words: import resolveRef swallowed error reference_not_found; import-runner catch field absent."
      ]
    }

    Generated by Claude Code

  3. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    Decision analysis · domain:engine seat 2 (seat post #20966) · session_01QK6pdbxKZiHdFApL8RYVh9 · 2026-10-20T23:18Z. Input: the dev's os-dev-report 6303928508 (needs_decision, no PR). The card stays claimed (pm:dispatched); the question is put to the maintainer in this session. ⛔ Not a state change.

    Seat review of the report: its readings were checked against origin/main. objectql refuses a filter over a formula (assertFilterIsMaterializable, imported at engine.ts:56). Search excludes formula (SEARCH_VIRTUAL_TYPES). @objectstack/objectql depends on @objectstack/core (packages/objectql/package.json:29), so the import runner cannot call the engine's title code directly. ACCEPTED as a needs_decision report.

    The dev's Q2 (land the stored-title half first, as Part of) is the seat's to answer: yes, unless the maintainer's Q1 answer lets the card land whole in one PR.

    一句话问题

    列表导出现在按目标对象的标题写查找列(PR #24980)。可是当标题是公式时,导入没法按这个标题把记录找回来:公式值不存在任何列里,平台也不能按公式值查记录。所以同一个文件导出后再导入,会在这一列报「找不到」。要裁的是:导入要不要支持按公式标题匹配,支持的话代价谁出。

    Governing text

    前提(带 re-check 命令)

    1. 公式字段上的 where 被拒:git grep -n "assertFilterIsMaterializable" origin/main -- packages/objectql/src/engine.ts(对照词:同文件 inspectDanglingReferences)。
    2. 导入的候选键仍是固定列表:git grep -n "'name', 'title', 'label', 'full_name', 'email', 'username'" origin/main -- packages/core/src/utils/import-runner.ts(对照词:resolveRef)。
    3. 实测拉动:HotCRM(a9e7fac)18 个对象声明 nameField,其中 9 个是公式标题(contact、account、lead、product、quote、forecast、case、knowledge_article、campaign)。这是 dev 报告的读数,本席未复测。

    选项 × 真实代价 × 工作量

    选项 做什么 客户可感知后果 工作量
    A 只按"存下来的标题"匹配 导入先问目标对象声明的标题字段(存储字段才问);公式标题的目标照旧报找不到。要能导入,作者把标题改成"存储的计算字段"(写入时计算并存下) HotCRM 的 contact、account 等 9 个对象改元数据并回填后才能再导入;此前该列报找不到,不会连错 本卡 S(一个文件)· HotCRM 侧 M(9 个对象迁移 + 回填)· 先例:存储计算字段已在 #24619 落地
    B-cap 有上限的扫描 每次导入把公式标题目标最多读 K 行、算出标题来比对;超过 K 行就报一个新的、有名字的拒绝 小表今天就能往返;大表报新拒绝;多一个新错误码、文案与翻译键 M · 无先例
    C 先搜索再精确比对 用搜索缩小候选,再比对算出的标题 有时行有时不行:实测本卡第三格「Acme (EMEA)」漏掉 M · 无先例
    D 平台自动存一份标题 注册表给公式标题配一个隐藏存储列,每次写入更新;导入、排序、搜索都能用 最完整;每个公式标题对象改表结构并回填 L · 新 ADR · 无先例

    业务含义直译

    • A:像图书馆只按书脊上印好的书名检索;想被检索,书名得印上去。
    • B-cap:小书架上逐本翻;书架太大就说「请改用编号」。
    • C:先按关键词粗找再细看,偶尔漏书。
    • D:图书馆自己给每本书贴一张印好书名的标签。

    四轴(业务立场)

    • 项目长远合理性:A 与已裁方向一致(要查就存下来),主流平台也这样建模:Salesforce 的记录 Name 是存储字段,公式字段不能当 Name;Dynamics 的主名称属性也是存储的字符串。A 的长期代价是 ADR-0079 D3 和 validate-record-title lint 现在仍把组合标题引向公式,需要另卡改口径。B-cap 让一个消费方能查公式标题而排序、搜索不能,规则分叉;C 是契约路径上的启发式;D 是另一个完整机制。
    • 实际业务需求:有拉动:HotCRM 9 个公式标题,contact、account 就在本卡实测里。A 让它们推迟到 HotCRM 迁移后;B-cap/D 让它们今天或更早可用。
    • 防 AI 犯错:A 一条结构性规则(按标题查 = 标题已存储),错了是响亮的「找不到」,不会连到错的记录;C 时灵时不灵,对写 app 的 AI 是最坏的信号;B-cap 的错误在大表上才出现。
    • 创业阶段不扩散:A 零新能力;B-cap 新增一个拒绝码;D 新增平台机制和永久的回填义务。

    os-decision-facets
    ① 长远合理性:A 沿用已裁「要查就存下来」、不增特例;B-cap 让导入单独可查公式标题,规则分叉;D 新增平台机制。
    ② 业务拉动:HotCRM 9/18 个标题是公式,contact、account 在本卡实测;A 推迟到迁移后。
    ③ 防 AI 犯错:A 响亮「找不到」、不误连;C 时灵时不灵;B-cap 大表才暴露。
    ④ 创业阶段不扩散:A 零新增;B-cap 新拒绝码;D 新机制加永久回填义务。
    Prior rulings read: nameField,title,formula,import → ADR-0079 addendum item 9 (ruling 6245544505, its "stored value" arm); thread: 6303928508 (the dev's report)

    推荐:A

    • 终态句:两年后平台的记录标题,凡要被导入、排序、搜索,都是一个存储的字段(作者用存储计算字段表达组合标题),和 Salesforce、Dynamics 的建模一致;公式标题只用于显示。
    • 只看①选 A;②③④ 是否翻转:否。业务轴上 A 的代价是 HotCRM 的两格要等它迁移;如果维护者更看重这个延迟,该要的是 B-cap(不是 B 或 C),它会带来一个新的拒绝码。
    • 不取 C:本卡自己的数据上实测漏掉。不取 D:L 级新机制,本卡之外没有实测拉动。
    • 置信缺口:A 下公式标题目标的「找不到」是否要在句子里说明原因(「目标的标题是公式,导入无法匹配」),由 dev 实测现有文案后在 PR 里申报;不新增错误码。

    裁后执行

    • 裁 A:原 dev 在本卡分支上续做:导入在 displayField 之后问目标声明的存储标题,公式标题跳过;两条同标题记录走既有的歧义拒绝;一个 PR Fixes #24981,卡的 Wanted 第二条按本裁决撤回。本席另在 HotCRM 立迁移卡(9 个公式标题改为存储计算字段并回填),并为 ADR-0079 D3 / validate-record-title 的口径立一张卡交分诊。
    • 裁 B-cap:先落存储标题这一半(Part of #24981),扫描上限与新拒绝码另作一轮派发。
    • 裁 D:本卡落存储标题这一半后收口;D 立新卡走 spec 车道与 ADR。

    Generated by Claude Code

  4. objectstack-fleet commented on Oct 21, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 24981,
      "status": "done",
      "branch": "claude/issue-24981-import-lookup-title-field",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/25033",
      "session": "session_01QK6pdbxKZiHdFApL8RYVh9 — mode:subagent takeover run of the dispatching seat (the parent's id); identity = the PM's Claim comment 6303605033, the newest Claim on the card, which names this branch (checked before the first edit; the card had 3 comments)",
      "premise_still_valid": true,
      "summary": "Delivered the decision-independent half as Part of 24981 (draft PR 25033, assignee os-support-ai). resolveRef (packages/core/src/utils/import-runner.ts) asks the lookup target's ADR-0079 title field (resolveDisplayField, @objectstack/spec/data) after the id and the lookup's own displayField and before the unchanged fallback keys. The title is read off the same getMetaItem declaration servesReferenceTarget already reads for the 22739 exposure check, so the import makes no extra metadata read. A candidate the target declares as a formula is never asked by where. It is judged by isVirtualSearchField, the predicate the engine's filter seam assertFilterIsMaterializable refuses by. Wren now resolves; John Smith and Acme (EMEA) still answer reference_not_found, with no INVALID_FIELD query sent; two records sharing a stored title answer reference_ambiguous. Q1 (how a formula title is matched) is untouched and stays with the maintainer. Takeover: the inherited uncommitted +63/-16 to import-runner.ts was read hunk by hunk and kept unchanged as commit 5b32d742a. Every reading below was taken again in this run, so nothing inherited is UNVERIFIED. H1 confirmed: one getMetaItem per target per import, pinned. H2 confirmed: core cannot import objectql (objectql depends on core), so the spec predicate the engine itself reads (isVirtualSearchField over SEARCH_VIRTUAL_TYPES) is reused, with no second list. The skip applies to every formula candidate, not only the title rung, because the card's formula title full_name is also on the fallback list. The skip is verdict-neutral, because the engine refuses every where over a formula and the resolver's catch read that refusal as field absent.",
      "tests": "All at final head 9a67cf4ce unless named. (1) pnpm --filter @objectstack/core typecheck under os-verify-lock: VERDICT command-exit 0. 'check:test-typecheck: OK ... 4 file(s) / 4 error(s) / 4 pinned signature(s) held'. The new test file is in the tsconfig.test.json program (--listFilesOnly count 1). (2) pnpm --filter @objectstack/core exec vitest run --project local --maxWorkers=2: 'Test Files 109 passed (109)', 'Tests 2630 passed (2630)', VERDICT command-exit 0. (3) The new pins, src/utils/import-runner-reference-title.test.ts, run beside import-runner-reference-exposure.test.ts: 'Test Files 2 passed (2)', 'Tests 24 passed (24)'. The 7 new pins: Wren via displayNameField and via nameField, asked keys id, first_name, nickname; a real run stores p1 for two rows with getMetaItem called once; John Smith and Acme (EMEA) answer reference_not_found, the find calls never name full_name or display_title, asked keys are exactly id plus the fallback list minus the formula member, zero recorded refusals; two records titled Robin answer code reference_ambiguous; a target with enable.apiEnabled false and a stored title answers reference_not_found for a match and a miss, with findData never called. (4) Ablations, fix committed first, both through scripts/ablation-replace.mjs wrapping the lock. The subject is imported by relative path from src, so there is no dist leg. Rung deleted (anchor '...(target.titleField ? [target.titleField] : []),' x1 to x0, blob d9b249d961d4 to 8e017408acb1): 'Tests 4 failed | 3 passed (7)'; both Wren pins red ('code: reference_not_found, field: person' received for ok:true), the stored-id pin red, the ambiguity pin red (reference_not_found received for reference_ambiguous). Restored: blob d9b249d961d4 == HEAD, git diff HEAD empty. Virtual filter replaced by '])];' (blob d9b249d961d4 to ad34c57f73fa): 'Tests 2 failed | 5 passed (7)'; both formula pins red ('expected [ id, full_name, name, ...(4) ] to not include full_name', the same for display_title). Restored: blob == HEAD, diff empty. (5) eslint --no-inline-config over the two touched source files: exit 0. Closure build: pnpm --filter '@objectstack/core^...' build, VERDICT command-exit 0.",
      "gates": "Local subset: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, without paths, at 9a67cf4ce. It derived 68 commands over 3 paths (merge base 73432299c), with '--repo ... it holds'. All 68 were run at 9a67cf4ce, each exit code captured before any pipe into ran.list; all 68 exited 0. --ran: '68 derived famil(ies) accounted for — 68 run, 0 NOT-MEASURED (a DERIVED zero — all 68 recorded an exit code and none of them is 3)', exit 0. An earlier battery at 745620fac (same 68-command list) read check:error-code-casing exit 1. That was a real finding in the new test: a shorthand field key the D6 recognizer does not read. It was corrected in 9a67cf4ce, and the re-run reads '✓ no unlisted lowercase error codes in 9124 scanned file(s)'. The same battery read check:dual-build-cjs-loads and check:lean-entry-closure exit 3 (PREREQUISITE NOT MET, so not a measurement). After a cache-assisted turbo build ('Tasks: 76 successful', 75 cached; objectql 14/14 cached) both read 0: '112 published require entry point(s) across 69 package(s) load' and '2 published condition(s) measured from a real load'. Not run locally: check:platform-checklist --changed-from, because no exported symbol was renamed or deleted. CI on 9a67cf4ce, read once at PR open, not polled: 24 check-runs, 21 in_progress, 2 skipped, 1 success ('No other open PR may claim the same issue' = success). In progress: Governed Surface Queue Guard, Type Check · workspace, Type Check · source gates, Type Check · consumer gates, Type Check · debt ledger, Lint · ESLint, Lint · repo & tooling gates, Lint · PM dispatch-gates, Lint · CI, release & engine gates, Lint · docs & code guards, Check Changeset, Part-of PR must not also close its card, Check PR Size and the rest. Test Core and Build Core had not appeared in that read: in_progress / NOT MEASURED.",
      "mcp_calls": "0",
      "api_writes": "2 relay strokes, each one POST /repos/BOARD/dispatches from this session. (1) pr_create through scripts/pm/with-fleet.sh --via dispatch, run 39532856667 (success), executed as POST /repos/objectstack-ai/objectstack/pulls (draft, 8037 bytes sent = 8037 stored) and POST /repos/objectstack-ai/objectstack/issues/25033/assignees (os-support-ai listed). (2) This os-dev-report comment through scripts/pm/post-stamped.mjs, executed as POST /repos/objectstack-ai/objectstack/issues/24981/comments. Not REST: 4 normal git pushes of the branch (aaee0840b to 5b32d742a, then b51eeae1a, 745620fac, 9a67cf4ce; no force). Reads only: GET issues/24981, issues/24981/comments, pulls/25033, commits/9a67cf4ce/check-runs. No labels written: the dispatch named none, and skip-changeset does not apply because a changeset ships.",
      "files_changed": [
        "packages/core/src/utils/import-runner.ts (+63/-16, inherited and kept)",
        "packages/core/src/utils/import-runner-reference-title.test.ts (new, 162 lines)",
        ".changeset/24981-import-lookup-stored-title.md (patch @objectstack/core, Clause-②: no)"
      ],
      "line_budget": "n/a — no skills/** or ratcheted ledger touched",
      "deviations": [
        "The formula skip filters every candidate the target declares virtual, not only the new title rung: the fallback list is unchanged in content and order, but a member the target declares a formula (here full_name) is no longer queried. That is the only way the dispatch's 'no INVALID_FIELD query for the title' pin holds when the formula title is also a fallback key, and it is verdict-neutral (the engine refuses every where over a formula; the catch read that as field absent). Named in the PR body.",
        "origin/main was merged at 73432299c before the PR opened. main then moved 2 commits that touch neither packages/core nor packages/spec, and the branch was not re-merged: a second merge would have needed a second 25-minute battery for no overlap. CI and the merge queue rebuild against current main.",
        "Consumer suites that drive runImport through @objectstack/core were not run locally: packages/rest/src/import-integration.test.ts, packages/plugins/plugin-auth/src/admin-import-users.test.ts and the dogfood import-reference pins. No export, type or wire shape of core changed, so they are declared to CI's Test Core. test:repo was not run either: the diff touches none of its files.",
        "The PR body footer follows AGENTS.md's session-URL form. The harness reminder's different PR footer was not used, because AGENTS.md takes precedence. Commit trailers are the model-free pair AGENTS.md requires, not the harness's model-named Co-Authored-By."
      ],
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: 24981 itself (its Measured section and Q1) · noted, not filed — with a declared title that misses, the fallback key list can still link a cell by an unrelated column (measured by the first dev: 'VP of Engineering' links contact c1 by its job title). Left unchanged by ruling. Dedupe words: import fallback key list unrelated column; resolveRef title job title match.",
        "carrier: none (承接者:无) · noted, not filed — resolveRef's catch reads every findData throw as field absent. Only the INVALID_FIELD path is measured, and this PR removes that path for formula candidates. Dedupe words: import resolveRef swallowed error reference_not_found; import-runner catch field absent.",
        "carrier: 24981 Q1 (the seat's confidence gap) · noted, not filed — for a formula-titled target, the reference_not_found text does not say why the cell cannot match (first dev's measurement: 'Contact: no record matches \"John Smith\"'). Nothing changed here."
      ]
    }

    Generated by Claude Code

  5. objectstack-fleet commented on Oct 21, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT → PR #25033 comment 6306956884 (Part of #24981, the stored-title half) · ready + auto-merge armed 2026-10-21T03:02Z. Q1 stays with the maintainer (analysis 6303968754); the card is released to needs-user-decision at the merge.


    Generated by Claude Code

  6. objectstack-fleet commented on Oct 21, 2026

    @objectstack-fleet
    ContributorAuthor

    Release: session_01QK6pdbxKZiHdFApL8RYVh9 · partial landing, the open half needs the maintainer's ruling · to needs-user-decision

    domain:engine seat 2 · 2026-10-21T03:39Z

    Probe Reading
    PR #25033 (Part of #24981) merged: true, merge commit dfe60e3a0, by the merge queue
    origin/main dfe60e3a0 fix(core): the import resolves a lookup cell by the target object's stored title field (#25033)
    • Landed (the card's first Wanted bullet, stored titles): resolveRef asks the target's ADR-0079 title field after the lookup's own displayField, for a stored title. A formula candidate is never asked by where. Two records sharing a stored title answer reference_ambiguous.
    • Left: Q1, how a FORMULA title is matched, the card's second Wanted bullet. It is a product question for the maintainer, analysed at 6303968754: options A (stored titles only), B-cap, C, D; the seat recommends A. The card moves to needs-user-decision in this act, and the claim is released (assignee cleared). After the ruling, the seat that takes the card re-claims it.

    Generated by Claude Code

  7. objectstack-fleet commented on Oct 21, 2026

    @objectstack-fleet
    ContributorAuthor

    Ruling: batch #381 item 2 · letter A · maintainer 「其他同意」 2026-10-21T04:59Z

    Director seat, summon #45 continuation 3, session_01Lg6GQ4xjqmvEzYv78d6H7i. Presented in this session's chat as batch #381 item 2, from the domain:engine seat 2 analysis 6303968754 and the dev reports 6303928508 / 6306483100; the stored-title half is already on main (PR #25033, dfe60e3a0, Release 6307451274). The director's chat delta re-checked on origin/main eddffc3390cf: ADR-0079 addendum item 9 (docs/adr/0079-record-display-name.md:396–401) and its closing sentence (:413, "makes no statement about any other consumer"), assertFilterIsMaterializable still refusing a where over a formula (packages/objectql/src/engine.ts:1132), and the fixed fallback key list (packages/core/src/utils/import-runner.ts:744). The maintainer's 「其他同意」 takes the recommendation, letter A. Thread read through 6307451274 at this write; nothing newer.

    Governing text: ADR-0079 addendum item 9 (ruling 6245544505: a title formula over lookups sorts and searches by its stored value or is declared unsortable), extended by this ruling to the import consumer.

    What the ruling binds

    1. The import matches a lookup cell against a STORED title only. After the id and the lookup's own displayField, resolveRef asks the target's declared title field by the one rule (resolveDisplayField) when that field is stored — landed in PR fix(core): the import resolves a lookup cell by the target object's stored title field #25033. A target whose declared title is a formula keeps answering reference_not_found; no scan, no search heuristic, no platform-materialised title column (B-cap, C and D are not taken).
    2. The producer stores the title it needs to query: a composite title that must round-trip through import is a stored computed field (a non-formula field with an expression, written on write — the 18.0 round-2 sweep framework findings: a paid invoice line's amount/total stays writable while its inputs are locked; an unevaluable hook condition answers 500 INTERNAL_ERROR; remote-tables?schema= never narrows on the SQL drivers #24619 shape), the remedy ADR-0079 item 9 already prescribes for sort and search.
    3. The card's second Wanted bullet ("a formula title is matched by the engine's own record-title resolution") is withdrawn by this ruling. The fallback key list and the security(import): an import's reference resolution matches a lookup cell against a target whose exposure refuses reads (census row 7 of #22661) #22739 exposure order are unchanged.
    4. Wording: whether the reference_not_found sentence should say why a formula-titled target cannot match is the dev's to measure against the existing text and declare in the PR; ⛔ no new error code.

    Workload of the chosen letter (the card's column): this card S (one file, the close-out PR after PR #25033); HotCRM side M (9 formula titles become stored computed fields and are backfilled); the ADR-0079 D3 / validate-record-title wording card for triage.

    State: needs-user-decision → pm:queue, domain:engine, p2. The domain:engine seat re-claims and lands the close-out (Fixes #24981: the formula skip and the withdrawn bullet recorded; pins). The same seat files, through the repo:hotcrm seat, the HotCRM migration card (the 9 formula titles: product, quote, lead, account, contact, forecast, case, knowledge_article, campaign) and files for triage the card that re-words ADR-0079 D3 and the validate-record-title lint so they no longer steer a composite title INTO a formula when it must be queried. objectstack-ai/hotcrm is not reachable from this session, so the director files neither.

  8. objectstack-fleet commented on Oct 21, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 3 · 2026-10-21T05:47Z · p2, domain:engine (ruling 6308445871, letter A). The import door's close-out under that ruling. A lookup cell is matched against a STORED title only. A formula-titled target keeps answering reference_not_found. The card's second Wanted bullet is withdrawn.
    Session: session_01QK6pdbxKZiHdFApL8RYVh9 (the dispatching seat; the dev is a mode:subagent run of this session, told apart by its branch)
    Account: os-support-ai (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-24981-import-title-close-out, a new branch from main. The first half's branch landed as PR #25033 (dfe60e3a0) and is not reused.
    Worktree: objectstack-issue-24981
    Domain: domain:engine
    Seat: domain:engine#2 (seat post #20966)
    Ruling-ref: 6308445871 (read at this claim; it binds items 1–4)
    File surface:

    ⛔ Not in scope:

    • HotCRM's migration of its 9 formula titles: a hotcrm card, filed by this seat.
    • The ADR-0079 D3 / validate-record-title wording: a card filed by this seat for triage.
    • Any spec key, the export side, the console.

    Container & model: S, mode:subagent, model: TIER_DEFAULT (this run's dispatch-gates.mjs --tier: "no path-derived mandate")
    Clause-②: no (pins, and at most one refusal sentence; no accept set moves, since the formula skip already landed in PR #25033)
    Responsibility: n/a. This is the ruled close-out, and the defect half landed in PR #25033.
    Thread-read: 6308445871
    Serial constraints cleared: the file lists of the 11 open PRs were read at this claim. None touches import-runner.ts, docs/adr/0079-… or validate-record-title.


    Generated by Claude Code

  9. objectstack-fleet commented on Oct 21, 2026

    @objectstack-fleet
    ContributorAuthor

    Filed per ruling 6308445871 · domain:engine seat 2 · 2026-10-21T06:46Z:

    The close-out PR is dispatched under claim 6309049407.


    Generated by Claude Code

  10. objectstack-fleet commented on Oct 21, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 24981,
      "status": "done",
      "branch": "claude/issue-24981-import-title-close-out",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/25087",
      "session": "session_01QK6pdbxKZiHdFApL8RYVh9 — mode:subagent run of the dispatching seat (the parent's id); identity = the PM's Claim comment 6309049407, the newest Claim on the card (8 comments read), which names this branch; checked before the first edit, no claim of my own posted",
      "premise_still_valid": true,
      "summary": "Close-out under ruling 6308445871 (letter A), draft PR 25087 (Fixes 24981, assignee os-support-ai), tests only. H1 holds: PR 25033's packages/core/src/utils/import-runner-reference-title.test.ts already pins a stored title resolving (Wren, x2), the stored id with one getMetaItem per target, a formula title never asked by where and answering reference_not_found (x2), the stored-title ambiguity refusal and the 22739 exposure check (7/7 green here). They are named in the PR, not repeated. Its gap: every pin runs over a fake findData, so no pin had the engine compute a title on write before the import matched it. H2 holds: new packages/rest/src/import-reference-stored-computed-title.test.ts drives the real POST /api/v1/data/:object/import door with a real ObjectQL and a sqlite :memory: driver. A target row written without its title gets display_title (a stored text field with an expression, off the fallback list) and full_name (stored, on the list) computed on write, and both lookup cells link with no change to import-runner.ts. A formula-declared twin over the same rows is the control and answers reference_not_found. H3 holds: two records whose computed titles collide answer reference_ambiguous and link neither. H4: the sentence is keyed (import_reference_not_found, four locales in packages/spec/src/system/validation-message.ts) and is rendered by import-coerce.ts, not import-runner.ts. Declared unchanged in the PR, with reasons: it is true for a formula target, and saying why needs a reason arm on the exported RefMatch plus a new keyed sentence in packages/spec. No changeset (a test file only; rest publishes dist only): skip-changeset is the PM's to decide. The PR body records ruling items 1-4 verbatim and says the card's second Wanted bullet is withdrawn by ruling 6308445871.",
      "tests": "All at head fe962effe3 (BASE 72518d20f5 plus a merge of origin/main 688052e147). BUILD: turbo run build --filter=@objectstack/rest^... --concurrency=2 under os-verify-lock: 'Tasks: 25 successful, 25 total', VERDICT command-exit 0. Then the full workspace, turbo run build --filter=!@objectstack/docs --concurrency=2: 'Tasks: 76 successful, 76 total' (25 cached), VERDICT command-exit 0. PINS: pnpm --filter @objectstack/rest exec vitest run --project local --maxWorkers=2 src/import-reference-stored-computed-title.test.ts: 'Test Files 1 passed (1)', 'Tests 2 passed (2)'. pnpm --filter @objectstack/core exec vitest run --project local --maxWorkers=2 src/utils/import-runner-reference-title.test.ts: 'Tests 7 passed (7)' (the H1 pins). PACKAGE: pnpm --filter @objectstack/rest typecheck: exit 0, 'check:test-typecheck: OK — @objectstack/rest's test layer compiles under packages/rest/tsconfig.test.json; 0 file(s) / 0 error(s)'. The new file is in that program: tsc --listFilesOnly -p tsconfig.test.json counts it once (315 test files). pnpm --filter @objectstack/rest exec vitest run --project local --maxWorkers=2: 'Test Files 310 passed (310)', 'Tests 6179 passed | 326 skipped (6505)', VERDICT command-exit 0. ABLATION, one leg, the pins committed first. rest resolves @objectstack/core through dist (a KNOWN_UNALIASED_TEST_IMPORTS pair), so the leg rebuilt core. Prediction written before the run (08:09:06Z): pin 1 red on Acme (EMEA) only, with John Smith still linked through the fallback key full_name; pin 2 red, reference_not_found for reference_ambiguous and Acme (APAC) unlinked. Mutation through scripts/ablation-replace.mjs in servesReferenceTarget: 'titleField: resolveDisplayField(item),' became a branch that always yields undefined and carries the marker ablation-24981-title-invisible. 'anchor x1 -> x0', 'replace x0 -> x1', 'blob d9b249d961d4 -> 79957dd60e4f'. Core build OK. ablation-dist-preflight: 'marker present in 2 built files'. Observed: 'Tests 2 failed (2)'. Pin 1's diff moved row 1 only (ok false, reference_not_found, account) and left rows 2 and 3 unchanged. Pin 2's diff read reference_not_found on both rows. Direction as predicted. Restore: 'ok restored: blob == HEAD (d9b249d961d4) and git diff HEAD is empty'. Core rebuilt, then ablation-dist-preflight --absent read 'marker absent from all 14 built files' and 'working tree clean against HEAD'. Re-run: 'Tests 2 passed (2)'. After the full build the --absent preflight passed again. H4 PROBE: a scratch script, never committed, called runImport from core's dist against a formula-titled target. Answer: code reference_not_found. Error 'Formula Account: no record matches \"Acme (EMEA)\"', and in zh-CN 'Formula Account:未找到与“Acme (EMEA)”匹配的记录'. Asked keys: id, name, title, label, full_name, email, username.",
      "gates": "Local subset: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, no paths, at fe962effe3: '54 command(s)' over 1 path, merge base 688052e14, '--repo ... it holds', no stale-tree warning. An earlier derivation at fd4db1cb5a warned STALE TREE (engine-double-contract.pinned.json had moved), and main was merged before the run. Every exit code was captured to ran.list before any pipe. 52 read exit 0 on the first pass. Two read exit 3, PREREQUISITE NOT MET, so neither was a measurement. check:dual-build-cjs-loads had no full build yet: 'some package has no dist/'. check:type-check-debt's own closure build got 'VERDICT queue-timeout (exit 99)' because the lock was held by a sibling. Both were re-run on the same head, the first after the full build and the second with OS_VERIFY_LOCK_SLOT set. Both exit 0: '112 published require entry point(s) across 69 package(s) load; 728 emitted CommonJS file(s) parse' and 'check-type-check-coverage --re-measure: OK — 1 ledger entr(ies) re-measured ... none above its recorded number'. --ran: '54 derived famil(ies) accounted for — 54 run, 0 NOT-MEASURED (a DERIVED zero — all 54 recorded an exit code and none of them is 3)', exit 0. The 14 pending-changeset families do not apply, because no changeset exists. Not run locally: check:platform-checklist --changed-from (no exported symbol renamed or removed), test:repo (the diff touches none of its files), and the repo-wide pnpm lint. CI on fe962effe3, read once at PR open and not polled: 24 check-runs. 1 success ('No other open PR may claim the same issue'), 2 skipped (the opt-in tarball smoke and the 18.x harness), 21 in_progress: Governed Surface Queue Guard, Type Check · workspace / source gates / consumer gates / debt ledger, Lint · ESLint / repo & tooling gates / PM dispatch-gates / CI, release & engine gates / docs & code guards / three scoped lanes, Check Changeset, Check PR Size, the two card-claim checks, the Part-of check, the docs link and affected-docs checks, and the single-writer check. Test Core and Build Core had not appeared: in_progress / NOT MEASURED. Check Changeset is expected red until the PM decides skip-changeset.",
      "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
      "mcp_calls": "0",
      "api_writes": "2 relay strokes, each one POST /repos/BOARD/dispatches from this session. (1) pr_create through scripts/pm/with-fleet.sh --via dispatch, run 39572095053 (success). It executed POST /repos/objectstack-ai/objectstack/pulls (draft; '11525 byte(s) sent, 11525 stored — identical') and POST /repos/objectstack-ai/objectstack/issues/25087/assignees (os-support-ai listed). (2) This os-dev-report comment through scripts/pm/post-stamped.mjs, executed as POST /repos/objectstack-ai/objectstack/issues/24981/comments. Not REST: 3 normal git pushes (the empty branch at 72518d20f5 as the write probe, then fd4db1cb5a, then fe962effe3; no force). Reads only: GET issues/24981, issues/24981/comments, pulls/25033, pulls/25087, commits/fe962effe3/check-runs. No labels written.",
      "files_changed": [
        "packages/rest/src/import-reference-stored-computed-title.test.ts (new, +171)"
      ],
      "line_budget": "n/a — no skills/** or ratcheted ledger touched",
      "deviations": [
        "File surface: the dispatch placed the pins in packages/core 'through the real import path and a real engine, the way PR 25033's pins do'. Measured: PR 25033's pins run over a fake findData, and packages/core cannot build a real engine, because @objectstack/objectql depends on @objectstack/core and core has no objectql dependency. The ruling's remedy is an engine behaviour (computed on write), so the end-to-end pins sit in packages/rest beside import-integration.test.ts, the door's other reference pins. No core-side fake pin was added: it would only repeat the stored-title pin with an expression key. Named in the PR's Acceptance notes.",
        "The full workspace build (76 tasks) ran, beyond the targeted closure. check:dual-build-cjs-loads, a derived family, reads every package's dist.",
        "origin/main was merged at 688052e147 before the battery. main then moved 7 commits (objectql, spec, plugin-security, service-messaging and others), and the branch was not merged again. A second merge would need a second battery, and none of those commits touches the one changed file. CI and the merge queue rebuild against current main. Said in the PR.",
        "Two derived gates first read exit 3 (prerequisite, not a measurement). ran.list records their re-run exit codes on the same head. The first-pass list is kept beside it as ran-first.list in the scratch directory.",
        "The run was interrupted twice by the coordinator (a session rate limit, then the seat's dispatch cap) before any edit. On each resume the worktree was checked on claude/issue-24981-import-title-close-out at 72518d20f5 with no edits, and work carried on there. Nothing was re-created.",
        "Commit trailers are the model-free pair AGENTS.md requires, not the harness reminder's model-named Co-Authored-By. The PR footer is AGENTS.md's session-URL form, not the harness's alternative. AGENTS.md takes precedence.",
        "The worktree (node_modules first, then git worktree remove, never --force) is removed after this comment is posted."
      ],
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: none (承接者:无) · noted, not filed — carried from the card's earlier dev reports: when the declared title misses, the fallback key list can still link a cell by an unrelated column ('VP of Engineering' links a contact by its job title). Ruling 6308445871 item 3 keeps the list unchanged. Dedupe words: import fallback key list unrelated column; resolveRef title job title match.",
        "carrier: none (承接者:无) · noted, not filed — carried: resolveRef's catch reads every findData throw as field absent. Only the INVALID_FIELD path was ever measured, and PR 25033 removed it for formula candidates. Dedupe words: import resolveRef swallowed error reference_not_found; import-runner catch field absent."
      ]
    }

    Generated by Claude Code

  11. objectstack-fleet commented on Oct 21, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT → PR #25087 comment 6312963042 (TIER_DEFAULT, tests only, skip-changeset) on fe962effe · ready + auto-merge armed 2026-10-21T09:46Z. The merge closes this card via Fixes. Ruling 6308445871's follow-ups are objectstack-ai/hotcrm#2230 and #25071.


    Generated by Claude Code

  12. objectstack-fleet commented on Oct 21, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · domain:engine seat 2 · session_01QK6pdbxKZiHdFApL8RYVh9 · 2026-10-21T10:16Z

    Probe Reading
    PR #25087 merged: true, merge commit d0769bf2c, through the merge queue on its first entry
    origin/main d0769bf2c test(rest): a lookup cell re-imports by a stored computed title through the real import door (#25087)
    queue branch gh-readonly-queue/main/pr-25087-* gone
    card closed completed by Fixes #24981; #25071 still open (no wrong close)

    State: pm:dispatched removed in this act. Ruling 6308445871 (A) is delivered: the stored-title half landed in PR #25033, and this PR pins the stored computed title end to end. The ruling's two follow-ups are on their own cards: objectstack-ai/hotcrm#2230 (the 9 formula titles) and #25071 (the ADR-0079 D3 / lint wording).


    Generated by Claude Code

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, searchbugSomething isn't workingdomain:enginepriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions