Actionist Knowledge Graph
P08 · Experience knowledge node

Archetypes, shells and layouts

Reuse application-level workflow skeletons without forcing every product into one five-area dashboard.

What we learned

Current synthesis from the research packet. Exact records and complete source artifacts remain visible below.

Research conclusions

  • Reject a universal five-area shell; Actionist owns a host frame while capability navigation varies by reuse shape.
  • Shopify and Atlassian prove the navigation boundary is a design choice, while the host visual contract is stable.
  • Five starting spines—case/workflow, field operations, learning/content, scheduling and CRM—cover most target industries.

What it owns

  • Case, portal, CRM, scheduling, finance, support and operations archetypes
  • Navigation and page topology
  • Required component slots
  • Industry variation points
  • Responsive shell behavior

What research already tells us

  • Ten B2B archetypes have been identified
  • Case/workflow and portal demand are strong while clean template supply is thin
  • Generic admin/dashboard templates are abundant but weakly differentiated
  • The inherited five-area ISSO shell is only a hypothesis

Open first-principles questions

  • Which archetypes cover 80% of the first 17 industries?
  • What is universal shell infrastructure versus archetype-specific UX?
  • Which side-nav variations should clients choose visually?
  • How does the shell absorb donor navigation?

Inputs

  • ProductSpec
  • TasteProfile
  • Component selections
  • Capability surfaces

Outputs

  • ArchetypeTemplate
  • NavigationPlan
  • PageTopology

Agent-sized workstream

Define the first archetype contracts and visual shell variants; start with case/workflow and client portal.

Linked research

  • B2B template shelfresearch/actionmodel-builder-research-2026-08-26/phase-8/lanes/03-b2b-template-shelf/outputs/b2b-template-shelf-report.md
  • AutoSaaS source and shell strategy[private local source withheld]
  • Industry atom specificationsresearch/actionmodel-builder-research-2026-08-26/phase-2/outputs/industry-atom-specifications.md

Where this beats a generator

Prompt-to-app rederives application structure on every run, which is why it holds up on dashboards and CRUD and falls apart on multi-step business logic. A tested archetype supplies the workflow skeleton as a known-good starting point, so the model is never asked to invent topology it cannot verify.

Companies and commercial surfaces

10 mined records. Search and inspect the full agent output; nothing is collapsed into a top-ten headline.

