You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
objectql/cli: a packages[] stack's own top-level residual items are judged by the namespace co-owner rule too (ADR-0150 child N follow-up) #31720
Filing gate: ④ coordination node: a follow-up of child N (#31670, PR #31717) of the epic #31527, from that PR's contract review (record 6728707576, finding N3). ⛔ Not a claim.
Ruling-ref: ADR-0150 D2 accepted (record 6724570466): packages that share a namespace keep each behavioural (type, name) unique across it, so a qualified address names exactly one item. Division of labour A (6723571682).
Business reason: inherited from the parent #31527. A qualified address /<namespace>/<name> must name one item. Today N's rule does not see one holder kind: a packages[] stack manifest's own top-level residual items, which register under the stack id without going through installPackage.
Reader: the next domain:server seat (preferably the one holding N, K and G1, since this is the same registry.ts region). The epic seat reviews the PR against the red lines.
Dedupe (open AND closed): namespace co-owner residual stack (none on point beyond #31670 itself).
class: d · type: Feature
Grade: p1, inherited from the parent.
Blocked-by: #31670
维护者速读
N 的「同一命名空间里名字不能重复」规则漏了一种情况:多包栈清单自己顶层的残余条目,不走安装门,所以安装门和 os validate 都没判它们。这张卡补上,同一个谓词。
What to build
Run N's one predicate (namespace-co-owner-names.ts) over the residual top-level items a packages[] stack registers under its own id, at the door that registers them, and in os validate / os build. Use the same message and code (NAMESPACE_CONFLICT, 422). It counts only when the stack's namespace equals one of its packages' namespaces, or another installed package's.
Surface
Expected file surface: objectql registry.ts (the residual registration path) and namespace-co-owner-names.ts; cli validate.ts / compile.ts, and the cli copy of the predicate.
Clause-②: no.
Narrowing: yes, the same rule as N, for one more holder kind (first-party count measured in the PR).
Acceptance — the epic's three red lines
Resolution never loosens.
Ambiguity is reported, never guessed. The refusal names every holder.
Independently releasable. Readings (a)–(d) as in every child. The narrowing is declared with its count.
Its one blocker, N #31670, is closed: PR #31717 merged as d655caf. Moving pm:blocked → pm:queue. Suggested seat: server seat 1, the same seat as N, because it touches the same hot file registry.tsinstallPackage. The epic red lines apply, and the PR pings the epic thread for review before it lands.
Claim: PM loop round 1 · #31720 · 2026-11-09T01:03Z · feature (p1; ADR-0150 child N follow-up, N's review finding N3)
Session: session_01ADHkmPF1skfu2kx89BEXZi
Account: os-steve
Branch: claude/project-thread-mjoky7 (the card thread's harness-pinned branch, the same thread as N #31670; platform exception to claude/issue-<n>-<slug>)
Worktree: objectstack-issue-31720
Domain: domain:server
Seat: domain:server#1
File surface: the residual-item registration path of a packages[] stack in packages/objectql/src/ (registry.ts or the engine seam that registers it), packages/objectql/src/namespace-co-owner-names.ts, packages/cli/src/utils/namespace-co-owner-names.ts, packages/cli/src/commands/validate.ts / compile.ts, their tests, a changeset (stop on breach; explain in the report)
Container & model: M, mode:thread, model: default tier (narrowing: the review of record runs at CONTRACT_REVIEW_TIER), effort: high
Clause-②: no (narrowing)
Metadata-protocol: narrowed
Ruling-ref: 6724570466 (D2); 6723571682 (division of labour A)
Responsibility: n/a — not a defect card
Thread-read: 6729750199
Premise: holds (read at cae8d8fe: N's predicate is on main via #31717d655cafb, asked only by refuseNamespaceNameConflicts in installPackage and by the cli walk; no call judges a stack's residual top-level items)
Serial constraints cleared: the same thread first lands a fixture-only PR (packages/cli/test/validate-namespace-name.test.ts, the #31661 prerequisite), and this card starts from fresh main after it merges. #31661 (Tier H) touches registry.ts comment lines and bare-name-one-holder.ts, on the same seat, and the dev leaves those hunks alone. G1 #31691 and K #31681 are this seat's, serial after this card. ⛔ The 12 types only, and no package-scoped resolution.
Order: standard order + server-seat1/31720-delta.md (project files).
{
"issue": 31720,
"status": "done",
"branch": "claude/project-thread-mjoky7",
"pr": "https://github.com/objectstack-ai/objectstack/pull/31767",
"session": "session_01ADHkmQv69sQL5nfT8xuPWs",
"premise_still_valid": true,
"summary": "A packages[] stack's residual top-level items (unclaimedTopLevel, registered under manifest.id without installPackage) are now judged by N's one predicate as one holder of the stack's manifest.namespace. The manifest service asks SchemaRegistry.refuseResidualNamespaceNameConflicts after every body installs and before any residual item registers, inside the one restore run, so a refusal (NamespaceNameConflictError, NAMESPACE_CONFLICT 422, every holder named) puts the whole artifact back. A residual that registers is recorded as a holder, so a package or another residual registering later is refused too (order-independent). N's package door and the new call share one private helper; no second predicate. 11 of the 12 types can be residual (no top-level jobs). CLI unchanged: inside one artifact a residual cannot share a covered name with its own bodies (slot claim; bodies refuse navigation/plugins; names required), and os validate/os build cannot see other artifacts' packages.",
"tests": "New: objectql manifest-service-residual-namespace-name.test.ts 32 passed (11 per-type refusals naming both holders + 11 other-namespace CONTROLs, holder shape, job never residual, later-package order test, CONTROLs: unheld name, dataset outside the twelve, sys, same stack again, refused stack records no holder, inside-one-artifact impossibility for all 11 types); with N's file 2 files/88 passed. Suites on 2faaebe9: objectql 575/11743 passed; cli 407/5775; metadata-protocol 328 passed 4 skipped/22595 passed 26 skipped; runtime 563/9059 passed 19 skipped. Ablations: refuse call removed -> 12/32 red; record call removed -> 1/32 red; each restored, plugin.ts blob == HEAD.",
"gates": "dispatch-gates --ran on 2faaebe9: 72 derived, 72 run, 0 NOT-MEASURED, 0 UNRUN, all exit 0. eslint objectql --no-inline-config exit 0; tsc objectql exit 0; check:adr-anchors exit 0. CI check-runs not yet cited (PR just opened).",
"dogfood_battery": "2faaebe9 · os-verify-lock: VERDICT command-exit 0 · Test Files 440 passed, 3 skipped (443) · Tests 3652 passed, 41 skipped (3693) · no failure",
"mcp_calls": "3 for this card — issue_read get, issue_read get_comments, pull_request_read get_check_runs; no write tools",
"api_writes": "2 — fleet-write relay pr_create (POST pulls, #31767); this comment via post-stamped.mjs (POST issues/31720/comments)",
"open_questions": [
{
"question": "CLI half: add the residual check to os validate / os build?",
"options": [
"A leave the CLI unchanged and state the bound (as built)",
"B add the call anyway as a guard against a future body shape that holds a name without a slot"
],
"recommendation": "A: inside one artifact the check can only answer [] (pinned in objectql for all 11 types, which goes red first if a body shape changes), so B ships code no test can turn red"
},
{
"question": "A residual whose stack has no namespace or a shareable one (base/system/sys)?",
"options": [
"A not judged, as for a package (isNamespaceJudged) (as built)",
"B judge it"
],
"recommendation": "A, N's rule unchanged"
},
{
"question": "Names: residualNamespacePackageOf, ResidualItems, SchemaRegistry.refuseResidualNamespaceNameConflicts / recordResidualNamespaceHolder; no new error code",
"options": [
"A keep",
"B rename"
],
"recommendation": "A, seat's call per house conventions"
}
],
"security_findings": "none",
"out_of_scope_findings": [
"The ADR anchor invariant of namespace-co-owner-names.ts names installPackage and os validate/os build as the predicate's callers; it does not yet name the manifest service's residual call. check:adr-anchors passes; a one-sentence anchor update is the seat's call."
],
"files_changed": [
"packages/objectql/src/namespace-co-owner-names.ts",
"packages/objectql/src/registry.ts",
"packages/objectql/src/plugin.ts",
"packages/objectql/src/index.ts",
"packages/objectql/src/manifest-service-residual-namespace-name.test.ts (new)",
".changeset/31720-residual-namespace-names.md (new)"
],
"line_budget": "6 files, +378 / -1 vs main",
"deviations": [
"No CLI change (see open question 1); the delta's os validate / os build half measured as unable to answer anything but []",
"HotCRM census NOT MEASURED (not in this container); first-party measured 0",
"Base side of Clause-② measured by ablation of each added call, not on a base checkout",
"Changeset bumps objectql only (cli unchanged)"
]
}
Activity
objectstack-fleet commentedon Nov 8, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: confirmed ·
domain:server· p1 ·pm:blocked· 2026-11-08T23:55Z⛔ Not a claim.
domain:server, p1, inherited.pm:blockedon its named predecessor (objectql: refuse a (type, name) held twice inside one namespace for the uncovered bucket 2/3 types (ADR-0150 child N) #31670 / PR feat(objectql)!: refuse a (type, name) held twice inside one namespace #31717).Generated by Claude Code
objectstack-fleet commentedon Nov 9, 2026
epic:#31527#1 · os-steve · session_01ADHkmP7o3uDTti21wLTfPf
Unblocked · 2026-11-09T01:01Z
Its one blocker, N #31670, is closed: PR #31717 merged as d655caf. Moving
pm:blocked→pm:queue. Suggested seat: server seat 1, the same seat as N, because it touches the same hot fileregistry.tsinstallPackage. The epic red lines apply, and the PR pings the epic thread for review before it lands.objectstack-fleet commentedon Nov 9, 2026
domain:server#1 · os-steve · session_01ADHkmPF1skfu2kx89BEXZi
Claim: PM loop round 1 · #31720 · 2026-11-09T01:03Z · feature (p1; ADR-0150 child N follow-up, N's review finding N3)
Session:
session_01ADHkmPF1skfu2kx89BEXZiAccount:
os-steveBranch:
claude/project-thread-mjoky7(the card thread's harness-pinned branch, the same thread as N #31670; platform exception toclaude/issue-<n>-<slug>)Worktree:
objectstack-issue-31720Domain:
domain:serverSeat:
domain:server#1File surface: the residual-item registration path of a
packages[]stack inpackages/objectql/src/(registry.tsor the engine seam that registers it),packages/objectql/src/namespace-co-owner-names.ts,packages/cli/src/utils/namespace-co-owner-names.ts,packages/cli/src/commands/validate.ts/compile.ts, their tests, a changeset (stop on breach; explain in the report)Container & model:
M,mode:thread,model: default tier(narrowing: the review of record runs at CONTRACT_REVIEW_TIER),effort: highClause-②: no (narrowing)
Metadata-protocol: narrowed
Ruling-ref: 6724570466 (D2); 6723571682 (division of labour A)
Responsibility: n/a — not a defect card
Thread-read: 6729750199
Premise: holds (read at
cae8d8fe: N's predicate is onmainvia #31717d655cafb, asked only byrefuseNamespaceNameConflictsininstallPackageand by the cli walk; no call judges a stack's residual top-level items)Serial constraints cleared: the same thread first lands a fixture-only PR (
packages/cli/test/validate-namespace-name.test.ts, the #31661 prerequisite), and this card starts from freshmainafter it merges. #31661 (Tier H) touchesregistry.tscomment lines andbare-name-one-holder.ts, on the same seat, and the dev leaves those hunks alone. G1 #31691 and K #31681 are this seat's, serial after this card. ⛔ The 12 types only, and no package-scoped resolution.Order: standard order +
server-seat1/31720-delta.md(project files).objectstack-fleet commentedon Nov 9, 2026
domain:server#1 · os-steve · session_01ADHkmQv69sQL5nfT8xuPWs
os-dev-report
{ "issue": 31720, "status": "done", "branch": "claude/project-thread-mjoky7", "pr": "https://github.com/objectstack-ai/objectstack/pull/31767", "session": "session_01ADHkmQv69sQL5nfT8xuPWs", "premise_still_valid": true, "summary": "A packages[] stack's residual top-level items (unclaimedTopLevel, registered under manifest.id without installPackage) are now judged by N's one predicate as one holder of the stack's manifest.namespace. The manifest service asks SchemaRegistry.refuseResidualNamespaceNameConflicts after every body installs and before any residual item registers, inside the one restore run, so a refusal (NamespaceNameConflictError, NAMESPACE_CONFLICT 422, every holder named) puts the whole artifact back. A residual that registers is recorded as a holder, so a package or another residual registering later is refused too (order-independent). N's package door and the new call share one private helper; no second predicate. 11 of the 12 types can be residual (no top-level jobs). CLI unchanged: inside one artifact a residual cannot share a covered name with its own bodies (slot claim; bodies refuse navigation/plugins; names required), and os validate/os build cannot see other artifacts' packages.", "tests": "New: objectql manifest-service-residual-namespace-name.test.ts 32 passed (11 per-type refusals naming both holders + 11 other-namespace CONTROLs, holder shape, job never residual, later-package order test, CONTROLs: unheld name, dataset outside the twelve, sys, same stack again, refused stack records no holder, inside-one-artifact impossibility for all 11 types); with N's file 2 files/88 passed. Suites on 2faaebe9: objectql 575/11743 passed; cli 407/5775; metadata-protocol 328 passed 4 skipped/22595 passed 26 skipped; runtime 563/9059 passed 19 skipped. Ablations: refuse call removed -> 12/32 red; record call removed -> 1/32 red; each restored, plugin.ts blob == HEAD.", "gates": "dispatch-gates --ran on 2faaebe9: 72 derived, 72 run, 0 NOT-MEASURED, 0 UNRUN, all exit 0. eslint objectql --no-inline-config exit 0; tsc objectql exit 0; check:adr-anchors exit 0. CI check-runs not yet cited (PR just opened).", "dogfood_battery": "2faaebe9 · os-verify-lock: VERDICT command-exit 0 · Test Files 440 passed, 3 skipped (443) · Tests 3652 passed, 41 skipped (3693) · no failure", "mcp_calls": "3 for this card — issue_read get, issue_read get_comments, pull_request_read get_check_runs; no write tools", "api_writes": "2 — fleet-write relay pr_create (POST pulls, #31767); this comment via post-stamped.mjs (POST issues/31720/comments)", "open_questions": [ { "question": "CLI half: add the residual check to os validate / os build?", "options": [ "A leave the CLI unchanged and state the bound (as built)", "B add the call anyway as a guard against a future body shape that holds a name without a slot" ], "recommendation": "A: inside one artifact the check can only answer [] (pinned in objectql for all 11 types, which goes red first if a body shape changes), so B ships code no test can turn red" }, { "question": "A residual whose stack has no namespace or a shareable one (base/system/sys)?", "options": [ "A not judged, as for a package (isNamespaceJudged) (as built)", "B judge it" ], "recommendation": "A, N's rule unchanged" }, { "question": "Names: residualNamespacePackageOf, ResidualItems, SchemaRegistry.refuseResidualNamespaceNameConflicts / recordResidualNamespaceHolder; no new error code", "options": [ "A keep", "B rename" ], "recommendation": "A, seat's call per house conventions" } ], "security_findings": "none", "out_of_scope_findings": [ "The ADR anchor invariant of namespace-co-owner-names.ts names installPackage and os validate/os build as the predicate's callers; it does not yet name the manifest service's residual call. check:adr-anchors passes; a one-sentence anchor update is the seat's call." ], "files_changed": [ "packages/objectql/src/namespace-co-owner-names.ts", "packages/objectql/src/registry.ts", "packages/objectql/src/plugin.ts", "packages/objectql/src/index.ts", "packages/objectql/src/manifest-service-residual-namespace-name.test.ts (new)", ".changeset/31720-residual-namespace-names.md (new)" ], "line_budget": "6 files, +378 / -1 vs main", "deviations": [ "No CLI change (see open question 1); the delta's os validate / os build half measured as unable to answer anything but []", "HotCRM census NOT MEASURED (not in this container); first-party measured 0", "Base side of Clause-② measured by ablation of each added call, not on a base checkout", "Changeset bumps objectql only (cli unchanged)" ] }Stamped 2026-11-09T03:12Z.