The app roster — about a dozen launcher apps
Maintainer, 2026-10-10 (binding for this phase):
- "see we don't have a gazillion apps" — about a dozen launcher apps.
- Settings packages belong in the settings apps; examples belong in the Examples app; categories stay as they are.
- "games are included in personal tier" — Chess, Role Play, Quality Time and Quality Time (de) are
tier: personal, and so is the Games host. - Personal and Games are new host apps. This directive is the owner's explicit go for these two new packages. (2026-10-12: Personal is no longer an app — see Personal is not an app below.)
This page records phase 2 of the plan in Apps live on the instance (Store/AppsOnTheInstance,
§6 and §8). Phase 2 changes only declarations: app, hostedIn, extensionSlot, tier and display
names. It copies no app data into anyone's home. The launcher still reads the _App records until
phase 1a's AppDirectory is switched on, so until then the existing install machinery does what it
always does with these declarations:
- a hosted package's tile is removed by the Store's hosted-tile purge (
HostedTilePurgeWatcher), and the package appears on its host's shelf instead; - the two new
preInstalledhosts, Personal and Games (Personal no app since 2026-10-12), are auto-installed like every pre-installed pack: each viewer gets their_Apptile and_Installrecord (StandardPacks,AppTileRefresh). Those are launcher bookkeeping, not app content; phases 4–6 retire them.
The roster
Only these packages may declare app: true. The literal set is APP_ROSTER in
scripts/validate-repos.py; adding a tile is a reviewed one-line change to it.
| App | Package | Notes |
|---|---|---|
| Threads | AI |
providers and harnesses are hosted in AI/AiThreads |
| Learning | Edu |
courses, the learning roadmap and the tours (host Edu/Courses) |
| Feedback | Feedback |
|
| Examples | Developer |
shown as Examples; the id and path stay Developer so every hosted path stays put |
| Approvals | Approvals |
|
| Expenses | Expenses |
|
| Signature | Signature |
keeps hostedIn: {user}/Settings (signingAuthority) for the signing-authority tab, so the per-user record path (Localizer.ShouldRegisterApp) still mints no tile for it; AppDirectory reads app: true |
| Games | Games (new) |
personal tier; host Games/Home; preInstalled (see below) |
Satellite repos carry their own roster: SocialMedia, Reinsurance, Crm, Manufacturing, the
FundReporting root, and none in Education.
Where every other package lives
Host (hostedIn) |
Slot (extensionSlot) |
Packages |
|---|---|---|
Developer/Home (Examples) |
examples (shown as Galleries) |
AppleMaps (new), GoogleMaps, OpenStreetMap, and the control galleries already hosted |
{user}/Settings |
connections |
Google, ICloud, HomeAssistant, AppleWeather, AppleMusic — each a tab of the person app's Connections group (2026-10-15) |
Games/Home |
games |
Chess, RolePlay, QualityTime, QualityTimeDe — all tier: personal |
Edu/Courses (Learning) |
tools |
LearningRoadmap, Training |
Edu/Courses (Learning) |
courses |
the Education courses and the three Reinsurance courses (satellite PRs) |
{user}/Settings |
ai |
MyAi (the person app's Extensions tab lists it) |
Admin (core Admin app) |
operations / aiProviders |
Hosting, Governance, BuildServer, Observability, AzureCostManagement (operations); Providers (aiProviders) — rendered by Administration › Operations and AI providers (Store/AdminTabs) |
SocialMedia/Home |
channels / campaigns |
LinkedIn, X, YouTube / Marketing (satellite) |
Reinsurance/Home |
underwriting · claims · finance · capital · operations · demo |
the insurance modules by line of work (satellite); demo: ReinsuranceDemo and Cornerstone (this repo) |
category values are unchanged everywhere.
Reachable on the day it lands
Until phase 1a's AppDirectory is the launcher's source (core #6446, behind Home:AppSource,
default Records), a tile exists only as a {viewer}/_App record, and the same deploy that hosts a
package purges its tile (HostedTilePurgeWatcher). So a host must be reachable before its guests
lose their tiles, and a package whose host has no shelf yet is not hosted yet:
- Personal and Games are
preInstalled, asDeveloperis. (Historical for Personal: since 2026-10-12 it is a host, not an app, and its connectors are reached through Settings › Connections › Accounts.) A brand-new package has no viewer install, andapp: truealone mints no record (AppTileRefresh.Missingmints only for an auto-installing app or one a viewer's manifest names), so without it the replacement host would be unreachable while the hosted tiles are purged. Each host page holds only its shelves; every game and connector on it keeps its own tier and its own Get action, sopreInstalledopens no paid content. Once the launcher readsAppDirectory, the Games tile is shown by plan (personal). - The Admin moves landed with phase 3. Administration renders two shelves through the Store's
Admin tabs — Operations (
hostedIn: Admin,extensionSlot: operations: Hosting, Governance, BuildServer, Observability, AzureCostManagement) and AI providers (aiProviders: Providers) — so those packages are sections of Administration, andHostingandProvidersleft the roster. The daily operations surfaces are Admin tabs too: Fleet console and Build queue (Hosting) and Governed activities (Governance).
Personal is not an app (2026-10-12)
Maintainer, 2026-10-12: "would this be personal settings? … centralize all the logins … don't call
the app 'Personal' but rather [the person's name] … put all settings associated to me there." The
Personal tile duplicated the person app's Connections › Accounts tab (Plugins #3312), which
already lists every connector with its live state. So Personal left APP_ROSTER: the package stays
as the host its connectors name (Personal/Home, slots unchanged, so none of them grows a tile), and
Personal/Home redirects a signed-in visitor to /{viewer}/Settings/ConnectedAccounts. The person
app is the one personal home: it carries the person's name on its launcher tile (core), and
Signature's Signing authority tab (Swisscom, Skribble, DeepSign) moves into its Connections
group once core carries a shared localized group key (a raw key would otherwise show in the rail).
Maintainer, 2026-10-15: "same for settings" — the connectors no longer name Personal/Home at all.
Each one is an in-app extension of the person app (hostedIn: "{user}/Settings", slot
connections) and contributes its own tab to the Connections group — Apple Music,
Apple Weather, Google, iCloud, Home Assistant, beside Accounts, Messaging and Signing
authority — through a UiContribution (context: PersonApp, requireAddressAccess) in
{Package}/PersonAppTabs/{Package}. The tab embeds the Connection area of the package's own node
({Package}/My…), which hands over to the viewer's own copy where the credentials live (Weather: the
viewer's _Connections record). One group, five tabs: no new one-item category. The messaging
channels (Teams, WhatsApp, iMessage) and Microsoft 365 are compiled modules that already render in
the Accounts and Messaging tabs, so they contribute no node-native tab.
The gate
check_app_roster in validate-repos.py fails a pull request when:
- a
Store/Pluginroot declaresapp: trueand is not on the roster; - a
hostedInnames a host that is not DECLARED inHOST_SLOTS— the literal host → slots contract ({user}/Settings,AI/AiThreads,Developer/Home,Personal/Home,Games/Home,Edu/Courses,Reinsurance/Home,Admin; a satellite adds its own host, e.g.SocialMedia/Home). A host is valid because its shelf is declared, never because a node exists at that path. A declared host inside this repo must also exist as a node (never a README, rawcontent/file or…/indexalias); hostedInwithoutextensionSlot, a slot the host does not render, a slot withouthostedIn, or an app that is also a section (a{user}/Settingstab excepted);- a roster entry that does not declare
app: trueor has no root at all.
The checker is one block, the same text in all seven plugin repos; only APP_ROSTER and
HOST_SLOTS are repo input. Its fixtures also run from main(), so a regression reds ordinary
validation.
Both failures are silent at runtime: a stray app is one more tile on every home, and a missing host
removes the package's tile and lists it on a shelf nobody renders. --self-test runs the gate over
fixtures in both directions.
Host apps and their shelves
| Host | Shelf | State |
|---|---|---|
Developer/Home |
DeveloperApp renders Store/area/Extensions per slot |
built |
Personal/Home |
none since 2026-10-12: the page forwards to the viewer's Settings › Connections › Accounts, which lists every connector with its state (see Personal is not an app below) | retired as an app |
Games/Home |
GamesApp, one section |
new, built the same way |
Edu/Courses |
the course catalog page embeds the tools shelf under More in Learning; courses are listed by the catalog's own query, never by the shelf, so a hosted course is not shown twice |
built |
{user}/Settings |
the person app's Extensions tab | exists |
AI/AiThreads |
the Threads app's shelves | exists |
Admin |
Administration › Operations and AI providers render the operations / aiProviders shelves (phase 3) |
✅ |
SocialMedia/Home |
SocialMediaApp (MeshWeaver.SocialMedia), Channels and Campaigns |
built (follow-up, 2026-10-10) |
Reinsurance/Home |
ReinsuranceApp (MeshWeaver.Reinsurance), six sections by line of work |
built (follow-up, 2026-10-10) |
Cornerstone (in this repo, category Insurance) is hosted by Reinsurance: hostedIn: "Reinsurance/Home",
slot demo, beside ReinsuranceDemo. Plugins' HOST_SLOTS carries the Reinsurance/Home entry so the
gate accepts it; the node itself lives in the satellite, so the node-exists check does not apply here.
Cornerstone stays tier: free. A hosted package loses its own tile, and the catalog lists hosted
packages only to admins. So a viewer who holds Cornerstone but not the enterprise Reinsurance app
reaches it only by its URL until phase 1a's AppDirectory shows hosted packages by plan.
The satellite hosts (follow-up, 2026-10-10). In phase 2, the SocialMedia and Reinsurance guests
named the satellite ROOT as their host, and no page there rendered a shelf. Each now has a host page,
SocialMedia/Home and Reinsurance/Home, built like Personal. Each root's entryPoint opens that
page, and the guests name it in hostedIn. Reinsurance replaced its single modules slot with one
slot per line of work. LinkedIn profile pins (ProfileAppPin, ProfileTilesEnsure) still mint
_App tiles. Making them sections of Social Media would retire two writers and their tile migration,
and would need a purge of the records already in every home. That is phase 4/5 work, recorded in
SocialMedia's Guide.
After a deploy — in this order
A merge reaches an instance through the registry once main's settle-locks pull request lands. Then:
Recycle the Store root (
enqueue_recycle(path: "Store", reason: "app roster deployed: rebind the catalog")), so its hub binds the new catalog. Recycling mints no tile for Games: they install nothing (Localizetakes itsNothingToInstallbranch), and the hosted-tile purge runs on that activation anyway.Run
RefreshAppTilesstraight after: aStore/Maintenancenode underAdmin/Maintenancewithtask: RefreshAppTiles,requestedAction: Run. This step mints the hosts' tiles and fixes the rename:AppTileRefresh.Missingmints a tile for every package that is an app,preInstalledand not hosted, which is exactly Games, in every home (Personal is no app since 2026-10-12).- A tile copies its package's name at install, so this also renames the
Developertiles to Examples.
Between the purge and this run there is a short window in which a home has neither the old guest tiles nor the new hosts. No data is touched: every package stays at its own URL and on its host's shelf. A viewer who renders the Store in that window self-heals the same way. Phase 1a's
AppDirectoryremoves the window, because the launcher stops reading records.Recycle the changed types:
Developer/DeveloperApp,Edu/CourseCatalog,Personal/PersonalApp(now a forward to Settings › Connections › Accounts) andGames/GamesApp, each withenqueue_recycle(path, reason). The reason is required and is recorded in the audit underAdmin/_Recycle.Verify on a real home (
search path:{user}/_Apps). Games is present and Personal is not; Google, iCloud, Home Assistant, Apple Music, Apple Weather, Learning Roadmap and the game tiles are gone; the Examples tile reads Examples.Games/Homerenders its section, andPersonal/Homeforwards a signed-in viewer to/{viewer}/Settings/ConnectedAccounts.