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.
Re-raise of #4375 with the downstream confirmation it asked for: the console import wizard never sends mappingName and hardcodes writeMode:"insert", so a named mapping's upsert can never reach a user #10102
Path: none | 清单区 studio-authoring:导入向导的命名映射 | 报告者的抓包成立,而本侧每一个可测的半边都已实测正确并已发布 ⇒ 差的是三条只有那个部署能给的读数
分诊重判:2026-09-20T18:54Z
Maintainer-action: ask the reporter (steedos-labs/hotcrm-heimao, outside this session's reach) for the three readings the 2026-09-05 measurement round named — (1) the status and body of GET /api/v1/meta/mapping from the console's own session; (2) whether the browser console carries the line [OBJECTSTACKDataSource] listImportMappings failed: — ⭐ the adapter swallows a refusal into an empty list, so that warn line is the ONLY discriminator between 「served empty」 and 「refused and swallowed」; (3) the four mappings' targetObject values against the object name AS THE CONSOLE ADDRESSES IT, plus that deployment's exact @object-ui/app-shell version — done when a comment on this card carries all three, or records that the deployment predates 17.1.0 or is not the objectui console.
{
"issue": 14026,
"status": "blocked",
"branch": "claude/issue-14026-wizard-named-mapping",
"pr": null,
"premise_still_valid": true,
"summary": "BLOCKED on repo routing: the import wizard UI is not in this repository, so none of the three blocks can be implemented here. `packages/console` is tracked in git with exactly four files — `.gitignore`, `CHANGELOG.md`, `README.md`, `package.json` — and no source at all; its own `package.json` description reads 'Prebuilt Console SPA pinned to this framework release... Source of truth: @object-ui/console (https://github.com/objectstack-ai/objectui)', its `files` field is `[dist, README.md, CHANGELOG.md]`, and its README states the `dist/` is a CI publish artifact built by `scripts/build-console.sh`, which clones objectui at the SHA in `.objectui-sha` (currently 9602dc820450dda956843c6cfe5b329bcf88c757). Repo-wide there are 22 `.tsx` files total: 14 are the docs site under `apps/docs`, 8 are `packages/client-react` (headless data/metadata/realtime hooks plus their tests). There is no wizard, no column-mapping step, no form component of any kind in this tree. PREMISE NOTE, stated plainly rather than forced into the boolean: the issue's technical premise — the wizard sends no `mappingName` and a hardcoded `writeMode` of insert — is NOT falsified, but it is also NOT verifiable in this tree, because no producer of that request body exists here. What fails is the ROUTING premise, that this repo is where the fix lands. I set `premise_still_valid` true so this is not misread as 'the defect is not real' and the card wrongly closed. Per-block verification of the PM's shape reading: BLOCK 3 (header matching by localized label) has no in-repo half either — `autoMatch`, `columnHeader`, `headerMatch`, `guessField`, `matchColumn` and `normalizeHeader` all return zero hits repo-wide, and the label handling that does exist in `packages/rest/src/import-prepare.ts` and `import-coerce.ts` is about select-option CELL values (localized option label accepted as a synonym for the code), never about column HEADERS — the server takes an explicit column-to-field `mapping` and does no header matching. BLOCKS 1 and 2 owe this repo NOTHING, which is the part most useful to triage: the framework side is already complete and the transfer is clean, with no split PR and no prerequisite to land first. `packages/spec/src/api/export.zod.ts:330` declares `mappingName` optional on `ImportRequest` and refines it mutually exclusive with an inline `mapping` at line 368; `packages/spec/authorable-surface/api.json` carries both `api/ImportRequest:mappingName` and `api/CreateImportJobRequest:mappingName`; `packages/rest/src/import-prepare.ts:312` reads `body.mappingName` off the raw body and `packages/rest/src/import-mapping.ts` resolves the artifact by `{ type: mapping, name: mappingName }` with 404 MAPPING_NOT_FOUND, 400 CONFLICTING_MAPPING, a targetObject mismatch guard and a sourceFormat guard, all covered by `packages/rest/src/import-integration.test.ts:492-592`. The SDK is a pure pass-through — `packages/client/src/index.ts:6217` is `import: async (object, request: ImportRequest)` whose body is `JSON.stringify(request)`, so `mappingName` reaches the server unchanged today with zero framework change. Discovery for block 1 also already exists: `GET /api/v1/meta/:type` is generic over the type registry (`packages/rest/src/rest-route-ledger.ts:154`, SDK `meta.getItems`), `mapping` is a registered runtime-creatable type in `packages/spec/src/kernel/metadata-type-schemas.ts:98` — whose own comment reads 'reusable import mapping; runtime-creatable so the wizard can save one' — and `MappingSchema` carries `targetObject` (`packages/spec/src/data/mapping.zod.ts:300`), so a wizard can list `GET /api/v1/meta/mapping` and filter by target object with no new endpoint. NO code was written, NO worktree was created and NO branch was pushed, because the card terminates before the first edit; the shared checkout at /home/user/objectstack is untouched (`git status --porcelain` empty). I deliberately did not reach into objectui to name the exact component path — the dispatch drew that boundary and the in-tree evidence is decisive without it. Transfer is the triage seat's call, not mine.",
"tests": "No build, no test and no gate was run: nothing was edited, so there was nothing to verify and no ablation to perform. What ran instead was location and premise verification against origin/main at e612dd0 (fetched this run), read-only, all in the shared checkout. `git ls-files packages/console` returns exactly `.gitignore`, `CHANGELOG.md`, `README.md`, `package.json`. `git ls-files | grep -cE '\\.(tsx|jsx)$'` returns 22, all under `apps/docs` or `packages/client-react` as enumerated. `git grep -rniI 'autoMatch|columnHeader|headerMatch|guessField|matchColumn|normalizeHeader' -- packages` returns zero hits. `git grep -rn 'skipBlankMatchKey|createMissingOptions|runAutomations'` finds the measured body keys only in docs, tests, and the server-side admin importer `packages/plugins/plugin-auth/src/admin-import-users.ts` — never in a wizard. `git grep -rn 'mappingName' -- packages scripts` returns the spec declarations, the REST resolver and prepare path, the integration tests and the liveness ledger, and nothing in `packages/client-react` or any UI. `ls -d ../objectui` confirms no sibling objectui checkout exists on this machine. The one reverse check worth naming: had any of the three blocks owed a framework-side half, that would have shown up as a missing discovery route or a missing `mappingName` declaration — both were looked for specifically and both are present, which is why this is a clean transfer rather than a split.",
"mcp_calls": "1 — the report comment on this issue. Every read went through git and the zero-quota public-repo page payload; a repo-scoped REST probe answered 403 and `gh` is absent in this container, so no REST channel was available.",
"open_questions": [
{
"question": "Where do the three blocks land, given the wizard UI is in objectstack-ai/objectui and this repo owes no framework-side prerequisite?",
"options": [
"A — Transfer objectstack-ai/objectui#10102 to objectui as one card, keeping the three blocks together. The dispatching PM notes this repo has moved console/analytics defects that way before (#5076 to objectui#4030, objectstack-ai/objectstack#5144 to objectui#4053).",
"B — Transfer as two cards: blocks 1 and 2 (named-mapping selection and mappingName pass-through) as one, block 3 (header matching by field name and localized label) as a separate small one, since block 3 is independent of the mapping work and lands on its own.",
"C — Keep objectstack-ai/objectui#10102 open here as a tracking card and open the objectui work separately, so the downstream reporter at steedos-labs/hotcrm-heimao#117 keeps one upstream card to watch."
],
"recommendation": "B, but this is the triage seat's call and I state it only so the option is on the table, not to push it. The reason to prefer B over A is that block 3 is a genuinely separate defect with its own crisp acceptance test — the same English-header template must match the same fields under zh-CN and en — and it can land while the interaction shape of blocks 1 and 2 is still being decided. That interaction shape is the real cost centre: how registered mappings are offered, which one is default when an object has several, and how a chosen mapping coexists with manual column mapping are decisions that will live on the screen for a long time, and the dispatching PM explicitly declined to pick. Whichever of A/B/C is chosen, note that a Console fix only reaches users after objectui lands it AND `.objectui-sha` is bumped here via `scripts/bump-objectui.sh`, so this repo will still see a follow-up pin PR even though it owns none of the code."
}
],
"out_of_scope_findings": [
"NOT filed, deliberately: the reporter's own note that objectstack-ai/objectstack#4375 carries `state_reason: completed` when it was in fact withdrawn, and should be `not_planned`. It is already written into the body of objectstack-ai/objectui#10102 that the triage seat will read, so a separate card would be a pure duplicate. Recording it here so it does not get lost if the body is skimmed — it matters because a withdrawn card reading as 'completed' is what nearly made this reporter conclude the gap was already fixed.",
"No in-tree defect was found. The framework-side import path was read closely while verifying the premise and is complete and well covered; nothing was noticed that would warrant a card."
]
}
端点已存在且通用:GET /api/v1/meta/mapping(rest-route-ledger.ts:154,SDK meta.getItems)。mapping 是运行时可创建类型(metadata-type-schemas.ts:98),其注释原文就是「runtime-creatable so the wizard can save one」;MappingSchema 带 targetObject(mapping.zod.ts:300),按目标对象过滤即可,不需要新端点
⚠️ Claimed as a measurement round, because both halves of this card's stated defect are FALSE on objectui's main — while the reported symptom is almost certainly real. pm:queue → pm:dispatched.
Claim: domain:cli execution seat, session session_01ARYe3yQTQCUFm5qPYNgKaJ
Branch: claude/issue-14026-import-mapping-selector-probe
Clause-②: no
⛔ Nothing here disputes the downstream PM's packet capture. The capture is a reading and it stands. What is falsified is the diagnosis built on it — and the difference decides which repository this card belongs to.
What the card says, and what objectui's main actually holds
The card, from a real browser session with packet capture on 17.1.0:
Measured on objectstack-ai/objectuiorigin/maina00db9e, in packages/plugin-grid/src/ImportWizard.tsx:
card's claim
reading
the wizard never sends mappingName
⛔ false — :596-600 returns a request carrying mappingName whenever opts.mappingName is set, and then deliberately omits the inline column mapping and write-mode (「mutually exclusive per the server contract」)
writeMode is hardcoded "insert"
⛔ false — :609 sends opts.writeMode, an ImportWriteMode; :1344-1345 is a Select offering grid.import.writeModeOpt.{insert,update,upsert}
The feature shipped in @object-ui/plugin-grid@11.5.0 (its CHANGELOG entry names framework objectstack-ai/objectstack#2611 and this exact behaviour); the package is at 17.6.0 today. ⇒ it is long released, ⛔ not an unreleased main-only fix.
⭐ So why did the capture show neither? The selector is FEATURE-DETECTED, and the probe looks unable to succeed
packages/data-objectstack/src/index.ts:4510, listImportMappings, with its own docblock:
…filters by targetObjectclient-side (the metadata index is name-only). Feeds the import wizard's "saved mapping" selector; a failure … degrades to an empty list, so the selector simply doesn't appear.
constresult=awaitthis.client.meta.getItems('mapping');constitems=Array.isArray(result?.items) ? result.items : Array.isArray(result) ? result : [];returnitems.filter((m)=>m&&m.targetObject===objectName);
⇒ no mapping selected ⇒ no mappingName in the request, and the wizard's own default write mode — which is exactly the capture. The wizard is not ignoring the mapping; the user was never offered it.
⭐ And here is the seam that makes this an objectstack question rather than an objectui one. packages/metadata/src/metadata-manager.ts:2469 states that the registry stores publish envelopes, ⛔ not raw spec documents:
MetadataManager's registry stores publish envelopes ({name, packageId, state, metadata: {...spec}}), not raw spec documents
If /meta/mapping answers with envelopes, then m.targetObject is undefined on every item — the mapping's targetObject lives at m.metadata.targetObject — and the filter above returns empty for everyone, always. The selector would then never appear on any deployment, which is precisely the reported symptom and explains why it looked like a hardcoded client.
⛔ What is NOT being claimed — this is a hypothesis with strong support, not a finished measurement
This seat has not observed a live /meta/mapping response. The :2469 docblock describes MetadataManager's registry; there may be an unwrapping step between it and the REST body. ⇒ the round dispatched here is a measurement, not a fix, and its first deliverable is the one reading that settles it: what does GET /meta/mapping actually return per item, and does any item carry a top-level targetObject?
Three outcomes, and ⛔ this seat picks none of them:
items carry top-level targetObject ⇒ the hypothesis is dead, the probe is fine, and the symptom needs a different cause (a deployment with no mapping artifacts at all is the next candidate — which would make the card a docs/UX question, not a bug).
items are envelopes ⇒ the defect is the filter reading the wrong depth, and it is one line in objectui — but the card's title and its repo:objectui routing are still wrong in substance, because the wizard was never the thing at fault.
the door refuses the mapping kind ⇒ it is an objectstack gap, and the routing inverts entirely.
Why this was worth measuring before dispatching a fix
This card has been through two seats. The first dev seat stopped correctly at blocked — the wizard is not in the objectstack repo (packages/console tracks four files, ⛔ no source) — and the PM seat then corrected its own claim honestly (「那是个偷懒的读数 —— 我只确认了目录存在」). Both were right about the repo. ⛔ Neither read the wizard's source, because it was not there to read. Dispatching it into objectui as written would have sent a dev to add a mappingName the wizard already sends.
⚠️ Also worth keeping: the card's own note that objectstack-ai/objectstack#4375 was closed with state_reason: completed when it was actually withdrawn, so it reads as 「fixed」 in search. That is a real hazard for exactly this kind of re-raise and ⛔ is not fixed by this card.
Re-check
git -C objectui show origin/main:packages/plugin-grid/src/ImportWizard.tsx | sed -n '588,612p'# mappingName + opts.writeMode
git -C objectui show origin/main:packages/data-objectstack/src/index.ts | sed -n '4505,4522p'# the probe and its filter
git -C objectstack show origin/main:packages/metadata/src/metadata-manager.ts | sed -n '2465,2472p'# the envelope shape
{
"issue": 14026,
"status": "done",
"branch": "claude/issue-14026-import-mapping-selector-probe",
"pr": "https://github.com/objectstack-ai/objectui/pull/7738",
"premise_still_valid": false,
"summary": "DELIVERABLE 1 (executed, not inferred). GET /api/v1/meta/mapping answers the spec envelope { type: 'mapping', items: [...] } with NO { success, data } wrapper, and every item is the raw mapping document with targetObject at the TOP LEVEL, decorated with _packageId / _provenance / _diagnostics; no item carries a nested metadata member. Verbatim item from the manifest path: { name: 'task_feed_import', label: 'Task feed import (manifest path)', sourceFormat: 'csv', targetObject: 'task', fieldMapping: [ { source: 'ID', target: 'id', transform: 'none' }, { source: 'Task Title', target: 'title', transform: 'none' } ], mode: 'upsert', upsertKey: ['id'], _packageId: 'probe_pkg', _provenance: 'package', _diagnostics: { valid: true } }. Verbatim item from the MetadataManager path: { name: 'task_service_import', label: 'Task service import (MetadataManager path)', sourceFormat: 'csv', targetObject: 'task', fieldMapping: [ { source: 'ID', target: 'id', transform: 'none' } ], mode: 'update', upsertKey: ['id'], _packageId: 'probe_fs_pkg', _diagnostics: { valid: true } }. Summary line printed by the probe: item count=3, top-level targetObject per item=['task','task','task'], nested metadata.targetObject per item=[null,null,null]. GET /api/v1/meta/types lists mapping in the live set (mapping-in-live-set=true), so the door does not refuse the kind. HOW: a vitest probe in objectstack packages/rest at origin/main 132742f10, mirroring import-integration.test.ts (real ObjectQL + better-sqlite3 :memory: + real ObjectStackProtocolImplementation + RestServer.registerRoutes(), then the registered GET /api/v1/meta/:type handler invoked with params.type='mapping'), with one mapping registered through EACH of the three producer paths: engine.registerApp({ id: 'probe_pkg', mappings: [...] }) (manifest path), engine.registry.registerItem('mapping', ...) (the import route's own test path), and new MetadataManager({ formats: ['json'] }).register('mapping', ...) installed as the 'metadata' service via the protocol's getServicesRegistry constructor argument (the registrar packages/metadata/src/plugin.ts uses for file-based artifacts). Both protocol.getMetaItems({ type: 'mapping' }) and the REST handler's res.json body were printed and agree. The probe file was not committed (objectstack unchanged); a copy is in the dev scratchpad. DELIVERABLE 2: branch 1 — the hypothesis is dead. What I measured toward the real cause, without inventing a third theory: (a) the consumer half is correct against the served body and now pinned (PR objectui#7738); (b) the whole selector plumbing is RELEASED, not main-only: npm pack of @object-ui/data-objectstack@17.1.0 carries listImportMappings with the identical targetObject filter (2 hits), @object-ui/plugin-grid@17.1.0 carries listImportMappings / mappingName / savedMapping (3/3/5 files), @object-ui/app-shell@17.1.0 carries the wizard mount (17.0.0 and 17.4.0 do not exist on npm); so the card's own diagnosis ('the wizard never sends mappingName and hardcodes insert', observed on '17.1.0') is falsified for the published packages as well as for origin/main a00db9e, unless the reporter's console predates 17.1.0 or is not the objectui console; (c) the console hands the wizard the raw ObjectStackAdapter (AdapterProvider.tsx builds it; ObjectView passes identityDataSource ?? dataSource), so feature detection is satisfied on every object except sys_user (see residue); (d) the only shipped example that declares mappings is examples/app-showcase, and it declares exactly one, targeting showcase_inquiry — so on a showcase deployment the selector appears on showcase_inquiry only and on no other object, by construction; the card's reporter says four mappings are registered, so 'no artifact registered' is not their case as stated, but 'no artifact whose targetObject equals the object name the console addresses' still is the first thing to read there. THE READING I CANNOT TAKE FROM HERE, and the one that decides the card: on the reporter's deployment, the status and body of GET /api/v1/meta/mapping from the console's own session, the browser console for the line '[OBJECTSTACKDataSource] listImportMappings failed:' (the adapter swallows any refusal into an empty list, and that warn line is the only discriminator between 'served empty' and 'refused'), and the four mappings' targetObject values against crm_plant_cost as the console names it. CONTRADICTIONS TO ZONE 2, stated as readings: A1 holds and is stronger than stated (the feature is in all three 17.1.0 packages, not only plugin-grid 11.5.0+). A2 holds as the mechanism that WOULD hide a failure; on the measured server there is no failure to hide. A3 is dead by execution on all three producer paths; by reading, the metadata-manager.ts docblock describes MetadataManager.validate's reasoning, MetadataManager.register stores whatever the caller hands it, the file loader hands the parsed document (applyProtection only stamps _packageId), and sys_metadata rows are peeled by convertStoredItem in the protocol's own overlay read — no path I executed or read stores envelopes for mapping. Clause-② re-declared from the actual diff: no — one test file plus an empty-frontmatter changeset; no governed surface, no published runtime code, no content/docs/releases.",
"tests": "PIN (objectui, all at head 6cbaed1, exit codes captured before any pipe; every build/test through scripts/pm/os-verify-lock.sh, VERDICT lines quoted): first run pnpm exec vitest run packages/data-objectstack/src/listImportMappings.test.ts — 'Test Files 1 passed (1) / Tests 2 passed (2)', VERDICT command-exit 0 — GREEN ON FIRST RUN, because the code is correct; the red leg is an ablation: after committing the pin, the filter in packages/data-objectstack/src/index.ts was mutated to the hypothesised envelope depth m.metadata?.targetObject === objectName (mutation confirmed on disk by anchored grep counts: before orig=1 mut=0, after orig=0 mut=1), run — 'AssertionError: expected [] to deeply equal [ \"task_feed_import\" ]', 'Test Files 1 failed (1) / Tests 1 failed | 1 passed (2)', ABLATION_RUN_EXIT=1; restore by git checkout HEAD -- absolute path inside a trap, proven by empty git diff HEAD --stat and worktree blob hash bad31df43ab03a0f85ccf61dbf748481499cfadd equal to HEAD blob; re-run — 2 passed, VERDICT command-exit 0. No dist is involved (vitest resolves ./index from source), so no dist preflight applies. PACKAGE SUITE: pnpm exec vitest run packages/data-objectstack/ — 'Test Files 56 passed (56) / Tests 739 passed (739)', VERDICT command-exit 0. TYPECHECK: pnpm --filter '@object-ui/data-objectstack^...' build (VERDICT command-exit 0) then pnpm --filter @object-ui/data-objectstack type-check — VERDICT command-exit 0; tsc --noEmit --listFiles counts the new test file in the population (1 hit). LINT: pnpm --filter @object-ui/data-objectstack lint — 0 errors, 424 pre-existing warnings, exit 0. node scripts/check-control-bytes.mjs — OK (6302 files), exit 0. node scripts/check-changeset-presence.mjs — exit 0 (empty frontmatter accepted); node scripts/check-changeset-no-major.mjs — exit 0. Whole-repo pnpm lint and pnpm check are CI-owned and were not run. PROBE (objectstack worktree at 132742f10, torn down after): pnpm --filter '@objectstack/rest^...' build — VERDICT command-exit 0 (held 235s); pnpm --filter @objectstack/rest exec vitest run --maxWorkers=2 src/meta-mapping-list-item-shape.probe.test.ts — run 1 (two paths) 'Tests 1 passed (1)' VERDICT command-exit 0, run 2 (three paths) 'Tests 1 passed (1)' VERDICT command-exit 0; the harness logs one sql-driver DATABASE_ERROR 'no such table: sys_metadata' (no platform objects registered) and the protocol still serves the registry items — harness artifact, not read as a defect. Write-route probe: empty branch push exit 0 before any edit. Lock waits observed: 91s, 265s, 302s, 24s, 13s, 0s — shared-box seconds.",
"mcp_calls": "8 — search_issues x3 (one dedup in objectstack: empty; two controls: the card's own title in objectstack answered objectstack-ai/objectui#10102, so the empty dedup is a reading), issue_read x2 (objectui#14026 answered 404 — the card lives in objectstack; objectstack#14026 read), create_pull_request x1, issue_write x1 (finding), add_issue_comment x1 (this report). PR body and this comment read back over the zero-quota REST path.",
"open_questions": [
{
"question": "The card's diagnosis is falsified on origin/main and on the published 17.1.0 packages, but the reporter's wire capture (no mappingName, writeMode insert) is a real observation on their deployment that this seat cannot re-take. How should the card proceed?",
"options": [
"A: return the card to the reporter with the three readings named in summary (GET /api/v1/meta/mapping status+body from the console session; the '[OBJECTSTACKDataSource] listImportMappings failed:' warn line; the four mappings' targetObject values vs crm_plant_cost) plus their exact @object-ui/app-shell version, then re-triage",
"B: close as not reproducible against the shipped stack",
"C: dispatch a dogfood round that boots app-showcase and drives the console's import wizard on showcase_inquiry in a browser to confirm the selector renders end to end"
],
"recommendation": "A, because every measurable half on this side is correct and released, and the one reading that discriminates 'served empty' from 'refused and swallowed' only exists on the reporter's server; C is a cheap confirmation if PM wants a browser-level reading before asking, but it cannot see their deployment either."
},
{
"question": "The adapter degrades every listImportMappings failure to an empty list by design, so a refused or broken door is indistinguishable in the UI from 'no mapping registered'. Should that stay silent?",
"options": [
"A: keep the swallow, rely on the new pin plus the producer-side pin (#15907)",
"B: keep the empty-list degrade for the selector but surface the failure (a wizard-level notice or a structured warning) so a capture like this card's is self-diagnosing"
],
"recommendation": "B, as a separate small card — not done here because branch 1 of the round forbids widening; the current behaviour is exactly what made a released feature read as a hardcoded client."
}
],
"out_of_scope_findings": [
"filed as objectstack-ai/objectstack#15907 (objectstack, label finding): GET /meta/mapping's per-item shape has no producer-side pin; the consumer pin in objectui#7738 carries a copied fixture and cannot notice a producer change. Surface published: yes — @objectstack/rest serves the door.",
"reported, not filed (PM to file or design-accept): packages/app-shell/src/views/identityImport.ts createIdentityImportDataSource returns { ...base, importRecords, ...job methods nulled }; the spread copies own properties only, and listImportMappings is a prototype method of ObjectStackAdapter, so on sys_user the wizard's dataSource has no listImportMappings and the saved-mapping selector is hidden by construction. Not the card's object. Surface published: yes — the same spread is in @object-ui/app-shell@17.1.0 dist (1 site). Whether a saved mapping should apply to identity import at all is a design question, which is why it is reported rather than filed.",
"reported, not filed: examples/app-showcase declares exactly one mapping, targeting showcase_inquiry, so the selector is demonstrable on one object only; if PM wants the showcase to exercise the selector on the task or project objects, that is a docs/example addition, not a defect. Surface published: examples are not published packages."
]
}
Measurement round complete — ⭐ the card's diagnosis is falsified, its observation is not. PM takes option A: this returns to the reporter with the three readings only their deployment can give. pm:dispatched stripped; ⛔ no routing label applied — that is triage's write.
domain:cli dispatching seat, session_01ARYe3yQTQCUFm5qPYNgKaJ. The round was dispatched as a measurement, ⛔ not a fix, precisely because this seat's own hypothesis might be wrong. It was.
Deliverable 1, executed on three producer paths — ⛔ not inferred from a type
GET /api/v1/meta/mapping answers { type: 'mapping', items: [...] }, and every item is the raw mapping document with targetObject at the TOP level, decorated with _packageId / _provenance / _diagnostics. ⛔ No item carries a nested metadata member. Probe summary:
Registered through each of the three producers — registerApp({ mappings }), registry.registerItem('mapping', …), and MetadataManager.register installed as the metadata service — against a real ObjectQL + sqlite + real protocol + RestServer's registered route table.
⇒ The envelope hypothesis is dead. The adapter's top-level targetObject filter is correct against the served body, and the wizard is correct because it was already correct.
⚠️Why this seat's reading was wrong, stated so it is not repeated: the metadata-manager.ts:2469 docblock about publish envelopes describes MetadataManager.validate's reasoning. register stores what the caller hands it, the file loader hands the parsed document (applyProtection only stamps _packageId), and sys_metadata rows are peeled by convertStoredItem in the protocol's own overlay read. ⭐ A docblock about one method is not a reading about another method's output — which is the same class of error as a lane-scoped grep answering a question about a file.
And A1 is stronger than this seat stated: the feature is in the published 17.1.0 packages
npm pack measurements: @object-ui/data-objectstack@17.1.0 carries listImportMappings with the identical targetObject filter; @object-ui/plugin-grid@17.1.0 carries listImportMappings / mappingName / savedMapping (3 / 3 / 5 files); @object-ui/app-shell@17.1.0 carries the wizard mount. (17.0.0 and 17.4.0 do not exist on npm.)
⇒ the card's 「向导根本不读已注册的命名映射」, observed on 17.1.0, is falsified for the published packages as well as for origin/main — unless the reporter's console predates 17.1.0 or is not the objectui console.
⛔ What is NOT concluded: the capture is real and this card is not closed
The reporter took a wire capture in a real browser session. That is a reading and it stands. What has been falsified is the diagnosis built on it. ⛔ 「Not reproducible」 (option B) is refused: every measurable half on this side is correct and released, which relocates the question to the reporter's deployment rather than dissolving it.
The three readings that discriminate, and only their server can give them
the status and body of GET /api/v1/meta/mapping from the console's own session;
the browser console line [OBJECTSTACKDataSource] listImportMappings failed: — ⭐ the adapter swallows any refusal into an empty list, so that warn line is the only discriminator between 「served empty」 and 「refused and swallowed」;
the four mappings' targetObject values against crm_plant_costas the console names it, plus the exact @object-ui/app-shell version in the deployment.
⚠️ The reporter states four mappings are registered, so 「no artifact registered」 is not their case as stated — but 「no artifact whose targetObject equals the object name the console addresses」 is still the first thing to read there.
Option C (a dogfood round booting app-showcase and driving the wizard in a browser) was considered and ⛔ not taken: it is a cheap confirmation of what is already measured twice over, and it cannot see the reporter's deployment either. ⚠️ If triage or the maintainer wants a browser-level reading before asking the reporter, C is available and cheap — that is a routing call, ⛔ not this seat's.
What the round shipped anyway
objectui#7738 (draft, Part of ⛔ not Closes): a pin feeding the verbatim measured body through a fetch stub so the real @objectstack/clientmeta.getItemsand the adapter's own filter both run. ⭐ It was green on first run — the code is correct — so the round proved it bites by ablation: mutating the filter to the hypothesised envelope depth turns it red (expected [] to deeply equal [ "task_feed_import" ]), restored with the blob hash proven equal to HEAD. A pin nobody has seen fail is not a pin that has been demonstrated.
Two residues filed separately: #15907 (the served item shape has no producer-side pin — the consumer pin carries a copied fixture and cannot notice a producer change) objectui#7740 (the identity-import data source drops listImportMappings through an object spread — published) and objectui#7741 (the swallow that made this card misdiagnose itself).
State
pm:dispatched stripped — ⛔ nothing is in flight on this card. It is waiting on the reporter, and this seat ⛔ does not apply the routing label for that; triage's write. Everything above is the reason.
Triage: lands in objectstack-ai/objectui (console import wizard) ⇒ stays here as a repo:objectui card; type Bug; priority:p1 unchanged; pm:queue.
Rationale: the fix is entirely in the console's generic import wizard — remove objectstack from the report and it still stands — so the landing repo is objectui. It was already labelled repo:objectui; what was missing was a state, which is why it has sat 9 days invisible to every queue scan. That is the half-state this sweep exists to heal, ⛔ not a re-routing.
priority:p1 is left as filed and is well-earned: a downstream PM confirmed it blocks the usability of a delivered feature on a live line, which is exactly the confirmation objectstack-ai/objectstack#4375's closure asked for before anyone re-raised it.
⚠️ The incidental request in this card is already satisfied — ⛔ do not action it
The card asks that objectstack-ai/objectstack#4375's state_reason be changed from completed to not_planned, because it was a withdrawal and reads as "fixed" in search. Measured just now:
GET /repos/objectstack-ai/objectstack/issues/4375
state=closed state_reason=not_planned
⇒ It already reads not_planned. Someone corrected it between the filing and today. ⛔ No write is made here, and the observation is recorded rather than repeated so the next reader does not go looking for a fix that is done.
⭐ The underlying point stands as good practice and matches the state model (「撤单/不做 ⇒ not_planned」): a withdrawal closed as completed is a search-time landmine. This card is the evidence that it cost someone real time — the filer says they nearly abandoned a live defect because of it.
Triage seat · session_013hshVTmHY5F7rhpNtYHa3m · R+165 · readings taken 2026-09-10T01:0xZ
Reconciliation under ruling 5725370464 item 2 (objectstack#18862 b — the twelve cross-author claim pairs) — skills seat, session_01W5y9kRg1YtYaMQYExVLRc2 · 2026-09-19T03:31Z.
⛔ No label, assignee or state change by this comment; the card stays pm:queue with no assignee.
Pair read: hotlong (5486688759 at 2026-09-01T00:26Z, branch claude/issue-14026-wizard-named-mapping — no PR in objectstack names it, and no head of that name on objectstack's or objectui's origin at 2026-09-19T03:27Z) + claude[bot] (5552047289 at 2026-09-05T13:11Z, a measurement round; no head, no PR). The later claimant is the retired identity, so the seat posts its release; the earlier claim belongs to a maintainer account and is asked, not released:
Release: session session_01ARYe3yQTQCUFm5qPYNgKaJ — 因 measurement round by the retired claude[bot] identity; no branch, no PR; the card is back in the queue unassigned — 去向 pm:queue
Ask (the ruling's one-working-day window): @hotlong — if the claim 5486688759 still stands, say so on this thread; on silence this seat records its release at the round after the window and the card keeps reading as free.
Reconciliation follow-up (ruling 5725370464 item 2, the one-working-day window opened by 5739013562 at 2026-09-19T03:31Z) — skills seat, session_01W5y9kRg1YtYaMQYExVLRc2 · 2026-09-20T03:35Z.
⛔ No label, assignee or state change by this comment; the card stays pm:queue with no assignee, and no Release: line is written here.
Window reading: no comment on this thread since the ask; the claim 5486688759 (hotlong, 2026-09-01T00:26Z) still names branch claude/issue-14026-wizard-named-mapping, which is on neither origin at 2026-09-20T03:02Z, and no PR in either repository references this card.
What the seat does about its own sentence 「on silence this seat records its release」: it does not write that line. Two rules meet here and the seat takes the stricter one (SKILL.md 「两条细则冲突 ⇒ 按更严的一条行动并立卡」): the dead-claim reclaim (SKILL.md :496 — a Release: with cause after a silent window) against the landed reader's retraction rule (scripts/pm/check-clause2-carriers.mjs, CLAIM_RETRACTION_RULE: a claim leaves the pool only by a later Release:by the same author, 「⛔ never a DIFFERENT author's line」, and the C9 remedy 「⛔ never a Release: on the holder's behalf」). A Release: written by this seat for a maintainer's claim would be prose to the reader and a forbidden act to the remedy. The conflict is filed as a skills-lane card (linked below in the seat's round report; the number is on the card that names this thread).
Board reading unchanged: pm:queue with no assignee is the free shape, and every reader ranks the card as free; the claim stands as the maintainer's to release or to act on, and the seat asks nothing further here.
pm:retriage — ⛔ this card is not dispatchable, and the pre-dispatch premise check is what found it
Hung by the domain:ui execution seat (Seat: domain:ui#2, session session_018HrVaotisyhgmot9o2MLRq) at 2026-09-20T18:33Z, in the same stroke as this comment. ⛔ pm:queue is NOT stripped and ⛔ no grade or route is touched — those are triage's to produce. This is a question, not a re-judgement.
What this seat was about to do, and why it stopped
This card is the lane's highest-priority open candidate and was next for dispatch. The protocol's pre-dispatch premise check sent this seat to the thread first. The thread says the premise is already falsified:
A measurement round by the domain:cli seat concluded on 2026-09-05T13:54Z:
⭐ the card's diagnosis is falsified, its observation is not. PM takes option A: this returns to the reporter with the three readings only their deployment can give.
It measured GET /api/v1/meta/mapping against three producer paths on a real ObjectQL + sqlite + RestServer stack, found every item carries targetObject at the top level, and concluded the adapter's filter 「is correct against the served body, and the wizard is correct because it was already correct」. It then measured the published packages by npm pack and found listImportMappings / mappingName / savedMapping present in @object-ui/data-objectstack@17.1.0, @object-ui/plugin-grid@17.1.0 and @object-ui/app-shell@17.1.0.
⇒ the card's 「向导根本不读已注册的命名映射」, observed on 17.1.0, is falsified for origin/mainand for the published 17.1.0 packages — unless the reporter's console predates 17.1.0 or is not the objectui console.
⛔ That round explicitly refused 「not reproducible」 and did not close the card: the reporter's wire capture is a reading and it stands. What it asked for are three readings only that deployment can give — the status and body of GET /api/v1/meta/mapping from the console's own session; the browser line [OBJECTSTACKDataSource] listImportMappings failed: (⭐ the adapter swallows a refusal into an empty list, so that warn line is the only discriminator between 「served empty」 and 「refused and swallowed」); and the four mappings' targetObject values against the object name as the console addresses it, plus the deployment's exact @object-ui/app-shell version.
The disagreement
Triage re-queued this card as pm:queue / repo:objectui / Bug / p1 on 2026-09-10T00:18Z. Read against the thread, ⛔ none of the three requested readings had arrived by then, and none has arrived since — the comments after that date are reconciliation, a reference-scope correction and this one.
⇒ the card is queued as dispatchable while what it actually waits on is a reading from outside this board. Dispatching it would send a dev to fix something two independent measurements say is already correct here.
What this seat asks triage to decide — ⛔ it is deliberately not deciding it
Is pm:queue the right state? A card waiting on an external reading looks like pm:blocked or pm:on-hold with a Restart-when: naming the three readings. ⛔ This seat does not change a state label on a card it did not claim.
Did the 2026-09-10 triage pass see the measurement round? If it did and re-queued deliberately, say so and this seat dispatches on the next round without re-asking. If it did not, the grade and state are worth retaking.
Who carries the request to the reporter? The card names steedos-labs/hotcrm-heimao's PM seat as the re-raiser. ⛔ That repo is outside this session's reach, so this seat cannot ask them.
⚠️ ⛔ Nothing here says the reporter is wrong. Two things are true at once: their capture is real, and every measurable half on this side is correct and released. The gap between those is exactly the three readings — and ⛔ it is not closable by a dev in this repository.
Meanwhile this seat takes the next candidate instead, and ⛔ will not dispatch this card while pm:retriage is on it.
Closed on the maintainer's instruction, 2026-09-22T02:43Z
Director seat, summon #26 (session_01SPwf6Kmqo1gqzCSWSuMtQM). Source, three parts: the maintainer, verbatim 「10102 关闭」, in this seat's chat on 2026-09-22 while answering decision batch #210. The card's Maintainer-action: (ask the reporter for three readings) is withdrawn rather than performed; the 2026-09-05 measurement round found nothing wrong on this side, and the missing readings can only come from the reporter's deployment.
State in this stroke:pm:awaiting-maintainer removed; closed not_planned (withdrawn by the maintainer; bug / domain:ui / priority:p1 stay as attribution). Reopen is free if the reporter supplies the three readings.
Activity
hotlong commentedon Sep 1, 2026
Claim:session9474bf6f-d90c-5a21-b347-0245cc7e5487· branchclaude/issue-14026-wizard-named-mapping同 objectstack-ai/objectstack#14010 / objectstack-ai/objectstack#14011 一批。我是下游
steedos-labs/hotcrm-heimao的 PM 席,按维护者直接指令(逐字:「上游需要解决的问题你也同步派发」)派发。三条边界与那两张一致:domain:*标签 —— 本仓分诊席的专属产出。opus(非claude-fable-5):本卡是实现面,不改契约接受面。命名映射已经是被声明的元数据、mappingName已经是接口收的参数 —— 缺的是向导去读它,没有新的公开可编写面。给接手 agent 的边界(同步公示):
packages/console在本仓、mappingName的处理在packages/rest/src/import-mapping.ts/import-prepare.ts,但没有定位到向导那几步的组件本身。本仓的若干控制台/分析面缺陷此前被移去了objectstack-ai/objectui(例如 Analytics surfaces resolve select-option labels but never apply the i18n bundle — reports and dashboards show English while lists and forms show the translation objectstack#5076→objectui#4030、[finding]userActions.editInlinehas two different defaults across surfaces, and neither is the spec's.default(false)#5144→objectui#4053)。若向导 UI 实际住在 objectui:停下报blocked,把定位结论写进报告 —— 那个仓不在我的访问范围内,转仓由本仓分诊席决定,不由你我。blocked,别顺着我的读数改。mappingName,单份映射时默认选它)作为独立可交付的一半 —— 并把 1 的缺口留成新卡。mappingName的接口路径对同一份重复数据得到同一结果」,而且要先看着它在修复前变红。这个缺陷的整个形态就是「两条通道结果相反」,所以守卫必须钉的是两条通道的一致性,不是任一条自己的行为。content/docs/releases/。变更走 changeset。下游侧:
steedos-labs/hotcrm-heimao#117已挂本卡,界面侧不做应用变通(维护者原则:元数据项目不开发专用导入入口,复用平台能力)。Generated by Claude Code
hotlong commentedon Sep 1, 2026
os-dev-report
{ "issue": 14026, "status": "blocked", "branch": "claude/issue-14026-wizard-named-mapping", "pr": null, "premise_still_valid": true, "summary": "BLOCKED on repo routing: the import wizard UI is not in this repository, so none of the three blocks can be implemented here. `packages/console` is tracked in git with exactly four files — `.gitignore`, `CHANGELOG.md`, `README.md`, `package.json` — and no source at all; its own `package.json` description reads 'Prebuilt Console SPA pinned to this framework release... Source of truth: @object-ui/console (https://github.com/objectstack-ai/objectui)', its `files` field is `[dist, README.md, CHANGELOG.md]`, and its README states the `dist/` is a CI publish artifact built by `scripts/build-console.sh`, which clones objectui at the SHA in `.objectui-sha` (currently 9602dc820450dda956843c6cfe5b329bcf88c757). Repo-wide there are 22 `.tsx` files total: 14 are the docs site under `apps/docs`, 8 are `packages/client-react` (headless data/metadata/realtime hooks plus their tests). There is no wizard, no column-mapping step, no form component of any kind in this tree. PREMISE NOTE, stated plainly rather than forced into the boolean: the issue's technical premise — the wizard sends no `mappingName` and a hardcoded `writeMode` of insert — is NOT falsified, but it is also NOT verifiable in this tree, because no producer of that request body exists here. What fails is the ROUTING premise, that this repo is where the fix lands. I set `premise_still_valid` true so this is not misread as 'the defect is not real' and the card wrongly closed. Per-block verification of the PM's shape reading: BLOCK 3 (header matching by localized label) has no in-repo half either — `autoMatch`, `columnHeader`, `headerMatch`, `guessField`, `matchColumn` and `normalizeHeader` all return zero hits repo-wide, and the label handling that does exist in `packages/rest/src/import-prepare.ts` and `import-coerce.ts` is about select-option CELL values (localized option label accepted as a synonym for the code), never about column HEADERS — the server takes an explicit column-to-field `mapping` and does no header matching. BLOCKS 1 and 2 owe this repo NOTHING, which is the part most useful to triage: the framework side is already complete and the transfer is clean, with no split PR and no prerequisite to land first. `packages/spec/src/api/export.zod.ts:330` declares `mappingName` optional on `ImportRequest` and refines it mutually exclusive with an inline `mapping` at line 368; `packages/spec/authorable-surface/api.json` carries both `api/ImportRequest:mappingName` and `api/CreateImportJobRequest:mappingName`; `packages/rest/src/import-prepare.ts:312` reads `body.mappingName` off the raw body and `packages/rest/src/import-mapping.ts` resolves the artifact by `{ type: mapping, name: mappingName }` with 404 MAPPING_NOT_FOUND, 400 CONFLICTING_MAPPING, a targetObject mismatch guard and a sourceFormat guard, all covered by `packages/rest/src/import-integration.test.ts:492-592`. The SDK is a pure pass-through — `packages/client/src/index.ts:6217` is `import: async (object, request: ImportRequest)` whose body is `JSON.stringify(request)`, so `mappingName` reaches the server unchanged today with zero framework change. Discovery for block 1 also already exists: `GET /api/v1/meta/:type` is generic over the type registry (`packages/rest/src/rest-route-ledger.ts:154`, SDK `meta.getItems`), `mapping` is a registered runtime-creatable type in `packages/spec/src/kernel/metadata-type-schemas.ts:98` — whose own comment reads 'reusable import mapping; runtime-creatable so the wizard can save one' — and `MappingSchema` carries `targetObject` (`packages/spec/src/data/mapping.zod.ts:300`), so a wizard can list `GET /api/v1/meta/mapping` and filter by target object with no new endpoint. NO code was written, NO worktree was created and NO branch was pushed, because the card terminates before the first edit; the shared checkout at /home/user/objectstack is untouched (`git status --porcelain` empty). I deliberately did not reach into objectui to name the exact component path — the dispatch drew that boundary and the in-tree evidence is decisive without it. Transfer is the triage seat's call, not mine.", "tests": "No build, no test and no gate was run: nothing was edited, so there was nothing to verify and no ablation to perform. What ran instead was location and premise verification against origin/main at e612dd0 (fetched this run), read-only, all in the shared checkout. `git ls-files packages/console` returns exactly `.gitignore`, `CHANGELOG.md`, `README.md`, `package.json`. `git ls-files | grep -cE '\\.(tsx|jsx)$'` returns 22, all under `apps/docs` or `packages/client-react` as enumerated. `git grep -rniI 'autoMatch|columnHeader|headerMatch|guessField|matchColumn|normalizeHeader' -- packages` returns zero hits. `git grep -rn 'skipBlankMatchKey|createMissingOptions|runAutomations'` finds the measured body keys only in docs, tests, and the server-side admin importer `packages/plugins/plugin-auth/src/admin-import-users.ts` — never in a wizard. `git grep -rn 'mappingName' -- packages scripts` returns the spec declarations, the REST resolver and prepare path, the integration tests and the liveness ledger, and nothing in `packages/client-react` or any UI. `ls -d ../objectui` confirms no sibling objectui checkout exists on this machine. The one reverse check worth naming: had any of the three blocks owed a framework-side half, that would have shown up as a missing discovery route or a missing `mappingName` declaration — both were looked for specifically and both are present, which is why this is a clean transfer rather than a split.", "mcp_calls": "1 — the report comment on this issue. Every read went through git and the zero-quota public-repo page payload; a repo-scoped REST probe answered 403 and `gh` is absent in this container, so no REST channel was available.", "open_questions": [ { "question": "Where do the three blocks land, given the wizard UI is in objectstack-ai/objectui and this repo owes no framework-side prerequisite?", "options": [ "A — Transfer objectstack-ai/objectui#10102 to objectui as one card, keeping the three blocks together. The dispatching PM notes this repo has moved console/analytics defects that way before (#5076 to objectui#4030, objectstack-ai/objectstack#5144 to objectui#4053).", "B — Transfer as two cards: blocks 1 and 2 (named-mapping selection and mappingName pass-through) as one, block 3 (header matching by field name and localized label) as a separate small one, since block 3 is independent of the mapping work and lands on its own.", "C — Keep objectstack-ai/objectui#10102 open here as a tracking card and open the objectui work separately, so the downstream reporter at steedos-labs/hotcrm-heimao#117 keeps one upstream card to watch." ], "recommendation": "B, but this is the triage seat's call and I state it only so the option is on the table, not to push it. The reason to prefer B over A is that block 3 is a genuinely separate defect with its own crisp acceptance test — the same English-header template must match the same fields under zh-CN and en — and it can land while the interaction shape of blocks 1 and 2 is still being decided. That interaction shape is the real cost centre: how registered mappings are offered, which one is default when an object has several, and how a chosen mapping coexists with manual column mapping are decisions that will live on the screen for a long time, and the dispatching PM explicitly declined to pick. Whichever of A/B/C is chosen, note that a Console fix only reaches users after objectui lands it AND `.objectui-sha` is bumped here via `scripts/bump-objectui.sh`, so this repo will still see a follow-up pin PR even though it owns none of the code." } ], "out_of_scope_findings": [ "NOT filed, deliberately: the reporter's own note that objectstack-ai/objectstack#4375 carries `state_reason: completed` when it was in fact withdrawn, and should be `not_planned`. It is already written into the body of objectstack-ai/objectui#10102 that the triage seat will read, so a separate card would be a pure duplicate. Recording it here so it does not get lost if the body is skimmed — it matters because a withdrawn card reading as 'completed' is what nearly made this reporter conclude the gap was already fixed.", "No in-tree defect was found. The framework-side import path was read closely while verifying the premise and is complete and well covered; nothing was noticed that would warrant a card." ] }Generated by Claude Code
hotlong commentedon Sep 1, 2026
PM 侧结论:这是一张纯转仓卡,本仓不欠任何前置。请分诊席转
objectstack-ai/objectui。派发的 agent 在第一次编辑前停下报
blocked,读数见上一条os-dev-report。我复核并接受它的结论,同时更正我自己在认领评论里的一个判断。我错在哪
我在认领评论里写「我核到
packages/console在本仓」,据此判定本卡提对了仓。那是个偷懒的读数 —— 我只确认了目录存在。实际上packages/console在 git 里只跟踪四个文件:一行源码都没有。 它自己的
package.json写着:files是[dist, README.md, CHANGELOG.md],而dist/是scripts/build-console.sh在 CI 里按.objectui-sha(当前9602dc82…)克隆 objectui 构建出来的产物。旁证:全仓一共 22 个
.tsx,14 个是apps/docs的文档站,8 个是packages/client-react的无头 hooks 及其测试。没有向导、没有列映射步骤、没有任何表单组件。我在派发词里预设了这个可能(点名了 objectstack-ai/objectstack#5076→objectui#4030、#5144→objectui#4053 的先例并要求停下报 blocked),但预设不等于核实过 —— 目录存在就下结论是我的失误。
失效的是路由前提(本仓是不是修它的地方),不是技术前提。向导不发
mappingName、writeMode硬编码insert这条读数没有被证伪 —— 它在本树里根本无从证伪,因为发出那个请求体的东西不在这里。缺陷是真的,只是家不在这儿。最有价值的那一半:框架侧已经齐了,是干净转仓,不用拆 PR
这是本次派发真正的产出 —— 块一与块二不欠本仓任何东西,objectui 那边可以直接开工,不需要等这里先落一个前置 PR:
mappingName进得了接口packages/spec/src/api/export.zod.ts:330已声明为ImportRequest的可选字段,:368有与内联mapping互斥的 refinepackages/spec/authorable-surface/api.json载api/ImportRequest:mappingName与api/CreateImportJobRequest:mappingNamepackages/rest/src/import-prepare.ts:312读body.mappingName;import-mapping.ts按{ type: mapping, name }解析,带 404MAPPING_NOT_FOUND/ 400CONFLICTING_MAPPING/ targetObject 不匹配守卫 / sourceFormat 守卫packages/rest/src/import-integration.test.ts:492-592packages/client/src/index.ts:6217是纯透传(JSON.stringify(request)),今天mappingName就能原样到服务端,零框架改动GET /api/v1/meta/mapping(rest-route-ledger.ts:154,SDKmeta.getItems)。mapping是运行时可创建类型(metadata-type-schemas.ts:98),其注释原文就是「runtime-creatable so the wizard can save one」;MappingSchema带targetObject(mapping.zod.ts:300),按目标对象过滤即可,不需要新端点块三(列头匹配)同样没有本仓的一半:
autoMatch/columnHeader/headerMatch/guessField/matchColumn/normalizeHeader全仓零命中;import-prepare.ts与import-coerce.ts里确实有 label 处理,但那是单元格值的(接受本地化选项 label 作为 code 的同义词),不是列头的 —— 服务端拿的是显式的列→字段mapping,不做任何列头匹配。转仓形状:建议拆两张(分诊席定,我只把选项摆上)
mappingName)一张;理由:块三是独立缺陷,验收判据很脆很干净 —— 同一份英文列头模板,在 zh-CN 与 en 两种界面语言下必须匹配到同一批字段 —— 它可以在块一/块二的交互形状还没定下来的时候先落地。而那个交互形状才是真正的成本中心(多份映射时怎么呈现、默认选哪个、与手工列映射如何共存),我在派发词里明确没有替 objectui 定。
scripts/bump-objectui.sh把.objectui-sha顶上去。 所以本仓最终仍会有一个 pin PR,尽管它一行相关代码都不拥有。一并提请注意(已写在本卡正文里,怕被略读)
#4375的state_reason是completed,而它实际是撤回。搜索时它看起来像"已修复" —— 我这次差点因此判定缺口已解决而不再跟进。建议改为not_planned。本卡的落地状态
没有创建 worktree、没有推分支、没有 PR,共享检出未被触碰(
git status --porcelain为空)。我也没有去 objectui 里定位那个组件的具体路径 —— 本树内的证据已经足够决定转仓,而那个仓不在我这个下游席位的访问范围内。转仓是分诊席的事。下游侧
steedos-labs/hotcrm-heimao#117已挂本卡,会跟着转。Generated by Claude Code
claude commentedon Sep 5, 2026
objectui'smain— while the reported symptom is almost certainly real.pm:queue→pm:dispatched.Claim:
domain:cliexecution seat, sessionsession_01ARYe3yQTQCUFm5qPYNgKaJBranch:
claude/issue-14026-import-mapping-selector-probeClause-②: no
⛔ Nothing here disputes the downstream PM's packet capture. The capture is a reading and it stands. What is falsified is the diagnosis built on it — and the difference decides which repository this card belongs to.
What the card says, and what
objectui'smainactually holdsThe card, from a real browser session with packet capture on 17.1.0:
Measured on
objectstack-ai/objectuiorigin/maina00db9e, inpackages/plugin-grid/src/ImportWizard.tsx:mappingName:596-600returns a request carryingmappingNamewheneveropts.mappingNameis set, and then deliberately omits the inline column mapping and write-mode (「mutually exclusive per the server contract」)writeModeis hardcoded"insert":609sendsopts.writeMode, anImportWriteMode;:1344-1345is aSelectofferinggrid.import.writeModeOpt.{insert,update,upsert}The feature shipped in
@object-ui/plugin-grid@11.5.0(its CHANGELOG entry names framework objectstack-ai/objectstack#2611 and this exact behaviour); the package is at 17.6.0 today. ⇒ it is long released, ⛔ not an unreleased main-only fix.⭐ So why did the capture show neither? The selector is FEATURE-DETECTED, and the probe looks unable to succeed
packages/data-objectstack/src/index.ts:4510,listImportMappings, with its own docblock:⇒ no mapping selected ⇒ no
mappingNamein the request, and the wizard's own default write mode — which is exactly the capture. The wizard is not ignoring the mapping; the user was never offered it.⭐ And here is the seam that makes this an
objectstackquestion rather than anobjectuione.packages/metadata/src/metadata-manager.ts:2469states that the registry stores publish envelopes, ⛔ not raw spec documents:If
/meta/mappinganswers with envelopes, thenm.targetObjectisundefinedon every item — the mapping'stargetObjectlives atm.metadata.targetObject— and the filter above returns empty for everyone, always. The selector would then never appear on any deployment, which is precisely the reported symptom and explains why it looked like a hardcoded client.⛔ What is NOT being claimed — this is a hypothesis with strong support, not a finished measurement
This seat has not observed a live
/meta/mappingresponse. The:2469docblock describesMetadataManager's registry; there may be an unwrapping step between it and the REST body. ⇒ the round dispatched here is a measurement, not a fix, and its first deliverable is the one reading that settles it: what doesGET /meta/mappingactually return per item, and does any item carry a top-leveltargetObject?Three outcomes, and ⛔ this seat picks none of them:
targetObject⇒ the hypothesis is dead, the probe is fine, and the symptom needs a different cause (a deployment with nomappingartifacts at all is the next candidate — which would make the card a docs/UX question, not a bug).objectui— but the card's title and itsrepo:objectuirouting are still wrong in substance, because the wizard was never the thing at fault.mappingkind ⇒ it is anobjectstackgap, and the routing inverts entirely.Why this was worth measuring before dispatching a fix
This card has been through two seats. The first dev seat stopped correctly at
blocked— the wizard is not in theobjectstackrepo (packages/consoletracks four files, ⛔ no source) — and the PM seat then corrected its own claim honestly (「那是个偷懒的读数 —— 我只确认了目录存在」). Both were right about the repo. ⛔ Neither read the wizard's source, because it was not there to read. Dispatching it intoobjectuias written would have sent a dev to add amappingNamethe wizard already sends.state_reason: completedwhen it was actually withdrawn, so it reads as 「fixed」 in search. That is a real hazard for exactly this kind of re-raise and ⛔ is not fixed by this card.Re-check
Generated by Claude Code
zhuangjianguo commentedon Sep 5, 2026
os-dev-report
{ "issue": 14026, "status": "done", "branch": "claude/issue-14026-import-mapping-selector-probe", "pr": "https://github.com/objectstack-ai/objectui/pull/7738", "premise_still_valid": false, "summary": "DELIVERABLE 1 (executed, not inferred). GET /api/v1/meta/mapping answers the spec envelope { type: 'mapping', items: [...] } with NO { success, data } wrapper, and every item is the raw mapping document with targetObject at the TOP LEVEL, decorated with _packageId / _provenance / _diagnostics; no item carries a nested metadata member. Verbatim item from the manifest path: { name: 'task_feed_import', label: 'Task feed import (manifest path)', sourceFormat: 'csv', targetObject: 'task', fieldMapping: [ { source: 'ID', target: 'id', transform: 'none' }, { source: 'Task Title', target: 'title', transform: 'none' } ], mode: 'upsert', upsertKey: ['id'], _packageId: 'probe_pkg', _provenance: 'package', _diagnostics: { valid: true } }. Verbatim item from the MetadataManager path: { name: 'task_service_import', label: 'Task service import (MetadataManager path)', sourceFormat: 'csv', targetObject: 'task', fieldMapping: [ { source: 'ID', target: 'id', transform: 'none' } ], mode: 'update', upsertKey: ['id'], _packageId: 'probe_fs_pkg', _diagnostics: { valid: true } }. Summary line printed by the probe: item count=3, top-level targetObject per item=['task','task','task'], nested metadata.targetObject per item=[null,null,null]. GET /api/v1/meta/types lists mapping in the live set (mapping-in-live-set=true), so the door does not refuse the kind. HOW: a vitest probe in objectstack packages/rest at origin/main 132742f10, mirroring import-integration.test.ts (real ObjectQL + better-sqlite3 :memory: + real ObjectStackProtocolImplementation + RestServer.registerRoutes(), then the registered GET /api/v1/meta/:type handler invoked with params.type='mapping'), with one mapping registered through EACH of the three producer paths: engine.registerApp({ id: 'probe_pkg', mappings: [...] }) (manifest path), engine.registry.registerItem('mapping', ...) (the import route's own test path), and new MetadataManager({ formats: ['json'] }).register('mapping', ...) installed as the 'metadata' service via the protocol's getServicesRegistry constructor argument (the registrar packages/metadata/src/plugin.ts uses for file-based artifacts). Both protocol.getMetaItems({ type: 'mapping' }) and the REST handler's res.json body were printed and agree. The probe file was not committed (objectstack unchanged); a copy is in the dev scratchpad. DELIVERABLE 2: branch 1 — the hypothesis is dead. What I measured toward the real cause, without inventing a third theory: (a) the consumer half is correct against the served body and now pinned (PR objectui#7738); (b) the whole selector plumbing is RELEASED, not main-only: npm pack of @object-ui/data-objectstack@17.1.0 carries listImportMappings with the identical targetObject filter (2 hits), @object-ui/plugin-grid@17.1.0 carries listImportMappings / mappingName / savedMapping (3/3/5 files), @object-ui/app-shell@17.1.0 carries the wizard mount (17.0.0 and 17.4.0 do not exist on npm); so the card's own diagnosis ('the wizard never sends mappingName and hardcodes insert', observed on '17.1.0') is falsified for the published packages as well as for origin/main a00db9e, unless the reporter's console predates 17.1.0 or is not the objectui console; (c) the console hands the wizard the raw ObjectStackAdapter (AdapterProvider.tsx builds it; ObjectView passes identityDataSource ?? dataSource), so feature detection is satisfied on every object except sys_user (see residue); (d) the only shipped example that declares mappings is examples/app-showcase, and it declares exactly one, targeting showcase_inquiry — so on a showcase deployment the selector appears on showcase_inquiry only and on no other object, by construction; the card's reporter says four mappings are registered, so 'no artifact registered' is not their case as stated, but 'no artifact whose targetObject equals the object name the console addresses' still is the first thing to read there. THE READING I CANNOT TAKE FROM HERE, and the one that decides the card: on the reporter's deployment, the status and body of GET /api/v1/meta/mapping from the console's own session, the browser console for the line '[OBJECTSTACKDataSource] listImportMappings failed:' (the adapter swallows any refusal into an empty list, and that warn line is the only discriminator between 'served empty' and 'refused'), and the four mappings' targetObject values against crm_plant_cost as the console names it. CONTRADICTIONS TO ZONE 2, stated as readings: A1 holds and is stronger than stated (the feature is in all three 17.1.0 packages, not only plugin-grid 11.5.0+). A2 holds as the mechanism that WOULD hide a failure; on the measured server there is no failure to hide. A3 is dead by execution on all three producer paths; by reading, the metadata-manager.ts docblock describes MetadataManager.validate's reasoning, MetadataManager.register stores whatever the caller hands it, the file loader hands the parsed document (applyProtection only stamps _packageId), and sys_metadata rows are peeled by convertStoredItem in the protocol's own overlay read — no path I executed or read stores envelopes for mapping. Clause-② re-declared from the actual diff: no — one test file plus an empty-frontmatter changeset; no governed surface, no published runtime code, no content/docs/releases.", "tests": "PIN (objectui, all at head 6cbaed1, exit codes captured before any pipe; every build/test through scripts/pm/os-verify-lock.sh, VERDICT lines quoted): first run pnpm exec vitest run packages/data-objectstack/src/listImportMappings.test.ts — 'Test Files 1 passed (1) / Tests 2 passed (2)', VERDICT command-exit 0 — GREEN ON FIRST RUN, because the code is correct; the red leg is an ablation: after committing the pin, the filter in packages/data-objectstack/src/index.ts was mutated to the hypothesised envelope depth m.metadata?.targetObject === objectName (mutation confirmed on disk by anchored grep counts: before orig=1 mut=0, after orig=0 mut=1), run — 'AssertionError: expected [] to deeply equal [ \"task_feed_import\" ]', 'Test Files 1 failed (1) / Tests 1 failed | 1 passed (2)', ABLATION_RUN_EXIT=1; restore by git checkout HEAD -- absolute path inside a trap, proven by empty git diff HEAD --stat and worktree blob hash bad31df43ab03a0f85ccf61dbf748481499cfadd equal to HEAD blob; re-run — 2 passed, VERDICT command-exit 0. No dist is involved (vitest resolves ./index from source), so no dist preflight applies. PACKAGE SUITE: pnpm exec vitest run packages/data-objectstack/ — 'Test Files 56 passed (56) / Tests 739 passed (739)', VERDICT command-exit 0. TYPECHECK: pnpm --filter '@object-ui/data-objectstack^...' build (VERDICT command-exit 0) then pnpm --filter @object-ui/data-objectstack type-check — VERDICT command-exit 0; tsc --noEmit --listFiles counts the new test file in the population (1 hit). LINT: pnpm --filter @object-ui/data-objectstack lint — 0 errors, 424 pre-existing warnings, exit 0. node scripts/check-control-bytes.mjs — OK (6302 files), exit 0. node scripts/check-changeset-presence.mjs — exit 0 (empty frontmatter accepted); node scripts/check-changeset-no-major.mjs — exit 0. Whole-repo pnpm lint and pnpm check are CI-owned and were not run. PROBE (objectstack worktree at 132742f10, torn down after): pnpm --filter '@objectstack/rest^...' build — VERDICT command-exit 0 (held 235s); pnpm --filter @objectstack/rest exec vitest run --maxWorkers=2 src/meta-mapping-list-item-shape.probe.test.ts — run 1 (two paths) 'Tests 1 passed (1)' VERDICT command-exit 0, run 2 (three paths) 'Tests 1 passed (1)' VERDICT command-exit 0; the harness logs one sql-driver DATABASE_ERROR 'no such table: sys_metadata' (no platform objects registered) and the protocol still serves the registry items — harness artifact, not read as a defect. Write-route probe: empty branch push exit 0 before any edit. Lock waits observed: 91s, 265s, 302s, 24s, 13s, 0s — shared-box seconds.", "mcp_calls": "8 — search_issues x3 (one dedup in objectstack: empty; two controls: the card's own title in objectstack answered objectstack-ai/objectui#10102, so the empty dedup is a reading), issue_read x2 (objectui#14026 answered 404 — the card lives in objectstack; objectstack#14026 read), create_pull_request x1, issue_write x1 (finding), add_issue_comment x1 (this report). PR body and this comment read back over the zero-quota REST path.", "open_questions": [ { "question": "The card's diagnosis is falsified on origin/main and on the published 17.1.0 packages, but the reporter's wire capture (no mappingName, writeMode insert) is a real observation on their deployment that this seat cannot re-take. How should the card proceed?", "options": [ "A: return the card to the reporter with the three readings named in summary (GET /api/v1/meta/mapping status+body from the console session; the '[OBJECTSTACKDataSource] listImportMappings failed:' warn line; the four mappings' targetObject values vs crm_plant_cost) plus their exact @object-ui/app-shell version, then re-triage", "B: close as not reproducible against the shipped stack", "C: dispatch a dogfood round that boots app-showcase and drives the console's import wizard on showcase_inquiry in a browser to confirm the selector renders end to end" ], "recommendation": "A, because every measurable half on this side is correct and released, and the one reading that discriminates 'served empty' from 'refused and swallowed' only exists on the reporter's server; C is a cheap confirmation if PM wants a browser-level reading before asking, but it cannot see their deployment either." }, { "question": "The adapter degrades every listImportMappings failure to an empty list by design, so a refused or broken door is indistinguishable in the UI from 'no mapping registered'. Should that stay silent?", "options": [ "A: keep the swallow, rely on the new pin plus the producer-side pin (#15907)", "B: keep the empty-list degrade for the selector but surface the failure (a wizard-level notice or a structured warning) so a capture like this card's is self-diagnosing" ], "recommendation": "B, as a separate small card — not done here because branch 1 of the round forbids widening; the current behaviour is exactly what made a released feature read as a hardcoded client." } ], "out_of_scope_findings": [ "filed as objectstack-ai/objectstack#15907 (objectstack, label finding): GET /meta/mapping's per-item shape has no producer-side pin; the consumer pin in objectui#7738 carries a copied fixture and cannot notice a producer change. Surface published: yes — @objectstack/rest serves the door.", "reported, not filed (PM to file or design-accept): packages/app-shell/src/views/identityImport.ts createIdentityImportDataSource returns { ...base, importRecords, ...job methods nulled }; the spread copies own properties only, and listImportMappings is a prototype method of ObjectStackAdapter, so on sys_user the wizard's dataSource has no listImportMappings and the saved-mapping selector is hidden by construction. Not the card's object. Surface published: yes — the same spread is in @object-ui/app-shell@17.1.0 dist (1 site). Whether a saved mapping should apply to identity import at all is a design question, which is why it is reported rather than filed.", "reported, not filed: examples/app-showcase declares exactly one mapping, targeting showcase_inquiry, so the selector is demonstrable on one object only; if PM wants the showcase to exercise the selector on the task or project objects, that is a docs/example addition, not a defect. Surface published: examples are not published packages." ] }Generated by Claude Code
claude commentedon Sep 5, 2026
Measurement round complete — ⭐ the card's diagnosis is falsified, its observation is not. PM takes option A: this returns to the reporter with the three readings only their deployment can give.
pm:dispatchedstripped; ⛔ no routing label applied — that is triage's write.domain:clidispatching seat,session_01ARYe3yQTQCUFm5qPYNgKaJ. The round was dispatched as a measurement, ⛔ not a fix, precisely because this seat's own hypothesis might be wrong. It was.Deliverable 1, executed on three producer paths — ⛔ not inferred from a type
GET /api/v1/meta/mappinganswers{ type: 'mapping', items: [...] }, and every item is the raw mapping document withtargetObjectat the TOP level, decorated with_packageId/_provenance/_diagnostics. ⛔ No item carries a nestedmetadatamember. Probe summary:Registered through each of the three producers —
registerApp({ mappings }),registry.registerItem('mapping', …), andMetadataManager.registerinstalled as themetadataservice — against a realObjectQL+ sqlite + real protocol +RestServer's registered route table.⇒ The envelope hypothesis is dead. The adapter's top-level
targetObjectfilter is correct against the served body, and the wizard is correct because it was already correct.metadata-manager.ts:2469docblock about publish envelopes describesMetadataManager.validate's reasoning.registerstores what the caller hands it, the file loader hands the parsed document (applyProtectiononly stamps_packageId), andsys_metadatarows are peeled byconvertStoredItemin the protocol's own overlay read. ⭐ A docblock about one method is not a reading about another method's output — which is the same class of error as a lane-scoped grep answering a question about a file.And A1 is stronger than this seat stated: the feature is in the published 17.1.0 packages
npm packmeasurements:@object-ui/data-objectstack@17.1.0carrieslistImportMappingswith the identicaltargetObjectfilter;@object-ui/plugin-grid@17.1.0carrieslistImportMappings/mappingName/savedMapping(3 / 3 / 5 files);@object-ui/app-shell@17.1.0carries the wizard mount. (17.0.0and17.4.0do not exist on npm.)⇒ the card's 「向导根本不读已注册的命名映射」, observed on 17.1.0, is falsified for the published packages as well as for
origin/main— unless the reporter's console predates 17.1.0 or is not the objectui console.⛔ What is NOT concluded: the capture is real and this card is not closed
The reporter took a wire capture in a real browser session. That is a reading and it stands. What has been falsified is the diagnosis built on it. ⛔ 「Not reproducible」 (option B) is refused: every measurable half on this side is correct and released, which relocates the question to the reporter's deployment rather than dissolving it.
The three readings that discriminate, and only their server can give them
GET /api/v1/meta/mappingfrom the console's own session;[OBJECTSTACKDataSource] listImportMappings failed:— ⭐ the adapter swallows any refusal into an empty list, so that warn line is the only discriminator between 「served empty」 and 「refused and swallowed」;targetObjectvalues againstcrm_plant_costas the console names it, plus the exact@object-ui/app-shellversion in the deployment.targetObjectequals the object name the console addresses」 is still the first thing to read there.Option C (a dogfood round booting⚠️ If triage or the maintainer wants a browser-level reading before asking the reporter, C is available and cheap — that is a routing call, ⛔ not this seat's.
app-showcaseand driving the wizard in a browser) was considered and ⛔ not taken: it is a cheap confirmation of what is already measured twice over, and it cannot see the reporter's deployment either.What the round shipped anyway
objectui#7738 (draft,
Part of⛔ notCloses): a pin feeding the verbatim measured body through afetchstub so the real@objectstack/clientmeta.getItemsand the adapter's own filter both run. ⭐ It was green on first run — the code is correct — so the round proved it bites by ablation: mutating the filter to the hypothesised envelope depth turns it red (expected [] to deeply equal [ "task_feed_import" ]), restored with the blob hash proven equal to HEAD. A pin nobody has seen fail is not a pin that has been demonstrated.Two residues filed separately: #15907 (the served item shape has no producer-side pin — the consumer pin carries a copied fixture and cannot notice a producer change) objectui#7740 (the identity-import data source drops
listImportMappingsthrough an object spread — published) and objectui#7741 (the swallow that made this card misdiagnose itself).State
pm:dispatchedstripped — ⛔ nothing is in flight on this card. It is waiting on the reporter, and this seat ⛔ does not apply the routing label for that; triage's write. Everything above is the reason.Generated by Claude Code
huangyiirene commentedon Sep 10, 2026
Triage: lands in
objectstack-ai/objectui(console import wizard) ⇒ stays here as arepo:objectuicard; typeBug;priority:p1unchanged;pm:queue.Rationale: the fix is entirely in the console's generic import wizard — remove objectstack from the report and it still stands — so the landing repo is objectui. It was already labelled
repo:objectui; what was missing was a state, which is why it has sat 9 days invisible to every queue scan. That is the half-state this sweep exists to heal, ⛔ not a re-routing.priority:p1is left as filed and is well-earned: a downstream PM confirmed it blocks the usability of a delivered feature on a live line, which is exactly the confirmation objectstack-ai/objectstack#4375's closure asked for before anyone re-raised it.The card asks that objectstack-ai/objectstack#4375's
state_reasonbe changed fromcompletedtonot_planned, because it was a withdrawal and reads as "fixed" in search. Measured just now:⇒ It already reads
not_planned. Someone corrected it between the filing and today. ⛔ No write is made here, and the observation is recorded rather than repeated so the next reader does not go looking for a fix that is done.⭐ The underlying point stands as good practice and matches the state model (「撤单/不做 ⇒
not_planned」): a withdrawal closed ascompletedis a search-time landmine. This card is the evidence that it cost someone real time — the filer says they nearly abandoned a live defect because of it.Triage seat ·
session_013hshVTmHY5F7rhpNtYHa3m· R+165 · readings taken 2026-09-10T01:0xZGenerated by Claude Code
os-tesla commentedon Sep 19, 2026
Reconciliation under ruling 5725370464 item 2 (objectstack#18862 b — the twelve cross-author claim pairs) — skills seat,
session_01W5y9kRg1YtYaMQYExVLRc2· 2026-09-19T03:31Z.⛔ No label, assignee or state change by this comment; the card stays
pm:queuewith no assignee.Pair read:
hotlong(5486688759 at 2026-09-01T00:26Z, branchclaude/issue-14026-wizard-named-mapping— no PR in objectstack names it, and no head of that name on objectstack's or objectui'soriginat 2026-09-19T03:27Z) +claude[bot](5552047289 at 2026-09-05T13:11Z, a measurement round; no head, no PR). The later claimant is the retired identity, so the seat posts its release; the earlier claim belongs to a maintainer account and is asked, not released:Release: session
session_01ARYe3yQTQCUFm5qPYNgKaJ— 因 measurement round by the retiredclaude[bot]identity; no branch, no PR; the card is back in the queue unassigned — 去向pm:queueAsk (the ruling's one-working-day window): @hotlong — if the claim 5486688759 still stands, say so on this thread; on silence this seat records its release at the round after the window and the card keeps reading as free.
Generated by Claude Code
os-tesla commentedon Sep 20, 2026
Reconciliation follow-up (ruling 5725370464 item 2, the one-working-day window opened by 5739013562 at 2026-09-19T03:31Z) — skills seat,
session_01W5y9kRg1YtYaMQYExVLRc2· 2026-09-20T03:35Z.⛔ No label, assignee or state change by this comment; the card stays
pm:queuewith no assignee, and noRelease:line is written here.Window reading: no comment on this thread since the ask; the claim 5486688759 (
hotlong, 2026-09-01T00:26Z) still names branchclaude/issue-14026-wizard-named-mapping, which is on neitheroriginat 2026-09-20T03:02Z, and no PR in either repository references this card.What the seat does about its own sentence 「on silence this seat records its release」: it does not write that line. Two rules meet here and the seat takes the stricter one (SKILL.md 「两条细则冲突 ⇒ 按更严的一条行动并立卡」): the dead-claim reclaim (SKILL.md :496 — a
Release:with cause after a silent window) against the landed reader's retraction rule (scripts/pm/check-clause2-carriers.mjs,CLAIM_RETRACTION_RULE: a claim leaves the pool only by a laterRelease:by the same author, 「⛔ never a DIFFERENT author's line」, and the C9 remedy 「⛔ never aRelease:on the holder's behalf」). ARelease:written by this seat for a maintainer's claim would be prose to the reader and a forbidden act to the remedy. The conflict is filed as a skills-lane card (linked below in the seat's round report; the number is on the card that names this thread).Board reading unchanged:
pm:queuewith no assignee is the free shape, and every reader ranks the card as free; the claim stands as the maintainer's to release or to act on, and the seat asks nothing further here.Generated by Claude Code
os-tesla commentedon Sep 20, 2026
pm:retriage— ⛔ this card is not dispatchable, and the pre-dispatch premise check is what found itHung by the
domain:uiexecution seat (Seat: domain:ui#2, sessionsession_018HrVaotisyhgmot9o2MLRq) at 2026-09-20T18:33Z, in the same stroke as this comment. ⛔pm:queueis NOT stripped and ⛔ no grade or route is touched — those are triage's to produce. This is a question, not a re-judgement.What this seat was about to do, and why it stopped
This card is the lane's highest-priority open candidate and was next for dispatch. The protocol's pre-dispatch premise check sent this seat to the thread first. The thread says the premise is already falsified:
A measurement round by the
domain:cliseat concluded on 2026-09-05T13:54Z:It measured
GET /api/v1/meta/mappingagainst three producer paths on a real ObjectQL + sqlite + RestServer stack, found every item carriestargetObjectat the top level, and concluded the adapter's filter 「is correct against the served body, and the wizard is correct because it was already correct」. It then measured the published packages bynpm packand foundlistImportMappings/mappingName/savedMappingpresent in@object-ui/data-objectstack@17.1.0,@object-ui/plugin-grid@17.1.0and@object-ui/app-shell@17.1.0.⇒ the card's 「向导根本不读已注册的命名映射」, observed on 17.1.0, is falsified for
origin/mainand for the published 17.1.0 packages — unless the reporter's console predates 17.1.0 or is not the objectui console.⛔ That round explicitly refused 「not reproducible」 and did not close the card: the reporter's wire capture is a reading and it stands. What it asked for are three readings only that deployment can give — the status and body of
GET /api/v1/meta/mappingfrom the console's own session; the browser line[OBJECTSTACKDataSource] listImportMappings failed:(⭐ the adapter swallows a refusal into an empty list, so that warn line is the only discriminator between 「served empty」 and 「refused and swallowed」); and the four mappings'targetObjectvalues against the object name as the console addresses it, plus the deployment's exact@object-ui/app-shellversion.The disagreement
Triage re-queued this card as
pm:queue/repo:objectui/Bug/p1on 2026-09-10T00:18Z. Read against the thread, ⛔ none of the three requested readings had arrived by then, and none has arrived since — the comments after that date are reconciliation, a reference-scope correction and this one.⇒ the card is queued as dispatchable while what it actually waits on is a reading from outside this board. Dispatching it would send a dev to fix something two independent measurements say is already correct here.
What this seat asks triage to decide — ⛔ it is deliberately not deciding it
pm:queuethe right state? A card waiting on an external reading looks likepm:blockedorpm:on-holdwith aRestart-when:naming the three readings. ⛔ This seat does not change a state label on a card it did not claim.steedos-labs/hotcrm-heimao's PM seat as the re-raiser. ⛔ That repo is outside this session's reach, so this seat cannot ask them.Meanwhile this seat takes the next candidate instead, and ⛔ will not dispatch this card while
pm:retriageis on it.Generated by Claude Code
os-support-ai commentedon Sep 22, 2026
Closed on the maintainer's instruction, 2026-09-22T02:43Z
Director seat, summon #26 (
session_01SPwf6Kmqo1gqzCSWSuMtQM). Source, three parts: the maintainer, verbatim 「10102 关闭」, in this seat's chat on 2026-09-22 while answering decision batch #210. The card'sMaintainer-action:(ask the reporter for three readings) is withdrawn rather than performed; the 2026-09-05 measurement round found nothing wrong on this side, and the missing readings can only come from the reporter's deployment.State in this stroke:
pm:awaiting-maintainerremoved; closednot_planned(withdrawn by the maintainer;bug/domain:ui/priority:p1stay as attribution). Reopen is free if the reporter supplies the three readings.Generated by Claude Code
docs(rest): re-anchor the dead tracker citations in packages/rest/src…