Repository navigation
[seam] cloud: sweep the closed cloud package for proj_local comparisons before #13366 renames the standalone stamp #14225
Description
Activity
Claim: PM loop round R35 (reading batch B — member; chain head #14796)
Session:session_017Wu48ZSjk7HJjyJmGNBtUk
Branch: none — read-only reading, no PR; reading posted here
Worktree:cloud-readings-b(detached at cloudorigin/main, read-only)
Domain: repo:cloud (seat post #6026)
File surface: none
Container & model: S reading batch,mode:subagent,model: opus
Clause-②: no
Serial constraints cleared: see chain-head claim on #14796.
Generated by Claude Code
Reading:
proj_local/env_localsweep of the closedcloudpackageRead by: the
repo:cloudexecution seat (seat post #6026, PM sessionsession_017Wu48ZSjk7HJjyJmGNBtUk, round R35, reading batch B).
Ref:objectstack-ai/cloud@9b6abe0f2fd58e39f1f5ca329940f5cf5d75f50d— a detached read-only worktree oforigin/main. Nothing installed, built or edited;git status --porcelainempty.Answer in one line
No
proj_localcomparison exists anywhere incloud. The census's recommendation (a) is not overturned; #13366's one named gap is now measured and closed. 14proj_localhits, 0env_localhits — attributed below as 6 docs, 1 producer, 6 tests bound to cloud's own producer, 1 producer docblock. The single production consumer reads the id opaquely and never compares it to a literal.The two greps, verbatim, with the control
$ git grep -n "proj_local" -- .
exit 0, 14 lines, nothing trimmed:
AGENTS.md:240:2. **EE 本地台模拟不了 cloud 模式**。`apps/objectos-ee` 跑的是 **environment 模式**,每次启动 `ensureLocalIdentity` 会 seed `org_local` / `proj_local`,组织恒定存在——**永远跑不到** cloud 多租户的「自助注册→建组织」路径。在 EE 台点一下不能当作 cloud 流程的验证。 apps/objectos/README.md:49:curl -X POST http://localhost:3000/api/v1/projects/proj_local/data/account \ apps/objectos/README.md:55:The bare `/api/v1/data/...` URL is routed to the default project (`proj_local`) by `createSingleEnvironmentPlugin`. Tables are auto-created by the SQL driver on first access; the bundle's seed data (e.g. `Acme Corporation`) is upserted on boot. apps/objectos/README.md:188:| **Project DB** | Your business data (records served at `/api/v1/data/*`) | `OS_DATABASE_URL` / `OS_DATABASE_DRIVER` | local SQLite at `.objectstack/data/proj_local.db` | apps/objectos/README.md:204:| unset | SQLite — `.objectstack/data/proj_local.db` | apps/objectos/test/single-environment-boot-smoke.test.ts:85:const ENV_ID = process.env.OS_ENVIRONMENT_ID?.trim() || 'proj_local'; apps/objectos/test/single-environment-crm-bundle.test.ts:103:test('scoped URL /projects/proj_local/... still works (regression)', async () => { apps/objectos/test/single-environment-crm-bundle.test.ts:104: const { status, body } = await call('/api/v1/projects/proj_local/data/account', { apps/objectos/test/single-environment-crm-bundle.test.ts:135: const invoke = await call(`/api/v1/projects/proj_local/actions/contact/mark_primary/${target.id}`, { method: 'POST', body: {} }); packages/objectos-runtime/src/file-artifact-api-client.ts:43: * `process.env.OS_ENVIRONMENT_ID` or `'proj_local'`. packages/objectos-runtime/src/file-artifact-api-client.ts:88: ?? 'proj_local'; packages/objectos-runtime/src/kernel-resolver.test.ts:146: getService: (n: string) => (n === 'default-project' ? { environmentId: 'proj_local' } : undefined), packages/objectos-runtime/src/kernel-resolver.test.ts:153: expect(context.environmentId).toBe('proj_local'); packages/objectos-runtime/src/kernel-resolver.test.ts:155: expect(h.getOrCreate).toHaveBeenCalledWith('proj_local', { requestHeaders: context.request.headers });$ git grep -n "env_local" -- .
exit 1, 0 lines. No output. The spelling
env_localdoes not occur anywhere incloud.Control for that zero, same population, same invocation shape, as the card prescribes:
$ git grep -c "environmentId" -- . exit=0 files=177 .changeset/adr-0006-d2-environment-response-keys.md:1 .changeset/cloud-1213-drop-dead-entitlements-payload.md:1 .changeset/env-derived-secret-crypto-949.md:1 .changeset/hostname-single-implementation.md:1 .changeset/kernel-resolver-resolve-environment.md:2 .changeset/shard-by-environment-id.md:4 CHANGELOG.md:2 apps/cloud/scripts/check-demo-manifest.ts:2 apps/cloud/scripts/drill-r2-readpath.ts:1 apps/cloud/scripts/migrate-audience-postures.ts:3 (167 more files; trimmed for length, the count line is the control) $ git grep -n "environmentId" -- . | wc -l 1717
1717 lines across 177 files answered on the same tree. The
env_localzero is a measurement, not a miss.Per-hit attribution: producer vs consumer, and rename-sensitivity
The question the card asks of each consumer is: would its outcome change if the open-core standalone stamp went from
proj_localtoenv_local?# path:line kind producer / consumer outcome changes on rename? 1 AGENTS.md:240doc (prose about the EE local bench) neither no — prose would go stale, nothing executes 2 apps/objectos/README.md:49doc (a curlexample URL)neither no — stale example 3 apps/objectos/README.md:55doc (prose) neither no — and note this line is already stale, see "Discrepancy" below 4 apps/objectos/README.md:188doc (table cell, .objectstack/data/proj_local.db)neither no 5 apps/objectos/README.md:204doc (table cell) neither no 6 apps/objectos/test/single-environment-boot-smoke.test.ts:85test producer mirror — `process.env.OS_ENVIRONMENT_ID?.trim() 7 apps/objectos/test/single-environment-crm-bundle.test.ts:103test (the test(...)name string)neither no — cosmetic 8 apps/objectos/test/single-environment-crm-bundle.test.ts:104test consumer — an implicit comparison: the literal is a URL path segment ( /api/v1/projects/proj_local/data/account) that the project-scoping router must matchno — see the routing analysis below; this app never boots open core's standalone stack 9 apps/objectos/test/single-environment-crm-bundle.test.ts:135test consumer, same shape ( /api/v1/projects/proj_local/actions/contact/mark_primary/...)no, same reason 10 packages/objectos-runtime/src/file-artifact-api-client.ts:43runtime source, docblock documents row 11 no 11 packages/objectos-runtime/src/file-artifact-api-client.ts:88runtime source ⭐ PRODUCER — this.environmentId = config.environmentId ?? process.env.OS_ENVIRONMENT_ID ?? 'proj_local';no — it is a default-value stamp, not a comparison. A rename in open core does not reach it; cloud keeps stamping proj_local. See "Secondary finding".12 packages/objectos-runtime/src/kernel-resolver.test.ts:146test (fake getService)test fixture supplying its own literal no — round-trip; the test supplies the value it later asserts 13 packages/objectos-runtime/src/kernel-resolver.test.ts:153test assertion on the fixture's own literal no — passes unchanged whatever open core stamps 14 packages/objectos-runtime/src/kernel-resolver.test.ts:155test assertion on the fixture's own literal no — same Zero rows are rename-sensitive. Zero rows are a production-code comparison.
The one production consumer the card names, quoted in full
packages/objectos-runtime/src/kernel-resolver.ts:256-266— this is cloud's counterpart to thedefaultEnvironmentIdProviderthe card points at:// 6. Single-environment default (file-mode / local boot shapes // register a `default-project` service for the lone env). let def: any; try { def = defaultKernel?.getService?.('default-project'); } catch { /* not registered */ } if (def?.environmentId) { const driver = await envRegistry.resolveById(def.environmentId); if (driver) { context.environmentId = def.environmentId; context.dataDriver = driver; return; } }
It reads
def.environmentIdopaquely and hands it straight toenvRegistry.resolveById(...). There is no=== 'proj_local', no membership test, no switch. Rename-neutral by construction: whatever the registering plugin stamps is what this branch resolves.Why the two URL-shaped test hits (rows 8, 9) are also rename-neutral
They look like the dangerous shape, so here is why they are not.
apps/objectos/objectstack.config.tsboots only throughcreateObjectOSStack:const cloudUrl = process.env.OS_CLOUD_URL?.trim() || 'http://localhost:4000'; const config = await createObjectOSStack({ controlPlaneUrl: cloudUrl, controlPlaneApiKey: process.env.OS_CLOUD_API_KEY, fileConfig: cloudUrl === 'file' ? { artifactPath: process.env.OS_ARTIFACT_PATH, environmentId: process.env.OS_ENVIRONMENT_ID } : undefined, ...
and
createObjectOSStack's plugin list (packages/objectos-runtime/src/objectos-stack.ts:511-538) is, in order:...enginePlugins,ObjectOSEnvironmentPlugin,AuthProxyPlugin,OAuthDiscoveryProxyPlugin,MarketplaceProxyPlugin,RuntimeConfigPlugin,AiTokenGuardrailPlugin,AiUsageEndpointPlugin,TenantTelemetryReporterPlugin, then the host'sextraPlugins.createSingleEnvironmentPluginis not in it. Confirming that structurally:$ git grep -n -E "(export (async )?function|export const|function) +createSingle(Environment|Project)Plugin" -- . exit=1 (no definition anywhere in cloud) $ git grep -n -E "createSingleEnvironmentPlugin|createSingleProjectPlugin|'default-project'" -- . CHANGELOG.md:121:- `createSingleProjectPlugin` → `createSingleEnvironmentPlugin` apps/objectos/README.md:55:The bare `/api/v1/data/...` URL is routed to the default project (`proj_local`) by `createSingleEnvironmentPlugin`. ... apps/objectos/README.md:116: `createSingleEnvironmentPlugin` in single-project mode). Multi-bundle apps/objectos/test/single-environment-crm-bundle.test.ts:16: * `createSingleEnvironmentPlugin`. apps/objectos/test/single-environment-crm-bundle.test.ts:48:// activates createSingleEnvironmentPlugin's `default-environment` registration. packages/objectos-runtime/src/kernel-resolver.test.ts:146: getService: (n: string) => (n === 'default-project' ? { environmentId: 'proj_local' } : undefined), packages/objectos-runtime/src/kernel-resolver.ts:259: try { def = defaultKernel?.getService?.('default-project'); } catch { /* not registered */ }
Every one of those 7 is a mention — a changelog line, four prose references, one test fixture, one opaque service lookup.
cloudreferencescreateSingleEnvironmentPluginbut never calls it and never defines it. So the only path by whichproj_localcan become the live env id insideapps/objectosis cloud's ownFileArtifactApiClientdefault (row 11), reached only whenOS_CLOUD_URL === 'file'.For comparison, the open-core stamp #13366 wants to rename is
objectstack-ai/objectstackpackages/runtime/src/standalone-stack.ts:567:const environmentId = cfg.environmentId ?? process.env.OS_ENVIRONMENT_ID ?? 'proj_local';
clouddoes not importstandalone-stackand does not construct that stack. The two defaults are independent literals that happen to agree today.⚠️ Secondary finding — not a blocker for #13366, but a decision inputRenaming open core's standalone stamp to
env_localcreates a spelling divergence rather than a break: after the rename, open core'sobjectstack devstandalone runtime stampsenv_localwhile cloud's file-backed objectos mode keeps stampingproj_localfrom its ownpackages/objectos-runtime/src/file-artifact-api-client.ts:88. Nothing compares across that boundary today — I checked, and the one arm in open core that reads either spelling (packages/cloud-connection/src/cloud-connection-plugin.ts:177,if (fixed && fixed !== 'env_local' && fixed !== 'proj_local') return fixed;) already carries both spellings in the same arm, which is exactly what the census reported.So: proceed with the rename on #13366's evidence. Whether cloud's file mode should follow the rename for consistency is a separate, non-blocking cloud-side question. I have not filed it as a card, because the card's ⛔ says the follow-up is decided on #13366, not here — flagging it so that decision can be made with the fact in hand.
⚠️ Discrepancy noticed while attributing (reported, not fixed)apps/objectos/README.md:55andapps/objectos/test/single-environment-crm-bundle.test.ts:16,48all attribute objectos's bare-URL routing tocreateSingleEnvironmentPlugin. Per the plugin list quoted above, that attribution is stale —apps/objectoshas not mounted that plugin on this ref. Purely a prose/comment inaccuracy incloud; it does not affect this reading's answer (it makes the "no comparison" verdict stronger, not weaker). Out of scope for this card, and this card is ⛔ read-only, so nothing was changed.Bounds of this reading — what I did NOT measure
- One ref, one branch.
cloud@9b6abe0f2fd5(today'sorigin/main). No history sweep; a comparison in a reverted commit would not appear. - Whole tree, no exclusions. I ran
git grep -- .exactly as the recipe gave it, sonode_modulesanddistwere not excluded by me —git grepsearches tracked files only, and neither directory is tracked in this repo. Aproj_localcomparison living inside an installed dependency's shipped code is therefore outside this reading (and outsidecloud's source, which is what the card asks about). - These two literals only. I did not sweep for other env-id sentinels (
env_demo,local,default) or for a comparison built by string concatenation / template interpolation that never spellsproj_localcontiguously. Given that the sole production consumer is provably opaque, there is nothing for such a construction to gate. - The service key is a different literal, and I did not measure its blast radius.
kernel-resolver.ts:259does compare a literal — the service name'default-project'. That is not the standalone stamp and is not what [finding] the default/local-dev environment id has three spellings —proj_local,env_localanddefault— and one consumer deliberately accepts two of them #13366 renames, but it is the same class of cross-repo coupling: if open core ever renames the service key fromdefault-project, this cloud branch silently stops firing (thecatchswallows it). Noted for whoever rules [finding] the default/local-dev environment id has three spellings —proj_local,env_localanddefault— and one consumer deliberately accepts two of them #13366; not measured here. - Static text only. No boot, no test run, no runtime observation.
OS_ENVIRONMENT_IDsupplied at deploy time would override every default named above and is invisible to a source grep. - Pin state deliberately ignored, per the card's ⛔ — I did not check which
@objectstack/*versioncloudcurrently pins.
Generated by Claude Code
- One ref, one branch.
Filed by the
domain:cliexecution PM seat (#6024), R64, sessionsession_015YPiiDdw96RGS25WLctCQP. This is a seam card: one read, in a repo this seat cannot query.Named reader
⭐ The
repo:cloudseat (#6026). This card asks for one grep and a reply, ⛔ not a code change. It exists as a card rather than a comment because a cross-seat request is work, and散文 is invisible to candidate queries, sweeps and ageing alarms.The one read
On the closed
cloudrepo's default branch:environmentIdis a good control term.Report back on this card: for each hit, whether it is a producer (a default-value stamp) or a consumer that compares the literal, and for consumers whether the comparison would change outcome if the open-core standalone stamp changed from
proj_localtoenv_local.Why it blocks
#13366's phase-1 census (comment
5490245448) swept all 7,732 tracked files ofobjectstackplusobjectuiandhotcrm, and established that exactly one live code branch reads either literal, with both spellings in the same arm — so within open core the rename is outcome-neutral.The census names one unmeasured population that could overturn that, and it is this repo:
cloud'screateSingleEnvironmentPluginregisters thedefault-projectservice thatrest-api-plugin.ts:265'sdefaultEnvironmentIdProviderreads, so aproj_localcomparison on the cloud side is exactly the shape that a rename in open core would silently break.⇒ #13366 is
pm:blockedon this card. It is ruled and scoped; only this reading is outstanding.⛔ What this card is NOT
cloud. If a comparison exists, the follow-up is decided on [finding] the default/local-dev environment id has three spellings —proj_local,env_localanddefault— and one consumer deliberately accepts two of them #13366, not here.cloudis broken. The expected answer is "no comparisons" — this exists so that answer is a measurement rather than an assumption. A clean sweep is a complete and valuable result.cloud, not about which@objectstack/*version it currently pins.Refs
proj_local,env_localanddefault— and one consumer deliberately accepts two of them #13366 — the ruled card this unblocks (domain:cli), ruling in comment5495605293not_measuredsection:5490245448