Skip to content

rest: the import door can address a mapping that two packages hold by name (ADR-0150 D3; after #32071) #32079

Closed

Description

@objectstack-fleet

domain:server#3 · os-steve · session_01ADHkmQXLfvyB5R53VDm3Ka

Epic: ADR-0150 (#31527). Split from #32071 by seat 3's step-0 ruling. Blocked-by: #32071 (same file, same seat, serial). Blocks: #31700. Lane: domain:server.

Today (after #32071)

Do

  1. Step 0: propose the qualified spelling for the import door, for example mappingName accepting the qualified address, or a package parameter. Reuse G1's qualifier and G2's namespace→package mapping, and never build a second one. Show that every unqualified request keeps rest: import mappingName and connector pull resolve the mapping by package (ADR-0150 D3; reader before #31700) #32071's answer. The seat rules on the name.
  2. A qualified request reaches exactly its holder. A qualifier naming a non-holder is refused with the same shape as the /meta door's not-held-by-qualifier.

Clause-②: yes (widening) is expected, because only a new optional spelling is added. Step 0 confirms it.
Pins: a bare request with two holders still answers 409; each qualified request answers 200 against its own holder; a non-holder qualifier is refused; with one holder, every answer is byte-identical to today; ablating the qualifier arm turns the pins red.
Epic red-line review before landing.

Activity

  1. added
    enhancementNew feature or request
    priority:p1High: required for production / M2
    pm:blockedBlocked by another issue/PR — body carries Blocked-by: #N
    area:devpathThe road — create, dev, verify, publish/install, connect an agent, iterate
    domain:serverDomain lane — seat card indexed by label:pm:seat
    on Nov 10, 2026
  2. objectstack-fleet commented on Nov 10, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: confirmed · domain:server · p1 · pm:blocked · pm:blocking · 2026-11-10T06:56Z

    Blocked-by: #32071

    ⛔ Not a claim.


    Generated by Claude Code

  3. added
    pm:blockingDerived cache from the Blocked-by reverse index: open card with open dependents — never hand-set
    on Nov 10, 2026
  4. objectstack-fleet commented on Nov 11, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: unblocked → pm:queue · domain:server · p1 · 2026-11-11T00:55Z

    ⛔ Not a claim.


    Generated by Claude Code

  5. added
    pm:queueReady for the PM dispatch loop
    and removed
    pm:blockedBlocked by another issue/PR — body carries Blocked-by: #N
    on Nov 11, 2026
  6. objectstack-fleet commented on Nov 11, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#6 · huangyiirene · session_01J8VVAnTcb4cZVkPdhkPicW

    Claim: PM loop round 3
    Session: session_01J8VVAnTcb4cZVkPdhkPicW
    Account: huangyiirene
    Branch: claude/issue-32079-import-mapping-qualifier
    Worktree: objectstack-issue-32079
    Domain: domain:server
    Seat: domain:server#6
    File surface: packages/rest/src/import-prepare.ts and packages/rest/src/import-mapping.ts (the import door's mappingName resolution and its qualified spelling), their tests, the import docs page under content/docs/** if the new spelling needs a line; root .changeset/. ⛔ Read-only reuse of metadata-protocol protocol-exact-qualifier.ts (G1's qualifier) and the G2 namespace→package mapping: open PRs #32214 and #32361 edit that file, so this card never edits it. ⛔ Not packages/spec/**: stop and report if the spelling needs a schema change. (stop on breach; explain in the report)
    Container & model: M, mode:subagent, model: default tier (dispatch-gates --tier: "floor sonnet · default opus · ceiling fable"; PM judgment: default), effort: xhigh
    Clause-②: yes
    Metadata-protocol: none
    Responsibility: n/a — not a defect card
    Thread-read: 6783698935
    Premise: holds (#32071 closed as completed via PR #32294, merged 2026-11-11T00:42Z; import-mapping.ts:96 on origin/main resolves getMetaItem({ type: 'mapping', name: mappingName }) with no qualifier)
    Serial constraints cleared: #32071 landed (the card's named predecessor). No open PR touches packages/rest/src/import-*.ts (every open PR's file list read at claim). #31700 is blocked by this card. #32183 (seat 3, PR #32327) changes packageScopedHoldersOf, which this card reads through getMetaItem; step 0 re-reads it on the tip.
    Maintainer scope order: the maintainer, in this seat's session, 2026-11-11T05:23Z: 「后续只处理 p1 任务」. This seat now dispatches only p1 cards.

    Claimed at 2026-11-11T05:27Z.

  7. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Nov 11, 2026
  8. objectstack-fleet commented on Nov 11, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#6 · huangyiirene · session_01J8VVAnTcb4cZVkPdhkPicW
    os-dev-report

    {
      "issue": 32079,
      "status": "done",
      "branch": "claude/issue-32079-import-mapping-qualifier",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/32413",
      "head": "280e939300d4e2a2fb6485e5e1cba697a6e0cb2f",
      "session": "session_01J8VVAnTcb4cZVkPdhkPicW",
      "premise_still_valid": true,
      "summary": "Step 0 follows the seat's ruling: the import door reuses the /meta door's qualified address and adds no key. mappingName 'NAMESPACE/NAME' or '_env/NAME' goes to the protocol's own resolveMetaItemAddress and then the exact qualifier (getMetaItem with packageId, i.e. admitExactQualifier) or admitEnvironmentQualifier. That is G1's qualifier and the namespace-to-package mapping in protocol-exact-qualifier.ts, read as a service and not edited. The holder's mapping is imported. A non-holder qualifier is refused 409 RESOURCE_CONFLICT with the not-held-by-qualifier sentence; its code and error equal GET /meta/mapping/NS/NAME on the same server. A name with no '/' sends the identical getMetaItem argument, and its answers are byte-identical to the base tree (pinned). A string that is no address reads the whole string as before (404), never the part after the '/'. A 'package' body key was measured and not built: ImportRequestSchema.parse drops an undeclared 'package' key, so it needs a spec change, which is the stop condition. On the card's own texts: Do 2 asks for the /meta door's shape, and the pins ask that bare answers stay #32071's. The import 409 matches /meta on status, code and sentence, but carries no details.candidates. /meta has carried that member since #32272, which landed after the card was written. Adding it would change the bare two-holder bytes, and the body is written in data-action-routes.ts, outside the surface. This is stated in the PR's Acceptance notes for the seat to judge.",
      "tests": "packages/rest/src/import-integration.test.ts gains a #32079 block on the real ObjectQL engine, protocol and sqlite store: two-holder qualified 200s; non-holder 409 equal to /meta; one-holder own/other namespace; the _env pair; no-address 404s; one-holder byte identity. At 280e939300 (locked: rebuild of rest^... exit 0, then the import files plus meta-qualified-item-route.test.ts): Test Files 4 passed (4), Tests 105 passed (105), rest typecheck exit 0, VERDICT command-exit 0. At a994aa8593: rest local suite Test Files 404 passed (404), Tests 7831 passed | 332 skipped. At ea9dee067f: rest local suite 404 files, 7824 passed | 332 skipped. Ablation at ea9dee067f via scripts/ablation-replace.mjs (WRAP mode): the qualifier arm was replaced by 'return bare;', and the anchor going 1 to 0 and blob 831e0167 to 29366dac show it landed. -t 3207 answered Tests 4 failed | 5 passed: the 4 qualified pins red, #32071's 3 pins plus the no-address and byte-identity pins green. Restore proven: blob 831e0167 equals HEAD and git diff HEAD is empty. Base measurement: under an EXIT INT TERM trap, the base tree 662fbf80's import-mapping.ts was swapped in. The byte pin's reads assertion passed and the five answers were captured as BARE_ONE_HOLDER_WIRE. Restored, and both blobs equal HEAD. eslint --no-inline-config on the 3 changed .ts files: exit 0. test:repo was not run locally (no file of that project is touched); CI's Test Core covers it.",
      "gates": "dispatch-gates --commands names 95 families for the 5 paths, the same list at ea9dee067f, a994aa8593 and 280e939300. --ran reconciliation at 280e939300: 95 derived, 95 run, 0 unrun. Local sweep at 280e939300: 91 exited 0 on the first pass. check:docs (1), check:skill-examples (3) and check:lean-entry-closure (1) read a dist that the concurrent locked rebuild was rewriting. Each was re-run after the rebuild and exited 0 ('247 generated files in sync', '344 prose examples type-check', 'Admitted set held exactly'). check:type-check-debt hit its own lock queue-timeout (exit 3), so it is NOT MEASURED locally; CI 'Type Check · debt ledger' is success at 280e939300. Sweep at a994aa8593: 93 exit 0; check:skill-examples was re-run, exit 0; check:dual-build-cjs-loads was a prerequisite refusal there and exited 0 at 280e939300 (122 entries across 72 packages load). CI at 280e939300 (53 check-runs: 38 success, 15 skipped, 0 failure): Lint & Repo Gates success, TypeScript Type Check success, Test Core success (8/8 shards), Build Core success, Governed Surface Queue Guard success, Check Changeset success, Test UI success, Live E2E UI success, Dogfood Regression Gate success. Lint UI, Type Check UI and Build & E2E UI were skipped by their path selectors. The dogfood shards are queue-only.",
      "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
      "mcp_calls": "0 — no MCP GitHub calls",
      "api_writes": "2 relay strokes — fleet-write pr_create (POST /repos/objectstack-ai/objectstack/dispatches; the relay ran POST /repos/objectstack-ai/objectstack/pulls and POST /repos/objectstack-ai/objectstack/issues/32413/assignees, read back identical, assignee huangyiirene) and this os-dev-report comment through post-stamped.mjs (POST /repos/objectstack-ai/objectstack/issues/32079/comments); git push is not counted",
      "files_changed": [
        ".changeset/32079-import-mapping-qualifier.md +12/-0",
        "content/docs/data-modeling/import-mappings.mdx +19/-6",
        "packages/rest/src/import-integration.test.ts +199/-1",
        "packages/rest/src/import-mapping.ts +74/-4",
        "packages/rest/src/import-prepare.ts +2/-0"
      ],
      "line_budget": "n/a — no skills/** path; 317 changed lines (+306/-11), under the 3000 human-merge threshold",
      "deviations": [
        "Merged origin/main twice: a994aa8593 before the PR opened (AGENTS §10), and 280e939300 on the resume order. The 7 later main commits touch none of the 5 paths, nor rest, core, objectql or metadata-protocol, and are not merged.",
        "The PR body is create-only. It cites readings up to a994aa8593 and points to this comment for the 280e939300 re-check.",
        "Four stray files were written to the filesystem root by a shell-variable scoping slip in background launches: /build.pid, /gates.pid, /rest-test2.pid, /run-gates.out. Removing them was refused by a safety check, so they are left for a person to delete; they are not in the repository.",
        "One test run spelled with a bare '--' was stopped by its recorded pids before any reading was used, and was re-run as 'vitest run --project local --maxWorkers=2'.",
        "The two merge commits carry git's default merge message without the trailer pair; the pre-push hook accepted them."
      ],
      "open_questions": [],
      "security_findings": "none",
      "out_of_scope_findings": [
        "carrier: domain:server#6 · noted, not filed — the import door's 409s (#32071's bare one and this qualified one) carry no details.candidates, while /meta's do since #32272. Seam: rest data-action-routes.ts writes { code, error } for every prepare failure. Adding the member widens both answers; it is the seat's call against card #32079's 'same shape'.",
        "carrier: none · noted in Acceptance notes — ImportRequestSchema.mappingName's .describe() (packages/spec/src/api/export.zod.ts) still describes the pre-#32071 resolution and not the qualified spelling: spec prose, no schema change needed.",
        "carrier: none · noted — a 501 NOT_IMPLEMENTED from the qualifier (an engine without the package-scoped reads, never a production composition) is answered 404 by the import door's catch, as the bare read already is on main.",
        "carrier: ui lane, after #31700 · noted — the Console import wizard (ui/packages/plugin-grid ImportWizard.tsx) sends bare mapping names and would need NAMESPACE/NAME once two namespaces hold one name; plugin-auth's identity import passes only getMetaItem, so the qualified spelling is no address there.",
        "carrier: none · noted — two packages of a shareable namespace (base, system, sys) holding one mapping name, or a mapping named like a /meta sub-resource literal, have no qualified import spelling. This is the /meta qualified path's own limit (seat ruling Q1 = A on #31691); /meta reaches them with ?package=."
      ]
    }
  9. objectstack-fleet commented on Nov 11, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#6 · huangyiirene · session_01J8VVAnTcb4cZVkPdhkPicW

    Landed · #32079 · 2026-11-11T15:44Z

    PR #32413 merged through the queue at 2026-11-11T15:35Z as f97a2d9a. The import door's mappingName now also takes the /meta door's qualified addresses, NAMESPACE/NAME and _env/NAME, through the same exact-qualifier resolution. A non-holder qualifier answers as /meta does. Bare names are byte-identical to before. The card was closed by Fixes; the seat removes pm:dispatched. #31700, blocked by this card, is triage's to re-check for unblocking.

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

Metadata

Metadata

Assignees

Labels

area:devpathThe road — create, dev, verify, publish/install, connect an agent, iteratedomain:serverDomain lane — seat card indexed by label:pm:seatenhancementNew feature or requestpm:blockingDerived cache from the Blocked-by reverse index: open card with open dependents — never hand-setpriority:p1High: required for production / M2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions