Repository navigation
Description
epic:#31527#1 · os-project-manager · session_01FEkQ5mLd7pR2PHjsPwiGkz
Filing gate: ④ coordination node: child N of the epic #31527 (parent and per-layer children), as ADR-0150 (docs/adr/0150-behavioural-metadata-addressed-by-package-objects-keep-the-literal-prefix.md, merged in #31586 at 5d1382a)'s execution plan lists it. Hand-over card: filed undispatched as the epic seat signs off (maintainer 2026-11-08T16:34Z 「专题卡当前任务处理完,合并后就下班」). ⛔ Not a claim.
Ruling-ref: per-type table A (6723462584); epic A 「立专题」 (6723499113); division of labour A 「留核心,其余交车道」 (6723571682); D2 (6724570466); ADR-0150 accepted by merge (#31586, 2026-11-08T21:16Z).
Business reason: inherited from the parent #31527. Behavioural metadata is addressed by (package, name), so two installed packages can each ship an item of the same name and every reader answers the right one, or refuses with the candidates, instead of silently taking the first match.
Reader: the next domain:server seat picks it from the queue (pm-dispatch selection) and accepts its PR against the red lines below.
Dedupe (open AND closed): namespace co-owner unique (4; top hits #31527(open) #25792(closed) #25403(closed), none on point: they are this epic, its parent #30806, or unrelated cards).
class: d · type: Feature
Grade: p1, inherited from the parent (self-graded under 「定级你可以自己决定」).
维护者速读
同一个命名空间里如果有两个软件包,它们的行为元数据(页面、报表、队列等 12 类)不能重名,安装和 os validate 时拒绝。这样以后「命名空间 + 名字」永远只指向一个条目。第一方实测 0 处冲突。
What to build
A (type, name) held twice inside one namespace is refused at install and os validate (D2, ruled 6724570466), on the ADR-0130 D3 object check, for the bucket 2/3 types phase 1 does not cover: sharing rule, queue, assignment rule, hook, job, app, page, dashboard, report, book, cube, tool. The refusal names both holders. Lands before G1 and G2, so a qualified address and a face always name one item.
Surface
- Expected file surface: objectql
registry.ts(installPackage), cli validate. - Clause-②: no.
- Narrowing: yes (measured first-party: 0 of 297 HotCRM keys).
Acceptance — the epic's three red lines (every child shares them)
- Resolution never loosens. No first-registered fallback, no environment-wide guess for a caller with a package, no silent pick.
- Ambiguity is reported, never guessed. Every refusal and every migration report names every candidate.
- Independently releasable (red line 3). The PR proves it with ADR-0150's four readings: (a) the phase-1 one-holder tests stay green; (b) bare-name behaviour (URLs, MCP, SDK) is unchanged for every name with one holder, except this card's declared narrowing; (c) any migration is re-runnable and never guesses; (d) its
Clause-②:declaration and, where it changes the protocol, its ADR-0087 migration entry. - The epic seat is off duty after hand-over: the accepting lane seat checks these lines itself, and a narrowing beyond the declared one goes to the maintainer before landing.
Parent: #31527.
Activity
objectstack-fleet commentedon Nov 8, 2026
domain:server#1 · os-steve · session_01ADHkmPF1skfu2kx89BEXZi
Claim: PM loop round 1 · #31670 · 2026-11-08T21:30Z · feature (p1; ADR-0150 child N, hand-over card of epic #31527)
Session:
session_01ADHkmPF1skfu2kx89BEXZiAccount:
os-steveBranch:
claude/project-thread-mjoky7(the card thread's harness-pinned branch; platform exception toclaude/issue-<n>-<slug>)Worktree:
objectstack-issue-31670Domain:
domain:serverSeat:
domain:server#1File surface:
packages/objectql/src/registry.ts(installPackage, beside the ADR-0130 D3 object check) and a predicate module inpackages/objectql/src/, theos validatepath inpackages/cli/src/, their tests, a changeset (stop on breach; explain in the report)Container & model:
L,mode:thread,model: default tier(narrowing: the review of record runs at CONTRACT_REVIEW_TIER),effort: xhighClause-②: no (narrowing)
Metadata-protocol: narrowed
Ruling-ref: 6724570466 (D2); 6723462584 (per-type table A)
Responsibility: n/a — not a defect card
Thread-read: none
Premise: holds (read at
5d1382a5: ADR-0150 is onmainvia #315865d1382a5; no same-namespace(type, name)refusal exists for the 12 bucket 2/3 types)Serial constraints cleared: seat 1's own draft PR #31661 (#31414, Tier H, waiting on approval) touches
registry.tscomment lines andbare-name-one-holder.ts. Same seat, so the dev leaves those hunks alone and rebases on #31661 if it lands first. No other open PR touchesregistry.ts. ⛔ No package-scoped resolution (child R, #31575). A narrowing beyond the 12 declared types goes to the maintainer before landing.Order: standard order +
server-seat1/31670-delta.md(project files).objectstack-fleet commentedon Nov 8, 2026
domain:server#1 · os-steve · session_01ADHkmQv69sQL5nfT8xuPWs
os-dev-report
{ "issue": 31670, "status": "done", "branch": "claude/project-thread-mjoky7", "pr": "https://github.com/objectstack-ai/objectstack/pull/31717", "session": "session_01ADHkmQv69sQL5nfT8xuPWs", "premise_still_valid": true, "summary": "One predicate (packages/objectql/src/namespace-co-owner-names.ts) decides whether a package declares a sharing rule, queue, assignment rule, hook, job, app, page, dashboard, report, book, analytics cube or tool under a name another package of its namespace already holds. SchemaRegistry.installPackage asks it right after the ADR-0130 D3 object check and throws NamespaceNameConflictError (NAMESPACE_CONFLICT, 422, every holder named); os validate and os build walk the artifact's packages[] in the boot's install order and ask the same predicate, with the same sentence. Shareable namespaces (base/system/sys) and packages without a namespace are not judged; #31661's hunks are untouched and merge cleanly with it.", "tests": "New: objectql registry-namespace-co-owner-names.test.ts 56 passed; cli utils/namespace-co-owner-names.test.ts + parity 2 files/63 passed; cli test/validate-namespace-name.test.ts 4 passed (row message asserted equal to the door's thrown message). Suites on 97b94ed7: objectql 573/11672 passed; cli unit 406/5754; metadata-protocol 328 passed 4 skipped/22595 passed 26 skipped; rest 395/7627 passed 332 skipped; runtime 563/9033 passed 19 skipped; phase-1 bare-name files alone 4/154 passed. Ablations: door call removed -> 17/56 red; validate branch inverted -> 1/4 red (validate exits 0); walk inverted -> 14/29 red; each restored, git diff HEAD 0 bytes.", "gates": "dispatch-gates --ran on 97b94ed7: 84 derived, 84 run, 0 NOT-MEASURED, 0 UNRUN, all exit 0 (check-plugin-teardown-shape --self-test and check:dual-build-cjs-loads first exit 3 on missing prerequisites, re-run green after fetching the fixture commit / building the five dist-less packages). eslint objectql and cli --no-inline-config exit 0; typecheck objectql, cli exit 0. CI check-runs not yet cited (PR just opened).", "dogfood_battery": "97b94ed7 · os-verify-lock: VERDICT command-exit 0 · Test Files 440 passed, 3 skipped (443) · Tests 3652 passed, 41 skipped (3693) · no failure", "mcp_calls": "4 — issue_read get, issue_read get_comments x2, pull_request_read get_files x1; no write tools", "api_writes": "2 — fleet-write relay pr_create (POST pulls, #31717); this comment via post-stamped.mjs (POST issues/31670/comments)", "open_questions": [ { "question": "Cold boot: refuse a deployment whose installed packages of one namespace already share one of these names, or only warn at the cold boot like phase 1?", "options": [ "A refuse at every install, boot included, like the ADR-0130 D3 object check (as built)", "B judge only after kernel:bootstrapped seals, warn at cold boot" ], "recommendation": "A, because D2 is ruled as an install refusal on the D3 check and the measured first-party population that would stop booting is 0" }, { "question": "Judge the sys namespace too?", "options": [ "A leave base/system/sys out, matching the namespace gate's exemption (as built)", "B judge sys as well" ], "recommendation": "A in this child; showcase's 22 sys packages hold 0 duplicates, cloud's sys packages are not measured, a later child can widen it" }, { "question": "Names: NamespaceNameConflictError, namespace-co-owner-names.ts, NAMESPACE_UNIQUE_TYPES / namespacePackageOf / namespaceNameConflicts / namespaceNameConflictMessage; no new error code", "options": [ "A keep", "B rename" ], "recommendation": "A, seat's call per house conventions" } ], "security_findings": "none", "out_of_scope_findings": [], "files_changed": [ "packages/objectql/src/namespace-co-owner-names.ts (new)", "packages/objectql/src/registry.ts", "packages/objectql/src/index.ts", "packages/objectql/src/registry-namespace-co-owner-names.test.ts (new)", "packages/objectql/src/federated-injected-column-readers.test.ts (one ledger row, forced)", "packages/cli/src/utils/namespace-co-owner-names.ts (new)", "packages/cli/src/utils/namespace-co-owner-names.test.ts (new)", "packages/cli/src/commands/validate.ts", "packages/cli/src/commands/compile.ts", "packages/cli/test/validate-namespace-name.test.ts (new)", "packages/cli/test/validate-build-gate-parity.test.ts (one roster row, forced)", ".changeset/31670-namespace-co-owner-names.md (new)", "scripts/adr-anchors/packages__objectql__src__namespace-co-owner-names.ts.json (new)" ], "line_budget": "13 files, +1235 / -0 vs main (559 source, 648 tests, 28 changeset and ADR anchor)", "deviations": [ "HotCRM census NOT MEASURED (not in this container); first-party measured 0", "Base side of Clause-② measured by ablation of the one added call at each door, not on a base checkout", "The spawn test is in the cli integration project; also run locally", "os-dev-report posted by the card thread; PR assignee/review request left to the seat (no MCP writes)" ] }Stamped 2026-11-08T23:15Z.