Skip to content

Bare-name phase 1: refuse a second package holding a non-object name whose consumers resolve without package context (ruling C on #30798) #30803

Open

Description

@objectstack-fleet

epic:#3600#1 · hotlong · session_01Q4EjjPXwX1YfHyKJUh4agu

Filing-gate category: ② execution of a maintainer ruling. Decision #30798 ruled C, maintainer verbatim (Claude Code session, 2026-11-06): 「同意 c」: every package-authored metadata name carries its namespace, phased. Routing, verbatim: 「能交给车队开发的你不要自己开发」.

Phase 1 of 3. Siblings: phase 2 lint and templates, phase 2 authoring skills, phase 3 rule and migration (filed together).

Problem (customer-visible)

When two installed packages ship a non-object item with the same bare name, many runtime consumers serve only one of them, usually silently and in install order. Measured per type in the audit table on #30798: the kernel metadata service, object-less action dispatch, AI tool names, function handlers behind hooks, picklists, mappings, datasets/cubes, email templates, webhooks, declared connectors, and flows (one armed, with a warning).

Ask

  1. Measure first. Boot one environment with two packages sharing one bare name for each type in that table, and record which resolve wrongly. The table is a code reading, not a booted measurement.
  2. Extend the one-name-one-holder registration refusal (the security catalog's rule, packages/objectql/src/security-catalog-namespace.ts; precedent feat(objectql)!: positions, permission sets and capabilities hold one name per deployment — a second holder is refused at registration, naming both #22197 +1080/−103 and feat(objectql)!: a cold boot refuses a package-held position or permission-set name the environment catalog already holds, as a hot install does (ADR-0048 N.3) #22365 +705/−43) to every type the measurement shows resolving without package context. The refusal applies at managed install, at package registration and at cold boot (as [decision] cold boot admits a package whose permission set or position name the environment catalog already holds (package registration runs before sys_metadata hydration), while a hot install of the same package is refused #22307 did), names both holders, and carries the rename in the message.
  3. Keep what already works: same-name actions on different objects (keyed objectName:name), job scheduling under appId:jobName, and the unmanaged import's all-type refusal.
  4. Record the narrowing on ADR-0048 §3.4. This refusal stays after phase 3 only as the backstop for packages without a namespace, the shared base/system/sys namespaces, and third-party packages in the deprecation window.

Out of scope: the types a separate security item covers. The security seat routes those; do not add them here unless that seat says so.

Reader: the domain:engine lane seat, from pm:queue.


Generated by Claude Code

Activity

  1. added
    priority:p1High: required for production / M2
    pm:queueReady for the PM dispatch loop
    domain:engineRetired 2026-10-22, alias of domain:server (engine surface); in-flight cards keep it until they land
    area:devpathThe road — create, dev, verify, publish/install, connect an agent, iterate
    on Nov 6, 2026
  2. objectstack-fleet commented on Nov 6, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: audit · domain:engine → domain:server · p1 kept · 2026-11-06T04:55Z

    ⛔ Not a claim.


    Generated by Claude Code

  3. added
    domain:serverDomain lane — seat card indexed by label:pm:seat
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    domain:engineRetired 2026-10-22, alias of domain:server (engine surface); in-flight cards keep it until they land
    pm:queueReady for the PM dispatch loop
    on Nov 6, 2026
  4. objectstack-fleet commented on Nov 6, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#3 · os-elon-musk · session_016WV4cytQjG9X1CrCgytUM5

    Claim: PM loop round 1 · 2026-11-06T05:21Z · seat 3's pick in the live server split
    Session: session_016WV4cytQjG9X1CrCgytUM5
    Account: os-elon-musk (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/project-thread-crfe5o
    Worktree: the card thread's own checkout of claude/project-thread-crfe5o
    Domain: domain:server
    Seat: domain:server#3
    File surface: packages/objectql/src/ (the one-name-one-holder module security-catalog-namespace.ts, or a sibling generalising it, + the registry / managed-install / cold-boot call sites it already uses, + tests); the per-type registrars the stage-1 measurement implicates, each reported to the seat before it is touched; pin files under packages/qa/dogfood/test/; docs/adr/0048-* §3.4 + its scripts/adr-anchors/ anchor (Tier H); the ledgers Metadata-protocol: narrowed requires (regenerated with repo tooling); root .changeset/ files. ⛔ lint / templates / examples (#30804), skills (#30805), the save door / defineStack (#30806), spec schema, ui, and any type the security seat's item covers (stop on breach; explain in the report)
    Container & model: L, mode:thread, model: default, effort: xhigh
    Clause-②: no (narrowing)
    Metadata-protocol: narrowed (provisional: confirmed or revised by the stage-1 measurement)
    Responsibility: n/a — ADR-0048 §3.4's coexistence predates the programme; this card executes ruling C on #30798 (6676670839), phase 1
    Thread-read: 6677272063
    Premise: holds on the code reading of #30798's audit table; stage 1 measures it on a booted two-package environment before any refusal code, and the seat confirms the type list before stage 2
    Serial constraints cleared: none at claim time. packages/objectql/src/protocol.ts / engine.ts are held by the facade programme (#30020, PR #30716): touched only if unavoidable, after telling the seat

    Staged: measurement first, then the seat's go. Contract review at CONTRACT_REVIEW_TIER owed before the queue (narrowing); docs/adr is Tier H.

  5. objectstack-fleet commented on Nov 6, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#3 · os-elon-musk · session_016WV4d1EuHiCqvh8VEz81QD
    os-dev-report

    {
      "issue": 30803,
      "status": "done",
      "branch": "claude/project-thread-crfe5o",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/30836",
      "session": "session_016WV4d1EuHiCqvh8VEz81QD",
      "premise_still_valid": true,
      "summary": "PR 1 of 4 (Refs #30803): a picklist, mapping or dataset name holds one package. New module packages/objectql/src/bare-name-one-holder.ts (covered types, declared names incl. nested plugins, rename = namespace prefix, BARE_NAME_COLD_BOOT_MODE = 'warn'); SchemaRegistry.installPackage and registerItem refuse a second package holder with the ADR-0112 envelope (NAMESPACE_CONFLICT, 422), every conflict in one refusal, naming both holders and the rename; the engine plugin seals the registry at kernel:bootstrapped, and a boot that already holds a clash warns once (or refuses under 'refuse'). The environment catalog is never a holder (ADR-0005 overlay). ADR-0048 §3.4 narrowed + 2026-11-06 addendum (Tier H). One file outside the dispatch's file surface: packages/cli/test/package-install-local-jobs-pull.integration.test.ts — its five fixture packages, installed into one kernel, all declared the mapping orders_pull, so CI Test Core (4/8) went red at 75d1339f; each package now names <namespace>_orders_pull (test-only, d154c622). Open for the maintainer, already routed by the seat (not a new question): whether the cold boot of an existing clash should refuse instead of warn — PR1 ships 'warn' and the flip is one constant (BARE_NAME_COLD_BOOT_MODE).",
      "tests": "pnpm --filter @objectstack/objectql exec vitest run src/registry-bare-name-one-holder.test.ts → 40 passed; @objectstack/objectql full suite → 556 files / 11108 tests passed; pnpm --filter @objectstack/objectql typecheck (incl. test-typecheck ratchet) exit 0. Dogfood pin bare-name-one-holder.dogfood.test.ts → 4 passed. cli fixture fix: package-install-local-jobs-pull.integration.test.ts → 8 passed (was 4/8-shard red in CI); pnpm --filter @objectstack/cli typecheck: tsc --noEmit exit 0, check:test-typecheck OK (3 files / 28 errors / 6 pinned signatures held, unchanged; first attempt OOMed at the 2 GB default heap, rerun with --max-old-space-size=8192). Ablation (src): the plugin's seal call removed → 19 of 40 unit cells red (every door refusal + the cold-boot warning), 21 control cells green; restored. Ablation (dist): dogfood pin against the pre-change objectql dist → 3 of 4 red, the fresh-names CONTROL green; green after rebuilding dist.",
      "gates": "dispatch-gates --commands at d154c622: 82 derived (81 at 75d1339f + pnpm check:cli-test-child-env for the cli test path), all run, every exit 0; --ran reconciliation: '82 derived famil(ies) accounted for — 82 run, 0 NOT-MEASURED'. Two needed a rerun: node scripts/check-plugin-teardown-shape.mjs --self-test exit 3 on the shallow clone (pinned fixture commit 621a4876 unreachable) → fetched that one commit, exit 0; pnpm check:dual-build-cjs-loads exit 3 PREREQUISITE NOT MET (no dist for 7 packages) → built them, exit 0 (116 entry points / 71 packages load). 5 extra families run beyond the derivation (error-code-provenance, changeset-fixed, error-code-casing, facade-delegation-only, published-readme-exports), all exit 0. CI at d154c622 (the PR's check-runs, not re-run locally): 50 check-runs, 37 success, 13 skipped, 0 failure — Test Core (1/8…8/8) success and the Test Core aggregate success (4/8 was red at 75d1339f, the cli fixture above), Build Core success, Type Check · workspace / consumer gates / source gates / debt ledger success, TypeScript Type Check success, Lint & Repo Gates success (ESLint, repo & tooling, docs & code guards, PM dispatch-gates, CI release & engine, scoped ×3); Lint UI / Type Check UI skipped (no ui path).",
      "dogfood_battery": "75d1339f · os-verify-lock: VERDICT command-exit 0 · Test Files 424 passed | 3 skipped (427) · Tests 3537 passed | 41 skipped (3578) · no failures. d154c622 changes only packages/cli/test/package-install-local-jobs-pull.integration.test.ts, which is not in the dogfood battery.",
      "mcp_calls": "5 — mcp__github__issue_read ×4, mcp__github__get_job_logs ×1; no write tool. Other reads were REST GETs through gh api (check-runs, PR, card).",
      "api_writes": "2 — POST /repos/objectstack-ai/objectstack/pulls (relay pr_create, PR #30836); POST /repos/objectstack-ai/objectstack/issues/30803/comments (relay comment, this report). git push to the PR branch is not a REST write.",
      "open_questions": [],
      "security_findings": "none",
      "out_of_scope_findings": [
        "carrier: cloud · noted, not filed — AI runtime consumers of agent/skill/tool names (service-ai agents, skills, action_NAME tool names, ToolRegistry) live in objectstack-ai/cloud; NOT MEASURED here (PR body Series section)",
        "carrier: seat · noted, not filed — analytics_cube: a non-host package's cube never reaches the analytics service (404 CUBE_NOT_FOUND in both orders), a reach gap, not a holder conflict; dedupe words: analytics cube non-host package CUBE_NOT_FOUND",
        "carrier: seat · noted, not filed — docs candidate: content/docs import-mappings page could state one package per mapping name (docs-drift bot found no contradicting doc); dedupe words: import mapping name one package"
      ]
    }

    Generated by Claude Code

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

Metadata

Metadata

Assignees

Labels

area:devpathThe road — create, dev, verify, publish/install, connect an agent, iteratedomain:serverDomain lane — seat card indexed by label:pm:seatpm:dispatchedDispatched to a dev agent by /pm-dispatchpriority: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