RankIdentityWhat the agent foundEvidenceSource
1Shopify admin + App Bridge—Left-rail host shell (~8-10 areas), separate gear settings route, store/org picker. Embedded apps run in an iframe while the HOST renders the navigation; apps declare nav declaratively via s-app-nav rather than choosing a numeric position. Host also owns title bar, toasts, modals and resource picker.observedstealShopify App Bridge developer documentation
2Atlassian Connect / Forge (Jira, Confluence)—Left-rail project nav plus top-bar global nav and app-switcher waffle. Donor apps surface only at host-defined MODULE types (issue panel, glance, project page, global page, admin page) - the host enumerates every legal surface. Left sidebar 240px, collapsed 20px; right sidebar 280px; right panel 368px. Forge UI Kit is a host component library; Connect is raw iframe.observedstealAtlassian Forge and Connect module documentation; page-layout@5.4.0/constants.js
3Zendesk + Apps framework—Icon-rail plus contextual panel (~5-7 areas); separate Admin Center console; product tray as app switcher. Donor apps live in fixed host slots (ticket_sidebar, nav_bar, top_bar, modal). ticket_sidebar is 320px fixed.observedstealZendesk Apps framework manifest reference
4VS Code—Activity bar 48px (compact 36, floating 36/28); sidebar default width Math.min(300, viewport/4), min 170px, stored default 300px. This is the ONLY genuinely proportional rail rule found across the whole corpus - and it is 25/75, capped, not 20/80.observedstealsrc/vs/workbench/browser/layout.ts:3026; activitybarPart.ts:50-56
5Grafana—Left-rail dockable MegaMenu at 320px (>=md) plus top bar. Plugins nest under /a/<id>/* so a donor keeps its internal hierarchy beneath one host nav row, and declare presence via an addToNav BOOLEAN - the host owns ordering. serve_from_sub_path is the best-documented sub-path support in the OSS corpus.observedstudyMegaMenu.tsx:22; Grafana configure-grafana docs
6Salesforce Lightning / Service Cloud + AppExchange—Top-bar app-scoped nav with an App Launcher waffle switcher; Setup is a SEPARATE admin console, not a nav item. AppExchange packages appear as first-class tabs; LWC and Visualforce canvas embed donor UI inside records; the utility bar is a bottom bar (width:100%, height:2.5rem) rather than a rail.inferredstudySalesforce Lightning and SLDS documentation
7Microsoft 365 shell / Teams apps—Persistent host app-launcher waffle across products; Teams personal apps and tabs are iframed donor surfaces that keep their own internal nav inside the frame while Teams owns the outer rail and identity.inferredstudyMicrosoft 365 and Teams app documentation
8IBM Carbon UI shell—Left panel 256px / 16rem. Carbon is the ONLY vendor found publishing a decision rule rather than just a token: use the left panel if there are more than five secondary navigation items, or if users switch between them frequently. Also states the left panel does not support three tiers of navigation. Breakpoints 320/672/1056/1312/1584px.observedstealcarbondesignsystem.com UI shell guidance
9Intercom (Canvas Kit)—Icon-rail plus contextual panel (~6-8 areas), separate gear settings route, workspace dropdown. Donor apps render via SERVER-DRIVEN JSON at five host locations - no iframe, no donor CSS at all. The host renders every pixel.observedstudyIntercom Canvas Kit documentation
10AWS Console—Top-bar unified navigation plus per-service left rails across 200+ service consoles; account/role and Region pickers. NO third-party embedded UI surface was found - Marketplace provisions resources rather than rendering donor UI.observedstudyAWS Console Unified Navigation survey

Repositories and OSS precedents

10 mined records. Search and inspect the full agent output; nothing is collapsed into a top-ten headline.

RankIdentityWhat the agent foundEvidenceSource
1backstage/backstage—Host shell whose entire purpose is absorbing third-party plugin UI into one nav. RouteRef indirection means a plugin declares a routing TARGET, never a URL; ExternalRouteRef is bound in app-config.yaml so plugin A links to plugin B without depending on it. NavItemBlueprint was REMOVED as a breaking change in v1.51.0 - nav is now auto-discovered from PageBlueprint title/icon, so nav and routes cannot drift.observedstealgh api repos/backstage/backstage + repository documentation
2luigi-project/luigi (source at SAP/luigi)—The purest OSS host shell: the host declares every navigation node (pathSegment, label, icon, category, children, viewUrl) and the donor contributes NO chrome whatsoever. virtualTree lets a node accept arbitrary child paths without enumerating them - the clean fix for a donor with its own deep router. Host holds the OIDC session; donor calls LuigiClient.getToken().observedstealgh api repos/luigi-project/luigi (source at SAP/luigi) + repository documentation
3marmelab/react-admin—The best-documented sub-path donor found. docs/Routing.md covers three cases: hash routing works unchanged; createBrowserRouter needs opts.basename; nested inside a host route you use <Admin basename='/admin'>. Docs state plainly that serving the admin from the sub path is your responsibility. <Admin layout={...}> replaces the entire shell, so a pass-through layout yields chrome-free content.observedstealgh api repos/marmelab/react-admin + repository documentation
4umijs/qiankun—v3 replaced the 2.x isolation flags with sandbox.styleIsolation built on native CSS @scope, defaulting to false. Its docs are the most honest in the corpus: styleIsolation is 'a one-way boundary' that does not stop host styles entering; the JS sandbox is explicitly 'not a security boundary for running untrusted code' and reads fall through to the host; and a menu, dialog or tooltip portaled to document.body falls outside the scope root so the donor's scoped selectors will not match it.observedstudygh api repos/umijs/qiankun + repository documentation
5module-federation/core—Runtime code sharing with negotiated shared dependencies. singleton defaults to FALSE so duplication is the silent default, and even singleton:true is defeated by a missing trailing slash ('react-dom' does not intercept react-dom/client, loading a second React). Ships a Bridge subsystem explicitly for framework isolation, ensuring React contexts and component trees between applications are isolated.observedstudygh api repos/module-federation/core + repository documentation
6smapiot/piral—The clearest self-registration model: registerPage(route, Component) with one component per page, and registration is ownership-scoped so pilet B cannot unregister pilet A's page. registerMenu/registerTile live in piral-menu/piral-dashboard rather than core; menu items go into global state and are rendered by the app shell's Menu component.observedstudygh api repos/smapiot/piral + repository documentation
7single-spa/single-spa—The most widely deployed host-shell router. Apps export bootstrap/mount/unmount; the host owns activity functions. single-spa-layout adds a router with base as a URL PREFIX rather than an exact match, and layout elements are static with no way to force re-render. Unlike qiankun it imposes no one-routing-app limit. navigateToUrl is the cross-app nav primitive.observedstudygh api repos/single-spa/single-spa + repository documentation
8refinedev/refine—Headless by construction - no chrome to strip. routerProvider adapts to the HOST's router rather than owning routing; data, auth and access control are provider interfaces.observedstealgh api repos/refinedev/refine + repository documentation
9nocobase/nocobase—Plugin-registered nav registry very close to Actionist's target, with runtime path substitution via APP_PUBLIC_PATH/API_BASE_PATH at container start rather than build time. BUT the licence incorporates Apache-2.0 while stating its supplementary terms prevail on conflict, and Section 5.2 forbids removing or changing NocoBase branding on the interface except the main logo in the upper left corner; Section 5.4 forbids public no-code/low-code SaaS.observedholdgh api repos/nocobase/nocobase + repository documentation
10directus/directus—High-profile donor candidate whose licence changed under everyone's feet. Now Monospace Sustainable Core License v1.0, Copyright 2026 Monospace Inc., granting use only for a Permitted Purpose defined as anything other than a Competing Use, forbidding you to move, change, disable or circumvent the licence key functionality, and granting GPL-3.0 only on the FOURTH ANNIVERSARY. PUBLIC_URL is documented for link generation, not sub-path serving; ROOT_REDIRECT defaults to ./admin with no documented way to relocate it.observedholdgh api repos/directus/directus + repository documentation

Innovation register

100 mined records. Search and inspect the full agent output; nothing is collapsed into a top-ten headline.

RankIdentityWhat the agent foundEvidenceSource
—Archetype-native topology—Each of the 10 archetypes ships its own nav skeleton derived from its data spine, not a shared N-slot rail.hypothesishypothesis-openP08 innovation lane, 2026-08-27
—Spine-derived nav—Nav items generated mechanically from the archetype's spine nouns (case_workflow -> Cases, Deadlines, Documents).inferredhypothesis-openBackstage derives nav from PageBlueprint registration - mechanical derivation from declared structure is a shipped pattern
—Stage-derived nav (workflow rail)—For case_workflow, top-level nav is the state machine's stages, not entities. Nav IS the pipeline.hypothesishypothesis-openP08 innovation lane, 2026-08-27
—Deadline-primary rail—case_workflow shell leads with the deadline clock; nav sorted by time-to-breach, not entity type.hypothesishypothesis-openP08 innovation lane, 2026-08-27
—Entity-derived nav—Nav mirrors the top-level entities of the data model, one row each.inferredhypothesis-openAttio ships object-driven nav
—Role-derived nav—The rail is computed from the viewer's role; two roles in one product see two different rails.inferredhypothesis-openISSO already ships agency vs model rails; SISOCRM defines a brokerage role matrix
—Icon rail + contextual panel—A narrow always-visible icon rail plus a wide contextual panel that changes per section.inferredhypothesis-openZendesk, Intercom, Datadog, VS Code activity bar 48px
—Dual rail—Two rails: outer for app/section switching, inner for within-section nav.inferredhypothesis-openFront; VS Code activity bar + sidebar
—Command-palette-primary—Minimal visible nav; the palette is the primary navigation surface.inferredhypothesis-openLinear, VS Code
—Zero-nav single surface—One surface, no rail; all movement is via in-content links and search.hypothesishypothesis-openP08 innovation lane, 2026-08-27
—Top-bar topology—Horizontal top nav instead of a rail, freeing full width for the app pane.inferredhypothesis-openSalesforce Lightning, ServiceNow, Xero, Metabase
—Hybrid top + rail—Top bar for global/product switching, rail for within-product nav.inferredhypothesis-openJira, Shopify, HubSpot
—Tile/launchpad home—Home is a tile grid of entry points rather than a dashboard.inferredhypothesis-openSAP Fiori launchpad
—Fixed N with N per archetype—Keep the fixed-tuple discipline but let N be set per archetype rather than globally 5.hypothesishypothesis-openP08 innovation lane, 2026-08-27
—Nav budget cap, not schema—Replace the fixed 5-tuple with a soft cap (5-7) enforced at generation time and warned, not typed.inferredhypothesis-openIBM Carbon publishes 'more than five secondary items' as its left-panel rule
—Depth limit of two—No third tier of navigation anywhere; forced flattening or in-page nav below tier 2.inferredhypothesis-openCarbon: 'The left panel does not support three tiers of navigation'
—Search-primary with thin rail—Search box is the largest element; rail exists only for orientation.hypothesishypothesis-openP08 innovation lane, 2026-08-27
—Object-switcher rail—Rail rows are data objects the user has pinned, not fixed product areas.hypothesishypothesis-openP08 innovation lane, 2026-08-27
—Two shells per product—Ship a separate internal shell and external shell rather than one shell with role gating.inferredhypothesis-openISSO already ships agency vs model vs client vs portal route groups
—Rail as status surface—Rail items carry live counts/stats so the rail doubles as an at-a-glance status board.inferredhypothesis-openISSO summaryItems already carry stat strings
—Fixed 320px host rail—Host rail specified as 320px at >=1056px viewport, not as a percentage.inferredhypothesis-openZendesk 320, Grafana 320, Metabase 324 - three independent corroborations
3Collapse-rate as the verdict—Ship the rail collapsible with per-user memory; permanent-collapse rate decides whether it earned its pixels.hypothesishypothesis-openP08 innovation lane, 2026-08-27
—Proportional rail with cap—Rail width = min(320px, viewport/4) rather than a flat constant.inferredhypothesis-openVS Code layout.ts:3026 - the only proportional rule found in the corpus
—Host rail carries only host-owned surfaces—The rail holds identity, tenant, settings, search, notifications - nothing else; all app nav is in the pane.hypothesishypothesis-openP08 innovation lane, 2026-08-27
—Host puck instead of rail—Collapse host-owned controls into a small persistent puck; give the rail's pixels to the app.hypothesishypothesis-openP08 innovation lane, 2026-08-27
—Top host bar, no rail—Host identity/settings/search live in a thin top bar; the entire width below is the app pane.inferredhypothesis-openMetabase app bar 52px; Stripe, Vercel
—Adaptive rail width per archetype—scheduling and inventory get a narrow rail (calendar/grid want width); case_workflow gets a wide one.hypothesishypothesis-openP08 innovation lane, 2026-08-27
—Rail collapses by viewport class, not px—Switch rail/icon-rail/bottom-bar by window size class rather than raw pixel breakpoints.inferredhypothesis-openMaterial 3 switches by window size class; Polaris and Primer both switch at 768px
—Donor pane must never be less than 1024px effective—Guarantee the app pane a minimum usable width; the rail yields first.hypothesishypothesis-openP08 innovation lane, 2026-08-27
—Rail hover-flyout when collapsed—Collapsed rail expands on hover rather than requiring a click.inferredhypothesis-openAtlassian collapses to a 20px stub with a 240px hover flyout
—Host owns identity absolutely—No donor may present a login, signup, or account UI; host injects session at the donor's auth seam.observedadopt-as-contractTEABLE-ABSORPTION-BRIEF success criteria 1 and 4; Luigi host-holds-token pattern
—Settings as host route, donor settings as sections—Host owns /settings; each donor's settings become a section inside it, never a peer nav item.inferredhypothesis-openFROZEN-PAGE-SKELETON gives Settings one host page with a module registry
—Settings in a separate console—Follow Salesforce/Zendesk: admin is a separate console, not competing for a nav slot.inferredhypothesis-openSalesforce Setup, Zendesk Admin Center, Metabase /admin
—Host-owned global search across donors—One search surface federating donor indexes.hypothesishypothesis-openP08 innovation lane, 2026-08-27
—Host-owned notification spine—All donor events normalize into one host notification model with host-coordinate deep links.inferredhypothesis-openSISOCRM consumes donor events into SISO-owned tables via Svix + event envelope
—Host-owned tenant switch—Tenant/workspace switching is host-only; donors receive tenant context and cannot change it.inferredhypothesis-openOWNERSHIP-AND-DATA-LAYER-DECISIONS: one server, separate schemas
—Theming tokens flow host->donor only—Host publishes tokens; donors consume them. No donor ships its own theme.observedhypothesis-openqiankun documents style isolation as one-way: host CSS enters the donor regardless
—Host-owned empty and error states—Donor empty/error states are replaced with host ones so failures look like one product.hypothesishypothesis-openP08 innovation lane, 2026-08-27
—Host-owned onboarding—No donor onboarding, tour, or welcome modal ever renders.inferredhypothesis-openMASTER-SYNTHESIS names replacing donor onboarding as typical adaptation
—Host-owned keyboard map—Host reserves a keyboard namespace; donors may not bind conflicting global shortcuts.inferredhypothesis-openISSO already reserves Cmd1-Cmd5 for rail sections
—Route re-mount with basename—Mount the donor under a host path prefix using its documented basename option.observedcandidatereact-admin <Admin basename>; Grafana serve_from_sub_path; Next.js inlines basePath at build time
—Nav registry injection—Donor declares nav intent; host renders it in host chrome and owns ordering.observedcandidateBackstage PageBlueprint auto-discovery; Piral registerMenu; Grafana addToNav boolean
—Host-declared nav config (donor declares nothing)—Host config enumerates every nav node including donor view URLs.observedcandidateLuigi navigation.nodes with viewUrl and virtualTree
—iframe isolation with host rail—Donor runs in an iframe; host provides the rail around it.observedfallback-onlywujie documents modal confinement; MDN Storage Access API requires transient activation; Firefox partitions since 103
—Reverse-proxy chrome stripping—Strip donor chrome at the proxy by rewriting HTML in flight.observedrejectApache: will not rewrite URL references inside HTML pages by default; mod_proxy_html has no knowledge of URLs within embedded script
—Web Component / shadow DOM isolation—Mount the donor inside a custom element, optionally shadowed.observedconditionaljd-opensource/micro-app docs; WHATWG same-root requirement for ARIA references
—Headless donor, host renders UI—Take the donor's engine and API only; rebuild every surface in host components.inferredcandidate-for-someRefine, Tremor, Cube have no chrome to strip
6Donor as embedded surface inside a host page—Donor renders as a component within a host-owned workflow page and is never a nav destination.observedprimary-candidateTEABLE-ABSORPTION-BRIEF: 'Teable is NOT a page'; FROZEN-PAGE-SKELETON folds donors under 11 host pages
—Donor as whole-slice page under host rail—One host nav row hands the entire page to the donor, which keeps its internal nav below the rail.observedcandidateFROZEN-PAGE-SKELETON: Tasks = Plane (whole-slice); Grafana /a/<id>/* nesting
8RouteRef indirection for donor links—Donors declare routing targets, never URLs; host binds targets to concrete paths in config.observedadopt-as-contractBackstage RouteRef and ExternalRouteRef bound in app-config.yaml
1Donor admission test as a gate—Four binary questions per donor answered by real attempts, not doc reads, before any absorption work.hypothesishypothesis-openP08 innovation lane, 2026-08-27
—MountProfile per donor—Record sub-path support, path-substitution timing, auth seam, chrome-disable mechanism, and licence constraint per donor.hypothesishypothesis-openP08 innovation lane, 2026-08-27
—Never let a donor pick a numeric position—Donors declare intent (label, icon, routeRef); the host assigns order.observedadopt-as-contractWordPress $position collisions patched by MD5 hash offset; Grafana addToNav boolean; Shopify s-app-nav
—Server-driven donor surfaces—Donor returns JSON describing its UI; host renders every pixel.inferredhypothesis-openIntercom Canvas Kit, Slack Block Kit
—Host component library for donors—Donors write declarative UI against host tokens and components.inferredhypothesis-openAtlassian Forge UI Kit, HubSpot UI extensions, Retool
—Closed surface catalogue—Host enumerates every legal donor surface; anything not listed is impossible.inferredhypothesis-openAtlassian Forge module types; Zendesk ticket_sidebar/nav_bar/top_bar/modal
—Admit no donor UI at all—Donors contribute data and actions; the host renders 100% of the interface.observedlive-optionAWS Console admits no third-party embedded UI
7Licence gate before chrome work—Read the LICENSE body before planning any chrome removal.observedadopt-as-contractNocoBase 5.2 forbids removing branding; Directus MSCL forbids circumventing the licence key
—Earned nav—Rail items appear only once the user has the data or permission to use them.hypothesishypothesis-openP08 innovation lane, 2026-08-27
—Usage-ranked nav—Rail order adapts to per-user click frequency.hypothesishypothesis-openP08 innovation lane, 2026-08-27
—Stage-gated nav—For case_workflow, nav reveals stages as the case advances.hypothesishypothesis-openP08 innovation lane, 2026-08-27
—Empty-state-aware nav—Sections with zero records show a setup affordance rather than an empty list.inferredhypothesis-openCommon SaaS pattern; not verified in this run
—Onboarding rail vs steady-state rail—A different, smaller rail for the first N sessions.hypothesishypothesis-openP08 innovation lane, 2026-08-27
—Pinned + overflow—A short pinned set plus a 'more' surface holding everything else.inferredhypothesis-openAzure Portal favourites; common pattern
—Role-progressive disclosure—Nav grows with the user's permissions rather than their tenure.inferredhypothesis-openSISOCRM defines a brokerage role matrix with confidentiality overrides
—Vocabulary skinning layer—One shell, one spine, per-industry entity names supplied as a config.hypothesishypothesis-openP08 innovation lane, 2026-08-27
5Vocabulary-isomorphism test—Compare state machines, deadline rules and document sets across the six case_workflow industries after renaming.hypothesishypothesis-openP08 innovation lane, 2026-08-27
—Vocabulary as the only differentiator (null hypothesis)—The six case_workflow industries differ ONLY in vocabulary.hypothesishypothesis-openP08 innovation lane, 2026-08-27
—Configurable stage machine—Stages, transitions and authority are data, not code.inferredhypothesis-openb2b shelf: the state machine and who may advance it is what differentiates case_workflow
—Deadline-rule engine as the product—The defensible asset for case_workflow is the deadline computation, not the shell.hypothesishypothesis-openP08 innovation lane, 2026-08-27
—Per-industry document set templates—Ship the required document set per industry as a template.inferredhypothesis-openb2b shelf names document set as part of the case_workflow spine
—Mobile-first shell for field_operations—field_operations gets a distinct mobile shell: bottom bar, camera-first, one-handed reach.inferredhypothesis-openb2b shelf: offline capture and evidence as first-class data
—Offline-capable shell—Shell and nav function with no network; queued writes surface in the rail.hypothesishypothesis-openP08 innovation lane, 2026-08-27
—Bottom bar below 768px—Rail becomes a bottom bar or full-width overlay under 768px.inferredhypothesis-openPolaris nav becomes full-width overlay below 768; Primer panes 100% width below 768
—Donor mobile behaviour is unowned risk—Donor responsive behaviour cannot be assumed and must be tested per donor per breakpoint.hypothesishypothesis-openP08 innovation lane, 2026-08-27
—Portal shell is minimal by requirement—The portal shell carries almost no chrome - no internal nav, no global search, no tenant switch.inferredhypothesis-openb2b shelf: a portal is an authorization product before it is a UI
—Touch target floor in the rail—Rail items meet a minimum touch target on all devices.inferredhypothesis-openMaterial 3 rail tokens; standard accessibility guidance
—Machine-readable nav manifest—The shell emits a manifest of every nav node, route and required capability that an agent can traverse.hypothesishypothesis-openP08 innovation lane, 2026-08-27
9Nav derived from route registration—Nav cannot drift from routes because it is derived from them.observedadopt-as-contractBackstage removed NavItemBlueprint in favour of deriving nav from PageBlueprint title/icon
—Deep-link addressability contract—Every meaningful state has a URL an agent can navigate to directly.hypothesishypothesis-openP08 innovation lane, 2026-08-27
—data-verify attributes on nav—Every nav node carries a stable machine-readable identifier for verification.inferredhypothesis-openLocal verifiable-frontend work uses a data-verify-* contract with window.__verify, DEV-only
—Nav as a testable artifact—Nav topology is asserted in tests: budget cap, depth limit, no orphan routes, no dead links.hypothesishypothesis-openP08 innovation lane, 2026-08-27
—Agent-operable settings—Settings are addressable and settable through the same contract as nav.hypothesishypothesis-openP08 innovation lane, 2026-08-27
—Shell as a compiled artifact—The builder emits shell source that is then owned and editable.hypothesishypothesis-openP08 innovation lane, 2026-08-27
—Shell as runtime config—The shell is data interpreted at runtime; regeneration is a config swap.inferredhypothesis-openLuigi is fully config-driven navigation
4Determinism check—Run the generator twice on identical inputs and diff byte-for-byte.hypothesishypothesis-openP08 innovation lane, 2026-08-27
—Shell diffing across regenerations—Show the client what changed in the shell between generations.hypothesishypothesis-openP08 innovation lane, 2026-08-27
—Visual side-nav variant chooser—The client picks a rail variant visually from a small set.hypothesishypothesis-openP08 innovation lane, 2026-08-27
—Route stability across regeneration—URLs survive shell regeneration so links and bookmarks do not rot.hypothesishypothesis-openP08 innovation lane, 2026-08-27
—Golden shell corpus—A fixed set of input specs with expected shell outputs as regression tests.hypothesishypothesis-openP08 innovation lane, 2026-08-27
—Generation-time nav budget enforcement—The generator refuses to emit a shell exceeding the budget cap or depth limit.hypothesishypothesis-openP08 innovation lane, 2026-08-27
—Nav budget cap as policy—A hard maximum on top-level rail items, enforced and reported.inferredhypothesis-openIBM Carbon left-panel rule
—Depth limit as policy—Maximum two tiers of navigation anywhere in a generated shell.inferredhypothesis-openCarbon: left panel does not support three tiers
—Donor nav admission rule—A donor gets a nav row only if it is a destination, not a capability.inferredadopt-as-contractTEABLE-ABSORPTION-BRIEF; FROZEN-PAGE-SKELETON gives exactly one whole-slice donor
—At most two whole-slice donors per product—Cap the number of donors that get their own page and internal nav.hypothesishypothesis-openP08 innovation lane, 2026-08-27
2Retire the fixed five-tuple type—Replace the compile-time 5-tuple with a validated variable-length list.observedrecommendedsidebar-factory.tsx:19-25 types sections as a fixed five-element tuple
—Slot ids must be semantic—Nav slot identifiers must name the work, not a positional product id.observedrecommendedISSO 'recon' means Team in one rail and Tasks in another; 'content-gen' means Tools and Insights
—One owner per nav row—Every rail row has exactly one owning system; no shared rows.inferredhypothesis-openOWNERSHIP-AND-DATA-LAYER-DECISIONS: one owner per table, never two
10Do not build marketplace—The marketplace archetype has zero demand anchor and should not be built speculatively.observedrecommendedb2b shelf: marketplace is primary for none and secondary for none across 17 industries
—Two rail width classes, not a continuum—Rail widths cluster into two functional classes rather than a continuum: ~160px forces donors to flatten their nav and use flyouts, while ~320px is wide enough to host a donor's nested nav inline. Choosing a width is therefore choosing whether donors may keep hierarchy.inferredhypothesis-openWordPress #adminmenu 160px vs Zendesk 320 / Grafana 320 / Metabase 324

Complete source register

57 mined records. Search and inspect the full agent output; nothing is collapsed into a top-ten headline.

RankIdentityWhat the agent foundEvidenceSource
—SRC-L01—DashboardSidebarInput.sections is typed as a fixed five-element tuple with the comment 'Must be exactly 5 sections'; six sections is a compile error.observedload-bearing: falsifies A15 as a flexible convention[private local source withheld]
—SRC-L02—SECTION_PRODUCTS is frozen as ['hub','intelligence','recon','agents','content-gen'].observedload-bearing[private local source withheld]
—SRC-L03—Comment 'Fixed section template - IDs, hotkeys, and fallback icons never change'; hotkeys Cmd1-Cmd5 bound to product ids.observedsupports A15 rejection as default[private local source withheld]
—SRC-L04—Agency rail maps Overview->hub, Content->intelligence, Team->recon, Webcam->agents, Tools->content-gen.observedevidence of slot-label drift[private local source withheld]
—SRC-L05—Model webcam rail maps Live->hub, Chat->intelligence, Tasks->recon, Menu->agents, Insights->content-gen. 'recon' therefore means both 'Team' and 'Tasks'; 'content-gen' means both 'Tools' and 'Insights'.observedload-bearing: semantic falsification of fixed slot ids[private local source withheld]
—SRC-L06—At least 8 top-level route groups exist (agency, model, client/[clientSlug], portal, content-gen, autosaas, chatters, social-manager, plus editor/gallery/knowledge); portal/ alone holds 20+ compliance sub-routes.observedload-bearing: five-area rail != app IA[private local source withheld] (directory listing)
—SRC-L07—Ownership table rules 'Shell / navigation rail -> OWN. Already replaced Plane's launcher'; Twenty record surfaces OWN-transplant; Plane/Documenso/Papermark/Activepieces SERVICE-downstream.observedload-bearing: host owns the rail[private local source withheld]
—SRC-L08—Names the failure mode: 'owning the security-critical parts while renting the parts that define your product'.observedadopted as absorb/preserve rationale[private local source withheld]
—SRC-L09—'Teable is NOT a page'; Tables must not be a top-level nav item; 'The broker never clicks Tables. They see a grid and it happens to be Teable'; a separate tables page 'becomes a second silo nobody updates'.observedload-bearing: donor-as-embedded-surface rule[private local source withheld]
—SRC-L10—Success criteria require donor UI to render inside the SISO shell with no login prompt and no reachable donor signup/login route.observedadopted as host identity contract[private local source withheld]
—SRC-L11—Status FROZEN. 11 host-owned pages (Dashboard, Deals, Buyers, Sellers, Tasks, Documents, Calendar, Reports, Marketing, Team, Settings) each with a base donor plus folded-in donors. No donor receives a nav entry named after itself. Tasks is the single 'whole-slice' donor (Plane).observedload-bearing: strongest local shell precedent[private local source withheld]
—SRC-L12—Section 5 'SaaS Shell Map': five primary product areas by default, 'borrows the ISSO dashboard pattern without freezing UI forever'; its gate is that the main activation workflow must be reachable through the shell.observedA15 origin traced[private local source withheld]
—SRC-L13—'no generic ISSO shell extraction' listed under Not yet complete.observedconfirms A15 never validated[private local source withheld]
—SRC-L14—Ten archetypes defined by data spine + authority model; 17 industries each mapped to a primary and secondary archetype.observedinput to coverage computationresearch/actionmodel-builder-research-2026-08-26/phase-8/lanes/03-b2b-template-shelf/outputs/b2b-template-shelf-report.md sec.2-3
—SRC-L15—Supply inversion: case_workflow (6/17 primary) and portal (6/17 secondary) have the thinnest clean-license supply; field_operations, learning_content, marketplace have zero shelf rows.observedload-bearing: build-order rationaleresearch/actionmodel-builder-research-2026-08-26/phase-8/lanes/03-b2b-template-shelf/outputs/b2b-template-shelf-report.md sec.7
—SRC-L16—Five areas 'should not become a constitutional constraint'; shells should be archetype-level assets tested against workflow comprehension and activation.observedthis run supplies the source-level receiptknowledge/00-MASTER-SYNTHESIS.md sec.'A fixed five-area shell is a hypothesis'
—SRC-L17—Eight reuse shapes named: intact service, embedded module/microfrontend, transplanted subsystem, extracted package, adapter, generated from pattern, template/archetype, custom delta. Distinguishes cosmetic from boundary adaptation.observedadopted as vocabularyknowledge/00-MASTER-SYNTHESIS.md sec.'Existing software rarely drops in untouched'
—SRC-L18—A15 'The ISSO five-area shell is universal' recorded as unproven, basis 'AutoSaaS convention only', test 'Compare against case/portal archetype task success'.observedreclassified this run to partially falsified at the semantic levelknowledge/02-ASSUMPTION-LEDGER.md A15
—SRC-L19—A32 mature services usually stay downstream (inferred); A33 product-defining surfaces owned/transplanted (inferred); A34 host can absorb donor identity/settings/navigation cleanly (UNKNOWN); A35 standardized settings/onboarding/branding adapter-driven (hypothesis).observedA34 is the target of gate E3knowledge/02-ASSUMPTION-LEDGER.md A32-A35
—SRC-L20—Bykonz exists as an archive of ~25 workstream directories plus desktop-1440/mobile-390 screenshots; includes bykonz-affine-admission, bykonz-review-donor, bykonz-integration-map, plane-delivery-candidate. Not a running application.observedblocker resolved; contents deferred[private local source withheld] (directory listing)
—SRC-L21—P08 open questions include 'Which archetypes cover 80% of the first 17 industries?' and 'How does the shell absorb donor navigation?'; known list already records the five-area shell as only a hypothesis.observedboth open questions addressed in this runsite/system-map/data/parts.json P08
—SRC-C01—Shopify embedded apps run in an iframe while the host renders navigation; apps declare nav declaratively (s-app-nav) rather than choosing a position.observedadopted: donors declare intent, host declares orderShopify App Bridge developer documentation
—SRC-C02—Zendesk app locations are fixed host-defined slots (ticket_sidebar, nav_bar, top_bar, modal); ticket_sidebar width is 320px fixed.observedload-bearing: 320px corroboration #1Zendesk Apps framework manifest reference
—SRC-C03—Grafana MegaMenu is 320px at >=md; plugins nest under /a/<id>/* and declare addToNav as a boolean; serve_from_sub_path is documented sub-path support.observedload-bearing: 320px corroboration #2 + nesting precedentGrafana MegaMenu.tsx:22 and Grafana configure-grafana docs
—SRC-C04—NAV_SIDEBAR_WIDTH is 324px; app bar 52px, subheader 48px, admin bar 65px.observed320px corroboration #3Metabase frontend nav/constants.ts
—SRC-C05—Sidebar default width is Math.min(300, mainContainerDimension.width/4); activity bar is 48px. This is the only genuinely proportional rail rule found in the corpus, and it is 25/75 capped.observedload-bearing: the only real citation for a proportional splitVS Code src/vs/workbench/browser/layout.ts:3026 and activitybarPart.ts:50-56
—SRC-C06—Carbon publishes the only vendor decision rule found: use the left panel if there are more than five secondary navigation items or if users switch between them frequently; and 'The left panel does not support three tiers of navigation'.observedadopted as nav budget cap + depth limit 2IBM Carbon Design System UI shell guidance
—SRC-C07—Left sidebar 240px, collapsed 20px (16 mobile); right sidebar 280px; right panel 368px.observedwidth class evidenceAtlassian page-layout@5.4.0/constants.js:26-32
—SRC-C08—Polaris navigation 240px, mobile max 360px, nav becomes full-width overlay below 768px. Primer panes go 100% width below 768px. Material 3 rail is 96dp collapsed / 80dp narrow / 220-360dp expanded, switching by window size class not raw px.observedadopted as collapse breakpoint guidanceShopify Polaris 13.9.5 styles.css; GitHub Primer PageLayout.module.css; Material 3 NavigationRail tokens
—SRC-C09—#adminmenu is 160px, folded 36px. The $position integer produces silent collisions patched by an MD5 hash offset, making menu order a function of what else is installed.observedload-bearing: governance rule - never let a donor pick a numeric positionWordPress admin-menu.css and add_menu_page $position behaviour
—SRC-C10—Three donor tiers recur across mature hosts: server-driven JSON (host renders, no donor CSS), host component library (donor writes against host tokens), raw iframe (donor freedom, visual drift). Consistency and expressiveness trade off monotonically.observedadopted as donor surface tieringAtlassian Forge/Connect module documentation; Slack Block Kit; Intercom Canvas Kit
—SRC-C11—No third-party embedded UI surface found in the AWS console; Marketplace provisions resources rather than rendering donor UI. Recorded as a deliberate negative data point.observednegative precedent: large hosts may refuse donor UI entirelyAWS Console (Unified Navigation) survey
—SRC-C12—The client-portal product formerly at copilot.com is now Assembly (docs.copilot.app 301 -> assembly.com/docs/); old docs.copilot.com and help.copilot.com do not resolve. practice.do returns 404 on all probed paths.observedidentity correction before client usedocs.copilot.app / assembly.com redirect chain; practice.do probes
—SRC-C13—111 commercial products were SURVEYED as a denominator space (topology, approximate area count, settings placement, multi-app switching, embedded-app surface); 24 observed and 87 inferred. Only the top 10 are RECORDED as per-row dossiers in top-companies.jsonl. The 111 figure describes surveyed breadth, not enumerated rows in this packet.inferreddenominator satisfied; do not quote inferred counts as measurementsCommercial denominator lanes A-D (111 products)
—SRC-C14—No published evidence was found linking nav topology or top-level area count to task success, comprehension or activation in any surveyed commercial product.unknownload-bearing: all comprehension scores in the matrix are judgementSearch for published comprehension/activation evidence tied to nav topology
—SRC-O01—Backstage is Apache-2.0. NavItemBlueprint was REMOVED as a breaking change in v1.51.0; nav items are now auto-discovered from PageBlueprint title/icon. RouteRef indirection means a plugin declares a routing target rather than a URL; ExternalRouteRef is bound in app-config.yaml so plugin A links to plugin B without depending on it.observedload-bearing: adopt RouteRef; nav derived from registration cannot driftgh api repos/backstage/backstage; docs/releases/v1.51.0.md; frontend-plugin-api/src/blueprints/PageBlueprint.tsx
—SRC-O02—Luigi is Apache-2.0 and is the purest OSS host shell: the host declares every navigation node (pathSegment, label, icon, category, children, viewUrl) and the donor self-registers nothing. virtualTree allows a node to accept arbitrary child paths. Host holds the OIDC session; donor calls LuigiClient.getToken(). isolateView defaults to FALSE, so same-domain nodes reuse one iframe and share a JS context unless opted out per node.observedload-bearing: host-owned nav config + host-holds-token patterngh api repos/SAP/luigi; docs/navigation-parameters-reference.md
—SRC-O03—GitHub API reports NOASSERTION but the LICENSE body is plain MIT. single-spa fires PopStateEvents and its docs state it 'deviates from the browser's default behavior in some cases'. Unlike qiankun it does not impose a one-routing-app limit. No CSS isolation whatsoever.observedload-bearing: NOASSERTION means unclassified, not restrictivegh api repos/single-spa/single-spa LICENSE body
—SRC-O04—qiankun v3 removed strictStyleIsolation/experimentalStyleIsolation; styleIsolation now uses native CSS @scope, defaults to false, and is explicitly 'a one-way boundary' - it stops the app's rules leaking out but does NOT stop host styles flowing in. @font-face remains global; cross-origin stylesheets need CORS or are dropped. A menu, dialog or tooltip rendered under document.body is outside the scope root so the app's scoped selectors will not match it. The JS sandbox is explicitly 'not a security boundary for running untrusted code' and reads fall through to the host.observedload-bearing: eliminates any option relying on donor CSS surviving or donor modals portalingumijs/qiankun docs/concepts/style-isolation.md and js-sandbox.md; docs/cookbook/migrate-from-2x.md
—SRC-O05—singleton defaults to FALSE, so dependency duplication is the silent default; even singleton:true is defeated by a missing trailing slash ('react-dom' does not intercept react-dom/client, loading a second React). Module Federation ships a Bridge subsystem explicitly for framework isolation, ensuring React contexts and component trees between applications are isolated.observedload-bearing: sharing one React tree across a donor boundary is vendor-conceded unreliablemodule-federation.io shared configuration docs
—SRC-O06—Documented sub-path support: with createBrowserRouter you set opts.basename; nested inside a host route you use <Admin basename='/admin'>. Docs state plainly 'it is your responsibility to serve the admin from the sub path'. <Admin layout={...}> replaces the entire shell, so a pass-through layout yields chrome-free content.observedload-bearing: the reference donor-absorption patternmarmelab/react-admin docs/Routing.md
—SRC-O07—NocoBase License Agreement incorporates Apache-2.0 but states its supplementary terms prevail on conflict. Section 5.2: 'It is not allowed to remove or change the brand, name, link, version number, license, and other information about NocoBase on the Software interface, except for the main LOGO in the upper left corner'. Section 5.4 forbids public no-code/low-code SaaS.observedload-bearing: chrome removal can be a licence violation, not an engineering taskgh api repos/nocobase/nocobase LICENSE.txt body
—SRC-O08—Directus is NOT BSL and NOT GPL today. It is MSCL-1.0-GPL (Monospace Sustainable Core License, 'Copyright 2026 Monospace Inc.') with a Permitted Purpose limited to non-Competing Use, a prohibition on moving/changing/disabling/circumventing the licence key functionality, and a Grant of Future License to GPL-3.0 effective only on the fourth anniversary. PUBLIC_URL is documented for link generation, not sub-path serving.observedload-bearing: any register recording Directus as BSL/GPL is stalegh api repos/directus/directus LICENSE body
—SRC-O09—28 of 104 repos returned NOASSERTION. Reading the bodies corrected verdicts in both directions: n8n and NocoDB are Sustainable Use Licence (non-OSI); Outline and Akaunting are BSL; InvoiceNinja is Elastic License 2.0; Odoo is LGPLv3; Twenty is AGPL-3.0 plus enterprise-licensed files; Teable apps are AGPL-3.0 while packages/ are MIT; single-spa is plain MIT that GitHub failed to classify.observedload-bearing: spdx_id is not a rights answergh api license bodies across the 104-repo denominator
—SRC-O10—Directory-scoped open-core is the dominant commercial pattern: ee/, enterprise/, premium/, x-pack, packages/ee/. A donor built from an ee/ path is a licence breach regardless of the top-level badge.observedadopted as licence gate ruleOSS denominator, directory-scoped open-core survey
—SRC-O11—Piral is MIT. registerPage(route, Component) with single-component-per-page; registration is ownership-scoped so pilet B cannot unregister pilet A's page. registerMenu/registerTile live in piral-menu/piral-dashboard, not core; menu items are registered in global state and rendered by the app shell. The pilet spec contains zero occurrences of iframe, sandbox or isolat - isolation is none, verified by negative evidence.observednav registry injection precedent with honest isolation limitssmapiot/piral pilet specification and API docs
—SRC-O12—Refine is MIT and headless by construction - no chrome to strip; routerProvider adapts to the host's router rather than owning routing. Refine documents NO basename/basePath of its own; sub-path behaviour is inherited from whichever router is plugged in.observedheadless-donor precedentrefinedev/refine documentation
—SRC-O13—micro-app defaults to scoped-CSS prefixing rather than shadow DOM, and documents that host styles still affect the sub-app (one-way leak). Enabling shadow disables the default scoped isolation - they are mutually exclusive, not layered, and the vendor warns to use shadow cautiously with React. wujie documents that in a plain iframe, modals can only display inside the iframe and cannot cover the whole page, and route state is lost on refresh.observedload-bearing: iframe modal confinementjd-opensource/micro-app and Tencent/wujie documentation
—SRC-O14—Reverse-proxy chrome stripping is brittle: Apache 'will not rewrite other response headers, nor will it by default rewrite URL references inside HTML pages'; nginx sub_filter is literal string replace with sub_filter_once defaulting on and directives not inherited once defined at the current level; mod_proxy_html with ProxyHTMLExtended On 'has no knowledge of what is a URL within an embedded script'; Traefik StripPrefix only sets X-Forwarded-Prefix, so a donor ignoring it escapes the mount. Runtime-generated URLs have no documented fix.observedload-bearing: proxy stripping scored low on evidence for good reasonnginx sub_module; Apache mod_proxy and mod_proxy_html; Traefik stripprefix docs
—SRC-O15—Iframe auth is a browser-policy problem: SameSite=Lax excludes navigations inside iframe elements; SameSite=None requires Secure; Firefox partitions storage by default since 103; the Storage Access API requires transient user activation so silent auth on load is unavailable, and grants expire after 30 days of inactivity. CHIPS gives per-host state, not cross-site SSO.observedload-bearing: iframe option scored 1 on identity coherenceMDN Set-Cookie, State Partitioning, Storage Access API; WHATWG HTML
—SRC-O16—Build-time vs runtime path substitution is a real architectural axis: Next.js inlines basePath into client bundles at build time so one build cannot serve two mount points, while NocoBase substitutes APP_PUBLIC_PATH at container start. Root-relative links silently escape a base path (SvelteKit requires prepending base). Tailwind Preflight collides with third-party libraries. A single host transform both traps donor z-index and re-anchors position:fixed, since stacking contexts are treated atomically.observedadopted into MountProfile contractNext.js basePath docs; SvelteKit config; Tailwind Preflight; MDN stacking context
—SRC-O17—Identity drift confirmed on several repos: calcom/cal.com redirects to calcom/cal.diy; rowyio/rowy -> buildship-ai/rowy; bytedance/garfish -> web-infra-dev/garfish; mattermost/focalboard -> mattermost-community/focalboard; creativetimofficial/material-dashboard -> creativetimofficial/ui (renamed and repurposed); kubernetes/dashboard is archived. open-mfe/openmfe returns 404 and does not exist at that path; laravel/nova is 404 (commercial).observedpin exact identities before any adoptiongh api repo resolution across the denominator
—SRC-O18—104 OSS repositories were SURVEYED as a denominator space with licence read from the LICENSE body via gh api; 28 NOASSERTION cases were resolved by reading the body. Only the top 10 are RECORDED as per-row dossiers in top-repos.jsonl. The 104 figure describes surveyed breadth, not enumerated rows in this packet.inferreddenominator satisfiedOSS denominator (104 repos)
—SRC-X01—Primary-only coverage reaches 82.4% (14/17) with 5 archetypes: case_workflow, field_operations, learning_content, scheduling, crm. Requiring BOTH primary and secondary, no subset of 7 or fewer reaches 80% (best 7 = 13/17, 76%); 8 archetypes give 15/17 (88%) and 9 give 17/17. case_workflow + portal together TOUCH 11/17 (65%) but SATISFY only 4/17 (24%). Six industries (construction, ecommerce, hospitality, logistics_freight, real_estate, saas) touch neither.observedload-bearing: answers the P08 open question, and answers it uncomfortablyThis run: coverage computation over the 17-industry primary/secondary mapping
—P08-SR-055—RETRACTION AND RE-VERIFICATION BY THE LANE OWNER. An earlier version of this record claimed the P08 label receipt was wrong (asserting recon='Comms'/'Chat Feed'). THAT CLAIM WAS ITSELF WRONG and is withdrawn. The P08 agent's original receipt is correct. Cause of my error: my extractor matched `label:` then scanned up to 400 chars for `product:`, which crossed the section/item nesting boundary and paired the first NESTED items[] label with the NEXT section's product. Re-extracted by walking back to each section object's own opening brace. VERIFIED SECTION-LEVEL PAIRS: agency rail = Overview->hub, Content->intelligence, Team->recon, Webcam->agents, Tools->content-gen. model rail = Live->hub, Chat->intelligence, Tasks->recon, Menu->agents, Insights->content-gen. content-gen rail (declares product BEFORE label) = Recon->recon, Intelligence->intelligence, Hub->hub, Content Gen->content-gen, Agents->agents — ALL FIVE SELF-CONSISTENT. Confirmed by reading raw source at agency:46-68 and content-gen:39-42/100-102.observedowner_error_retracted_agent_receipt_upheld[private local source withheld]}/sidebar-config.tsx
—P08-SR-056—LANE-OWNER VERIFIED. SISOCRM's rail is a literal RAIL_GROUPS array: 4 groups, 13 destinations. overview=[Dashboard,Calendar]; brokerage=[Deals,Buyers,Sellers]; operations=[Tasks,Documents,TABLES,AI,Reports]; company=[Marketing,Team,Settings]. `{ id: 'tables', label: 'Tables', icon: Table2, to: '/tables' }` is a REAL top-level rail destination — which CONTRADICTS TEABLE-ABSORPTION-BRIEF.md:16,18 ('A Tables page: No' / 'The broker never clicks Tables'). The 'zero donor-named nav entries' claim is FALSE as built. FROZEN-PAGE-SKELETON's 11 pages all shipped; the build added 2 unplanned (Tables, AI).observedCONTRADICTS_zero_donor_nav_claim[private local source withheld]
—P08-SR-057—LANE-OWNER VERIFIED — FIRST REAL MEASUREMENT ON ASSUMPTION A07. Patch sizes reproduce exactly: documenso-siso-frame 17, teable-siso-native-icons 27, teable-siso-records 30, twenty-siso-local 35, papermark-siso-community 62, teable-siso-embed 100, affine-siso-local 130, teable-siso-absorption 273; TOTAL 674. The GRADIENT is the finding: preserving a donor behind an iframe costs 17-62 lines of CSP/config, while absorbing identity and the data layer costs 273 lines across 9 files — touching the donor's auth strategy, SSR auth hop, DB provider and PUBLIC API validation schema (the regex /^[a-z]\w{0,62}$/i widened to accept a schema-qualified `siso.buyer_profile`).observedA07_false_as_universal_true_in_bounded_region[private local source withheld] (wc -l, all 8 patches)

Source: site/system-map/data/parts.json#P08 · preserved research datasets remain inline below their source-backed synthesis.