Skip to content

finding(app-shell): exclusion-reason-truthfulness's import set excludes app-shell, so a false "no renderer" on a shell singleton passes green #7117

Description

@os-warren

Found while doing the one-line reword in #7092 (PR #7119). Filed, not fixed — widening the guard is a test-design decision well outside that card, and this is latent today, not a live false green.

The gap

packages/app-shell/src/views/metadata-admin/previews/__tests__/exclusion-reason-truthfulness.test.ts pins the class "an exclusion reason claiming no renderer must not have one". It asks the runtime ComponentRegistry, and its coverage is therefore bounded by its own side-effect import set:

import '@object-ui/components';
import '@object-ui/plugin-chatbot';
import '@object-ui/plugin-form';

Its own header names this exact hazard and states the maintenance rule:

Scope is bounded by the import set. A renderer registered in a package NOT imported here reads as unregistered, which would let a false "no renderer" pass. ... Widen the set — and its positive probes — when a new package starts registering page blocks.

app-shell has since become such a package and the set was not widened:

So for the five shell singletons, the guard cannot see a renderer that exists.

Measured, not argued

On ab85b515e I mutated PALETTE_EXCLUSIONS['app:launcher'] to 'no renderer ZZMUTZZ' — a string that DOES match the guard's CLAIMS_NO_RENDERER regex /\bno\s+(?:\w+\s+){0,2}renderer\b/i — confirmed the mutation on disk (injected-text count 1, anchor count 0, blob hash moved off the HEAD blob), and ran the suite:

Test Files  1 passed (1)
      Tests  4 passed (4)

Green. A reason asserting app:launcher has no renderer passes, while app-shell/src/views/app-launcher-renderer.tsx registers one. The tree was restored and the restore verified by blob-hash match plus an empty git diff HEAD.

The mechanism is two-layered, which is why @object-ui/components being imported does not save it: per #7091's own docblock, app:launcher sits only in PROTOCOL_COMPONENTS, registered when a host opts in via registerPlaceholders() — which only apps/console does — rather than in the eager PALETTE_PLACEHOLDER_BLOCKS. So it is absent from that harness's registry twice over.

Why latent rather than live

No shell singleton's reason currently claims "no renderer". The two entries that do — ai:chat_window and element:form — are inside the imported packages' scope, so today's ledger is correctly judged. #7092's reword deliberately left app:launcher's new wording renderer-agnostic, so it does not enter this population either.

The cost is future-tense and exactly the cost #6071 and #5837 already paid once on this ledger: the next author who writes "no renderer" over one of the five shell singletons gets a green from the file whose stated purpose is to refuse it.

Repair sketch (not prescribed)

Add the app-shell registering leaves to the import set with the positive probes the header's own discipline requires — one probe per import, so an unpopulated registry fails loudly rather than passing vacuously. Worth checking first whether importing app-shell from a test inside app-shell creates a cycle with its register-builtins leaf; if it does, importing the four renderer modules directly is the narrower move.

Refs: #7092 · PR #7119 · PR #7091 · #6757 · #6071 · #5837.

