Skip to content

metadata-protocol: duplicatePackage renames a token that names both a prefixed package object and one of its fields as the object, so a copied view's column or form field names a field the copy does not have (family close-out) #23561

Closed

Description

@objectstack-fleet

Filing gate ①, finding class (a), the close-out card for the duplicatePackage "names out of step" family (#23527, #23537, #23538). reach: the named producer ObjectStackProtocolImplementation.duplicatePackage (the method the packages duplicate route calls), on a real kernel (ObjectKernel + ObjectQLPlugin, memory driver), measured at main 8226755ee9 and at PR #23559's head dbd69f7592. The HTTP door was not driven.

Filed by domain:spec seat 4 (#18917) · sunhaolin · session session_0121ooBYRmS8ziFXm9ai5YHm, from #23538's dev report 6181410407 (open question and out-of-scope finding 1). ⛔ Not a claim. Lane, type and grade are triage's.

What happens (measured)

The source object dupsrc_customer has a field keyed and named dupsrc_customer. That token is both a prefixed package object's name and a field key. The free-text rewrite renames it as the object everywhere it appears as a value:

Pull, measured: across examples/app-crm, app-showcase and app-todo (51 object names, a grep of *.object.ts), no field key equals an object name. The repro is synthetic.

What done looks like

A copied value that names a FIELD keeps naming that field, in list-view columns and form sections[].fields (the sites to enumerate). A value that names the OBJECT still follows the object's rename.

The token is ambiguous, so the fix picks a semantics. The dev's readings:

  • (B) rename such a name only at object-reference sites, never in free text, extending the bare-name policy (about 15 lines plus a pin);
  • (C) rename the field too, which reverses the landed rule that a fields key's field part is never read.

Triage decides whether this is a seat call or a decision card.

Noted, not measured (read from the code): a view CONTAINER row (no ., for example ticket_views) is still renamed by the prefix swap alone, so a bare object's container copies under the source's name. A container name has no declared <object>. identity, so it is not a contract breach. It is recorded here for the family, not for a fix.

Reader who acts: triage, to grade and route. The fix lands in duplicatePackage (packages/metadata-protocol/src/protocol.ts), after PR #23559 (#23538) lands.

Dedupe

MCP search_issues on objectstack-ai/objectstack, closed included, query duplicatePackage field reference renamed as object free-text rewrite field token equals object name copied view column unknown field: 1 hit, #23538 (open), the parent family card, which is not this residual.

Dedupe words: duplicatePackage field token equals object name; copied view column unknown field after duplicate; form sections field dangling after duplicate.

Activity

  1. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade · bug · priority:p3 · domain:spec · pm:queue · direction B · land after PR #23559 · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-15T01:03Z

    Read fresh. When a field key equals a prefixed package object's name, duplicatePackage's free-text rewrite renames it as the object. A copied list-view column is then refused loudly (after PR #23559), but a form view's sections[].fields copies silently with a field the copy does not have.

  2. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 7
    Session: session_01D6F9axfoPzR7t8G1J7Ytzz
    Account: baozhoutao (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-23561-duplicate-object-name-token
    Worktree: objectstack-issue-23561
    Domain: domain:spec
    Seat: domain:spec#3 (seat post #18883)
    File surface (at origin/main 32e03d2fd or later; stop on a breach and explain it in the report): packages/metadata-protocol/src/protocol.ts (duplicatePackage's rename, from ~26386) and packages/metadata-protocol/src/reference-sites.ts, their tests, .changeset/23561-*.md.
    Container & model: M, mode:subagent, model: default (no path-derived mandate)
    Clause-②: no
    Responsibility: n/a — the family close-out after PR #23559 (cdc42eb49)
    Thread-read: 6181968665
    Serial constraints cleared: PR #23559 has merged as cdc42eb49. Open PRs touching protocol.ts do not reach duplicatePackage: #23504 (hunks ~25889–26050, uninstall), #23565 (the save door), #23469 (no protocol.ts hunk at this read).

    Read on origin/main 32e03d2fd at 2026-10-15T02:28Z: duplicatePackage at protocol.ts:26386.


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 19, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 23561,
      "status": "done",
      "branch": "claude/issue-23561-duplicate-object-name-token",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/24475",
      "head": "e7a7b375ed6e61d61346c7e4eae7cf7c93542b3b",
      "session": "session_01D6F9axfoPzR7t8G1J7Ytzz",
      "premise_still_valid": true,
      "summary": "Ruled direction B is implemented in duplicatePackage (packages/metadata-protocol/src/protocol.ts). The fields record keys of every object row in the source package are collected, and any prefixed renamed object name that is also such a key is left out of the free-text regex. It is then rewritten only at object-reference properties, the existing bare-name path; reference-sites.ts is not edited. The field-key set is package-wide, the superset of the two readings. As the ruling implies, free text naming such an object (a description) is left as stored; the landed description pin is flipped, and the whole-identifier rule is re-pinned on a new unambiguous object dupsrc_note. Earlier blocker: the classifier refused the first push. The maintainer then added permission rules; after that, origin/main 26501ae24f was merged (clean, delta vs main is exactly 3 files), the tests were re-run, the branch was pushed and draft PR #24475 was opened.",
      "tests": "At head e7a7b375ed. The objectql closure was rebuilt (exit 0). Five duplicate suites: Test Files 5 passed (5), Tests 30 passed (30). metadata-protocol full suite: Test Files 246 passed | 3 skipped (249), Tests 20655 passed | 19 skipped. Typecheck: metadata-protocol and objectql exit 0. eslint on the 2 touched files: 2 files, 0 errors, 0 warnings; type-aware linting is not enabled. spec test:repo: 61 files and 1033 tests passed, measured at efed56ba5b before the merge; the diff touches no spec file. dispatch-gates at e7a7b375ed: 69 derived, and --ran reads 68 run, 1 NOT-MEASURED. NOT MEASURED: check:dual-build-cjs-loads (exit 3, PREREQUISITE NOT MET: needs every package's dist). Ablation via ablation-replace: the anchor went from 1 hit to 0, the marker was present in 2 dist files, and the pin file read 5 failed | 1 passed, more diagnostics than the 2 predicted. Restore: blob == HEAD, git diff HEAD empty, --absent preflight clean, 6 passed.",
      "mcp_calls": "0",
      "api_writes": "4 — git push x2 (empty branch at 32e03d2fd7; e7a7b375ed); pr_create via fleet-write relay (POST /repos/objectstack-ai/objectstack/pulls draft + POST issues/24475/assignees baozhoutao); this os-dev-report comment (POST issues/23561/comments). Zero label writes: the dispatch named no label, and a changeset is present, so skip-changeset does not apply.",
      "gates": "69 derived, 68 run exit 0, 1 NOT-MEASURED (check:dual-build-cjs-loads, prerequisite)",
      "deviations": "The first push was refused by the permission classifier (earlier run). Work resumed only after the maintainer added permission rules, per the coordinator. spec test:repo was not re-run after the merge, because the diff does not touch packages/spec.",
      "files_changed": ["packages/metadata-protocol/src/protocol.ts", "packages/objectql/src/protocol-duplicate-package-names-in-step.test.ts", ".changeset/23561-duplicate-object-name-token.md"],
      "open_questions": [],
      "out_of_scope_findings": ["carrier: PR 24475 acceptance notes · noted, not filed: a dotless view container name is still renamed by the prefix swap alone (recorded only, per triage 6181968665)"]
    }

    Generated by Claude Code

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions