Repository navigation
feat(objectql)!: an agent and a skill hold one name per package (bare-name phase 1, 4/4) - #31375
Conversation
…-name phase 1, 4/4) Measured first on a booted showcase with two packages sharing one agent and one skill name, both orders: /meta/agent/NAME serves the first-registered package's agent, an MCP client's prompts/get of a skill resolves the first-registered package's skill (listSkillPrompts keeps the first row per name), silently; a third package installed after the boot answers 200 and is shadowed. agent and skill join BARE_NAME_ONE_HOLDER_TYPES as the AI family, the last: after the cold boot's seal the package door and the item seam refuse a second holder with the first family's envelope; the cold boot warns. A tool is not covered. ADR-0048 records the outcome as P1.9 and closes the series; the anchor invariant names the fourth family. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FEkQ5pr7Ua2kPRCMZNupZg
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FEkQ5pr7Ua2kPRCMZNupZg
📓 Docs Drift CheckThis PR changes 1 package(s): 4 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 2 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 21 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 eff639863c43fcb67f2bdea461df91c0e9bde7fc && git checkout eff639863c43fcb67f2bdea461df91c0e9bde7fc
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 7189fb2a2f765b84c26c47e63f13adbb81f4d3da a9d8e39701956668d5480cd984e9eb8de78d5093 && git checkout -B drift-repro 7189fb2a2f765b84c26c47e63f13adbb81f4d3da && git merge --no-ff a9d8e39701956668d5480cd984e9eb8de78d5093
node scripts/docs-audit/affected-docs.mjs --json 7189fb2a2f765b84c26c47e63f13adbb81f4d3da
|
|
domain:server#5 · os-project-manager · session_01FEkQ5o8PE7ZtVjcor51wBZ Contract-review-claim: session_01FEkQ5o8PE7ZtVjcor51wBZ · head 15ed46b · 2026-11-08T04:57Z |
|
domain:server#5 · os-project-manager · session_01FEkQ5o8PE7ZtVjcor51wBZ Contract reviewServed-tier: Two faces at once: the rules face ( Check-runs on ① Derived judgments
② Semver level
③ Boundary flagsEvery deviation in report 6717468349, answered:
Out-of-scope findings in the report, answered or escalated:
Tier H. ④ Design judgmentThe ADR-0048 changes, against their first consumers and the rulings.
The narrowing itself, against the published spec on
Series convention: a fourth per-family test file and dogfood file rather than a Findings, graded. Must-fix: none. Should-fix: (a) the cloud-fetched Implemented-by: VERDICT: PASS Generated by Claude Code |
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FEkQ5pr7Ua2kPRCMZNupZg
|
domain:server#5 · os-project-manager · session_01FEkQ5o8PE7ZtVjcor51wBZ Contract reviewServed-tier: A delta on record 6717571232 (the PASS on Check-runs on ① Derived judgmentsNothing moved. The delta adds no hunk outside the ADR's prose: ② Semver levelNothing moved. The changeset is byte-identical to the reviewed head: ③ Boundary flags
④ Design judgmentThe delta against the rule it states. The old sentence stacked two "among them" clauses; the new one — "Every other type keeps §3.4 as written, among them a Break attempts, re-run on the delta. None of the scenarios can move on a two-line ADR prose edit with no code hunk: both orders, a third package after the boot, the package door and the item seam, cold-boot warn vs post-seal refuse, built-in or baseline items (none in this repository), an Findings, graded. Must-fix: none. Should-fix: none newly owed on this head — (b) closed by the delta; (a) carried by card #31296. Nits (standing, nothing owed): the HotCRM reading for the changeset's producers line; a fourth per-family test file against AGENTS.md's shared-harness preference (series precedent, PR 2/3). Out-of-scope (escalated to the seat, unchanged): Implemented-by: VERDICT: PASS Generated by Claude Code |
|
domain:server#5 · os-project-manager · session_01FEkQ5o8PE7ZtVjcor51wBZ 维护者速读
席位意见:建议批准。机制与前三步相同,ADR 与代码、消费方一致;复审提出的 ADR 文字问题已在本头修正。 席位核对 — ACCEPT ·
|
Requested by Leehom · project thread
Fixes #30803
PR 4 of 4, the last of phase 1's series by type family: PR 1 #30836 (the data family), PR 2 #31006 (the request family), PR 3 #31093 (the flow family), this one the AI family (
agent,skill), per ruling 6688041914. Claim 6716532253 (domain:server#5, card-thread session_01FEkQ5pr7Ua2kPRCMZNupZg).Clause-②: no (narrowing) — the engine's package door (
SchemaRegistry.installPackage) and item seam (SchemaRegistry.registerItem) refuse, after the cold boot, a package registration they accepted before: one whose agent or skill bears a name another installed package holds. Nothing is widened.Metadata-protocol: narrowed
Skills-docs: none —
skills/**does not teach that two packages may share an agent or skill name, and the naming rule itself is phase 2's (#30805); the prescription ships in the refusal and warning text and in ADR-0048's 2026-11-06 addendum (P1.9).docs/adr/0048-cross-package-metadata-collision.md(header, §3.4 note, the addendum's status line, P1.5 and the new P1.9). The seat routes the approver.维护者速读
NAMESPACE_CONFLICT,点出两个持有包和改名建议(与 feat(objectql)!: a picklist, mapping or dataset name holds one package (bare-name phase 1, 1/4) #30836、feat(objectql)!: an API, an object-less action and an engine function hold one name per package (bare-name phase 1, 2/4) #31006、feat(objectql)!: a flow, a webhook, a connector and an email template hold one name per package (bare-name phase 1, 3/4) #31093 同一机制)。这是该系列的收尾,合并即关闭 Bare-name phase 1: refuse a second package holding a non-object name whose consumers resolve without package context (ruling C on #30798) #30803。/meta/agent/NAME给先注册包的 agent;MCP 客户端按名取 skill 提示词,拿到的是先注册包的 skill(另一个被静默丢弃),/meta/skill/NAME同样;都不告警。启动后再装一个同名包,今天照常 200 并被遮蔽。tool、rag_pipeline不在裁决列表里,不受影响。示例应用和平台包都没有声明 agent 或 skill,现有部署不会因此启动失败(冷启动只告警)。回滚即 revert 本 PR。packages/objectql/src/bare-name-one-holder.ts(列表末尾加入 AI 族、两个类型的理由短句)、ADR-0048 P1.9 与 P1.5、registry-bare-name-one-holder-ai-family.test.ts。pnpm --filter @objectstack/objectql exec vitest run src/registry-bare-name-one-holder-ai-family.test.ts——预期 26 passed。What changes
packages/objectql/src/bare-name-one-holder.ts— the covered types grow from ten to twelve:agentandskilljoinBARE_NAME_ONE_HOLDER_TYPESlast, as the AI family (BARE_NAME_REGISTRY_TYPESstays derived); their collection keys (agents,skills), consumer clauses and nouns, empty built-in and overridable-baseline sets. Module doc: the two measurements, the family closing the series.packages/objectql/src/registry.ts,packages/objectql/src/plugin.ts— comments name the twelve types; no code change. Both doors and the cold-boot seal are generic over the list.packages/objectql/src/registry-bare-name-one-holder-flow-family.test.ts— its type-list cell now pins its own family's slot (slice(0, 10)); the whole list is pinned by the AI family's file.docs/adr/0048-cross-package-metadata-collision.md(Tier H) — header Addenda entry and §3.4's 2026-11-06 note name the twelve types and drop "to follow"; the addendum's status line names P1.9 as the last change; P1.5 becomes the series' record ("The series, complete"); new P1.9 — the measurement, what is refused, what is not in the list (tool,rag_pipeline), the cold boot, the series' close.scripts/adr-anchors/packages__objectql__src__bare-name-one-holder.ts.json— the invariant names the fourth family and its served holder..changeset/30803-bare-name-ai-family.md—@objectstack/objectqlminor, both declaration lines, BREAKING Why / Before / Now / The cold boot / Who moves / Unchanged,adr-0087: not-required (no-migration-prescription), measured producers.Why (measured)
Booted showcase + two
AppPluginpackages (com.qa.bare.alpha,com.qa.bare.beta) sharing one name per type, in both registration orders, on30e0bd16; thenPOST /marketplace/install-localof a third package (gamma) declaring all held names (a temporary dogfood file, deleted):agentGET /meta/agent/NAMEalpha/beta— first-registered200, shadowedagentmetadataservice (get('agent', NAME), the MCPagent_promptread)skillprompts/get(listSkillPromptsover the mergedGET /meta/skilllist)alpha/beta— first-registered; the other row dropped200, shadowedskillGET /meta/skill/NAMEalpha/beta— first-registeredtool(not in the ruling)GET /meta/tool/NAMEalpha/beta— first-registered200, shadowedrag_pipeline(not in the ruling)defineStackrefuses theragPipelineskey; nothing registeredThe agent runtime that resolves an agent or a tool by name for chat lives in objectstack-ai/cloud and is NOT MEASURED here. Both ruled types resolve without package context, so both join the list.
Verification
At head
15ed46b6(feat55c70231cut on30e0bd16, thenorigin/mainmerged once ate7354255: six commits, none in this PR's files, no conflict). The unit and dogfood pins, the gates and the battery ran on15ed46b6; the ablation, the typechecks and the full objectql suite ran on55c70231:packages/objectql/src/registry-bare-name-one-holder-ai-family.test.ts(new, 26 cells, realObjectKernel+ObjectQLPlugin): the type list (all twelve, in family order) and the two labels;declaredBareNamesoveragentsandskillsand a nested plugin, a tool declaring nothing; for each of the two types the data family's matrix — package door (both holders, rename, no record left), ABLATION before the seal, item seam, nested plugin, same-package reload (CONTROL), uninstall releases, environment registration never judged and never a holder (CONTROL), the cold boot (warns once naming both and the rename; reload keeps both, a third refused naming both;'refuse'refuses with the doors' envelope); CONTROLs — two packages' tools under one name both install after the seal, one package's agent and another's skill under one name never meet; the reason names only the types it carries; a built-in skill name is refused at the package door. With the data, request and flow families' pins andhook-binder.test.ts: 5 files / 180 passed.packages/qa/dogfood/test/bare-name-one-holder-ai-family.dogfood.test.ts(new, booted showcase + twoAppPluginpackages +MarketplaceInstallLocalPlugin): the cold boot boots and logs ONEWARNline naming the agent and the skill, both packages and the renames, never the shared tool;/meta/agent/NAME,/meta/skill/NAMEand the MCP skill prompt keep servingalpha;POST /marketplace/install-localofgammadeclaring the held agent name and ofdeltadeclaring the held skill name are each422 PLUGIN_REGISTER_FAILEDnaming both holders and the rename, the package list unchanged; CONTROL:epsilonwith fresh agent and skill names plus the shared tool name installs, and its agent and skill prompt serve. With the three earlier families' dogfood files: 4 files / 16 passed.ablation-replace.mjs, restored with blob == HEAD andgit diff HEADempty):agentandskillfiltered out ofBARE_NAME_ONE_HOLDER_TYPES(markerABL4) → the AI family's unit file 18 of 26 red (the list anddeclaredBareNamescells, every refusal at both doors, each ABLATION cell's after-seal half, the cold-boot warn / reload / refuse cells, the reason and built-in cells; the 8 green are, per type, the same-package reload, the uninstall release and the environment CONTROL, plus the tool and agent-versus-skill CONTROLs); objectql rebuilt with the mutation (ablation-dist-preflight: marker in 4 built files; the DTS step failed on the mutated literal's type, TS2322, after the JS bundles were written) → the dogfood pin 3 of 4 red (no warning line;gammaanddeltainstalled), the CONTROL green. Restored, rebuilt (marker absent from all 14 built files, tree clean) → 4 of 4 green.pnpm --filter @objectstack/objectql typecheckexit 0 (incl.check:test-typecheck: 39 files / 233 errors / 64 pinned signatures held, unchanged);pnpm --filter @objectstack/dogfood exec tsc --noEmitexit 0; eslint (--no-inline-config) overpackages/objectql/srcand the dogfood file exit 0, no findings.@objectstack/objectqlfull suite underos-verify-lock: 568 files / 11516 tests passed (VERDICT command-exit 0).node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commandsat15ed46b6(merge basee7354255, 9 paths): 90 derived families, every one run with its exit code captured before any pipe, all 90 exit 0 on the first run (thecheck:dual-build-cjs-loadsprerequisites were already built on this worktree);--ran: "90 derived famil(ies) accounted for — 90 run, 0 NOT-MEASURED" (exit 0). The gates first ran on55c70231;mainmoved during that run, so it was stopped,mainmerged and the whole derived list re-run on15ed46b6(the derivation was the same 90).pnpm --filter @objectstack/dogfood test, underos-verify-lock) at15ed46b6:VERDICT command-exit 0· Test Files 438 passed | 3 skipped (441) · Tests 3622 passed | 41 skipped (3663) · no failures (held the lock 1801s on a shared box). Ran because the title carries!andClause-②carries the(narrowing)arm.Kept
toolandrag_pipelinekeep §3.4 as written; cold boot stays ruling B (BARE_NAME_COLD_BOOT_MODE = 'warn', untouched).Acceptance notes
agent: the open framework's one by-name read of a package agent is/meta/agent/NAME. The kernelmetadataservice (what MCPagent_promptreads) lists no package agent at all on the composed runtime; agents are platform-owned (ADR-0063 §2), and the cloud runtime that resolves one by name for chat was not measured. The ruling keptagentin this card and the/metadoor is a by-name read without package context, so it joins.tool: same first-registered answer at/meta/tool/NAME; not in the ruling's nine, so not added (reported to the seat).rag_pipeline:defineStackrefusesragPipelinesas an unrecognised stack key, though the engine's collection loop and the manifest spelling table still list it; nothing measured beyond that (reported to the seat).Human Minimum
packages/specholds no runtime logic. (not touched)main, one pull request (the fourth of a series by type family, per the ruling).packages/spectouched: n/a.content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.🤖 Generated with Claude Code
https://claude.ai/code/session_01FEkQ5pr7Ua2kPRCMZNupZg