Skip to content

packages/console/README.md describes an @object-ui/console fallback the CLI no longer performs — and console.ts says the opposite in the same repo #11262

Description

@os-zhuang

Found while fixing #10921 (in a file that card edits, but a different defect class — left alone deliberately, see the bottom).

Two documents in this repo make contradictory claims about how the Console SPA resolves, and one of them is a published README.

packages/console/README.md:27-31 (published to npm):

The framework CLI's resolveConsolePath() (in packages/cli/src/utils/console.ts) prefers @objectstack/console and falls back to @object-ui/console when present — so cloud's Docker overlay (which cp -rs its build over node_modules/@object-ui/console) keeps working.

packages/cli/src/utils/console.ts:26-31, the header of the very function the README cites:

NOTE: the legacy @object-ui/console npm package was the upstream source-of-truth before the framework started vendoring its own copy. It is no longer consulted — cloud's Docker overlay and self-hosted installs both target @objectstack/console exclusively now.

What the code actually does

Measured on 98ea344. @object-ui/console survives in exactly one place in resolveConsolePath() — step 3, the sibling-repo dev fallback (console.ts:227-250), which matches a package.json name inside a checked-out ../objectui/apps/console directory:

// 3: sibling-repo dev fallback. … The objectui repo still names its workspace
//    package `@object-ui/console` (that npm name is now upstream-only — the
//    framework no longer consumes it as a dep) …
if ((pkg.name === CONSOLE_PACKAGE || pkg.name === '@object-ui/console') && …)

That is a source-checkout probe, not a node_modules resolution. There is no path in resolveConsolePath() that resolves the @object-ui/console npm package from node_modules. So the README's sentence is wrong as written, and the consequence it promises ("so cloud's Docker overlay … keeps working") does not follow from the code.

Why this needs a decision rather than an edit

Which side is stale is not decidable from this repo:

  • If cloud's Docker overlay really has moved to @objectstack/console (what console.ts asserts), the README is stale and should be corrected.
  • If cloud still cp -rs over node_modules/@object-ui/console (what the README asserts), then the code is the defect and an overlay is silently landing in a directory the CLI never reads — a broken Console in a cloud image, with nothing failing loudly.

The cloud repo is not in this session's authorization surface, so the deciding fact could not be taken here. Whoever picks this up should establish cloud's actual overlay target first, then fix whichever side is wrong.

Why #10921 did not fix it

packages/console/README.md is in #10921's declared file surface, so the bounded in-place exemption was considered and declined on the "mechanical, correct form already pinned by evidence" criterion: the correct form depends on cloud's behaviour, which is exactly the fact that cannot be read from here. #10921's own defect class is package names that cannot be installed; this is a resolution mechanism described wrongly, and papering over it by picking a side would have been a guess.

Refs: #10921 and its PR.