Activity

  1. added
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    on Sep 1, 2026
  2. self-assigned this
    on Sep 1, 2026
  3. os-warren commented on Sep 1, 2026

    @os-warren
    CollaboratorAuthor

    🔒 Claimed — domain:ui execution seat (objectui)

    • Session: session_012wwHa4aaFybxXrfmfHioDM
    • Branch: claude/issue-7117-truthfulness-guard-import-set
    • Build tier: opus (⚠️ Fable 5 quota exhausted; the standing maintainer exemption lowers the build tier only)

    ⚠️ Seat half-state, disclosed: I flipped this card's labels and assignee ~20 minutes before writing this comment, so for that window it was assigned with no claim recorded. Per this repo's CLAUDE.md a claim is assign plus a session ID and branch, so the claim dates from this comment, not from the label flip. No code was written in the gap and no branch existed. Flagging it because an assignee without a claim comment is exactly what makes another agent's claim-check ambiguous — the same half-state a predecessor seat reported on #6795 and five other cards.

    Not clause ② — a test's own import set and its probes. Nothing enters or leaves any published surface.

    Why this is worth a slot

    It was found the way the best findings on this lane are found: an ablation predicted GREEN, got GREEN, and then asked why. Setting a PALETTE_EXCLUSIONS reason to 'no renderer ZZMUTZZ' — which does match exclusion-reason-truthfulness.test.ts's CLAIMS_NO_RENDERER regex — still passed 4/4, because the guard's import set never grew to include app-shell, which now registers four page blocks (#6757, #7091).

    ⇒ A guard that would pass the exact false claim it exists to catch. Latent today (no shell singleton currently makes that claim, and PR #7119's reword keeps it that way), so this is prevention, not a live bug.

    ⭐ Structurally it is the same defect as the card it came from, one level up: #7092 was a comment certifying adjacent code; this is a test certifying a claim it cannot see.

    ⚠️ The fence that makes this non-trivial — from the finding's own text

    it needs one positive probe per new import or it guards vacuously

    Widening the import set is the easy half. A guard that imports app-shell but never proves the registration actually happened in the test environment is still blind — it just fails differently. ⇒ Every import added must come with a probe that must hit, and the report must show each one hitting. That is the whole difficulty of this card, and a PR that widens the set without them will be sent back.

    ⚠️ The existing suite already models this: it carries two anti-vacuity guards of its own ("the registry under test is actually populated" and "the ledger still contains a no-renderer claim to check"). Match that standard; do not regress it.


    Generated by Claude Code

  4. os-warren commented on Sep 1, 2026

    @os-warren
    CollaboratorAuthor

    os-dev-report

    {
      "issue": 7117,
      "status": "done",
      "branch": "claude/issue-7117-truthfulness-guard-import-set",
      "pr": "https://github.com/objectstack-ai/objectui/pull/7133",
      "premise_still_valid": true,
      "blindness_reproduced": true,
      "leg0_ablation": {
        "predicted": "GREEN — the guard is blind; a reason matching CLAIMS_NO_RENDERER on a key that HAS a renderer should still pass",
        "observed": "GREEN — 'Test Files 1 passed (1)' / 'Tests 4 passed (4)', VITEST_EXIT=0, with PALETTE_EXCLUSIONS['app:launcher'] = 'no renderer ZZMUTZZ' while views/app-launcher-renderer.tsx registers a renderer for it",
        "blob_before": "186b4a2de89fcc150474b5861ee1e2d56bdc50a3",
        "blob_after": "1734fcd9888fd864b379f4ab0b9e6b2d71fe95bd",
        "mutation_proven_how": "anchor count 1 to 0, injected-marker count 0 to 1, blob hash moved off the HEAD blob; the script aborts as 'reading VOID' if either count or the hash is unchanged",
        "restore_proven_how": "restored by state, not by exit code: git checkout HEAD -- (absolute path), then hash-object back to 186b4a2de89fcc150474b5861ee1e2d56bdc50a3 (equal to the HEAD blob), git diff HEAD 0 bytes, git diff --cached 0 bytes, injected-marker count back to 0"
      },
      "at_risk_population_rederived": "PALETTE_EXCLUSIONS holds 8 keys, not 5 shell singletons. Exactly 3 shell-singleton entries exist (app:launcher, global:notifications, user:profile); nav:menu and global:search are NOT excluded and never enter the guard's loop. The blind set — a ledger key with a real registered renderer invisible to the old import set — is exactly 3: app:launcher, global:notifications (app-shell) and record:chatter (plugin-detail). element:record_picker and element:text_input were already covered by @object-ui/components. ai:chat_window, element:form and user:profile have no real renderer anywhere (repo-wide grep, zero hits, with a control that hits).",
      "registration_paths_per_key": {
        "app:launcher": "REAL renderer, app-shell views/app-launcher-renderer.tsx, EAGER at module load (ns=app, label='App Launcher'); also listed in the opt-in PROTOCOL_COMPONENTS of @object-ui/components, but no opt-in is needed to see it",
        "global:notifications": "REAL renderer, app-shell views/global-notifications-renderer.tsx, EAGER at module load (ns=global)",
        "record:chatter": "REAL renderer, @object-ui/plugin-detail, EAGER (ns=record, label='Chatter Feed'), same component as record:discussion",
        "element:record_picker": "REAL renderer, @object-ui/components (ns=element) — already covered",
        "element:text_input": "REAL renderer, @object-ui/components (ns=element) — already covered",
        "user:profile": "NO real renderer anywhere; only the PlaceholderRenderer scaffold, and only under the opt-in registerPlaceholders() (ns=protocol-placeholder), which just apps/console calls",
        "ai:chat_window": "NO renderer anywhere, deliberately — omitted from PROTOCOL_COMPONENTS so a referencing schema fails loudly",
        "element:form": "NO renderer anywhere; not in PROTOCOL_COMPONENTS either"
      },
      "mechanism_chosen_and_why": "Leaf imports plus a DERIVED coverage guard, not the package barrel and not a static registration manifest. (1) The six views/*-renderer.tsx leaves and @object-ui/plugin-detail are imported directly: 553ms marginal for four leaves vs 6105ms for the barrel, measured on the same baseline. The barrel is viable and cycle-free — it loaded and registered correctly — so this is a cost decision, not a feasibility one; it drags the console, marketplace, cloud and diagnostics graphs into a pure-logic gate in the cheap `unit` project, whose whole design point is not paying for graphs it does not touch. (2) The barrel's one real advantage — tracking the package automatically — is bought for 0ms by a new test, 'the import set covers every page block app-shell registers', which reads the leaf list from the directory, derives each leaf's registered key from its own ComponentRegistry.register(...) call, and requires every one to resolve. A hand-maintained list is exactly what drifted here, so the app-shell half is derived rather than restated. (3) A static registration manifest was rejected: it is a second declaration of what the runtime registry already answers, and it would drift from the registry the same way this import set drifted from the registrations — the guard's value is that it asks the SAME question the reason string answers, of the live registry. (4) registerPlaceholders() is deliberately NOT called: it would make the file answer 'has a renderer' for types that have only the dashed 'Component Placeholder' scaffold (user:profile, measured), asserting a falsehood in the opposite direction; this repo's own prose treats the scaffold as not-a-renderer.",
      "import_cost_measured": "Marginal cost after @object-ui/components + plugin-chatbot + plugin-form are loaded: four app-shell leaves 553ms total (app-launcher 251ms, global-notifications 164ms, nav-menu 128ms, global-search 10ms); @object-ui/plugin-detail 570ms; the app-shell barrel 6105ms (and it pulls plugin-detail transitively, so a following plugin-detail import measured 0ms). End to end for the same probe file: leaves 9.4s vs barrel 15.1s. The shipped guard file went from 8.94s to 11.36s total duration (import 8.82s to 10.99s). No import cycle was observed on any route. All figures are shared-box seconds taken under the container's verify lock, which excludes other locked runs only.",
      "positive_probes_added": [
        { "import": "@object-ui/plugin-detail", "probe": "ComponentRegistry.get('record:chatter')", "must_hit_result": "HIT — asserted in 'the registry under test is actually populated'; ablation A2 turns RED naming [Function RecordChatterRenderer], so the import is load-bearing rather than decorative" },
        { "import": "../../../app-launcher-renderer.js", "probe": "ComponentRegistry.get('app:launcher'), derived from the leaf's own register() call", "must_hit_result": "HIT — and ablation A1 (the card's own false claim) now turns RED naming [Function AppLauncherRenderer]" },
        { "import": "../../../global-notifications-renderer.js", "probe": "ComponentRegistry.get('global:notifications'), derived", "must_hit_result": "HIT" },
        { "import": "../../../global-search-renderer.js", "probe": "ComponentRegistry.get('global:search'), derived", "must_hit_result": "HIT" },
        { "import": "../../../nav-menu-renderer.js", "probe": "ComponentRegistry.get('nav:menu'), derived", "must_hit_result": "HIT" },
        { "import": "../../../record-approvals-renderer.js", "probe": "ComponentRegistry.get('record:approvals'), derived", "must_hit_result": "HIT" },
        { "import": "../../../record-attachments-renderer.js", "probe": "ComponentRegistry.get('record:attachments'), derived", "must_hit_result": "HIT — ablation A3 deletes this one import and the derived guard turns RED naming the file, the key and the exact import line to add" }
      ],
      "existing_antivacuity_guards_preserved": true,
      "post_fix_ablation": {
        "predicted": "RED on all three legs: A1 the card's own false claim on app:launcher, A2 the same claim on record:chatter, A3 one renderer-leaf import deleted",
        "observed": "RED on all three, each with its specific named assertion and each reporting 'Tests 1 failed | 4 passed (5)' so the suite really executed rather than collapsing to 'no tests' behind a plausible exit 1. A1: \"PALETTE_EXCLUSIONS['app:launcher'] says \\\"no renderer ZZMUTZZ\\\", but a renderer IS registered for it ... expected [Function AppLauncherRenderer] to be falsy\" — the exact mutation that passed 4/4 in leg 0. A2: same shape, [Function RecordChatterRenderer]. A3: \"views/record-attachments-renderer.tsx registers 'record:attachments' and this file does not import it, so 'record:attachments' reads as UNREGISTERED here ... expected undefined to be truthy\". All three ran against the COMMITTED fix, so each restore leg pointed at a HEAD that already contained the implementation; every leg proved its mutation on disk (anchor count, marker count, blob hash all moved) and its restore by state (blob back to the HEAD blob, git diff HEAD and git diff --cached both 0 bytes)."
      },
      "any_live_false_claim_found": false,
      "gates": [
        { "name": "vitest run (the guard file)", "exit": 0, "verdict": "green", "raw": "Test Files  1 passed (1) / Tests  5 passed (5)" },
        { "name": "vitest run --project unit (whole project)", "exit": 0, "verdict": "green", "raw": "Test Files  801 passed (801) / Tests  12489 passed | 9 skipped (12498)" },
        { "name": "vitest run packages/app-shell/src/views/metadata-admin/previews/", "exit": 0, "verdict": "green", "raw": "Test Files  45 passed (45) / Tests  521 passed (521)" },
        { "name": "turbo run type-check --filter=@object-ui/app-shell (script: tsc --noEmit AND tsc -p tsconfig.test.json)", "exit": 0, "verdict": "green", "raw": "Tasks:    30 successful, 30 total" },
        { "name": "eslint (changed file, plain form)", "exit": 0, "verdict": "green", "raw": "no output" },
        { "name": "node scripts/check-changeset-presence.mjs", "exit": 0, "verdict": "green", "raw": "declares 1 changeset(s): .changeset/truthfulness-guard-import-set-7117.md. Every one of them has an EMPTY frontmatter — declared as releasing nothing, which is the explicit exemption and a complete answer to this gate." },
        { "name": "node scripts/check-changeset-no-major.mjs", "exit": 0, "verdict": "green", "raw": "No changeset declares a `major` bump." },
        { "name": "node scripts/check-control-bytes.mjs", "exit": 0, "verdict": "green", "raw": "check-control-bytes: OK (scanned 5899 tracked text file(s); skipped 85 binary)" },
        { "name": "tsc -p tsconfig.test.json run directly, BEFORE the dependency closure was built", "exit": 2, "verdict": "NOT_MEASURED", "raw": "error TS2307: Cannot find module '@object-ui/i18n' / '@object-ui/core' / '@object-ui/components' ... across files this PR never touches — an unbuilt workspace closure. Re-taken through turbo, which builds the closure first, and that run is the green row above." }
      ],
      "controls_used": "1) Leg-0 control run BEFORE any mutation: the unmutated suite at 4 passed (4), so the harness was known to execute. 2) Every ablation leg carries an anchor count that must be non-zero before the edit and must move after it, plus a blob-hash change; the script aborts rather than reporting if either is unchanged. 3) The repo-wide grep for a registration of ai:chat_window / element:form / user:profile returned zero WITH a control term in the same query shape (namespace: 'element') that returned many hits. 4) The grep for gates referencing this test file returned zero with a control that hit (block-types.ts names the file). 5) The derived coverage guard carries three controls of its own so it cannot pass vacuously: the leaf list must be non-empty, every leaf's key must be extractable, and the derived list must still contain app:launcher and global:notifications. 6) tsc --listFiles confirmed the edited test file is really in the tsconfig.test.json program (6 hits) rather than excluded as it is from tsconfig.json. 7) check-control-bytes reported a real population (5899 files), not a collapsed scan. 8) All exit codes captured by redirect-then-read, never through a pipe.",
      "assumptions_falsified": [
        "FALSIFIED — 'the five shell singletons are the full at-risk population'. PALETTE_EXCLUSIONS holds 8 keys and exactly 3 shell singletons; nav:menu and global:search are not excluded at all and never enter the loop. The blind set is 3 keys, and one of them (record:chatter) is not a shell singleton and not in app-shell.",
        "FALSIFIED (in its operative half) — 'app:launcher registers only via opt-in PROTOCOL_COMPONENTS, so a probe that does not opt in will report it unregistered'. True of @object-ui/components, but since #7091 app-shell registers the REAL renderer eagerly at module load; the probe finds it with no registerPlaceholders() call (ns=app, label='App Launcher'). Opting in would have been the wrong move: it registers the placeholder scaffold for ~120 protocol types, which would make the guard answer 'has a renderer' for user:profile, whose only registration is that scaffold.",
        "REFINED — 'widening the import set is possible without an import cycle or a heavy side-effect chain'. No cycle on any route, including the barrel. But the cost is not uniform and it decided the mechanism: leaves 553ms vs barrel 6105ms. The finding's own hedge ('importing the four renderer modules directly is the narrower move') was right, though not for the reason it gave — the barrel does not cycle, it is simply 11x heavier.",
        "CONFIRMED — 'no reason currently makes a false no-renderer claim'. Only ai:chat_window and element:form match CLAIMS_NO_RENDERER, and neither has a registration anywhere in the repo (zero-hit grep with a control that hits). Latent, not live, exactly as filed.",
        "CONFIRMED — 'this needs no production-code change'. The diff is one test file plus one empty-frontmatter changeset.",
        "REJECTED with reasoning — 'the guard should assert against a registration manifest rather than the live registry'. A manifest is a second declaration of what the live registry already answers, and it would drift from the registrations the same way this import set did. The value of asking the runtime registry is that it is the SAME question the reason string answers. What was adopted instead is a derived guard over the leaf directory, which makes the IMPORT SET self-checking without introducing a second source of truth about what is registered."
      ],
      "summary": "Reproduced the blindness first (leg 0: predicted GREEN, observed GREEN — 'no renderer ZZMUTZZ' on app:launcher passed 4/4 while a renderer is registered), then re-derived the at-risk population by measurement rather than from the card: 3 blind ledger keys, not 5 shell singletons, and one of them (record:chatter, from @object-ui/plugin-detail) is outside app-shell. Widened the import set to the six views/*-renderer.tsx leaves and plugin-detail, each with a positive probe that hits, and added a derived guard that reads the leaf list from the directory so a seventh renderer leaf reds this file instead of silently shrinking its coverage — a hand-maintained list is what drifted, so the app-shell half is derived. Both pre-existing anti-vacuity guards are preserved verbatim and neither is weakened. Post-fix, the leg-0 mutation now turns RED naming AppLauncherRenderer.",
      "tests": "All runs at 778fb78b4 unless noted. Guard file: 'Test Files 1 passed (1)' / 'Tests 5 passed (5)'. Whole unit project (the decisive leak check — that project runs isolate:false, so the added side-effect registrations are visible to every other unit file sharing a worker): 'Test Files 801 passed (801)' / 'Tests 12489 passed | 9 skipped (12498)', exit 0. Previews directory across all projects: 'Test Files 45 passed (45)' / 'Tests 521 passed (521)'. turbo type-check for @object-ui/app-shell: 'Tasks: 30 successful, 30 total' (the package script is tsc --noEmit AND tsc -p tsconfig.test.json; --listFiles confirmed the edited file is in that program with 6 hits). eslint clean. Three post-fix ablations, each predicted RED and observed RED with its specific named assertion, each proving its mutation on disk by anchor count plus marker count plus blob-hash change and its restore by state (git diff HEAD and git diff --cached both 0 bytes, blob back to the HEAD blob). No dist rebuild leg applies — these are source-resolved workspace imports through vitest, not dist-resolved. One NOT MEASURED, reported as such and re-taken: tsc -p tsconfig.test.json run directly before the dependency closure was built produced TS2307 'Cannot find module @object-ui/*' across untouched files.",
      "mcp_calls": 8,
      "open_questions": [
        {
          "question": "user:profile is a PALETTE_EXCLUSIONS shell singleton with NO renderer anywhere — not even the eager PALETTE_PLACEHOLDER_BLOCKS set — so an authored page carrying it draws SchemaRenderer's red unknown-type panel in every host except apps/console, which opts into registerPlaceholders(). That is the same gap #6757 and #7091 closed for the other four members of the family. Not filed: it looks like a deliberate later phase of the 2026-08-26 objectstack#12183 decomposition ruling rather than a defect, and filing it blind risks duplicating that plan.",
          "options": ["A — leave it; the ruling already sequences the decomposition and this is simply a phase not yet reached", "B — file it as a finding so the asymmetry is recorded where the next reader of the ledger will see it", "C — PM confirms against the objectstack#12183 phase list and files only if it is genuinely unplanned"],
          "recommendation": "C — it is one lookup on the platform side that I cannot do from here, and it decides between A and B without guessing. The observation costs nothing to carry until then; nothing is broken today."
        }
      ],
      "out_of_scope_findings": [
        "filed as #7134: the `unit` vitest project's isolate:false is justified by a comment claiming there is 'no ComponentRegistry or DOM state to leak across files', but both halves of that hazard live in that project today — this guard file WRITES ten side-effect registrations into the shared singleton, and packages/fields/src/__tests__/capability-multiselect-retired.test.ts:81-82 asserts ComponentRegistry.get(...) is toBeUndefined(), an absence assertion that a shared registry can silently satisfy. Latent, not live: the whole unit project is 801/801 green with the widened import set, measured. Filed unassigned with labels finding + tooling, after a targeted dedup search whose control returned results and showed nothing covering it."
      ]
    }

    Generated by Claude Code

  5. os-warren commented on Sep 1, 2026

    @os-warren
    CollaboratorAuthor

    🟢 LANDED — closing as completed

    PR #7133 merged to main as 2b3964aff: "test(app-shell): widen the exclusion-reason truthfulness guard's import set so a false 'no renderer' cannot pass".

    Landing verified with a control

    probe, in previews/__tests__/exclusion-reason-truthfulness.test.ts expected measured
    app-launcher-renderer — subject, the widened import >0 3
    CLAIMS_NO_RENDERER ⚠️ control — pre-existing, must hit >0 3

    The blindness was reproduced before it was fixed, and re-proven after

    Leg 0 predicted GREEN and got GREEN: 'no renderer ZZMUTZZ' — which does match the guard's regex — passed 4/4 while a real renderer was registered for that key. Post-fix, that exact mutation turns RED, naming [Function AppLauncherRenderer].

    ⚠️ And each ablation leg reported Tests 1 failed | 4 passed (5), asserting the passing count alongside the failing one — so a suite that collapsed to "no tests" behind a plausible exit 1 could not masquerade as the predicted red. That trap was hit elsewhere on this lane the same session; guarding against it explicitly is why this red is trustworthy.

    ⭐⭐ My at-risk population was wrong in both directions

    I dispatched this as "the five shell singletons". Measured: PALETTE_EXCLUSIONS holds 8 keys, of which exactly 3 are shell singletons — nav:menu and global:search are not excluded at all and never enter the guard's loop.

    And the real blind set is 3, one of which is record:chatter — neither a shell singleton nor in app-shell, but in @object-ui/plugin-detail. ⇒ A fix scoped the way my order described would have left a third of the blind set uncovered while looking complete.

    ⭐ And one of my warnings would have caused the opposite error

    I cautioned that app:launcher registers only via opt-in PROTOCOL_COMPONENTS, so a probe not opting in would report it unregistered. True of @object-ui/components — but since #7091 app-shell registers the real renderer eagerly, so the probe finds it with no opt-in.

    ⚠️ Worse, opting in as I implied would have been actively wrong: registerPlaceholders() registers the dashed scaffold for ~120 protocol types, which would make the guard answer "has a renderer" for user:profile, whose only registration is that scaffold. My warning named a real hazard and prescribed the move that creates a different one.

    ⭐ The fix beat the fence I set

    My fence was "one positive probe per added import, or it guards vacuously." Seven probes, all hitting — and then the failure mode was closed one level up: the guard reads the leaf list from the directory and derives each key from the leaf's own register() call. A hand-maintained list is exactly what drifted here, so restating one would have rebuilt the defect inside the fix. Ablation A3 proves it: delete one leaf import and the guard names the file, the key, and the import line to add.

    Rejecting the static manifest was right for the same reason — a manifest is a second declaration of what the live registry already answers, and it would drift the same way. The guard's value is asking the same question the reason string answers, of the live registry.

    Mechanism cost is a measurement, honestly bounded: leaf imports 553ms vs barrel 6105ms, and the report says plainly that the barrel is viable and cycle-free — a cost decision, not a feasibility one. "We couldn't" and "we chose not to" age very differently for the next reader.

    Filed from this work


    Generated by Claude Code

  6. removed their assignment
    on Sep 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatfindingtooling

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions