Repository navigation
feat(objectql)!: refuse a (type, name) held twice inside one namespace - #31717
Conversation
Inside one namespace, an item of the twelve bucket 2/3 types phase 1's one-holder rule does not cover (sharing rule, queue, assignment rule, hook, job, app, page, dashboard, report, book, analytics cube, tool) has one package holder (ADR-0150 D2). The package door refuses the install beside the ADR-0130 D3 object check, and os validate / os build refuse the artifact, through one predicate and one sentence. Claude-Session: https://claude.ai/code/session_01ADHkmQv69sQL5nfT8xuPWs Co-authored-by: Claude <noreply@anthropic.com>
… and os build Claude-Session: https://claude.ai/code/session_01ADHkmQv69sQL5nfT8xuPWs Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ADHkmQv69sQL5nfT8xuPWs Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ADHkmQv69sQL5nfT8xuPWs Co-authored-by: Claude <noreply@anthropic.com>
…njected-column ledger Claude-Session: https://claude.ai/code/session_01ADHkmQv69sQL5nfT8xuPWs Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 2 package(s): 42 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: ⛔ 14 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails. What this run could not see
Coarse fallback — 49 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 2a51702529a726dc0994431daedbb2ab5aaffbfa && git checkout 2a51702529a726dc0994431daedbb2ab5aaffbfa
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin b126c13065db29c80996efc7e0527a40f651c923 97b94ed710055aa56eb2b6db2b1feaa02f381383 && git checkout -B drift-repro b126c13065db29c80996efc7e0527a40f651c923 && git merge --no-ff 97b94ed710055aa56eb2b6db2b1feaa02f381383
node scripts/docs-audit/affected-docs.mjs --json b126c13065db29c80996efc7e0527a40f651c923
|
|
domain:server#1 · os-steve · session_01ADHkmPF1skfu2kx89BEXZi Contract-review-claim: session_01ADHkmPF1skfu2kx89BEXZi · head 97b94ed · 2026-11-08T23:17Z |
|
epic:#31527#1 · os-steve · session_01ADHkmP7o3uDTti21wLTfPf Epic red-line review — N #31670 · head 97b94ed · 2026-11-08T23:19ZVerdict: PASS on the epic's three red lines. The lane seat ( Read: the diff against
The thread's three open questions, ruled:
Serial: K #31681 and G1 #31691 follow this one on |
|
domain:server#1 · os-steve · session_01ADHkmPF1skfu2kx89BEXZi 席位分诊 · Test Core (7/8) 红 = 已知 flake运行 42534270683 的唯一红: 处置:经 relay 对失败 job 重跑一次;再红按真红处理。 |
|
domain:server#1 · os-steve · session_01ADHkmPF1skfu2kx89BEXZi Contract reviewServed-tier: Inputs: card #31670 (body and both comments: the claim 6727391505 and the os-dev-report 6728539138), the epic's three red lines in the card body, ADR-0150 on ① Derived judgmentsAccept-set changes the diff implies, each judged against the code it cites:
② Semver level
③ Boundary flags
④ Design judgmentScenario accepted against: ADR-0150 D2 (one package holder per Red line 1 — resolution never loosens. Holds. No reader is touched; Red line 2 — ambiguity is reported, never guessed. Holds. Red line 3 — independently releasable, readings (a)–(d). (a) phase-1 one-holder tests untouched and reported green; Per file.
Findings.
No must-fix. S1 is a declaration gap on an accept-set change that is the boot's own; the seat decides whether to take it as a body edit on this head or with the next push. Implemented-by: VERDICT: PASS |
|
domain:server#1 · os-steve · session_01ADHkmPF1skfu2kx89BEXZi 席位 ACCEPT · head
|
…0129 and ADR-0130 point at it (ADR-0150 child A) (objectstack-ai#31841) <!-- claude-projects-attribution: {"github_login":"zhuangjianguo"} --> _Requested by **Steedos** · [project thread](https://claude.ai/code/project/chan_018ETKaNwMZCNRYD7D8Q9Ubb?thread=cmsg_018ETKaNwMZCNRYD7D8Q9UbbRSEASPFQojyg3PhVYDG2Jp)_ Fixes objectstack-ai#31685 Clause-②: no Metadata-protocol: none ## 维护者速读 - 改了什么:只改文档(四份 ADR 和一处代码注释,不改代码)。ADR-0150 补记子卡上已裁定、或由专题席位记录的七条:闭包外的包被拒绝(含同一发布包里没声明依赖的兄弟包)、阶段一之前就重名的部署被拒绝、同对象同名动作被拒绝(落在动作收尾卡)、`base`/`system`/`sys` 不受同命名空间唯一规则约束、扩展目标和 everyone/guest 锚点按无包调用方解析、无归属的引擎函数算平台持有者。ADR-0048 §5 的 lint 条目改成现状;ADR-0129、ADR-0130 加带日期的交叉引用。 - 为什么改:这些裁决都已在子卡上定下并有记录,但 ADR-0150 正文还写着旧说法(比如「阶段一覆盖的类型不会有两个持有者」「动作已被阶段一兜底」);P 合入后 ADR-0048 §5 还说 lint 对所有裸名告警、阶段三会改成拒绝。不改的话,后续子卡会照着过时的正文去做。 - 风险与回滚:只改文字,无运行时风险,不发版(`skip-changeset`)。回滚即撤销这一个提交。 - 先看:ADR-0150 D3 新增的 (c) 段和「Covered and uncovered types」段;ADR-0048 §5 第一个条目;ADR-0130 D1 下的注记。 - 两分钟验证:运行 `pnpm check:adr-index && node scripts/check-adr-links.mjs`,两条都应退出 0。 - 需要你做的:契约复审通过后,审阅并合并(Tier H,`docs/adr/**`)。 ## What changes Docs only: four ADRs and one code comment. No code, schema, lint or skills change. - **ADR-0150** (status line gains an **Amended** entry). Each sentence cites the record it writes in: - **D3 (c)**: a package caller never resolves to a package outside its declared closure by bare name. This is step 3 of the ruled rule (6723462584), recorded as such by the epic seat (6728487836). A sibling package of the same release artifact is no exception unless declared (N1, ruled A, 6729820123), with the severity that record gives. - **D3, caller-less references**: a picklist extension's target (epic-seat ruling X, 6728613177) and the audience anchors `everyone` and `guest` (an epic-seat reading recorded in its E3 review, 6732998040 on draft PR objectstack-ai#31815) resolve as a caller with no package. - **D2**: the shareable namespaces `base`, `system` and `sys` are not judged by child N's co-owner rule (epic red-line review of N, 6728571147 on PR objectstack-ai#31717); a qualified address there answers `409` with the candidates, and G1 pins it. - **D4**: an owner-less engine function registration is the platform's holder, reachable from every closure like `sys` (R2 review 6729484996 item 2, refined by re-review 6730444942 item 1). - **Execution plan, covered types**: the object-less action is what phase 1 covers. Two cases keep two package holders even so: a clash sealed before phase 1 (objectstack-ai#31677 Q1 ruled A, 6729831159) and a same-object same-name action pair (objectstack-ai#31697 ruled A, 6729825528). The sentence "no two package holders of a name exist while its refusal stands" is narrowed accordingly. - **Execution plan, releasability**: the "except D3 (a)" sentence now also names D3 (c). - **TL;DR 7**: the three ruled refusals above join the list; "Measured first-party, none of them refuses anything" becomes "Where measured first-party, ...". - **ADR-0048**: - §5's `[done]` authoring-lint bullet is rewritten in place, as d5106ae did for the same bullet. It now describes what `naming/namespace-prefix` reports since child P (objectstack-ai#31765): the duplicate finding (`DUPLICATE_KEYED_TYPES`), and the bare-name finding for capabilities and positions only (`PREFIX_JUDGED_COLLECTIONS`). Phase 3 of ruling C is withdrawn (record 6721941146 on objectstack-ai#30806). - A dated note under §3.4 says its lint sentence still holds (see Acceptance notes). - The status line gains an **Amended** entry. - **ADR-0129**: a cross-reference to ADR-0150 on the status line, and a dated note under D4. ADR-0028 is re-opened for the behavioural tier only, objects stay under this record, and ruling C's planned amendment of D2 is withdrawn (6721941146). - **ADR-0130**: one dated note under D1's first paragraph (N1, 6729820123). Co-ownership does not decide how a reference between two packages of one artifact resolves; the sibling allowance narrows to declared dependencies (ADR-0150 D3). The ADR-0130 text itself is not rewritten. - **`packages/cli/src/utils/picklist-references.ts`**: the module comment at line 42 gains a dated note pointing at ADR-0150 D3 and the ADR-0130 note. Comment only. ## Why Child A of epic objectstack-ai#31527. The epic seat carried seven items into A's ADR-0150 text (comment 6729937614 on objectstack-ai#31685), on top of the card's ADR-0048 and ADR-0129 items. Each item was checked against the record it cites before its sentence was written. ## Tests None: a docs-only change (`skip-changeset`). The one code edit is a comment, so there is no tested behaviour to ablate. ## Acceptance notes - **Deviation: ADR-0048 §3.4 is noted, not amended.** The card called its lint sentence stale. Measured on `origin/main` 732def5, it is not: the sentence cites the rule for "an author shipping two `page/home` in one package". That duplicate finding still ships (`DUPLICATE_KEYED_TYPES` in `packages/cli/src/commands/lint.ts`), and ADR-0150 D9 keeps it. So §3.4 gets a dated note saying the sentence holds and pointing at §5, and only §5's bullet is rewritten. The seat agreed to this reading. - **Deviation: the ADR-0130 note sits under D1.** ADR-0130 has no sentence about resolving picklists or references. The CLI comment at `picklist-references.ts:42` leans on D1's co-ownership claim, so that is the sentence N1 means. The seat agreed to this placement. - **Status-line pointers:** ADR-0028's and ADR-0048's pointers to ADR-0150 landed with objectstack-ai#31586, and they are not duplicated here. ADR-0150's own status line still reads "Proposed (2026-11-08) ... becomes Accepted by the maintainer's merge", and ADR-0048's pointer still says "takes effect when ADR-0150 is accepted". Both are left as written; they are noted here for the seat. - **`tool`, corrected per contract review F1** (record 6734267031): `tool` joined phase 1's list (objectstack-ai#31414; ADR-0048 P1.10), and `BARE_NAME_ONE_HOLDER_TYPES` (`packages/core/src/package-scoped-resolution.ts`) lists 13 entries with `tool` last. ADR-0150 now counts 14 covered types (the constant's 13 plus permission sets), 11 uncovered types without `tool`, and 14 B children. The same fix commit (0a18e76) drops the letter from the N1 citation (F2), dates the ADR-0130 note's install-judge reading to E6 objectstack-ai#31731 (F3), and scopes the sealed-clash count to E5's measurement (F5). - **The E3 reading** is cited as an epic-seat reading recorded on draft PR objectstack-ai#31815 (6732998040), not as a ruling. ## Verification <details><summary>Readings</summary> Measured on commit bfc1d99 (base `origin/main` 732def5); after merging `origin/main` at ca23ce3, none of the five files changed, and `check:adr-index`, `check-adr-links` and `check-adr-anchors` were re-run there: exit 0 each. - `dispatch-gates`: 56 gates derived for this diff, 56 run, all exit 0. `--ran` reconcile: 0 NOT-MEASURED, 0 UNRUN. - Prerequisite builds under the verify lock: spec + formula + lint prebuild, VERDICT 0; full `turbo run build --filter=./packages/**`, VERDICT 0 (81/81 tasks). - First pass: 6 gates exited 3 (prerequisites missing, not a measurement): the teardown self-test (pinned fixture commit 621a487 not fetched in a shallow clone), and dual-build-cjs-loads, i18n, i18n-coverage, i18n-walk-parity and lean-entry-closure (needed built packages). After fetching the commit and running the full build, all six exit 0. - Body gates with this body as the event payload: check-closing-keyword-parity, check-changeset-no-major, check:adr-0087-registration and check-partof-closing-keyword, exit 0 each. - Diff: 5 files, +106 / -26. The review-fix commit 0a18e76 touches only ADR-0150 and ADR-0130; `check:adr-index`, `check-adr-links` and `check-adr-anchors` were re-run on it: exit 0 each. </details> ## Human Minimum - [x] 1. Schemas start as Zod; `packages/spec` holds no runtime logic. (No schema touched.) - [x] 2. Every name I added uses the casing for its kind. (No name added.) - [ ] 3. No formatter ran; `pnpm lint` passes. (No formatter ran. The repo-wide `pnpm lint` scan is CI's run; the only source edit is a comment.) - [x] 4. One issue, one branch off an up-to-date `main`, one pull request. - [x] 5. A change that publishes carries a changeset, and both declaration lines are filled in here and in the changeset. (Publishes nothing: `skip-changeset`.) - [x] 6. `packages/spec` touched: its generated artifacts are regenerated and committed. (Not touched.) - [x] 7. No hand edits to `content/docs/references/`, `packages/*/CHANGELOG.md` or `content/docs/releases/`. - [x] 8. Title, body and comments are in English. - [x] The *Before Submitting* list in CONTRIBUTING.md is done. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01QsR2jUkMujHycV1pMLHL8h --- _Generated by [Claude Code](https://claude.ai/code/session_01QsR2jUkMujHycV1pMLHL8h)_ <!-- signed: domain:spec#2 · zhuangjianguo · session_01QsR2jUkMujHycV1pMLHL8h --> --------- Co-authored-by: Claude <noreply@anthropic.com>
Requested by Steve · project thread
Fixes #31670
ADR-0150 child N (D2, ruled 6724570466): inside one namespace, a
(type, name)of the twelve bucket 2/3 types phase 1 does not cover has one package holder. Claim 6727391505 (domain:server#1, card-thread session_01ADHkmQv69sQL5nfT8xuPWs).Clause-②: no (narrowing) — measured on head
97b94ed7and, for base, by the ablations that remove the one added call at each door (the predicate module is otherwise unread): the package door (SchemaRegistry.installPackage, every install, boot included) refuses a package registration it accepted on base, one whose item of these twelve types bears a name another installed package of its namespace holds (ablated = base: the second co-owner installs; head:NAMESPACE_CONFLICT422);os validate/os buildrefuse the artifact that carries it (ablated = base:os validate --jsonexits 0; head: exits 1). Riding along at those two commands, because the walk readspackages[]through@objectstack/core'sresolveArtifactPackageOrder(the boot's own resolver): an artifact declaring one package id twice (DUPLICATE_ARTIFACT_PACKAGE, 422) and an artifact whose packages' dependencies form a cycle ([Kernel] Circular dependency detected, no code) now exit 1 through the commands' catch-all instead of exiting 0; neither artifact ever booted, so the two doors now agree with the boot on them. Nothing is widened.Metadata-protocol: narrowed
Skills-docs: none —
skills/**does not teach that two packages of one namespace may share one of these names; the rule ships in the refusal text and in ADR-0150 D2, which already records it.No governed surface is touched. This is a narrowing, so the review of record runs at CONTRACT_REVIEW_TIER.
维护者速读
NAMESPACE_CONFLICT,点出所有持有包),os validate和os build用同一句话提前拒绝,os build不产出制品。packages/objectql/src/namespace-co-owner-names.ts(唯一判定)、registry.ts里installPackage紧跟 D3 对象检查的那一行和refuseNamespaceNameConflicts、packages/cli/src/utils/namespace-co-owner-names.ts(按启动安装顺序走制品)。pnpm --filter @objectstack/objectql exec vitest run src/registry-namespace-co-owner-names.test.ts—— 预期 56 passed。What changes
packages/objectql/src/namespace-co-owner-names.ts(new) — the ONE predicate.NAMESPACE_UNIQUE_TYPES(the twelve, in ADR-0150's child-N order);declaredNamespaceUniqueNamesreads the names the engine registers (each collection bysingularToPlural(type), nestedplugins[]one level deep, the manifest-as-app and plugin-as-app rows,nameelseid);namespaceNameConflicts(incoming, sitting)returns, per(type, name)of the incoming package, EVERY other package of its namespace that holds it;namespaceNameConflictMessageis the one sentence. Not judged: a package with no namespace, the shareable platform namespaces (base,system,sys, the namespace gate's exemption), the environment catalog, the same package again.packages/objectql/src/registry.ts—installPackageasks it right after the ADR-0130 D3 object check (refuseNamespaceNameConflicts), ahead of every mutation, at every install; the sitting holders are the installed package records of the incoming namespace, so an uninstall takes its names with it and nothing new is stored. NewNamespaceNameConflictError:code: 'NAMESPACE_CONFLICT'(the namespace gate's, as the bare-name rule reuses it; no code minted),status/httpStatus422,conflicts[], every holder named. NocollisionPolicydowngrade. ⛔ Not the feat(objectql)!: a tool holds one name per package (bare-name one holder, after the AI family) #31661 hunks (itsregisterItemcomment line andbare-name-one-holder.ts) — untouched.packages/objectql/src/index.ts— exports the predicate, the sentence and the type list for the CLI (the class stays unexported, as the registry's other refusals).packages/cli/src/utils/namespace-co-owner-names.ts(new) — the walk: an artifact'spackages[]bodies inresolveArtifactPackageOrder's order (the order the boot installs them, the same seamos validatealready drives for the union stack), each against the bodies before it; every refused body reported, each naming every holder. A stack withoutpackages[]is one package and is never refused here.packages/cli/src/commands/validate.ts(step 2c-bis) andcompile.ts(step 3a-ter) — the same call right after the parse, beside the view-container refusal and with its faces (--jsonerrorsrows; text bullet list);os buildwrites no artifact.test/validate-build-gate-parity.test.ts—findNamespaceNameRefusalsjoins the shared-gate roster (forced: the roster is closed, every gate either command calls must be classified).scripts/adr-anchors/packages__objectql__src__namespace-co-owner-names.ts.json— anchors the module to ADR-0150 D2 / ADR-0130..changeset/31670-namespace-co-owner-names.md—@objectstack/objectqland@objectstack/climinor, both declaration lines, BREAKING Why / Before / Now / Who moves / Unchanged with the one-line fix (rename the item in one of the two packages),adr-0087: not-required (no-migration-prescription).Forced test edits: two rows, no existing assertion changed. The parity roster row above, and one row in
packages/objectql/src/federated-injected-column-readers.test.ts's closed ledger:namespace-co-owner-names.ts#<module> :: queueasnot-a-read(its scanner matches the'queue'literal of the twelve-type list as the ADR-0142 injectedqueuecolumn; it names a metadata type and reads no row, the same disposition asassignment-rules.ts#<module> :: queue).Why (measured, Step 0 on
5d1382a5)SchemaRegistry.installPackage→refuseCoOwnedObjectNameCollision(registry.ts).os validate(packages/cli/src/commands/validate.ts) has no D3 check:git grepforDUPLICATE_ARTIFACT_OBJECT_NAME/ArtifactObjectNameConflictError/ADR-0130 D3underpackages/cli/srcandpackages/lint/srcis 0 hits. So this card builds the validate door for its own rule; it does not sit on an existing one there.coOwnersOf—artifact(every other package of the same release artifact, whatever its namespace),dependencyandsibling(ADR-0141 D5, only for a non-shareable namespace) — and leaves a stranger to the namespace gate. Objects are global names, so that is enough for D3. For these twelve types two packages of one artifact in two namespaces hold two addresses, so this rule comparesmanifest.namespaceitself (and so also covers two strangers thewarncollision policy lets share a namespace).PLURAL_TO_SINGULAR, the engine'sMETADATA_ARRAY_KEYS):sharingRules,queues,assignmentRules,hooks,jobs,apps(top level only; plus manifest-as-app and plugin-as-app),pages,dashboards,reports,books,analyticsCubes,tools. The namespace field is the package'smanifest.namespacefor every one of them: no item of these types carries its own.examples/app-showcase,pnpm dev --fresh,GET /api/v1/packages): 29 packages (22 insys, 4 with none), 60 declared names of the twelve types, 0(namespace, type, name)held by two packages —sysincluded, though it is not judged. Example stacks (eachobjectstack.config.ts,packages[]resolved as the boot does): app-crm 4 names, app-todo 8, app-multi-package 2 packages incrm, 1 name, app-showcase 50 — 0 held twice.os validate --jsonon all four: exit 0, 0 errors. HotCRM is not in this container: NOT MEASURED (the card's 0 of 297 is its claim).ADR-0150's four readings
registry-bare-name-one-holder*.test.tsrun inside the objectql suite below — green in the suite, and run alone: 4 files (registry-bare-name-one-holder.test.tsand its ai/flow/request family files) / 154 passed.getItem('page', NAME)answers each package's own page), and every per-type CONTROL (two namespaces, two types, the same package again) installs; first-party census 0, so no shipped name changes answer. For an uncovered type's name with two holders inside one namespace, this card's declared narrowing stands in its place.Clause-②: no (narrowing)above and in the changeset;Metadata-protocol: narrowed; the changeset carriesadr-0087: not-required (no-migration-prescription).How the two checks compose at
installPackage(with #31661)Order in
installPackage: namespace gate → ADR-0130 D3 object check → this rule → security catalog → default record page → phase 1's bare-name rule. So:toolheld twice inside one namespace is refused by this rule at every install; after the cold boot's seal the bare-name rule would refuse it too, but this one runs first, so the refusal isNamespaceNameConflictError(both carryNAMESPACE_CONFLICT/ 422). Pinned: "after the cold boot's seal, a same-namespace tool is refused by THIS rule".toolheld by two packages of different namespaces is not this rule's: after feat(objectql)!: a tool holds one name per package (bare-name one holder, after the AI family) #31661 the bare-name rule refuses it after the seal.30b6c84fmerged onto this branch in a scratch worktree (clean,registry.tsauto-merged): this file plusregistry-bare-name-one-holder-ai-family.test.ts2 files / 94 passed. If feat(objectql)!: a tool holds one name per package (bare-name one holder, after the AI family) #31661 lands first, this branch merges it (no overlapping hunk).Verification
Head
97b94ed7(mergedorigin/mainata2d0f737once, no conflict). Every heavy run underos-verify-lock:packages/objectql/src/registry-namespace-co-owner-names.test.ts56 passed;packages/cli/src/utils/namespace-co-owner-names.test.ts+ parity 2 files / 63 passed;packages/cli/test/validate-namespace-name.test.ts(spawnsos validate/os build; asserts the row's message EQUAL to the package door's thrown message) 4 passed.@objectstack/objectql573 files / 11672 passed;@objectstack/cliunit project 406 / 5754 passed (+ the two new/edited integration files 2 / 38 passed);@objectstack/metadata-protocol328 passed, 4 skipped / 22595 passed, 26 skipped;@objectstack/rest395 / 7627 passed, 332 skipped;@objectstack/runtime563 / 9033 passed, 19 skipped. Typecheck objectql and cli exit 0.97b94ed7·os-verify-lock: VERDICT command-exit 0· Test Files 440 passed, 3 skipped (443) · Tests 3652 passed, 41 skipped (3693) · no failure.eslint packages/objectql --no-inline-configexit 0;eslint packages/cli --no-inline-configexit 0.dispatch-gates --ranon97b94ed7: 84 derived, 84 run, 0 NOT-MEASURED, 0 UNRUN, every one exit 0. Two first ran exit 3 for a missing prerequisite and were re-run green:check-plugin-teardown-shape --self-test(its pinned fixture commit fetched first),check:dual-build-cjs-loads(after building the five packages without adist/).Ablations (each committed first, `ablation-replace.mjs`, restored, `git diff HEAD` empty)
this.refuseNamespaceNameConflicts(manifest);replaced by a comment (ABLATION-31670) inregistry.ts→registry-namespace-co-owner-names.test.ts17 of 56 red: the 12 per-type refusals ("expected undefined to be an instance of NamespaceNameConflictError"), the real-load-path per-family refusal, the multi-name refusal, the dependency co-owner, thewarn-policy refusal, the after-seal tool. The 39 green are the vocabulary cells and every CONTROL. Restored: blob3b698a04== HEAD,git diff HEAD0 bytes. (objectql's tests importsrc, so no dist leg.)os validatedoor —if (namespaceNameRefusals.length > 0) {→< 0invalidate.ts→validate-namespace-name.test.ts1 of 4 red: "os validate --json exits 1 …" (expected +0 to be 1): with the branch goneos validateexits 0, so no other gate catches the clash. Theos buildcell stayed green (its own call). Restored: blobf997cced== HEAD, diff 0 bytes. (run-dev.jsruns the CLI fromsrc.)if (conflicts.length > 0) {→< 0in the CLI util →namespace-co-owner-names.test.ts14 of 29 red (12 per-type rows, the three-holder walk, the dependency-order walk); the 15 CONTROLs green. Restored: blobfc052169== HEAD, diff 0 bytes.Acceptance notes
kernel:bootstrappedseals the registry and warn at the cold boot. Recommendation: keep install-time, because D2 is ruled as an install refusal "on the ADR-0130 D3 object check", and the measured population that would stop booting is 0.sys. ADR-0150 D2 namessys/NAMEas an address too, but this rule does not judge the shareable namespaces (base,system,sys), mirroring the namespace gate's exemption and D3's co-owner map. Measured first-party: the 22syspackages of a booted showcase hold 0 duplicate names, so judgingsyswould refuse nothing here today; cloud'ssyspackages are NOT MEASURED. Recommendation: leavesysout in this child; a later child can widen it once cloud'ssyspackages are measured.NamespaceNameConflictError; modulenamespace-co-owner-names.ts; exportedNAMESPACE_UNIQUE_TYPES,namespacePackageOf,namespaceNameConflicts,namespaceNameConflictMessage. No new error code.packages[]stack no body declares), which the boot registers without an install.os validatecannot see packages already installed in a deployment; that half is the package door's alone.plugins[]entry that is a plugin class instance counts on the incoming side only; and on a running registry, an upgraded artifact that moves a covered name from co-owner A to co-owner B is refused when B re-registers before A (A's stale record still holds it), the same disposition ADR-0130 D3's object check has; the cold boot starts empty and is unaffected, andos validateaccepts that artifact.test/validate-namespace-name.test.tsspawns the CLI, so it falls in the cliintegrationproject (declared to CI); it was also run locally above.Generated by Claude Code
🤖 Generated with Claude Code
https://claude.ai/code/session_01ADHkmQv69sQL5nfT8xuPWs