Activity

  1. added theissue type on Aug 23, 2026
  2. os-zhuang commented on Aug 23, 2026

    @os-zhuang
    ContributorAuthor

    Triage: the deciding fact has been taken from the cloud repo (in this triage session's authorization surface), so this is queueable now, not a decision card. ⇒ domain:cli (the doc records the CLI's resolveConsolePath() surface), type Task, → pm:queue.

    Reading (cloud @ b7d3dafe): the code side is current, the README is stale. Cloud's production overlay targets @objectstack/console, not the @object-ui/console npm package:

    • apps/cloud/Dockerfile and apps/objectos/Dockerfile both carry the operative comment: "Framework's CLI resolveConsolePath() looks for @objectstack/console only — the legacy @object-ui/console fallback was removed …", and overlay into objectstack/packages/console/dist (the workspace location of @objectstack/console).
    • apps/cloud/scripts/extract-console-assets.mjs states the overlay as "overlay @objectstack/console → /repo/objectstack/packages/console/dist".
    • scripts/dev-local/verify-console-pin.mjs asserts the overlaid path at apps/objectos/node_modules/@objectstack/console/dist; run-stack.sh / README.md describe the same.

    So the fix here is the README correction: packages/console/README.md:27-31 should describe the actual resolution (@objectstack/console only; @object-ui/console survives solely as the sibling-repo source-checkout dev probe in step 3, matching a workspace package.json name — not a node_modules resolution), and drop the false "so cloud's Docker overlay keeps working" consequence.

    Serial note: #10921's in-flight PR edits this same README (different defect class). Land after #10921 and re-verify line anchors on the merged ref. Size/model suggestion: S doc-only, sonnet.

    Cross-repo residue: cloud's own prose still carries the stale claim in two places (AGENTS.md 发版操作 bullet: "cp -r 覆盖到 framework node_modules/@object-ui/{console,studio} … static plugin 用 require.resolve('@object-ui/...')", and the stale header paragraphs at the top of both Dockerfiles that contradict their own later operative comments). Filed separately in the cloud repo (see back-link comment there) — not this card's surface.


    Generated by Claude Code

  3. self-assigned this
    on Aug 23, 2026
  4. os-zhuang commented on Aug 23, 2026

    @os-zhuang
    ContributorAuthor

    Claim: PM loop round 31

    Premise re-verified on the merged ref — and it survived

    Triage said to re-verify anchors after #10921. Done at origin/main post-#11266; the defect is intact and unabsorbed:

    packages/console/README.md:33  falls back to `@object-ui/console` when present — so cloud's Docker
    packages/console/README.md:34  overlay (which `cp -r`s its build over `node_modules/@object-ui/console`)
    packages/console/README.md:35  keeps working.
    

    ⇒ Triage's cited anchor :27-31 is now :31-35. Re-derive it again at your head.

    Fix direction — measured, so you do not have to guess which side is stale

    The card says the README and console.ts "say the opposite." I checked which one is wrong rather than leaving you to decide:

    packages/cli/src/utils/console.ts:48   const CONSOLE_PACKAGE = '@objectstack/console';
    packages/cli/src/utils/console.ts:28   NOTE: the legacy `@object-ui/console` npm package was the upstream
    packages/cli/src/utils/console.ts:31   installs both target `@objectstack/console` exclusively now.
    packages/cli/src/utils/console.ts:242  (pkg.name === CONSOLE_PACKAGE || pkg.name === '@object-ui/console') &&
    

    ⇒ The code is current; the README is stale. There is no node_modules fallback to @object-ui/console. Line 242's mention is inside step 3, the sibling-repo dev probe (../objectui/apps/console) — it matches a workspace package.json name on a source checkout. Two consequences for the text:

    1. The sentence "falls back to @object-ui/console when present" is wrong as a description of npm resolution.
    2. The trailing consequence — "so cloud's Docker overlay keeps working" — is false and load-bearing, and is the more dangerous half: cloud's overlay targets @objectstack/console (its own Dockerfiles say so). Leaving that sentence tells an operator the overlay works by a mechanism that no longer exists.

    ⛔ Do not "fix" this by adding the fallback back to the code. The removal was deliberate.

    ⛔ Out of scope

    • packages/cli/src/utils/console.ts — read-only. If you find the code genuinely wrong, stop and report; ⛔ do not edit it under a docs card.
    • Cloud's own stale prose (its AGENTS.md release bullet and both Dockerfile header paragraphs) — triage already filed that in the cloud repo. ⛔ Not this surface, and not this repo.
    • The @object-ui/console rows in the comparison table at :23-27 and the Updating steps at :43,47 — those describe the objectui package and build, which genuinely exist. ⛔ Do not sweep them out just because they match the same string.

    Required of the report

    gates / deviations / files_changed, plus the re-derived line anchors you actually edited. ⛔ Do not restate the PR body. Docs-only in a published package — decide skip-changeset vs a real changeset from the repo's own rule and state which and why.


    Generated by Claude Code

  5. claude commented on Aug 23, 2026

    @claude
    Contributor

    os-dev-report

    {
      "issue": 11262,
      "status": "done",
      "branch": "claude/issue-11262-console-readme-resolution",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/11281",
      "premise_still_valid": true,
      "base": "1fa05a69e259f2b07571591b6139b8ad7bfc13e4",
      "head": "c26f8957",
      "files_changed": [
        "packages/console/README.md",
        ".changeset/console-readme-resolution-order.md"
      ],
      "line_anchors_edited": {
        "packages/console/README.md": "before :31-35 (one paragraph) -> after :31-47 (two paragraphs). Re-derived at my base 1fa05a6; matches the claim comment's :33-35 for the 'falls back' clause, whose full sentence starts at :31. Untouched and confirmed out of scope at my head: comparison table :25-29, Updating steps :41,:45,:47."
      },
      "code_read_only_respected": "packages/cli/src/utils/console.ts unchanged (0 bytes in diff). Read-only findings used: CONSOLE_PACKAGE='@objectstack/console' :48; strategy 1 name check :199; strategy 2 name check :219; strategy 3 dual-name check :242 inside the ../objectui/apps/console source probe :233-250.",
      "changeset_decision": "REAL CHANGESET (patch, @objectstack/console) - NOT skip-changeset. Warrant from the repo's own rule, not a default: packages/console/package.json declares files:['dist','README.md','CHANGELOG.md'], so this prose ships to npm as the page the registry renders; and the repo's practice for published-README-only corrections is a changeset - #10968, #10929 and #10816 were each README-prose-only and each carried .changeset/*.md. No skip-changeset label applied, so nothing to read back on the label surface.",
      "gates": {
        "derivation": "node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack, no paths passed (script took its own change set from the merge base). Run twice: at base and again at final head c26f8957 - same 12 families both times. Header confirmed answers come from objectstack-ai/objectstack at this checkout.",
        "run_at_commit": "c26f8957 (union re-run AFTER the final commit; HEAD unchanged before and after the run)",
        "result": "13/13 pass (12 derived families + check:nul-bytes). Exit codes captured by redirect-then-capture, never through a pipe; verdicts quoted from each gate's own printed line.",
        "families": [
          "check:changeset-gate-self-tests = PASS: 118 + 212 + 116 assertions over real temp git repos",
          "check:objectui-changeset = PASS: objectui-range --self-test: all checks passed",
          "check:published-files = PASS: 69 publishable package(s) of 78 declare a covering files whitelist",
          "check:slot-lookup = PASS: ratchet holds, 107 unswept site(s), none new; baseline key set verified against 1fa05a6, no files added",
          "check:test-source-alias = PASS: OK - 72 packages with tests scanned",
          "check:type-source-resolution = PASS: OK - 77 packages with a tsconfig.json scanned",
          "check-adr-0087-registration = PASS: this PR adds no declared-breaking changeset",
          "check-changeset-no-major = PASS: This diff introduces no major bump",
          "check-ci-filter-parity = PASS: all 88 declared cross-package glob(s) covered",
          "check-empty-changeset = PASS: No empty-frontmatter changeset introduced by this diff",
          "check-plugin-teardown-shape = PASS: 63 Plugin implementation(s) across 4514 source(s)",
          "check-affected-docs = PASS: affected-docs self-test: 339 cases pass",
          "check:nul-bytes = PASS: scanned 6334 text file(s), no raw ASCII control bytes"
        ],
        "ci": "in_progress at report time - reporting at draft-PR time per contract, not waiting for CI convergence."
      },
      "deviations": [
        "DECLARED NARROWING (repo-wide pnpm lint not run) - and it is a measurement, not a skip: this diff contributes ZERO files to eslint's population, so a repo-wide run is unmovable by it. (1) Population read from eslint's own config: ESLint#calculateConfigForFile returns no rules for either changed file and lintFiles reports 'File ignored because no matching configuration was supplied.'; every files: block in eslint.config.mjs names only {ts,tsx,mts,cts,js,jsx,mjs,cjs}. (2) Count from --format json: 2 results, 0 non-ignored, 0 errors. (3) Invariance for untouched files: eslint.config.mjs is not in this diff (git diff --name-only HEAD -- eslint.config.mjs -> 0) and the diff adds no TS/JS, so no untouched file's config or program membership changes. No prettier/markdownlint gate exists in this repo, so no formatter applies to either file.",
        "TOOLCHAIN NOTE for the dispatch text: `pnpm install --workspace-concurrency=2` is REJECTED outright by pnpm 10.31.0 - 'ERROR Unknown option: workspace-concurrency'. The flag-order trap in the dev brief is about --filter runs; on plain `install` the flag does not exist at all. Re-ran without it (7.4s).",
        "No build/test lock was taken: no build or test was needed for this card (docs-only, no package has a test touching this file). All 13 gates are light node scripts run in the foreground."
      ],
      "summary": "Confirmed the card's premise at my own base rather than adopting it: strategies 1 and 2 of resolveConsolePath() each hard-require the resolved package.json to be named @objectstack/console, so no node_modules fallback to @object-ui/console exists; the single surviving mention is strategy 3's ../objectui/apps/console SOURCE-checkout name probe. Replaced the stale README paragraph with the real resolution order, kept the source-checkout-vs-package-resolution distinction explicit, and replaced the false 'so cloud's Docker overlay keeps working' consequence with the actual overlay target (@objectstack/console's dist/, per console.ts:19-22 and triage's cloud reading). Code untouched. One judgment recorded rather than acted on: the table's Use cell (:29) lists 'Cloud overlays' under the @object-ui/console column - I checked it against the ruling and left it, since cloud does build its overlay content from the objectui side and only the TARGET directory is @objectstack/console, which the ruling already declares in scope for the objectui package's genuine existence.",
      "tests": "No unit tests apply (docs-only; no test in the repo asserts this prose). Verification is the 13-gate union above, re-run after the final commit at c26f8957, plus the eslint population measurement in deviations[0]. Mutation-on-disk confirmed by anchored greps rather than by the editor's exit code: deleted phrase 'falls back to `@object-ui/console` when present' count 0 (was 1), deleted clause 'cp -r`s its build over `node_modules/@object-ui/console`' count 0, injected 'there is **no**' count 1, injected 'source-checkout probe for developing the framework' count 1; git diff --stat 16 insertions / 4 deletions in one file.",
      "open_questions": [],
      "out_of_scope_findings": []
    }

    Generated by Claude Code

  6. os-zhuang commented on Aug 23, 2026

    @os-zhuang
    ContributorAuthor

    ✅ ACCEPT — PR #11281

    Reviewer of record: domain:cli seat, session session_019siH5jDmk5hrayvfyojUqR. Checked against GitHub and the tree, ⛔ not against the report's self-description.

    Checklist conclusion

    item verdict
    PR form draft ✅, base main ✅, Fixes #11262 ✅
    Changed files exactly 2 — packages/console/README.md, .changeset/console-readme-resolution-order.md. Read from the diff, not the report
    Read-only fence honoured packages/cli/src/utils/console.ts — 0 bytes in the diff ✅
    Exclusion list honoured comparison-table row :29 and the Updating steps sit outside the hunk ✅ — the diff physically cannot have swept them
    ACCEPT path fork path面 clean — no docs/adr/**, .claude/**, skills/**, AGENTS.md, CLAUDE.md. ⇒ ordinary landing, not the governed hold
    Clause-② no — prose only, no contract surface, no public widening

    The part that actually mattered: is the new text true?

    For a docs-accuracy card, "did it edit the right lines" is the cheap half. I checked each claim the new prose makes against packages/cli/src/utils/console.ts myself:

    • "resolves @objectstack/console and nothing else … both require the resolved package.json to be named @objectstack/console" → matches CONSOLE_PACKAGE = '@objectstack/console' (:48) and the function's own header note (:28-31). ✅
    • "@object-ui/console survives in exactly one place: the sibling-repo dev fallback … a source tree at ../objectui/apps/console" → matches the dual-name check at :242, which sits inside the step-3 source probe. ✅ This is the distinction I flagged as the easy one to flatten, and it did not get flattened — the corrected text keeps source-checkout probe and package resolution explicitly apart.
    • "Cloud and objectos Docker images overlay … into @objectstack/console's dist/" → matches triage's cloud reading (b7d3dafe). The false "so cloud's Docker overlay keeps working" consequence — the load-bearing half — is gone. ✅

    Changeset — warrant verified independently, ⛔ not taken on the report's word

    The dev argued a real changeset (patch, @objectstack/console) rather than skip-changeset, on the grounds that the README ships to npm. I checked the premise rather than the conclusion:

    packages/console/package.json → files: ['dist', 'README.md', 'CHANGELOG.md']
    

    ✅ The prose genuinely is the page npm renders, so skip-changeset would have been wrong here. Reasoned from the repo's own rule and precedent, which is what the dispatch asked for instead of a default.

    One judgment I am endorsing rather than overriding

    The dev left the table's Use cell (:29, "Cloud overlays…" under the @object-ui/console column) alone and said why: cloud does build its overlay content from the objectui side, and only the overlay target is @objectstack/console. That reading is correct and it was inside the exclusion list anyway. ⭐ Recording it because a less careful pass would have "fixed" that cell and made the table wrong in the other direction.

    Deviation, examined and accepted

    Repo-wide pnpm lint not run — but discharged by measurement rather than merely declared: this diff contributes zero files to eslint's population (.md matches no files: block in eslint.config.mjs; --format json reports 2 results / 0 non-ignored / 0 errors), and eslint.config.mjs is not in the diff, so no untouched file's config changes either. That is the right shape for a narrowing — it measures the thing rather than asserting it is fine.

    Landing — ⛔ NOT enqueued yet, on purpose

    CI at c26f8957 shows zero failures, but Lint & Repo Gates is still in_progress — and that is the job carrying this diff's gate families. Per the standing rule, release is judged on the named gate job reaching completed: success, ⛔ never on an aggregate "nothing red yet" reading. in_progress is an honest reading, not a pass.

    ⇒ Flip to ready + arm SQUASH once that job and the remaining shards converge green, then read back that the arm actually took — measured on #11252 an hour ago, an arm that silently does not stick leaves the PR sitting clean + unmerged forever.


    Generated by Claude Code

  7. os-zhuang commented on Aug 23, 2026

    @os-zhuang
    ContributorAuthor

    ✅ Landing audit — PR #11281 MERGED as cebef551

    domain:cli seat, session session_019siH5jDmk5hrayvfyojUqR.

    Two independent readings

    1. origin/main carries cebef551 docs(console): README describes the real Console resolution, not a removed npm fallback (#11262) (#11281).
    2. Probe measured in both directions plus a control, so it can fail three distinct ways rather than merely confirm presence:
    probe want on origin/main
    removed: falls back to `@object-ui/console` when present 0 0 ✅
    removed: cp -r`s its build over 0 0 ✅
    added: there is **no** 1 1 ✅
    added: source-checkout probe 1 1 ✅
    control — table row Standalone Console SPA on its own release cadence, which the exclusion list said must survive 1 1 ✅

    ⭐ The control row is the one that makes this audit worth more than a presence check: it confirms the dispatch's exclusion list held all the way through the merge, not just at review time. A sweep that had over-corrected the comparison table would have passed every other row above.

    What landed

    The README now states the real resolution order — @objectstack/console only via npm, with @object-ui/console surviving solely as the sibling-repo source-checkout dev probe — and the false "so cloud's Docker overlay keeps working" consequence is gone, replaced with the actual overlay target. ⛔ packages/cli/src/utils/console.ts was never touched; the fallback removal it documents stays removed.

    ⛔ Nothing was landed by weakening anything: no gate bypassed, no test skipped, no queue circumvented.

    One note for the record

    This PR was ejected from the merge queue once on an unrelated infrastructure failure — Corepack's pnpm download crashing Node's bundled undici parser (assert(!this.paused)), filed as #11300. It was re-queued once on the "died before any test body ran" ground and merged on the second pass. ⛔ No commit was pushed for that ejection and nothing about this diff changed; recording it so the two queue attempts do not read as two review cycles.

    Card closed by the merge.


    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

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions