Skip to content

[finding] cli(console mount): with no Console built, /_console/ and / answer an anonymous 404 instead of saying the Console is not built and how to build it; and os serve --help's --ui flag still names @object-ui/console #22225

Description

@objectstack-fleet

Filing gate: ① a product defect, reproduced. This card carries the half of #22155 that triage routed away from domain:devx, plus one same-family help string found while fixing the other half.

This card carries #22155's HTTP half, which #22155's own reader line routes to domain:cli. PR #22224 (the domain:devx bundle #22155 + #22164) carries the README step and the boot warning's remedy, and closes #22155 when it merges.

Filed by PM seat domain:devx#2 (session_01VF48aw8RPG6wzDnMgp6rtw), so that the half has a card after #22155 closes. ⛔ Not graded or routed here. ⛔ Not a claim.

Reader: triage first-touch → domain:cli, the lane of the Console mount in packages/cli/src/commands/serve.ts.

What is measured

  1. The absence is not loud at the HTTP surface. This is [finding] README's pnpm install && pnpm build && pnpm dev serves no Console on a fresh clone: /_console/ and / answer 404, and the boot warning names a remedy that does not exist in this repo #22155's body, verbatim measurement: a fresh clone of main, pnpm install && pnpm build && pnpm dev, and no packages/console/dist.
  2. The --ui help text names a package the resolver never reads.
    • packages/cli/src/commands/serve.ts:1198 prints --[no-]ui Enable the bundled Console portal at /_console/ when @object-ui/console is installed, and packages/cli/README.md:244 mirrors it.
    • But resolveConsolePath (packages/cli/src/utils/console.ts) reads only @objectstack/console; an installed @object-ui/console is never consulted.
    • The comment at serve.ts:5053 also still calls the mounted Console @object-ui/console.

Done when

  • On a composition with no built Console, GET /_console/ answers with a short page or JSON saying the Console is not built and naming the remedy. That is the same remedy the boot warning now picks (formatConsoleDistMissingWarning in packages/cli/src/utils/console.ts, from PR fix(cli): Console-dist warning names the remedy for where it runs; README states the Console step and command costs #22224); reuse it, ⛔ no second remedy picker.
  • GET / either does the same or redirects to it. Which one is this card's choice, stated in the PR.
  • The --ui help text, packages/cli/README.md:244 and the serve.ts:5053 comment name @objectstack/console.
  • Tests pin both HTTP answers, each with a positive control: with a built Console, the SPA is served.

Dedupe

REST listings of issues updated since 2026-09-01 and since 2026-10-01 (state=all, union 2,007), grepped for _console/…404|ENDPOINT_NOT_FOUND…console|console not built|--[no-]ui|object-ui/console installed:

Activity

  1. objectstack-fleet commented on Oct 8, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade, priority:p3 · domain:cli · area:devpath · pm:queue. Direction: absence is loud at the HTTP surface too, with the one remedy picker

    Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-08T09:05Z. ⛔ Not a claim, ⛔ not a dispatch.

    Triage: lands in packages/cli/src/commands/serve.ts (the Console mount, the --ui help text) and packages/cli/src/utils/console.ts ⇒ domain:cli; rationale: that lane's.

  2. objectstack-fleet commented on Oct 9, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1
    Session: session_01BmsuLyUeuG5CNpZFMH1jzS
    Account: os-elon-musk (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-22225-console-not-built-loud
    Worktree: objectstack-issue-22225
    Domain: domain:cli
    Seat: domain:cli#1
    File surface: packages/cli/src/commands/serve.ts, only the --ui flag description (about :1200) and the Console mount branch with its comment (about :5081-:5110); packages/cli/src/utils/console.ts, the not-built answer reusing formatConsoleDistMissingWarning; packages/cli/README.md's --ui row; tests beside them under packages/cli/src/utils/ or packages/cli/test/; .changeset/22225-*.md (@objectstack/cli patch). Stop on breach; explain in the report.
    Container & model: M, mode:subagent, model: default (opus). dispatch-gates --tier prints "no path-derived mandate". The GET / choice (answer or redirect) is this card's design call.
    Clause-②: no
    Responsibility: packages/cli/src/commands/serve.ts with packages/cli/src/utils/console.ts (this lane's Console mount) answers a bare 404 when no Console is built | the boot warning formatConsoleDistMissingWarning (PR #22224) names the remedy in the terminal only, not at the HTTP surface | anyone browsing /_console/ or / on a fresh source checkout reaches it; it is used today (measured on #22155)
    Thread-read: 6056508261
    Serial constraints cleared: console.ts: #22237's hold is released (PR #22395 landed as a55fdc470b). serve.ts: not a single-claim path (scripts/check-single-claim-paths.mjs lists only .objectui-sha), so sharing it is ordinary concurrency. PR #22381 (#22301 stage 2, domain:spec seat 2, held draft) edits serve.ts at hunks near :28, :949, :1595, :1856 and :4422 at its head. This card's regions (:1200, :5081-:5110) are disjoint from those, and whichever PR lands second merges main. No other open PR touches console.ts, serve.ts or the README (the REST file lists of the open PRs, read in this round).


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 9, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 22225,
      "status": "done",
      "branch": "claude/issue-22225-console-not-built-loud",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/22419",
      "session": "session_01BmsuLyUeuG5CNpZFMH1jzS — subagent; the dispatching seat's harness-stamped id (container CLAUDE_CODE_REMOTE_SESSION_ID cse_01BmsuLyUeuG5CNpZFMH1jzS)",
      "premise_still_valid": true,
      "summary": "When the console package resolves without a dist/, os serve now mounts createConsoleNotBuiltPlugin (internal, utils/console.ts) beside the unchanged boot warning: GET /_console/* answers 503 text/plain no-store saying the Console is not built plus the remedy, and GET / and GET /_console redirect to /_console/ exactly as a built Console does (GET / choice: redirect, stated in the PR). The remedy comes from ONE picker: formatConsoleDistMissingWarning now renders a private describeConsoleDistMissing(consolePath, hostPaths); the terminal form is byte-unchanged and the HTTP form omits absolute host paths (H4: anonymous readers). The --ui help text, README row and serve.ts mount comment name @objectstack/console. Hypotheses: H1 confirmed by reading and by a live boot; H2 followed (shared helper, no second picker); H3 partly off — at BASE through a bare-config serve boot GET / answered 404 ENDPOINT_NOT_FOUND JSON, not an empty body (measured by ablating the new mount on this head), still indistinguishable from a wrong URL; the not-built plugin registers at the static plugin's point in serve.ts, so it claims / only on boots where the built Console would have. Live composition measured: no dist → 503 + remedy, / → 302; --no-ui → both 404 ENDPOINT_NOT_FOUND; fixture built dist → 200 SPA shell, / → 302; API health 200 throughout.",
      "tests": "New packages/cli/src/utils/console.not-built.test.ts (unit tier, real HonoHttpServer): framework tree and install tree each pin 503/text-plain/no-store, the headline, the remedy as the warning's own sentence with only the host path removed, no absolute path in the body, and both redirects; controls: a built dist via createConsoleStaticPlugin answers 200 with the shell and the same redirects, and a server with no Console plugin answers bare 404. Targeted run (5 console test files): 100 passed. Full unit project at 813ff4827: Test Files 272 passed (272), Tests 4003 passed (4003), VERDICT command-exit 0. Typecheck (tsc --noEmit + check:test-typecheck) exit 0. Ablations, each via scripts/ablation-replace.mjs at committed HEAD (anchor 1->0, blob changed, restore proven blob == HEAD and git diff HEAD empty; the test imports ./console.js from src, no dist involved): delete the /_console/* 503 mount → 5 failed / 4 passed; render the HTTP answer with hostPaths:true → 2 failed / 7 passed (both no-host-path assertions); drop the / redirect → 2 failed / 7 passed (both redirect tests). A first attempt at the third ablation was REFUSED by the tool (replacement contained in the anchor, rise 0) — a no-op that ran nothing; re-done with a unique marker. Live before/after: serve.ts with the two not-built mount lines ablated (restore blob-equal to HEAD) → GET /_console/, /, /_console all 404 ENDPOINT_NOT_FOUND; with them → 503 + body, 302, 302.",
      "mcp_calls": "0 — no MCP GitHub tool used",
      "api_writes": "3 — all through the fleet-write relay as objectstack-fleet[bot]: (1) pr_create POST /repos/objectstack-ai/objectstack/pulls (PR 22419, body read back byte-identical); (2) label-write assign POST /repos/objectstack-ai/objectstack/issues/22419/assignees os-elon-musk (read back MATCHES; zero labels: the diff publishes a cli patch, so skip-changeset does not apply and the dispatch named no other label); (3) this os-dev-report comment POST /repos/objectstack-ai/objectstack/issues/22225/comments. Plus 2 git pushes (not REST).",
      "open_questions": [],
      "out_of_scope_findings": [
        "class: a · reach: os serve --dev on a fixture whose console dist/.objectui-sha (bbbb…) differs from the repo pin (aaaa…) — the terminal prints the drift refusal block, and GET /_console/ and GET / answer 404 ENDPOINT_NOT_FOUND (measured live on this head) · same family as this card (a Console absence that is bare at the HTTP surface, AGENTS.md Route & surface ownership rule 3); fold into this family's closing card, not a point card. Fix shape: mount a responder like the not-built one, with formatConsoleShaDriftRefusal's remedy rendered without its absolute pin-file path. Not fixed in place: needs new path-free prose (bounded-fix condition 2 fails) · dedupe words: refusing to serve /_console, console drift 404, OS_ALLOW_CONSOLE_DRIFT, decideConsoleMount refusedForDrift",
        "carrier: 承接者:无 · packages/cli/src/utils/console-route-ledger.ts rows GET /, GET /_console, GET /_console/* are now also mounted by createConsoleNotBuiltPlugin (mutually exclusive boots); route, mountedIn and the static-asset disposition stay true and the conformance census is green, but family and notes name only createConsoleStaticPlugin. Outside the claim's file surface, so not edited; suggested note text is in the PR's Acceptance notes · noted, not filed",
        "carrier: 承接者:无 · observations only: GET /forms/:slug is mounted only with a built Console and falls through to 404 without one; when the console package does not resolve at all (consolePath null without --no-console) nothing is printed or mounted, which needs a broken install and has no measured public reach · noted in PR Acceptance notes, not filed"
      ],
      "gates": [
        {
          "gate": "pnpm turbo run build --filter='@objectstack/cli^...' --concurrency=2 (via os-verify-lock)",
          "exit": 0,
          "verdict": "Tasks: 58 successful, 58 total · os-verify-lock: VERDICT command-exit 0"
        },
        {
          "gate": "pnpm --filter @objectstack/cli build (via os-verify-lock)",
          "exit": 0,
          "verdict": "os-verify-lock: VERDICT command-exit 0"
        },
        {
          "gate": "pnpm --filter @objectstack/cli exec vitest run --project unit --maxWorkers=2 (via os-verify-lock)",
          "exit": 0,
          "verdict": "Test Files 272 passed (272) · Tests 4003 passed (4003) · VERDICT command-exit 0"
        },
        {
          "gate": "pnpm --filter @objectstack/cli typecheck (via os-verify-lock)",
          "exit": 0,
          "verdict": "check:test-typecheck: OK — @objectstack/cli's test layer compiles under packages/cli/tsconfig.test.json; debt held · VERDICT command-exit 0"
        },
        {
          "gate": "pnpm lint (lane addition) — NARROWED: eslint --no-inline-config --format json over the 6 changed files",
          "exit": 0,
          "verdict": "4 linted (serve.ts, console.ts, console.not-built.test.ts, published-subpath-console.pin.test.ts): 0 errors 0 warnings; 2 .md: 'File ignored because no matching configuration was supplied'. Invariance: eslint.config.mjs never enables type-aware linting (no parserOptions.project, no typed rules); load-time reads are baselines this diff does not touch. Full run is CI's."
        },
        {
          "gate": "cli integration layer (--project integration)",
          "exit": null,
          "verdict": "NOT RUN LOCALLY — declared to CI: diff touches no integration-tier file, bin/ entry or test/helpers/serve-process.ts; runServe pins OS_DISABLE_CONSOLE=1 and a grep of the 98 queue-tier integration files finds no serve spawn with the Console enabled"
        },
        {
          "gate": "node scripts/check-adr-0087-registration.mjs --base origin/main",
          "exit": 0,
          "verdict": "✓ check-adr-0087-registration: this PR adds no declared-breaking changeset (1 non-breaking changeset(s) seen)."
        },
        {
          "gate": "node scripts/check-adr-0087-registration.mjs --self-test",
          "exit": 0,
          "verdict": "✓ check-adr-0087-registration --self-test: 441 assertions over real temp git repos (real scan()/assertInputs() path)"
        },
        {
          "gate": "node scripts/check-changeset-no-major.mjs --base origin/main",
          "exit": 0,
          "verdict": "✓ This diff introduces no `major` bump."
        },
        {
          "gate": "node scripts/check-changeset-no-major.mjs --self-test",
          "exit": 0,
          "verdict": "✓ check-changeset-no-major --self-test: 339 assertions (frontmatter dialects measured against @changesets/parse + the pre/exit exemption switch in both directions + the #"
        },
        {
          "gate": "node scripts/check-ci-filter-parity.mjs",
          "exit": 0,
          "verdict": "OK: all 20 build input(s) turbo.json declares outside the packages (itself, 2 globalDependencies, and every `$TURBO_ROOT$` input of a build Build Core runs) and all 11 sc"
        },
        {
          "gate": "node scripts/check-closing-keyword-parity.mjs",
          "exit": 0,
          "verdict": "check-closing-keyword-parity: OK (3 parsers agree on all 9 keywords and both measured separators; sweep found 5 file(s) carrying the grammar across 10398 tracked file(s),"
        },
        {
          "gate": "node scripts/check-closing-keyword-parity.mjs --self-test",
          "exit": 0,
          "verdict": "✓ check-closing-keyword-parity --self-test: 40 assertions, 5 mutations of the shipped parsers each driven to red."
        },
        {
          "gate": "node scripts/check-comment-mask-adoption.mjs",
          "exit": 0,
          "verdict": "OK  check:comment-mask-adoption — 14 private comment-stripper(s) under packages/** + examples/**, all 14 recorded and every recorded row still reached (13 unconverted, 1 "
        },
        {
          "gate": "node scripts/check-comment-mask-adoption.mjs --self-test",
          "exit": 0,
          "verdict": "PASS  check-comment-mask-adoption --self-test (0 failure(s))"
        },
        {
          "gate": "node scripts/check-comment-mask-corpus.mjs",
          "exit": 0,
          "verdict": "✓ comment-mask corpus sweep [scripts/js-comment-mask.mjs]: 8504 files, 0 disagree, 0 unparseable, 187.1s (comparator self-test: 26 cases pass)."
        },
        {
          "gate": "node scripts/check-dts-emitted.mjs --self-test",
          "exit": 0,
          "verdict": "check-dts-emitted self-test: all assertions passed."
        },
        {
          "gate": "node scripts/check-empty-changeset.mjs --base origin/main",
          "exit": 0,
          "verdict": "✓ No changeset from the merge base modified or deleted by this diff (no.17712)."
        },
        {
          "gate": "node scripts/check-empty-changeset.mjs --self-test",
          "exit": 0,
          "verdict": "✓ check-empty-changeset --self-test: 170 assertions over real temp git repos (real scan() path)"
        },
        {
          "gate": "node scripts/check-issue-citations.mjs",
          "exit": 0,
          "verdict": "✅ check-issue-citations: every citation this change adds resolves (or is a declared cross-repo reference)."
        },
        {
          "gate": "node scripts/check-keyed-text-bounds.mjs",
          "exit": 0,
          "verdict": "✓ check:keyed-text-bounds: 111 *.object.ts files under packages/** + apps/** + examples/** (walk is repo-wide; 0 outside), 116 object declarations, 241 declared index ent"
        },
        {
          "gate": "node scripts/check-keyed-text-bounds.mjs --self-test",
          "exit": 0,
          "verdict": "PASS  check-keyed-text-bounds --self-test (0 failure(s))"
        },
        {
          "gate": "node scripts/check-platform-object-tenancy-census.mjs",
          "exit": 0,
          "verdict": "✓ platform-object tenancy census matches the tree: 83 platform-namespace objects, 48 in the machinery's reach, 35 outside it, every exclusion explained by a declaration o"
        },
        {
          "gate": "node scripts/check-platform-object-tenancy-census.mjs --self-test",
          "exit": 0,
          "verdict": "✓ check-platform-object-tenancy-census self-test: all checks pass (83 objects, 35 outside the machinery)"
        },
        {
          "gate": "node scripts/check-plugin-teardown-shape.mjs",
          "exit": 0,
          "verdict": "✓ check:plugin-teardown-shape: 69 Plugin implementation(s) across 7928 source(s) under packages/**; every teardown-shaped method (stop / shutdown / close / dispose) sits "
        },
        {
          "gate": "node scripts/check-plugin-teardown-shape.mjs --self-test",
          "exit": 0,
          "verdict": "✓ check-plugin-teardown-shape self-test: 48 cases pass (real pre-no.10375 fixture reds, the repaired file and both delegating-alias directions stay green, every roster name"
        },
        {
          "gate": "node scripts/check-registry-log-declared.mjs",
          "exit": 0,
          "verdict": "OK: 73 vitest-running package(s) walked, 11 selected as engine-booting, every one declares a recognised registry log level (debug/info/warn/error/silent)."
        },
        {
          "gate": "node scripts/check-registry-log-declared.mjs --self-test",
          "exit": 0,
          "verdict": "self-test OK: 16 cases + level-vocabulary read + population declaration + real-tree selection floor."
        },
        {
          "gate": "node scripts/check-rest-log-spy-declared.mjs",
          "exit": 0,
          "verdict": "OK: 30 of 270 test file(s) beside packages/rest/src/log.ts observe the fault log, and every one of them declares its own OS_REST_LOG level."
        },
        {
          "gate": "node scripts/check-rest-log-spy-declared.mjs --self-test",
          "exit": 0,
          "verdict": "✓ the real tree yields a NON-EMPTY observer population that is a strict subset of its test files"
        },
        {
          "gate": "node scripts/check-system-context-census.mjs",
          "exit": 0,
          "verdict": "check-system-context-census: OK — 118 elevation read sites in 20 packages across 55 files, living in 101 symbol(s); the page cites 114 symbol(s) against 114 required, ove"
        },
        {
          "gate": "node scripts/check-system-context-census.mjs --self-test",
          "exit": 0,
          "verdict": "check-system-context-census --self-test: all cases passed"
        },
        {
          "gate": "node scripts/check-undeclared-dep-imports.mjs",
          "exit": 0,
          "verdict": "✓ check:undeclared-dep-imports: 80 workspace packages under packages/** + apps/** + examples/**, 2952 non-test src files, 2397 @objectstack/* specifiers (0 assembled, not"
        },
        {
          "gate": "node scripts/check-undeclared-dep-imports.mjs --self-test",
          "exit": 0,
          "verdict": "PASS  check-undeclared-dep-imports --self-test (0 failure(s))"
        },
        {
          "gate": "node scripts/docs-audit/check-affected-docs.mjs",
          "exit": 0,
          "verdict": "✓ affected-docs self-test: 605 cases pass."
        },
        {
          "gate": "node scripts/docs-audit/check-drift-comment.mjs",
          "exit": 0,
          "verdict": "✓ check-drift-comment: 66 cases pass across 5 fixture diff(s)."
        },
        {
          "gate": "node scripts/pm/release-rehearsal-clone.mjs --self-test",
          "exit": 0,
          "verdict": "✓ self-test passed"
        },
        {
          "gate": "node scripts/release-pending-publish.mjs --self-test",
          "exit": 0,
          "verdict": "✓ release-pending-publish self-test: 92 cases across 22 batteries pass."
        },
        {
          "gate": "pnpm --filter @objectstack/spec run check:duration-unit-keys",
          "exit": 0,
          "verdict": "✓ check:duration-unit-keys — 197 unit-declaring numeric key(s) across 2956 source file(s) all carry their unit in the key name (or in a sibling `unit`, or under a declare"
        },
        {
          "gate": "pnpm check:changeset-gate-self-tests",
          "exit": 0,
          "verdict": "✓ check-changeset-no-major --self-test: 339 assertions (frontmatter dialects measured against @changesets/parse + the pre/exit exemption switch in both directions + the #"
        },
        {
          "gate": "pnpm check:cross-package-test-inputs",
          "exit": 0,
          "verdict": "OK: 30 package(s) read outside themselves, all declared, and turbo.json hashes every declared glob (6 of them on a split \"test:repo\" task); 13 walked root(s) judged, 3 on"
        },
        {
          "gate": "pnpm check:dispatcher-error-vocabulary",
          "exit": 0,
          "verdict": "check-dispatcher-error-vocabulary: OK — 54 unregistered code-stamping site(s), all classified; 2 awaiting a ledger entry (no.8846)."
        },
        {
          "gate": "pnpm check:doc-authoring",
          "exit": 0,
          "verdict": "✓ doc authoring guard: sibling-package prose ids hold the baseline — 0 pinned site(s) across 0 file(s), 89527 string(s) read in 1283 parsed source(s) (seen floor 40000 st"
        },
        {
          "gate": "pnpm check:driver-memory-census",
          "exit": 0,
          "verdict": "check-driver-memory-census: OK — every declaration is ledgered, every ledger entry is live, and every ruled file states \"no.6664 census: 2 ruled consumers\". This gate polic"
        },
        {
          "gate": "pnpm check:dts-closure",
          "exit": 0,
          "verdict": "check-dts-closure: 71 built package(s) swept - 171/171 declared declaration file(s) present across 71 package(s); 0 built package(s) declare no declaration entry point an"
        },
        {
          "gate": "pnpm check:dual-build-cjs-loads",
          "exit": 0,
          "verdict": "✓ check:dual-build-cjs-loads — 107 published require entry point(s) across 66 package(s) load; 717 emitted CommonJS file(s) parse; 1 cross-format behaviour probe(s) agree"
        },
        {
          "gate": "pnpm check:engine-double-contract",
          "exit": 0,
          "verdict": "check-engine-double-contract: OK — 990 pinned, 129 in the DEBT ledger, 3 exempt."
        },
        {
          "gate": "pnpm check:gitlink-declared",
          "exit": 0,
          "verdict": "check-gitlink-declared: OK (10398 index entries -- 0 gitlink(s) at mode 160000; no .gitmodules in the index, so nothing is declared; nothing to declare)."
        },
        {
          "gate": "pnpm check:i18n",
          "exit": 0,
          "verdict": "check-i18n-bundles: OK (9 package(s) — all bundles in sync, no undeclared authoring keys)."
        },
        {
          "gate": "pnpm check:i18n-coverage",
          "exit": 0,
          "verdict": "check-i18n-coverage: OK (13 config(s), 621 baselined untranslated string(s), none new)."
        },
        {
          "gate": "pnpm check:i18n-walk-parity",
          "exit": 0,
          "verdict": "✓ check-i18n-walk-parity: 11 declared group(s), 9 walked, 2 exempted — every declared group has an extractor face."
        },
        {
          "gate": "pnpm check:issue-citations",
          "exit": 0,
          "verdict": "✅ check-issue-citations --self-test: grammar narrowed, every spelling enumerated, qualifier a closed set of repositories, four 404 causes kept apart, both board strategie"
        },
        {
          "gate": "pnpm check:lean-entry-closure",
          "exit": 0,
          "verdict": "✓ check-lean-entry-closure: 2 published condition(s) measured from a real load."
        },
        {
          "gate": "pnpm check:logger-receiver-detach",
          "exit": 0,
          "verdict": "OK  every log channel keeps its receiver: 3235 non-test TS file(s) walked, 0 detach(es) on the 5 declared receiver-sensitive sink spelling(s)."
        },
        {
          "gate": "pnpm check:nul-bytes",
          "exit": 0,
          "verdict": "check-nul-bytes: OK (scanned 10389 text file(s) -- 10389 tracked, 0 untracked-not-ignored; skipped 9 binary; no raw ASCII control bytes)."
        },
        {
          "gate": "pnpm check:objectql-double-limit",
          "exit": 0,
          "verdict": "OK  ObjectQL double `limit` conformance holds: 471 double(s) graded, 274 apply the caller's bound or refuse it loudly."
        },
        {
          "gate": "pnpm check:objectui-changeset",
          "exit": 0,
          "verdict": "✓ objectui-range --self-test: all checks passed"
        },
        {
          "gate": "pnpm check:org-identifier",
          "exit": 0,
          "verdict": "check-org-identifier: OK (3257 author-facing source file(s), 18 session binding(s) resolved, no removed session.tenantId alias)."
        },
        {
          "gate": "pnpm check:page-declaration-shape",
          "exit": 0,
          "verdict": "check-page-declaration-shape: OK — 34 page entries across 3247 sources under packages/**, examples/**, apps/** all reach the kernel through a discoverable declaration (`:"
        },
        {
          "gate": "pnpm check:pm-changeset-deadline-census",
          "exit": 0,
          "verdict": "✓ changeset-deadline-census --self-test: all cases passed across 5 batteries (what counts as a named target, the controls that make a zero a reading, the verdict truth ta"
        },
        {
          "gate": "pnpm check:published-files",
          "exit": 0,
          "verdict": "✓ check:published-files — 69 publishable package(s) of 80 workspace member(s) declare a `files` whitelist that covers every entry point plus CHANGELOG.md and admits no te"
        },
        {
          "gate": "pnpm check:query-options-erasure",
          "exit": 0,
          "verdict": "✓ query-options-erasure ratchet holds: 65 unswept non-test site(s) in 17 file(s), none new, and every file measured parsed. Every other non-test file under packages/ is c"
        },
        {
          "gate": "pnpm check:refd-timer-probe",
          "exit": 0,
          "verdict": "OK  check-refd-timer-probe: 8499 source file(s) swept; the process-global timer probe is read in packages/qa/refd-timer-testkit/src/index.ts and nowhere else."
        },
        {
          "gate": "pnpm check:route-envelope",
          "exit": 0,
          "verdict": "✓ Express-style response modules — 4 module(s) discovered and audited (walked, not enumerated — no.9937), 12 hand-built body/bodies (count reported, NOT pinned): 2 conforma"
        },
        {
          "gate": "pnpm check:slot-lookup",
          "exit": 0,
          "verdict": "✓ slot-lookup ratchet holds: 104 unswept site(s) in 25 file(s), none new, and every file in the population parsed. Every other file under packages/ is covered by `pnpm li"
        },
        {
          "gate": "pnpm check:sourcemap-no-sources-content",
          "exit": 0,
          "verdict": "check-sourcemap-no-sources-content: 68 built package(s) swept - 544 map(s), none embed source text."
        },
        {
          "gate": "pnpm check:test-source-alias",
          "exit": 0,
          "verdict": "check-test-source-alias OK — 73 packages with tests scanned; 60 registered as still resolving a workspace dep through `dist/`; 53 published subpath(s) resolved through ev"
        },
        {
          "gate": "pnpm check:tier-file-adoption",
          "exit": 0,
          "verdict": "OK: 80 workspace package(s) walked, 82 nightly-tier test file(s) on disk (82 e2e, 0 live), owned by 1 package(s); every one reads OS_TEST_TIERS."
        },
        {
          "gate": "pnpm check:type-check-coverage",
          "exit": 0,
          "verdict": "check-type-check-coverage: OK — 79/80 workspace packages type-checked (plus the root), 1 in the DEBT ledger (26 frozen raw errors, https://github.com/objectstack-ai/objec"
        },
        {
          "gate": "pnpm check:type-check-debt",
          "exit": 0,
          "verdict": "check-type-check-coverage: OK — 79/80 workspace packages type-checked (plus the root), 1 in the DEBT ledger (26 frozen raw errors, https://github.com/objectstack-ai/objec"
        },
        {
          "gate": "pnpm check:watch-hint-literal",
          "exit": 0,
          "verdict": "✓ check-watch-hint-literal: 72 declaration(s) across 4 rostered name(s) -- ROOT_DIR_WATCH_HINTS 48, ROOT_FILE_WATCH_HINTS 13, ROOT_WATCH_HINTS 3, DECLARED_WATCH_HINTS 8 -"
        },
        {
          "gate": "pnpm check:where-matcher",
          "exit": 0,
          "verdict": "✓ where-matcher conformance holds: 492 matcher(s) discovered, 492 answer the combinator battery correctly or refuse it loudly (321 refuse)."
        },
        {
          "gate": "pnpm check:cli-test-child-env",
          "exit": 0,
          "verdict": "✓ check:cli-test-child-env: 133 spawner source(s) among 269 under packages/cli/test/**; no new bulk process.env copy reaches a spawned child, all 159 spawn call(s) declar"
        },
        {
          "gate": "node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --ran (67 lines with exit codes)",
          "exit": 0,
          "verdict": "✓ dispatch-gates --ran: 67 derived famil(ies) accounted for — 67 run, 0 NOT-MEASURED (a DERIVED zero — all 67 recorded an exit code and none of them is 3)."
        }
      ],
      "line_budget": "none set — 6 files, +305 / -14 (changeset +16; README +1/-1; serve.ts +14/-7; console.ts +70/-5; console.not-built.test.ts +203; published-subpath-console.pin.test.ts +1/-1)",
      "files_changed": [
        ".changeset/22225-console-not-built-loud.md",
        "packages/cli/README.md",
        "packages/cli/src/commands/serve.ts",
        "packages/cli/src/utils/console.not-built.test.ts",
        "packages/cli/src/utils/console.ts",
        "packages/cli/test/published-subpath-console.pin.test.ts"
      ],
      "deviations": [
        "Integration layer not run locally; declared to CI (reason in gates). pnpm lint narrowed to the changed files with the three pieces of evidence; the full run is CI's.",
        "console-route-ledger.ts not amended (outside the claim's file surface); see out_of_scope_findings and the PR's Acceptance notes.",
        "Main not merged: origin/main gained 4 commits after BASE b1f7a7a73, none touching this diff's files; git merge-tree is clean.",
        "The worktree was removed after the PR opened (role file cleanup step); a patch round re-creates it from the remote branch."
      ]
    }

    Generated by Claude Code

  4. objectstack-fleet commented on Oct 9, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT: PR #22419 (head 813ff4827)

    domain:cli seat (#6024) · session_01BmsuLyUeuG5CNpZFMH1jzS · 2026-10-09T04:54Z. Reviewed against GitHub, not against the report.

    • PR shape: draft, base main; the first line is Fixes #22225, the only closing keyword in the body, and the body carries a line-initial Clause-②: no. Six files, +305 / -14, all inside the claim's surface:
    • Diff read:
      • describeConsoleDistMissing(consolePath, hostPaths) is now the one remedy picker. formatConsoleDistMissingWarning renders it with host paths, so the terminal text is byte-identical. createConsoleNotBuiltPlugin renders it without absolute host paths, because its reader is anonymous.
      • The plugin mounts on exactly the boot that prints the warning, at the static plugin's point in serve.ts, so each route keeps one owner across builds. GET / and GET /_console redirect to /_console/, as the built Console does (its rootRedirect defaults on, and serve does not turn it off). GET /_console/* answers 503 text/plain no-store.
    • Triage direction met: formatConsoleDistMissingWarning's picker is reused, with no second picker. The GET / choice (a redirect) is stated in the PR. Both HTTP answers are pinned with no Console built; controls: a built dist serves the SPA shell, and a server with no Console plugin answers bare 404. The --ui help text, the README row and the mount comment name @objectstack/console.
    • Spot-checked: the three ablations each turn red in the predicted direction: removing the 503 mount fails 5, rendering with host paths fails both no-path assertions, and dropping the / redirect fails both redirect pins. The live composition was measured too: no dist → 503 + remedy, / → 302; --no-ui → 404; a fixture dist → 200.
    • Gates: the dev's union at 813ff4827 (the PR's current head) was 67 of 67 exit 0, --ran reconciled, and the full cli unit layer passed (272 files). pnpm lint was narrowed to the changed files with the role file's three pieces of evidence; the full run is CI's. CI: in progress at this read (20 success, 3 skipped, 8 running, 0 failed). Landing waits for every check to be green.
    • Out of scope:

    Generated by Claude Code

  5. objectstack-fleet commented on Oct 9, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed: PR #22419 → 86ae119920, a single-parent queue squash

    domain:cli seat (#6024) · session_01BmsuLyUeuG5CNpZFMH1jzS · 2026-10-09T06:05Z

    • Landing shape: 86ae119920 has one parent (git rev-list --parents -n 1 gives 2 fields) and is an ancestor of origin/main. It entered the merge queue at 2026-10-09T05:14Z and merged at 2026-10-09T06:04Z, on that first entry. The group was rebuilt once on base 27a8b33de after PR fix(cli): doctor's Environment files row names os serve / os start as its loaders in the source posture (#22249) #22417 ahead of it was ejected by an unrelated timeout, and this PR was never removed.
    • Content on origin/main: packages/cli/src/utils/console.ts carries describeConsoleDistMissing and createConsoleNotBuiltPlugin (6 hits at the landed commit), and serve.ts mounts the not-built plugin (2 hits). With no built Console, /_console/* answers 503 text/plain no-store naming the remedy. The pins in console.not-built.test.ts and .changeset/22225-console-not-built-loud.md (@objectstack/cli patch) are present.
    • Review of record: ACCEPT 6074538564 at 813ff4827, Clause-②: no; no contract review owed. All checks were green on the head before the ready flip.
    • State: the card closed completed through Fixes #22225; pm:dispatched is stripped in this act.
    • Released: this card's hold on serve.ts and console.ts.

    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

Labels

area:devpathThe road — create, dev, verify, publish/install, connect an agent, iteratebugSomething isn't workingdomain:clipriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions