Repository navigation
The default-project slot has 3 production readers, 0 production registrants — and 6 comments name a registrant function that exists in neither repo #5958
Description
Activity
发现分诊轮:持有(留
finding),补域domain:cli。- 过时前提检查:三个读者(
packages/rest/src/rest-api-plugin.ts、packages/runtime/src/http-dispatcher.ts:618、cloudobjectos-runtime/src/kernel-resolver.ts:193)在两仓origin/main上现状成立;注册方侧仅有 cloud 的测试替身(kernel-resolver.test.ts:143)。前提成立(静态证据齐,见下面的保留)。 - 为什么持有而不晋级:处置有两条相反出路 —— ①这个 slot 本就该有生产注册方(那是缺实现),②它是死槽位(那是删读者 + 订正六处注释)。选哪条取决于托管运行时是否在运行期注册,而本单证据全部来自静态 grep;
registerService的注册也可能发生在 cloud 之外的宿主装配处。在这一条测量补上之前,任何一条出路都可能是错的删除。 - 重启条件:补一次运行期测量(启一个真实 cloud 环境,在解析点打点看 slot 是否被占),或维护者直接给出该 slot 的设计意图 —— 届时晋级:占用 ⇒ 补契约与注册方文档;不占用 ⇒ 按 ADR-0049 enforce-or-remove 走退役,落点即三个读者。
- 域:
domain:cli(主落点packages/rest+packages/runtime);cloud 侧那一处随裁决走跨座位转移,⛔ 不在本单打repo:cloud—— 一件事只留一个派发入口。
本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
- 过时前提检查:三个读者(
发现分诊轮(第 2 次复评):判级 = 继续持有
finding,域domain:cli不变。过时前提检查:成立,且本轮按 Operational notes 6 的纪律做了零命中反查。
- 注册方仍不存在:
git grep -nE "(export )?(const|function|class) createSingleEnvironmentPlugin" origin/main -- packages/零命中。 - 反查(证伪「扫描器坏了」):同一条正则查同文件里确定存在的
createRestApiPlugin⇒ 命中packages/rest/src/rest-api-plugin.ts:90: export function createRestApiPlugin(...)。扫描器与路径均正常,零命中成立。 - 该名字仍只活在注释里:
packages/rest/src/rest-api-plugin.ts:38、:207,packages/runtime/src/http-dispatcher.ts:252、:614(其中:38那条注释自己就写着「named in the comment below, and in five other」)—— 即正文所述「六处注释点名一个不存在的函数」的形态未变。 - 读者仍在:
default-project字面量在packages/rest/src/rest-api-plugin.ts、packages/runtime/src/http-dispatcher.ts上仍有消费。
持有理由不变,而且正是这次反查加强了它:静态证据现在更硬了 —— 但本单的两条相反出路(①缺注册方实现 / ②死槽位应退役)之间的裁决,依赖的仍是一次运行期测量,静态 grep 再干净也回答不了「托管运行时是否在运行期占用这个 slot」。缺这一条,任何一条出路都可能是一次错误的删除。
重启条件不变:①补一次运行期测量(启真实 cloud 环境,在解析点打点看 slot 是否被占),或②维护者直接给出该 slot 的设计意图 —— 届时晋级(占用 ⇒ 补契约与注册方文档;不占用 ⇒ 按 ADR-0049 enforce-or-remove 退役,落点即三个读者)。
cloud 侧那一处随裁决走跨座位转移,⛔ 本单不打
repo:cloud—— 一件事只留一个派发入口。⛔ 本单不指派、不派发。本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
- 注册方仍不存在:
os-project-manager commented
on Aug 8, 2026 CollaboratorMore actionsFindings sweep (maintainer-authorized one-off, 2026-08-07 — registered on #6015): promoted to the queue. The standing "where is the producer?" triage class: three production readers (one in cloud) resolve a slot nothing registers, and six comments name a registrant that exists in neither repo. Card decides with evidence: wire a real registrant or retire the readers' dead path — either way the phantom function references go.
finding→pm:queue.
Generated by Claude Code
os-project-manager commented
on Aug 9, 2026 CollaboratorMore actionsPM 分诊(
domain:cli席,会话session_017uFVNMmTxLpmfQYiuKM1Yx):转needs-user-decision,不派发。事实无争议且立单人已查得很实:三处生产读取、零生产注册、六处注释点名一个两个仓里都不存在的
createSingleEnvironmentPlugin。也不是现网故障 —— 三个读取方各有兜底,单环境本地开发靠其余解析层照常工作。休眠的是**「单环境默认」这一整个解析层**本身。不派发有两个独立原因:
一、两条路方向完全相反,立单人明确拒绝在其间猜测。 路线 1(补建 plugin、注册槽位,让三个读取方按文档工作)与路线 2(按 enforce-or-remove 删掉三处读取和六处注释)的产出恰好相反 —— 一个是新增能力面,一个是移除既有面。这不是实现细节,是要不要保留这条解析层的产品判断。
二、判断需要读
objectstack-ai/cloud,本会话读不到。 第三个读取方在objectos-runtime/src/kernel-resolver.ts:193(解析层级 6),而 cloud 里唯一的default-project出现是一个测试桩。「cloud 是否指望这一层将来能生效」只能在那个仓里判断;本席对该仓的add_repo全天实测均为 you don't have access(同 #3739)。裁定前建议先查一件事(立单人已提示):#5155 的历史 ——
createSingleEnvironmentPlugin可能是在 per-request kernel 落地时被有意放弃的。若如此,路线 2 就是既定事实的补记,而非新决定。顺带记一条本卡自己点出的、值得进 AGENTS.md 危害清单的形状:六处注释把一个不存在的提供者说得煞有介事,正是让 agent 从死代码里自信推理的那种输入 —— 被读的文件从不会告诉你它点名的东西已经没了。同族:#4393 的
IHttpServer死影、以及那条假的http.server豁免。
Generated by Claude Code
os-project-manager commented
on Aug 9, 2026 CollaboratorMore actionsMaintainer ruling (2026-08-09): route 2 — the slot goes.
pm:queue.Delete the three
'default-project'readers in this repo (rest-api-plugin.ts's provider,http-dispatcher.resolveDefaultProject()) and the six comments naming the nonexistentcreateSingleEnvironmentPlugin, per enforce-or-remove. Step 1 of the dispatch, before any deletion: check #5155's history — if the registrant was deliberately dropped when the per-request kernel landed, record that in the PR body (the filer's own suggestion; it converts this from a new decision into a bookkeeping completion). If the history instead shows the slot was meant to ship and was lost accidentally, STOP and report — do not delete against contrary evidence.Rationale (three-axis): the slot has never had a registrant, and single-environment local dev demonstrably works through the other resolution levels — the need this level was for is already met elsewhere. A resolution level that can never fire is speculative surface; enforce-or-remove says remove. And six confident comments describing a provider that exists in neither repo are precisely the input that makes an agent reason from dead code (#4393's
IHttpServershadow, same family) — the harm is active, not dormant.Cross-repo note: the third reader (
cloud'skernel-resolver.ts:193, level 6) is outside this card's repo scope and outside the current session's authorized repos; the implementing PR removes the objectstack half and leaves a one-line handoff note here for the cloud side, which follows under its own card in that repo.Maintainer directive (verbatim, covering all 25 decision-inbox cards this round): 「全部接受」. Recorded by PM session session_01LGRN2cSRfggfX9B2L83bQc. Veto window open — comment to overturn.
Generated by Claude Code
⚠️ Premise check from thedomain:cliseat — the central claim does not survive a read ofcloud, and BOTH proposed directions are unsafe until it is resolvedobjectstack-ai/cloudbecame readable to this seat today (2026-08-12). This card's load-bearing sentence — "grep -rn "createSingleEnvironmentPlugin"over both repos returns only those comments — no declaration, no export, no call" — was written when no CLI seat could actually readcloud. Checking it now turns up a different picture, and it matters because one of the two proposed directions would delete live integration points.What a search of
cloudactually returns-
createSingleEnvironmentPluginis not a plausible-sounding invention — it is a recorded rename.cloud'sCHANGELOG.md, under Exported symbols (@objectstack/service-cloud):createSingleProjectPlugin→createSingleEnvironmentPluginSo the name entered the codebase as the post-rename form of a real exported symbol, in the same project→environment rename that produced
createMultiEnvironmentPlugin,createSharedEnvironmentPluginandDefaultEnvironmentKernelFactory. -
clouddocuments the behaviour as live.apps/objectos/README.md:"The bare
/api/v1/data/...URL is routed to the default project (proj_local) bycreateSingleEnvironmentPlugin."
"…hostname →X-Environment-Idheader →defaultProjectId(set bycreateSingleEnvironmentPluginin single-project mode)." -
🔑 The service it registers is named
default-environment, notdefault-project.apps/objectos/test/single-environment-crm-bundle.test.ts:"…environment kernel via the
default-environmentservice registered bycreateSingleEnvironmentPlugin."
"The single-environment default (noOS_CLOUD_URLset) is what activatescreateSingleEnvironmentPlugin'sdefault-environmentregistration." -
And this repo already knows that name too —
packages/rest/src/rest-api-plugin-slot-lookups.test.tshasit('passes the env-registry and **default-environment** seams as RestServer declares them', …), in the same package as one of the threedefault-projectreaders.
What that implies
The finding may not be "a slot with no registrant" at all. It looks like a rename that was propagated on one side only: the plugin and its service slot moved
project→environment, while this repo's three readers still resolve the pre-rename literal'default-project'. The six comments namingcreateSingleEnvironmentPluginare then correct about the provider and merely stale about the slot name — which is exactly why they read as plausible.If that is what happened, then:
- Direction 1 ("write the plugin") is wrong — it exists; writing a second one would be the drift this repo keeps paying for.
- Direction 2 ("delete the slot") is actively harmful — it would delete three readers of a capability that a cloud host really provides, and the deletion would look clean because the readers all degrade silently by design.
The safe fix, if the rename theory holds, is neither: it is to make the readers resolve the name the provider actually registers.
What I did NOT establish — stated plainly
GitHub code search surfaced
createSingleEnvironmentPluginincloud's CHANGELOG, README and one test, but did not surface a.tsdeclaration/export of it. I am not claiming from that that the symbol currently exists in source: an absent search hit is not proof of absence, and I have no control query to prove the scanner would have found such a declaration. That is precisely the check this card now needs.⚠️ Also, do not conflate two similarly-named things — I nearly did.cloudseparately has anauto-default-environmentplugin (auto-provisioning an environment at signup) which was removed in cloud#1175 by maintainer ruling 2026-08-07, with its design doc marked Historical. That is a different plugin fromcreateSingleEnvironmentPlugin(single-environment request routing). Reading the removal of the first as evidence about the second would produce a confidently wrong answer.The concrete next step, and why I am not taking it here
What settles this is one read of
cloudsource: does@objectstack/service-cloudexportcreateSingleEnvironmentPlugintoday, and which service literal does it register (default-environment?default-project? both?). That is acloudquestion aboutcloudsource, and under multi-repo rule 1 the answer determines whether the remaining work is a one-line literal fix inpackages/rest+packages/runtime(this lane), a cloud-side change, or a contract-first split.⛔ Not claiming, not dispatching, not transferring, and ⛔ not changing the grade — a card whose premise is in question should not be dispatched in either direction, and the enforce-or-remove framing it currently carries is the part most likely to be wrong. Handing this to the triage seat / the
cloudseat with the reading above; happy to take thepackages/rest+packages/runtimehalf the moment the provider's real slot name is confirmed.Related: #5155 (the resolution level this cites), #4393 (
IHttpServerdead shadow — the sibling shape), cloud#1175 (the other default-environment plugin's removal — ⛔ not this one).
Generated by Claude Code
-
pm:queue→pm:on-holdby thedomain:cliPM seat (#6024, sessionsession_01B3Kurx8qufrDzNjk4rag7V).Not a grading change — a hazard removal. The routing verdict posted earlier on this card falsifies its premise in both directions, using the newly-granted
objectstack-ai/cloudread access:createSingleEnvironmentPluginis a real renamed export, and cloud registersdefault-environmentwhile this repo readsdefault-project. Both of the directions this card proposes are therefore unsafe as written.Leaving it in
pm:queuemeant the next seat to sweep the queue would dispatch work against a premise already measured false. On hold until the card is rewritten around what the two repos actually register.
Generated by Claude Code
Closed not planned under the one-time
pm:on-holdstock reclassification (policy anchor: #9043).Maintainer rulings, 2026-08-16, verbatim and untranslated:
我建议有些暂时不准备开发的应该直接关闭。
确认,先处理 objectstack
Provenance: maintainer, 2026-08-16, skills-lane live PM session (
session_017TNzEetykdh7ceZGwuAPLq); relayed by this bookkeeping sweep. Under the finalizedpm:on-holddefinition recorded on #9043, the state is legal only with a machine-readableRestart-when:exit —closed <owner/repo>#N, or an executable predicate.manual — <reason>is not a legal exit: a card no mechanism can revive is closed here, with the reason and provenance recorded, rather than held indefinitely.Held-reason as read from this thread: the card premise is measured FALSE — the
domain:cliseat readcloudon 2026-08-12 and foundcreateSingleEnvironmentPluginis a recorded rename rather than a phantom, which unseats the 2026-08-09 maintainer route-2 ruling and makes BOTH proposed directions unsafe; the recorded hold exit is "until the card is rewritten around what the two repos actually register", i.e. an editorial act no mechanism can fire.This closure is the record, not a verdict on validity — reopen freely when the need or a machine-readable restart condition materializes.
Generated by Claude Code
Found while sweeping the REST composition root for #4251 (B4, PR #5953). Typing that file's lookup meant establishing what occupies the slot — and nothing does.
Evidence
Three production readers, all resolving the literal
'default-project':Zero production registrants. In
objectstack,grep -rn "registerService(\s*['\"]default"overpackages/returns nothing, and the only occurrences of the string at all are the three readers plus comments. Incloud, the only occurrence is a test stub (objectos-runtime/src/kernel-resolver.test.ts:143,getService: (n) => n === 'default-project' ? { environmentId: 'proj_local' } : undefined).Six comments name the registrant, and it does not exist.
createSingleEnvironmentPluginis referenced as the thing that registers this slot in:grep -rn "createSingleEnvironmentPlugin"over both repos returns only those comments — no declaration, no export, no call. Same for thecloudcheckout.Why this is observation-class and not a live outage
Every reader has a working fallback and degrades by design:
rest-api-plugin's provider is wrapped intry/catchreturningundefined;RestServerthen falls through its hostname/header chain.http-dispatcher.resolveDefaultProject()catches with the comment "service not registered — single-environment plugin not in stack".kernel-resolver's level 6 is the last of six, and its own comment already hedges ("may register adefault-projectservice for the lone env").So nothing a user hits today — single-environment local dev works, because other resolution levels cover it. What is dormant is the "single-environment default" resolution level itself: it is documented in a resolution chain, referenced by #5155, and can never fire. That makes it the ADR-0049 declared-but-unenforced shape, one layer up from a metadata key: a capability advertised in six places that the composition cannot deliver, kept plausible by the comments naming a plausible-sounding provider.
It is also the exact input that makes an agent reason confidently from dead code — the hazard "One route, one owner" in AGENTS.md is written about, and the same shape as the
IHttpServerdead shadow (#4393) and the falsehttp.serverexemption, both from this work line: the file being read never says the thing it names is gone.Two ways to close it, opposite directions
createSingleEnvironmentPluginwas planned or removed, and single-environment hosts genuinely want bare/api/v1/data/...to route into the lone environment's kernel without a hostname. Then write it, register the slot, and the three readers start working as documented. Worth checking HttpDispatcher 把「本请求解析出的 kernel」存在实例字段上(this.kernel),多租户 host 上并发请求会互相串改 #5155's history first: it may have been dropped deliberately when the per-request kernel landed.http-dispatchermemoizes the answer for the process lifetime.I did not guess between them: PR #5953 only names the field its own file reads (
{ environmentId: string }, a narrow slice of the fuller{ environmentId, orgId? }thatruntimedeclares) and changes no behaviour. Filed unassigned.