Skip to content

feat: asset browser tab shell and Assets tab on the published provider - #377

Merged
Krande merged 2 commits into
mainfrom
feat/asset-browser-tab
Sep 22, 2026
Merged

Krande merged 2 commits into
mainfrom
feat/asset-browser-tab

Conversation

@Krande

@Krande Krande commented Sep 22, 2026

Copy link
Copy Markdown
Owner

Phase 2 of the core asset browser (Phase 1 = #371): the Files | Assets tab shell and an Assets tab over published collections. No delivery yet — loading into the scene comes with Phase 3.

What

  • Tab shell — in REST mode the tree drawer's title slot carries Files | Assets. Files is today's TreeViewComponent on its unchanged store and stays mounted while hidden (3D pick → row sync keeps working). Notebook/websocket viewers are unchanged.
  • @/assets/* (React-free): projection, assetIndex, hierarchy, resolve, coverage, orphans, freshness, spines, merge, assetView, rowFacts. Every badge a row shows is a pure function of one AssetView.
  • assetBrowserStore + loader — collection indexes merged as a union oldest-first; subtree spines fetched lazily on expand, once per (root, revision); responses for a collection/scope the user left are dropped.
  • Rows / banners — published-at / covered / content-below badges, gap (uncovered leaves below), dimming only for explored branches, stale, older tree (subject's hierarchy_revision predates the tree shown); banners for mixed resolutions, half-written revisions, unreadable manifests, malformed keys. Orphans (removed / ahead) listed under the root once no unfetched spine could hold them; until then "not placed yet" with a place action.
  • BackendGET /assets/index?collection=…&manifests=true folds each revision's delivery / provider / hierarchy_revision so the tab badges without a fetch per subject. Opt-in; the plain fold is unchanged.
  • assetsApi is deliberately not spread into the plugin-facing viewerApi facade (that surface arrives with plugin API 1.6.0).

Verification

  • Frontend: 965 tests (964 pass, 1 skipped); 166 new asset tests + loader test; tsc clean; seam check OK.
  • Python: asset + route tests pass; black/ruff/isort clean; bundle provenance OK.
  • Layering gates: no source-format or provider tokens under src/frontend/src/assets, components/asset_browser, the store/loader.
  • End to end in Chromium (production bundle, local REST server, demo scope with a 41k-row synthetic spine, both orphan causes, a drifted leaf, a half-written revision): expanding the 41k spine = one ~70 ms main-thread task after fetch; latest↔run mode switch ≤ ~55 ms.

🤖 Generated with Claude Code

Phase 2 of the core asset browser. The tree drawer gains a fixed
`Files | Assets` tab pair in REST mode; Files is today's tree on its
unchanged store and stays mounted while hidden, so pick -> row sync keeps
working. Outside REST mode the drawer is unchanged.

The Assets tab browses published collections as one lazily assembled
forest read through a single derived AssetView:

- @/assets/{types,projection,assetIndex,hierarchy,resolve,coverage,
  orphans,freshness,spines,merge,assetView,rowFacts}: React-free, tested
  under node --test (166 tests incl. a 41k-row synthetic spine).
- assetBrowserStore + a React-free loader: collection indexes merged as a
  union oldest-first, subtree spines fetched once per (root, revision) on
  expand, stale responses dropped on collection/scope change.
- Rows: published-at / covered-from-above / content-below badges, gap
  (uncovered leaves below), dimmed only when explored, stale, and
  "older tree" when a subject's hierarchy_revision predates the tree shown.
  Banners for mixed resolutions, half-written revisions, unreadable
  manifests and malformed keys. Orphans (removed / ahead) are listed under
  the root once no unfetched spine could still hold them; until then they
  are "not placed yet" with a place action.

Backend: GET /assets/index gains manifests=true, folding each revision's
delivery / provider / hierarchy_revision so the tab badges without one
fetch per subject.

Measured in Chromium on the production bundle: expanding a 41k-row spine
costs one ~70 ms main-thread task after fetch; a mode switch <= ~55 ms.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

PR Review

👋 I checked your PR and found no issues. Thanks!

  • ✅ PR title is ok
  • ✅ Exactly one release label
  • ✅ SOURCE_KEY secret is set
  • ✅ Calculated next version: "0.81.0"

@github-actions

github-actions Bot commented Sep 22, 2026

Copy link
Copy Markdown

🚀 Profiling Results (Top 20 most expensive calls)

Function Calls Duration (s)
<built-in method builtins.exec> (~:0) 2016 22.0858
<module> (<string>:1) 1 22.0857
test_bench_batch_tessellate (tests/profiling/test_cad_backend_bench.py:63) 1 6.5902
run (tests/profiling/test_cad_backend_bench.py:73) 6 6.3464
batch_tessellate (src/ada/visit/tessellate.py:1102) 1446 6.3454
test_build_big_ifc_pipe (tests/profiling/test_ifc_creation.py:48) 1 5.9939
tessellate_geom (src/ada/visit/tessellate.py:830) 1440 5.7629
__truediv__ (src/ada/api/spatial/part.py:2042) 8 5.6940
tessellate_occ_geom (src/ada/visit/tessellate.py:684) 1440 5.2144
tessellate_shape (src/ada/visit/tessellate.py:554) 1440 5.2002
to_ifc (src/ada/api/spatial/assembly.py:292) 5 4.9131
sync (src/ada/cadit/ifc/store.py:200) 5 4.5050
sync_added_physical_objects (src/ada/cadit/ifc/write/write_ifc.py:92) 5 4.4463
add (src/ada/cadit/ifc/write/write_ifc.py:582) 2200 4.3666
tessellate (src/ada/cad/__init__.py:1163) 1440 4.2266
add_object (src/ada/api/spatial/part.py:309) 1201 4.0003
add_pipe (src/ada/api/spatial/part.py:164) 200 3.9822
add_section (src/ada/api/spatial/part.py:294) 801 3.3254
add (src/ada/api/containers/sections.py:139) 805 3.3241
equal_props (src/ada/sections/concept.py:100) 241399 3.0239

@Krande
Krande merged commit 3f8084c into main Sep 22, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant