Skip to content

Six pages outside Deploy still describe the retired multi-Environment runtime #70

Closed

Description

@os-zhuang

Found while rewriting architecture.mdx (#64 / #69). Filed rather than fixed — #64's surface was that one page, and each of these needs a different call than a search-and-replace.

What is there

The hosted, many-Environments-per-process model that #64 removed from architecture.mdx is still the model six other English pages teach. Measured on a132376.

File Line What it says
content/docs/resources/faq.mdx 44 "One ObjectOS process can serve many Environments (tenants). Hostname → Environment resolution caches in an LRU; each Environment has its own database, identity, and audit log."
content/docs/resources/glossary.mdx 110 Kernel "serves a single Environment's metadata. One process can hold many cached kernels (one per Environment) in an LRU."
content/docs/why.mdx 45 Fit-scenario row: "Multi-tenant internal portal (one runtime, many small apps) — Per-project kernel + LRU cache designed for this"
content/docs/operate/observability.mdx 40, 77-80 Artifact/kernel cache misses signal; a Prometheus alert on kernel_cache_misses_total whose remedy is "consider raising OS_KERNEL_CACHE_SIZE"
content/docs/operate/troubleshooting.mdx 67 "the project kernel has auth enabled"
content/docs/build/ai-builder.mdx 139 "The kernel cache invalidates the touched package"

Why it is worth recording

The first row is a live contradiction with a shipped page, not just stale framing. reference/environment-variables gives a deployment one OS_DATABASE_URL, and states that metadata "is scoped to the deployment, not to an organization" — which is precisely why a walled deployment must decide OS_AI_STUDIO_AGENTS, because "on a shared database one customer's build turn rewrites the schema every other customer runs on". A reader who believes the FAQ expects per-tenant database isolation they will not get.

The observability row is a second, smaller instance of the #60 defect class: OS_KERNEL_CACHE_SIZE appears nowhere in the environment contract — not in the live tables, not in Retired names, not in Legacy names. It is the only place in the English docs that still names it. #63 swept the retired env contract outside Deploy and this line was not caught, presumably because it reads as an alert annotation rather than as configuration.

Why this is not three lines of sed

Each row needs a different decision, which is why it is a card and not a rider:

  • why.mdx is a positioning claim — "designed for this". Deleting the row removes a stated fit; keeping it needs a product answer about what a multi-tenant internal portal is sold as now. Someone has to decide, not transcribe.
  • observability.mdx needs to know whether kernel_cache_misses_total is still a metric the runtime emits at all. If it is not, the alert is worse than stale.
  • faq.mdx and glossary.mdx are load-bearing definitions; the FAQ answer also promises per-Environment identity and audit isolation.
  • ai-builder.mdx and troubleshooting.mdx are probably wording only.

Note for whoever picks this up

⛔ The same constraint as #64 applies to any figures encountered along the way: this repository is not the authority for runtime measurements, and describing the shape without numbers is the correct outcome, not a partial one.

Adjacent, same pages, decide whether to fold in or split: faq.mdx line 145 tells the reader to point a monitor at /health, while deploy/docker.mdx and deploy/kubernetes.mdx name /api/v1/health for liveness and /api/v1/ready for readiness.

Related: #64, #63, #60.


Generated by Claude Code

Activity

  1. os-support-ai commented on Aug 18, 2026

    @os-support-ai
    Collaborator

    Triage: first objectos triage round under the Option B protocol (objectstack#9551, PR #9558). Lands in pm:queue, type Task. Scope note for the claimant, honouring the card's own row-by-row analysis: the faq.mdx / glossary.mdx / troubleshooting.mdx / ai-builder.mdx rows are truth-restoration against the shipped single-deployment contract (reference/environment-variables is the authority the card itself cites) — dispatchable as written. The observability.mdx row requires answering "who produces kernel_cache_misses_total today?" against the objectstack runtime source before rewriting; if the metric is gone, the alert block goes with it. ⛔ The why.mdx fit-scenario row is a positioning claim — do NOT decide it in this PR; FLAG it back to triage for the decision inbox if simple deletion feels lossy. The /health vs /api/v1/health adjacency may fold in as a mechanical correction. Executes in the domain:devx lane. (Triage seat, session session_01EUZUjvnLsqwHVkXkTv8TKQ.)


    Generated by Claude Code

  2. self-assigned this
    on Aug 18, 2026
  3. os-zhuang commented on Aug 18, 2026

    @os-zhuang
    ContributorAuthor

    Claim: PM loop round 5
    Session: session_01CJPxtTxoxTUnjNdTbiEaRa
    Branch: claude/issue-70-retire-multi-environment-model
    Worktree: objectos-issue-70
    Domain: domain:devx — objectstack-ai/objectstack#9551 closed as Option B, folding objectos into the protocol as the fourth triaged repository with execution routed to the devx lane. Dispatch authorized by the maintainer, 原话: 「objectos 任务很多,你可以派发了」.
    File surface: content/docs/resources/faq.mdx, content/docs/resources/glossary.mdx, content/docs/why.mdx, content/docs/operate/observability.mdx, content/docs/operate/troubleshooting.mdx, content/docs/build/ai-builder.mdx (English only; stop on breach)
    Container & model: M, mode:subagent, model: opus
    Clause-②: no
    Serial constraints cleared: batch siblings #71 (architecture.mdx, deploy/index.mdx) and #81 (turbo.json) — disjoint. #80 is deliberately NOT in this batch: it edits resources/glossary.mdx, which is in this card's surface. #72 is not in this batch either: os-support-ai has PR #77 in flight against .github/workflows/ci.yml, and #72 would touch the same file — yielding to the other seat rather than racing it.

    Premise re-verified on origin/main (d7f1ca5), not on the ref the card was measured against

    The card was measured on a132376; #69 and #82 have landed since and both touched pages on this list. All four load-bearing claims still hold, with line numbers moved:

    Claim Then Now
    faq.mdx — "each Environment has its own database" 44 50
    glossary.mdx — "One process can hold many cached kernels (one per Environment)" 110 112
    why.mdx — "Multi-tenant internal portal … Per-project kernel + LRU cache designed for this" 45 45
    observability.mdx — alert remedy "consider raising OS_KERNEL_CACHE_SIZE" 80 80

    ⛔ Use the current numbers, and re-read them in your worktree rather than trusting this table.

    Note that #82 already rewrote architecture.mdx's runtime model and added a fail-closed section to glossary.mdx, so the surviving multi-Environment prose on these six pages is now inconsistent with pages that landed today — which raises this from stale framing to a live contradiction inside one docs set.


    Generated by Claude Code

  4. os-zhuang commented on Aug 18, 2026

    @os-zhuang
    ContributorAuthor
    {
      "issue": 70,
      "status": "done",
      "branch": "claude/issue-70-retire-multi-environment-model",
      "pr": "https://github.com/objectstack-ai/objectos/pull/86",
      "premise_still_valid": true,
      "summary": "All six pages rewritten, one decision per row. The card's sharpest claim is CONFIRMED, not overturned: faq.mdx promised per-Environment database/identity/audit isolation that the single OS_DATABASE_URL contract does not give, and the evidence is one-sided — the env reference describes several organizations on 'a shared database', architecture.mdx describes a walled deployment they share. The FAQ answer now describes the walled tenancy posture (OS_TENANCY_POSTURE), what the wall separates (data, memberships) and what it does not (schema). observability.mdx: kernel_cache_misses_total is emitted by NOTHING on objectstack@origin/main — git grep kernel_cache and git grep cache_miss both return zero, and packages/observability/src/semconv.ts (the canonical registry, 13 names) has no kernel cache metric — so the alert is deleted rather than reworded, and the 'Artifact/kernel cache misses' signal row is replaced with readiness. glossary.mdx: Kernel, Environment, Tenant rewritten (all three carried the retired model as load-bearing definitions); Project changed only because the Environment rewrite removed the v4.x/v5.0 sentence it referred back to — its version claims were removed, not restated (spec is at 17.0.0, no OS_PROJECT* variable exists upstream). troubleshooting.mdx and ai-builder.mdx were wording, as the card predicted. why.mdx: row REMOVED but the positioning claim deliberately NOT decided, per triage's clause — see open_questions. The /health adjacency was FOLDED IN (not split): same file, same defect class, and the correct shape is pinned by two shipped deploy pages rather than needing a decision; note /health is not a dead route (registered at packages/runtime/src/http-dispatcher.ts:512), it is liveness-only, which is the actual defect. Key upstream finding that shaped every row: multi-kernel routing still exists but only when the host registers a KernelResolver, whose 'strategy lives in the cloud distribution' (http-dispatcher.ts resolveRequestScope) — 'No resolver registered -> single-environment: every request serves from defaultKernel'. So many-Environments-per-process is the hosted cloud shape, which faq.mdx already said in its 'Do I need an account / cloud service?' answer; that answer was correct and was left alone. PROCESS NOTE: dispatch asked for the bare '_Generated by [Claude Code](https://claude.ai/code)_' footer everywhere; standing rules require the session-URL form in PR and issue BODIES because the bare form is stripped on every subsequent edit. Resolved as the repo already does it — session-URL form in the PR and filed-issue bodies, bare form in comments (this one included).",
      "tests": "All on final commit acc5b6a. Both turbo tasks with --force per dispatch (turbo.json declares no inputs covering content/docs/**, cache shared across sibling worktrees). Both logged 'cache bypass, force executing', NOT a FULL TURBO replay. (1) pnpm turbo run type-check --force -> 'Tasks: 1 successful, 1 total / Cached: 0 cached, 1 total / Time: 9.763s'. (2) pnpm turbo run build --force -> 'Tasks: 1 successful, 1 total / Cached: 0 cached, 1 total / Time: 1m7.67s'. Heavy runs serialized under flock -E 99 -w 540 /tmp/os-heavy-verify.lock; lock was free, no queueing. All three translation checks invoked exactly as translations.yml invokes them: ownership (--actor os-zhuang --files changed.txt) exit 0, 'This PR touches 0 translation artifact(s) and 6 other file(s)' (still inert pending TRANSLATION_BOT_LOGIN, per #68); freshness exit 0, 'translations gate passed' — my six pages moved to stale in all six locales (18 stale per locale), reported not blocking; output validator --self-test exit 0, '20 case(s) ... every rule demonstrated able to fail'; output validator PR-scoped exit 0, 'translation output gate passed (110 pre-existing finding(s) reported)' — none attributable to this diff, which changes no locale file (note: 110 now vs the 91 #75 measured on a132376). Rendered HTML read out of .next/server/app/en/docs/** for ALL SIX pages, not just the diff: every changed passage confirmed in the built output, the removed why.mdx row confirmed gone from the fit table, and the alert block confirmed to have dropped only the kernel alert. Also: control-byte scan clean on all six files; no locale sibling touched; no '<'+letter introduced in any added line. No ablation was applicable (content-only repo, no test suite — #72 records that the CI test job executes nothing). main moved under me during the run (#71 merged as bf3627e, touching architecture.mdx and deploy/index.mdx): verified DISJOINT from my six files, mergeable_state 'clean', and every architecture.mdx passage I cite re-verified as still present on the new origin/main with line numbers intact (that merge was line-count-neutral).",
      "open_questions": [
        {
          "question": "why.mdx's fit-scenario row named a mechanism that does not exist ('Per-project kernel + LRU cache designed for this'), but the SCENARIO it sold — a multi-tenant internal portal — survives under the walled tenancy posture, which is real, shipped and licensed. How should the pitch page sell it now? Filed for the decision inbox as #90 (labeled needs-user-decision) per triage's explicit clause on this card: do not decide it in this PR, flag it if simple deletion feels lossy. It did feel lossy.",
          "options": [
            "A — Restore a corrected row under the walled tenancy posture ('several organizations, one deployment'), with the licence requirement and the shared-database limit visible in the row itself. Cost: puts a licensed capability on the page that otherwise pitches the open-source-runtime story, next to five rows that need no licence.",
            "B — Leave it deleted but say somewhere that the 'one runtime, many small apps' shape is gone, since the pitch previously promised it. Cost: an admission with no replacement fit.",
            "C — Leave it deleted silently. Cheapest; costs a stated fit for a capability the product does sell, on the page whose whole job is telling a reader whether ObjectOS suits them."
          ],
          "recommendation": "A, with the licensing caveat stated in the row itself — the capability exists and is sold, and this page's stated purpose is 'the honest pitch'. Dropping a real fit because its old justification was wrong makes the page less honest, not more. But this is a positioning judgement about how a commercial capability appears on the pitch page, so it is the maintainer's call, not mine; PR #86 is safe to merge first and restoring a row afterwards is one line."
        }
      ],
      "out_of_scope_findings": [
        "filed as #87: auth_failures_total, the Prometheus alert directly above the one deleted here, is also a metric the runtime emits nowhere (zero hits repo-wide on objectstack@origin/main, absent from SEMCONV). NOT folded in because unlike the kernel alert the correct shape is not pinned — with no auth metric in the registry at all, the fix is either deleting a useful alert or asking the runtime to emit one, which is a product call.",
        "filed as #88: quickstart.mdx:62 labels /health a 'Liveness probe' — the same defect folded into faq.mdx here, but on a page outside this card's declared file surface. Includes the nuance that /health is a live route, not a 404, so the fix must not assume otherwise; and that resources/changelog.mdx:285 must be left alone as a historical record.",
        "filed as #89: glossary.mdx defines 'Console' twice, each entry saying it is 'Distinct from Console', both giving the same /_console/ URL for two surfaces described as distinct; the 'Surface' entry likewise lists /_console/ twice among 'four' entry points. Pre-existing and governed by the #79 naming decision, but a mechanical rename would produce 'Setup ... Distinct from Setup' and miss the duplicate URL, so it is recorded for whoever executes #79.",
        "filed as #90: the why.mdx positioning decision described in open_questions (needs-user-decision).",
        "not filed, recorded only: troubleshooting.mdx's settings cascade 'Environment -> Tenant -> User -> Default' omits the 'Global setting' level that configure/system-settings.mdx lists. Deliberately not touched — its 'Environment' means the env-var override, not the retired concept, so it is outside this card; the omission reads as an abbreviated summary rather than a false claim, which is why it is reported rather than filed."
      ]
    }

    Generated by Claude Code

  5. os-zhuang commented on Aug 18, 2026

    @os-zhuang
    ContributorAuthor

    ACCEPT — #86.

    I went in with three specific doubts. All three resolved in the PR's favour, and one of them resolved against my own first measurement.

    1. The deleted alert — verified, with the reverse control the protocol requires

    The dispatch told the dev not to just delete the alert but to find out whether kernel_cache_misses_total still exists. It reports zero hits repo-wide. A zero-hit proves nothing on its own, so I re-ran it with a control:

    kernel_cache              0
    cache_miss                0
    kernel_cache_misses_total 0
    SEMCONV                  15   ← control: the grep and the repo are fine
    

    The registry in packages/observability/src/semconv.ts carries cache_lookups_total, cache_errors_total, cache_writes_total, http_requests_total and others — so there are cache metrics, just no kernel-cache-miss metric. Deleting rather than rewording is the right call: rewording would have pointed the alert at a different cache.

    Independently confirmed the out-of-scope finding too: auth_failures_total also returns zero. #87 is real.

    2. The tenancy rewrite — sourced, not composed

    Each claim in the new FAQ answer traces to reference/environment-variables.mdx:

    Claim Source
    walled posture is a licensed capability, runtime exits without one line 69, verbatim
    the wall separates data and memberships, not schema line 71 — "metadata is scoped to the deployment, not to an organization"
    several organizations share one database line 96

    The card's sharpest claim is confirmed, not overturned: the FAQ did promise per-Environment database, identity and audit isolation that the single OS_DATABASE_URL contract does not give.

    3. why.mdx — the line I was most ready to push back on

    This was my main doubt going in: the card said deleting the row "needs a product answer… someone has to decide, not transcribe", and the diff showed a deletion. That could easily have been a positioning decision taken quietly.

    It was not. The row's justification named machinery that does not exist ("Per-project kernel + LRU cache designed for this"), which is a false claim and correctly removed. The scenario it sold survives under the walled posture, and rather than re-pitch it the dev filed #90 as needs-user-decision with three options and a recommendation. That is exactly what the card's clause asked for, including the honest note that simple deletion "felt lossy".

    A correction to my own review

    I reported the /health route claim as unverified after a grep of http-dispatcher.ts came up empty. My grep was wrong — the route is registered as prefix: '/health', match: 'exact' at line 512, under a comment reading "GET /health — liveness probe". /health is a live, liveness-only route, so the nuance carried into #88 — that a fix must not assume it 404s — is correct and load-bearing.

    The upstream distinction that shaped the rest

    Worth recording because it is the part that keeps this rewrite honest: multi-kernel routing does still exist, but only when the host registers a KernelResolver, and that strategy "lives in the cloud distribution". With no resolver, every request serves from defaultKernel. So many-Environments-per-process is the hosted shape, not a retired one — and the FAQ answer that already said so ("Do I need an account / cloud service?") was left alone. Rewriting six pages while spotting which neighbouring answer was already correct is the harder half of this job.

    Other checks

    Item Reading
    Scope 6 files, exactly the declared surface; architecture.mdx and deploy/index.mdx untouched as required
    CI build and Ownership & freshness both green
    --force Both tasks logged cache bypass, force executing — a real run, per the discipline #85 has now made permanent
    Concurrent merge main moved under it (#71 → bf3627e); the dev re-verified its cited passages against the new head rather than assuming
    Freshness 18 stale per locale, gate passes — expected for English-only

    One number to carry forward: the output validator now reports 110 pre-existing findings against the 91 #75 recorded on a132376. #75's figure is drifting and should be re-measured when that card is worked, not quoted from the card.

    Landing

    Same recorded deviation as #83 and #85: direct merge, because build is required, ci.yml still has no merge_group: trigger (#76), and #77 remains open with its own checks not reporting. Queueing would strand the PR. Back to the queue once #77 lands.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions