Repository navigation
fix(metadata-protocol): duplicatePackage keeps a copied field's key and name, and a bare object's view item name, in step with what they name - #23559
Conversation
…nd name, and a bare object's view item name, in step with what they name A field's `name` that echoes its key follows the key, the free-text rewrite matches an object's name only as a whole identifier (left boundary added), a qualified view item's object part takes the copied object's name, and a value equal to a renamed view item's whole name follows it. Claude-Session: https://claude.ai/code/session_0121ooBYRmS8ziFXm9ai5YHm Co-authored-by: Claude <noreply@anthropic.com>
…plicate-names-in-step
…nameName's start-of-name swap Claude-Session: https://claude.ai/code/session_0121ooBYRmS8ziFXm9ai5YHm Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 1 package(s): 1 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 2 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 11 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 513921e990f367826c36b9bfca5d97eaa8ad268f && git checkout 513921e990f367826c36b9bfca5d97eaa8ad268f
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 7ffc57846a97afde24fbfc59b6b05d7562ef4df0 dbd69f7592a9701164110b32d6ba9e1b3f1d8510 && git checkout -B drift-repro 7ffc57846a97afde24fbfc59b6b05d7562ef4df0 && git merge --no-ff dbd69f7592a9701164110b32d6ba9e1b3f1d8510
node scripts/docs-audit/affected-docs.mjs --json 7ffc57846a97afde24fbfc59b6b05d7562ef4df0
|
席位核对
Verdict: ACCEPT. Not governed (
|
Fixes #23538
Clause-②: no
What this does
duplicatePackage(packages/metadata-protocol/src/protocol.ts, ADR-0070 D4) promises to rewrite "every intra-package reference". Three copied names fell out of step with what they name. All edits are in theduplicatePackageregion: the free-text rename, the row-name rename anddeepRewrite. The source-row read is untouched.nameagree. The free-text regex had a right identifier boundary and no left one, and an object'sfieldskeys are never renamed outside a reference site. So the field keyeddupsrc_customerwas copied withname: 'dupdst_customer', andx_dupsrc_customerwithname: 'x_dupdst_customer'. Two rules now hold:namethat echoes its key follows the key (deepRewrite). Both are kept, "through none", the reading consistent with the landed permission-field rule ("the field part is never read").x_dupsrc_customerstays in a description and in a view'scolumns, the wayrenameNameswaps the prefix only at the start of a name.OBJECT.VIEWKEYname follows its object. For aviewrow with a qualified name, the object part takesrenameMap's rename, whole, and the view key is left as stored:ticket.boardcopies asdupdst_ticket.board. That is exactly the rename itsobjectproperty takes. An object the copy does not rename keeps its items' names. This also covers an outside object that carries the source prefix:dupsrc_ext.boardused to becomedupdst_ext.boardwhile itsobjectstayeddupsrc_ext.target: 'ticket.entry'becomesdupdst_ticket.entry. This applies to whole values only, and only to names of view items this copy renames.Mechanism assumptions (Zone 2), measured on
origin/main8226755ee9:x_dupsrc_customeronly. A value EQUAL to the object's name (dupsrc_customer) needs no left boundary to match, so the left boundary alone does not satisfy the Done line. The field'snamehas to follow its key's decision. Both changes landed, each with its own pin and ablation.renameNamerenames only names with the source prefix. A bare object's item keptticket.board, andgetMetaItem({ type: 'view', name: 'ticket.board' })served the source (packageId: com.qa.dupsrc,object: ticket).Evidence (real kernel: ObjectKernel + ObjectQLPlugin, memory driver)
New pin file
packages/objectql/src/protocol-duplicate-package-names-in-step.test.ts, 5 cases, each with its negative control:main8226755ee9nameagree;x_dupsrc_customerkeeps both (neg. control); the data plane inserts by the key; the copied set's FLS rules landfailed[]holdsdupsrc_ops,security-fls-unknown-fieldondupdst_customer.dupsrc_customeranddupdst_customer.x_dupsrc_customercolumns)see x_dupdst_customer.dupdst_ticket.board; the by-name read serves the copy, andticket.boardserves the sourceticket.boarddupext_account.board,dupsrc_ext.board)dupsrc_ext.boardcopied asdupdst_ext.boardtarget: 'ticket.entry'Main run:
Tests 5 failed (5). Head run:Tests 29 passed (29)over the five duplicate suites (names-in-step,unprefixed-object,permission-field-keys,objects-key-collision,protocol-package-lifecycle).Ablations. One per mutation, each through
scripts/ablation-replace.mjs(anchor hit 1 to 0, blob changed). Thenpnpm --filter @objectstack/metadata-protocol buildandablation-dist-preflight(marker present in 2 built files). Then the pin file. Then the restore, proven by blob == HEAD3d7ac7e2e7b3and an emptygit diff HEAD, then a rebuild and--absentpreflight (marker absent from all 24 built files, tree clean).x_dupdst_customernames no field of the copy, so the save door refused that view (list-view-field-unknown), which also reds cases 1, 3 and 4Tests and gates (final head
dbd69f7592, after mergingorigin/main086fa4640f)pnpm --filter @objectstack/metadata-protocol exec vitest run:Test Files 236 passed | 3 skipped (239),Tests 28409 passed | 19 skipped.@objectstack/objectql--project local, as two shards: 210 + 210 files,Tests 4052 passed+Tests 4067 passed.pnpm --filter @objectstack/metadata-protocol typecheckexit 0.pnpm --filter @objectstack/objectql typecheckexit 0 (check:test-typecheck: OK).node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderived 67 commands from a fresh tree. Every exit was captured before any pipe.--ranprinted:67 derived famil(ies) accounted for — 66 run, 1 NOT-MEASURED.pnpm check:dual-build-cjs-loads, which exited 3 withPREREQUISITE NOT MET(it needs every package'sdist/; a fullpnpm buildis outside this card's local scope). NOT MEASURED locally; CI'sLint & Repo Gatesruns it.Acceptance notes
name. Measured with fielddupsrc_customerondupsrc_customer:columns: ['full_name', 'dupsrc_customer']is refused at the copy:view/dupdst_customer.board failed author-time validation … config.columns[1] [list-view-field-unknown]. A form view withsections[].fieldsnaming it copies silently as['full_name', 'dupdst_customer'].main8226755ee9the list view copied with columndupdst_customer, which matches the renamednamebut not the key the data plane addresses (engine.insert('dupdst_customer', { dupdst_customer })answersUnknown field 'dupdst_customer').ticket_views) is still renamed by the prefix swap alone, so a bare object's container keeps the source's name. A container name is ungrammared (no declaredOBJECT.identity), so this is not a contract breach.protocol-duplicate-package-permission-field-keys.test.tsis updated. It described this defect as live ("renames such a field'snamebut not itsfieldskey … a separate defect"), which this change makes false. It now points at the new pin file.objectskeys when a renamed key meets one the set already holds: one grant is dropped, and the copy can gain edit and delete the source never granted #23537 landed as PR fix(metadata-protocol): duplicatePackage refuses a copied item whose renamed object reference meets a name it already holds #23545 (8226755ee9). metadata-protocol: findReferencesToMeta ("Used by") misses a permission set that names an object only in itsfieldskeys (OBJECT.FIELD), so the panel can call an object safe to delete while field rules name it #23539 remains open and is untouched here (referencedNamesAt,collectReferenceHits,findReferencesToMetaandreference-sites.tsare not edited). PR feat(metadata-core,metadata-protocol)!: the sys_metadata family declares no organization column; indexes re-keyed (ADR-0131 D6/D7, C7b S2) #23469's source-row read line is not edited either.Changeset:
.changeset/23538-duplicate-names-in-step.md,@objectstack/metadata-protocolpatch.Session
session_0121ooBYRmS8ziFXm9ai5YHm, os-dev fordomain:specseat 4.Generated by Claude Code