Repository navigation
Description
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
- 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.
- 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. - Keep what already works: same-name actions on different objects (keyed
objectName:name), job scheduling underappId:jobName, and the unmanaged import's all-type refusal. - 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/sysnamespaces, 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
objectstack-fleet commentedon Nov 6, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: audit ·
domain:engine→domain:server· p1 kept · 2026-11-06T04:55Z⛔ Not a claim.
domain:engineis a retired alias ofdomain:server. This card is part of the bare-name / unmanaged-install programme following [decision] A non-object metadata name shared by two installed packages often resolves to one package silently: which naming contract replaces ADR-0048 §3.4? #30798, and keeps the p1 it was filed with. Any ADR text it touches is Tier H.Generated by Claude Code
objectstack-fleet commentedon Nov 6, 2026
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_016WV4cytQjG9X1CrCgytUM5Account:
os-elon-musk(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/project-thread-crfe5oWorktree: the card thread's own checkout of
claude/project-thread-crfe5oDomain:
domain:serverSeat:
domain:server#3File surface:
packages/objectql/src/(the one-name-one-holder modulesecurity-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 underpackages/qa/dogfood/test/;docs/adr/0048-*§3.4 + itsscripts/adr-anchors/anchor (Tier H); the ledgersMetadata-protocol: narrowedrequires (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: xhighClause-②: 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.tsare held by the facade programme (#30020, PR #30716): touched only if unavoidable, after telling the seatStaged: measurement first, then the seat's go. Contract review at
CONTRACT_REVIEW_TIERowed before the queue (narrowing);docs/adris Tier H.objectstack-fleet commentedon Nov 6, 2026
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
objectstack-fleet commentedon Nov 6, 2026
domain:server#3 · os-elon-musk · session_016WV4cytQjG9X1CrCgytUM5
Progress · 2026-11-06T11:48Z · PR 1 of 4 landed: PR #30836 merged through the queue as
2a6a28db96(Refs #30803; the card stays open and dispatched).kernel:bootstrappedseal (BARE_NAME_COLD_BOOT_MODE = 'warn'), ADR-0048 §3.4 narrowing + 2026-11-06 addendum; typespicklist,mapping,datasetapi, object-lessaction, function registry,webhook,connector,flow,email_template,agent,skill) wait for the maintainer's answer on which of them the separately-held security subset of #30798 covers'warn'ships, arefuseruling is a one-constant follow-upobjectstack-fleet commentedon Nov 6, 2026
domain:server#3 · os-elon-musk · session_016WV4cytQjG9X1CrCgytUM5
Ruling recorded · 2026-11-06T14:58Z · cold boot of an existing bare-name clash: the maintainer chose B, warn at boot and refuse new installs (decision card, 2026-11-06T14:57Z).
BARE_NAME_COLD_BOOT_MODE = 'warn'. A deployment that already carries a clash boots and logs both packages and the rename path; a new install or registration that would clash is refused at the package door. No follow-up PR is owed for this ruling.7 remaining items
objectstack-fleet commentedon Nov 6, 2026
domain:server#2 · os-tesla · session_01L9qibyvxbrLP4jm4PargoH
Claim: PM loop round 1 · take-over of PR 2 of 4 (#31006) on
domain:server#3's request 6690572980 on mailbox #30985 · 2026-11-06T17:05ZSession:
session_01L9qibyvxbrLP4jm4PargoHAccount:
os-tesla(the card's assignee)Branch:
claude/project-thread-crfe5o(PR #31006 as left by thedomain:server#3card thread, which has stood down; no new push is made by this seat)Worktree: none for the review; a card thread is opened on the same branch only if the review owes a change
Domain:
domain:serverSeat:
domain:server#2File surface: exactly PR #31006's eight files (
docs/adr/0048-cross-package-metadata-collision.md,packages/objectql/src/{bare-name-one-holder.ts,hook-binder.ts,plugin.ts,registry.ts,registry-bare-name-one-holder-request-family.test.ts},packages/qa/dogfood/test/bare-name-one-holder-request-family.dogfood.test.ts, one changeset). PR 3 and PR 4 are not in this claim.Container & model:
M, review take-over,model: CONTRACT_REVIEW_TIER(dispatch-gates --tier: MANDATORY fromdocs/adr/**, no one-line exemption),effort: xhigh(thedocs/adr/**floor)Clause-②: no (narrowing)
Metadata-protocol: narrowed
Responsibility: as on the card and PR 1 #30836 (merged
2a6a28db); unchanged by this take-over.Thread-read: 6690280341
Premise: holds. PR #31006 is open, draft, head
bb786448, mergeable clean, 37 success / 13 skipped / 0 failed; os-dev report 6690087672.Serial constraints cleared:
nonenew; the card's own PR 3 and PR 4 follow PR 2.Resume-from:
claude/project-thread-crfe5o@bb786448Next: the contract review at
CONTRACT_REVIEW_TIER(the two open questions in 6690280341 included), then ACCEPT,pm:awaiting-merge, and the Tier H hand-off toos-zhuang.objectstack-fleet commentedon Nov 6, 2026
domain:server#2 · os-tesla · session_01L9qibyvxbrLP4jm4PargoH
Claim amendment · 2026-11-06T17:20Z · amends the PR 2 of 4 take-over claim 6690638720 on this card
Worktree: the review owed a change (record 6690893976, should-fix 1 and 3), so a card thread now works on the same branch
claude/project-thread-crfe5o: sessionsession_01L9qibxXA6Z1QEsocQJhugE, pushing by merge only, no new PR.File surface (added):
scripts/adr-anchors/packages__objectql__src__bare-name-one-holder.ts.json(theinvariantsentence, already named in the claim) and.changeset/30803-bare-name-one-package-holder.md(PR 1's unconsumed changeset: the cold-boot "open call" sentence becomes ruling B, 6687840782). Optional: the ADR-0048 P1.1 heading (nit 1). Should-fix 2 (the runtime's silent bind refusal) is not in this PR; the seat files it as its own card. Everything else in the claim stands.objectstack-fleet commentedon Nov 6, 2026
domain:server#2 · os-tesla · session_01L9qibxXA6Z1QEsocQJhugE
os-dev-report
{ "issue": 30803, "status": "done", "branch": "claude/project-thread-crfe5o", "pr": "https://github.com/objectstack-ai/objectstack/pull/31006", "session": "session_01L9qibxXA6Z1QEsocQJhugE", "premise_still_valid": true, "summary": "Delta on PR 2 of 4 for contract review 6690893976 (VERDICT PASS): should-fix 1 and should-fix 3, plus nit 1, at head 247853de (one commit on bb786448, pushed by merge-free fast-forward; no rebase, no force). Three prose files, +3/-3, no code: (1) scripts/adr-anchors/packages__objectql__src__bare-name-one-holder.ts.json invariant now names both families with their served holder (data family first-registered; request family = the endpoint matcher's API, an object-less action's handler, the engine function registry's function, last-registered) and three doors: package door, item seam, and the hook binder's bind (bindHooksToEngine in hook-binder.ts, through SchemaRegistry.claimBareNameFunctions); same ADR citations ADR-0048 and ADR-0005. (3) .changeset/30803-bare-name-one-package-holder.md (PR 1's, pending): 'Whether that boot should be refused instead is the maintainer's open call;' became 'The maintainer ruled this on 2026-11-06: the boot warns, and only a new holder is refused;' with the rest of the sentence and the 'first-registered holder keeps being served' sentence untouched. This is a DELIBERATE CORRECTION: check-empty-changeset (Check Changeset) reds by design and the seat's record confirms it. (nit 1) ADR-0048 P1.1 heading now ends 'for the data family: picklist, mapping, dataset' (code spans in the file). Two standard-text points: the PR body was NOT patched by this thread, because os-dev rule 3 has the dev write a PR body once, at pr_create, and the seat write later changes, which overrides the order's line asking for it; the refreshed body (verification line for 247853de, the DELIBERATE CORRECTION section, two What-changes bullets, footer stripped, signed trailer as last line) is ready as a relay actions file whose dispatch.mjs --dry-run exits 0: /mnt/project-files/server-seat-2/r2026-11-06/out/31006-delta-body-patch.json. And origin/main was not merged: AGENTS.md multi-agent section 10 merges main into an open PR only on a GitHub conflict, a main-caused red or a queue removal, the PR read mergeable clean, so os-dev rule 1's merge-first on resume yields to AGENTS.md; main is 15 commits ahead of the merge base (one touches ADR-0048 section 5, no overlap with this PR's hunks).", "tests": "No code changed, so no suite was run. The anchor file parses as JSON; the control-byte scan of the three files is empty; the pre-push hook check:commit-card-trailers passed on the commit.", "gates": "At 247853de, dispatch-gates --commands derives 82 families for the whole PR. Run: the 39 that read the three changed files (31 matched by these paths, 8 declared whole-tree), each command with stdin closed and its exit code recorded before any pipe. 38 exit 0, including check:adr-anchors (OK, 111 anchored files), check-adr-links (991 links resolve), check:adr-index, check:adr-symbol-anchors, check:doc-authoring, check:closed-ceremony-text, check-closing-keyword-parity (sweep and self-test), check-comment-mask-corpus (21197 files, 0 disagree), check-adr-0087-registration --base origin/main, check-changeset-no-major --base origin/main, check:changeset-gate-self-tests, and check:doc-formula-expressions (first exit 3 PREREQUISITE NOT MET, then exit 0 after building the lint closure under os-verify-lock, VERDICT command-exit 0, 99 s). One exit 1: check-empty-changeset --base origin/main, the DELIBERATE CORRECTION refusal on PR 1's changeset, expected. Reconciliation: '82 derived, 39 run, 0 NOT-MEASURED, 43 UNRUN'. The 43 unrun read only the code and test paths this delta leaves untouched; they ran at 0990e5dd (74 of 74 exit 0, report 6690087672) and CI was green at bb786448. The derivation flagged its tree as 15 commits behind origin/main (release.yml and five scripts changed); not re-derived on main, see the merge note in summary. CI at 247853de, read once right after the push: 47 check-runs, 12 success, 13 skipped, 22 in progress (Check Changeset among them; expected to red as above), 0 failed. Not waited on.", "dogfood_battery": "NOT RERUN at 247853de: the delta changes three prose files the battery does not read, and the order scoped reruns to the derived gates. Last battery: 0990e5dd, VERDICT command-exit 0, Test Files 428 passed and 3 skipped (431), Tests 3560 passed and 41 skipped (3601) (report 6690087672).", "mcp_calls": "4 reads, 0 writes: mcp__github__issue_read x2 (card body, card comments), mcp__github__pull_request_read x2 (PR, PR comments). Other reads were unauthenticated REST GETs (the PR body, the check-runs).", "api_writes": "1: POST /repos/objectstack-ai/objectstack/issues/30803/comments (relay comment, this report). git push to the PR branch is not a REST write. The PR body patch was dry-run only and is handed to the seat.", "open_questions": [], "security_findings": "none", "out_of_scope_findings": [] }objectstack-fleet commentedon Nov 6, 2026
domain:server#2 · os-tesla · session_01L9qibyvxbrLP4jm4PargoH
ACCEPT → PR #31006 comment 6691516559 (head
247853de) · 2026-11-06T17:49Z · contract review 6690893976 + delta 6691463846 PASS; theCheck Changesetred is a confirmed DELIBERATE CORRECTION of PR 1's pending note. Tier H:pm:awaiting-merge, review requested from the governed approvers; the PR stays draft until approved, then the seat lands it. Should-fix 2 (the runtime's swallowed post-seal bind refusal) becomes its own card.objectstack-fleet commentedon Nov 7, 2026
domain:server#2 · os-tesla · session_01L9qibyvxbrLP4jm4PargoH
Landing · 2026-11-07T04:02Z · PR #31006 MERGED 2026-11-07T03:33Z as
902f162c(Refs #30803, PR 2 of 4, the request family): an API, an object-less action and an engine function now hold one name per package. It was enqueued by the maintainer through os-zhuang. The card stays open. PR 3 and PR 4 go back to the queue in the series order, and the last PR carriesFixes. The seat movespm:dispatched→pm:queueand unassigns, so the next server seat with a free slot picks up PR 3 from the series plan on this card.objectstack-fleet commentedon Nov 7, 2026
domain:server#1 · sunhaolin · session_017xRBcTJTE7kSbcMoJQ4Txf
Claim: PM loop round 1 · PR 3 of 4 (
flow,webhook,connector,email_template) on seat 2's release 6701997408 · 2026-11-07T04:49ZSession:
session_017xRBcTJTE7kSbcMoJQ4TxfAccount:
sunhaolin(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-30803-bare-name-pr3-flow-familyWorktree:
objectstack-issue-30803Domain:
domain:serverSeat:
domain:server#1File surface:
packages/objectql/src/(bare-name-one-holder.tsand the registry / package-door / item-seam / cold-boot call sites PR 1 and PR 2 use, plus a newregistry-bare-name-one-holder-*.test.ts); the registrars offlow,webhook,connectorandemail_templatethat the dev's measurement shows serving a bare name without package context, wherever they live (each named in the report with the reason);packages/qa/dogfood/test/(one dogfood pin, as PR 2);docs/adr/0048-cross-package-metadata-collision.md(the §3.4 note and the phase-1 addendum rows for these four types);scripts/adr-anchors/packages__objectql__src__bare-name-one-holder.ts.json; one changeset. ⛔packages/spec/**, ⛔skills/**, ⛔agentandskill(PR 4). Stop on breach; explain in the report.Container & model:
M,mode:subagent,model: CONTRACT_REVIEW_TIER(dispatch-gates --tier: MANDATORY fromdocs/adr/**, no one-line exemption),effort: xhigh(thedocs/adr/**floor)Clause-②: no (narrowing)
Metadata-protocol: narrowed
Responsibility: n/a — not a defect card; this card executes ruling C on #30798, phase 1
Thread-read: 6701997408
Premise: holds (read on
origin/main24bc2593at 2026-11-07T04:49Z:BARE_NAME_ONE_HOLDER_TYPESispicklist,mapping,dataset,api,action,function; none of the four PR 3 types is covered)Serial constraints cleared: PR 1 (#30836,
2a6a28db) and PR 2 (#31006,902f162c) have merged; the dev works on the merged code. #29594 (seat 2,pm:dispatched) claimspackages/objectql/src/registry.tsandservice-automation/src/flow-precedence.ts: its only open PR is #31027 (docs/adr/0146only) and its PR 3 has not started, so there is no live code overlap now. Whichever lands second mergesmain. #30806 and #30808 staypm:blockedon this card.Rulings carried (binding, from this card's thread): cold boot B, warn at boot and refuse new installs (6687840782); all nine types stay in this card, in the series PR3 =
flow+webhook+connector+email_template, PR4 =agent+skillwithFixes #30803(6688041914). This PR carriesRefs #30803 (PR 3 of 4), neverFixes. Tier H (ADR-0048): a human merges.objectstack-fleet commentedon Nov 7, 2026
domain:server#1 · sunhaolin · session_017xRBcTJTE7kSbcMoJQ4Txf
os-dev-report
{ "issue": 30803, "status": "done", "branch": "claude/issue-30803-bare-name-pr3-flow-family", "pr": "https://github.com/objectstack-ai/objectstack/pull/31093", "session": "session_017xRBcTJTE7kSbcMoJQ4Txf", "premise_still_valid": true, "summary": "PR 3 of 4 (Refs #30803), the flow family, on PR 1's mechanism (#30836) as PR 2 extended it (#31006): a flow, a webhook, a connector and an email template hold one package. Measured first (card ask 1) on a booted showcase with two AppPlugin packages sharing one name per type, both orders: the automation engine arms ONE flow per name (the lexicographically-first package, alpha in both orders, with its precedence warning) while GET /meta/flow/NAME serves the first-registered declaration; the webhook dispatcher's declared reader keeps the first-registered webhook and never subscribes the other, silently; GET /meta/connector/NAME (the picker's read) serves the first-registered descriptor, silently, and two provider-bound instances already refuse the boot (ADR-0097 duplicate); a send's template resolves the first-registered email template, silently. A third package installed after the boot under any held name answered 200 and was shadowed. All four resolve without package context, so all four join BARE_NAME_REGISTRY_TYPES (bare-name-one-holder.ts, now the one ordered list of ten with BARE_NAME_REGISTRY_TYPES derived); SchemaRegistry.installPackage and registerItem refuse a second holder after the seal with PR 1's envelope (NAMESPACE_CONFLICT, 422, both holders, the rename), install-local answering 422 PLUGIN_REGISTER_FAILED. Two particulars: email_template is a bundled type (registry key pkg:name@locale), so the holder reading and the cold-boot seal strip the member through bundleBaseKey and the NAME holds the bundle; and the email service's built-in templates (com.objectstack.service.email) are an OVERRIDABLE BASELINE (new OVERRIDABLE_BASELINE_PACKAGES / isOverridableBaseline, exported) because plugin-email's loader serves any other package's same-named member over them by contract (ADR-0131 D6) — that package neither holds a template name nor is refused one, the first other package holds it and a second is refused naming the first. No registrar outside packages/objectql was touched: all four register through registerMetadataCollections → registerItem(..., ownerId), and their consumers (service-automation flow-precedence, plugin-webhooks declared reader, the /meta by-name door, plugin-email's loader) were read, not changed. Cold boot stays ruling B ('warn', BARE_NAME_COLD_BOOT_MODE untouched). ADR-0048: header, §3.4 note, P1.5, P1.6, new P1.8 (Tier H); anchor invariant updated; one changeset (objectql minor). PR4 (agent, skill, the closing line) not started, per the series.", "tests": "Measurement (card ask 1, temporary dogfood file, deleted): booted showcase + alpha/beta AppPlugins sharing qa_shared_flow / qa_shared_hook / qa_shared_conn / qa_shared_tpl, both orders — flow: getFlow().label = 'alpha flow' in BOTH orders with the precedence warning naming both; GET /meta/flow/NAME = alpha in alpha>beta, beta in beta>alpha; webhook: declaredWebhookNamed().packageId = first-registered, no warning; connector: GET /meta/connector/NAME = first-registered, listItems returns both; provider-bound instance under one name: boot REFUSED 'duplicate declarative connector instance name ... (ADR-0097)'; email_template: renderTemplate().subject = first-registered; GET /meta/email_template/NAME the same; install-local gamma declaring all four held names: 200 in both orders, every consumer unchanged. registry-bare-name-one-holder-flow-family.test.ts (new) → 54 passed; with the data- and request-family pins and hook-binder.test.ts → 4 files / 154 passed (152 before the two member-key cells). @objectstack/objectql full suite → 565 files / 11476 passed (VERDICT command-exit 0); @objectstack/runtime full suite → 553 files / 8882 passed, 19 skipped (VERDICT command-exit 0). pnpm --filter @objectstack/objectql typecheck exit 0 incl. check:test-typecheck (39 files / 233 errors / 64 pinned signatures held, unchanged); @objectstack/dogfood tsc --noEmit exit 0. Dogfood pin bare-name-one-holder-flow-family.dogfood.test.ts → 4 passed; the data and request families' dogfood files → 8 passed; email-template-materialization.dogfood.test.ts (a fixture app shipping auth.password_reset beside the built-in) → 4 passed. Ablations (src, each via ablation-replace.mjs, restored with blob == HEAD and git diff HEAD empty): the four types removed from BARE_NAME_ONE_HOLDER_TYPES → 39 of 54 red; the baseline exclusion removed from bareNamePackageHolders → 3 red (an app's override refused naming the baseline; the cold boot warns about it; two apps' warning names the baseline); bundleBaseKey no longer applied to the member key → 2 red (the member-key holder cell and the seal's bundled-clash cell). Ablation (dist): objectql built from the merge base's three sources (preflight --absent: marker absent from all 14 built files) → the dogfood pin 4 of 4 red (no bare-name warning line; gamma and delta install-local answered 200 and installed; the CONTROL's import undefined); rebuilt from HEAD (marker present in 8 built files, tree clean) → 4 of 4 green.", "gates": "dispatch-gates --commands --repo objectstack-ai/objectstack at e01df46c: 82 derived, all run with exit codes captured before any pipe; --ran reconciliation '82 derived famil(ies) accounted for — 82 run, 0 NOT-MEASURED' (exit 0). Two reruns after a prerequisite: pnpm check:dual-build-cjs-loads exit 3 PREREQUISITE NOT MET (seven packages had no dist on the fresh worktree) → built them under the lock, rerun exit 0 (116 entry points / 71 packages load); pnpm check:type-check-debt exit 3 PREREQUISITE NOT MET (its closure build timed out on the verify lock behind the dogfood battery, exit 99) → rerun under the lock with the same slot, exit 0 (--re-measure OK, 0 raw tsc errors). pnpm lint at e01df46c: exit 0. CI on the PR: not yet read at report time (in_progress) — the PR's check-runs are the gates' CI reading.", "dogfood_battery": "e01df46c · os-verify-lock: VERDICT command-exit 0 · Test Files 435 passed | 3 skipped (438) · Tests 3600 passed | 41 skipped (3641) · no failures (held the lock 1189s on a shared box). Ran because the PR title carries `!` and Clause-② carries the (narrowing) arm.", "mcp_calls": "0 — no MCP GitHub tool was called; every GitHub read was a REST GET through `gh api` (the card, its comments, #30798, PR #31006) and every write went through the relay.", "api_writes": "2 — POST /repos/objectstack-ai/objectstack/pulls (relay pr_create, PR #31093, read back identical: 15138 bytes sent, 15138 stored); POST /repos/objectstack-ai/objectstack/issues/30803/comments (relay comment via post-stamped, this report). No labels, assignees or reviewers written (none named by the order; the diff publishes objectql, so no skip-changeset). git push to the branch (2 pushes + the empty-branch probe) is not a REST write.", "open_questions": [], "security_findings": "none", "out_of_scope_findings": [ "carrier: seat · noted, not filed — `GET /connectors` answered 404 on the showcase composition during the measurement (the connector catalog route is not mounted on that composition; `/meta/connector/NAME` and the registry list were used instead). Observation only, no reach measured beyond the dogfood boot; dedupe words: GET /connectors 404 showcase composition route", "carrier: seat · noted, not filed — a first app's override of a built-in email template is served silently by design (plugin-email's loader contract, ADR-0131 D6); this PR refuses only a SECOND app's override. Whether the first override should be reported at boot is the email plugin's own question; dedupe words: email template built-in override silent boot report", "carrier: seat · noted, not filed — `pnpm check:type-check-debt` and `check:dual-build-cjs-loads` exit 3 (PREREQUISITE NOT MET) on a fresh worktree: the first needs the verify lock for its closure build (it timed out behind the dogfood battery and was rerun under the lock), the second needs seven dists a dogfood-closure build does not produce (built, rerun exit 0). Both are harness facts PR 1 also met, not findings; dedupe words: dual-build-cjs-loads prerequisite dist type-check-debt verify lock" ] }