The app roster — about a dozen launcher apps

Maintainer, 2026-10-10 (binding for this phase):

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:

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
Personal Personal (new) free; host Personal/Home; preInstalled (see below)
Games Games (new) personal tier; host Games/Home; preInstalled (see below)
Hosting Hosting the fleet console. It stays a tile because it must: the core Admin app has no Operations section that links Hosting/Console yet, and the console is the control plane's daily surface. It moves into Administration › Operations with phase 3
Providers & Models Providers the shared provider keys. It stays a tile because it must, for the same reason: Administration has no AI-providers section yet. It moves there with phase 3

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
Personal/Home accounts Google, ICloud
Personal/Home home HomeAssistant, AppleWeather
Personal/Home entertainment AppleMusic
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)
(phase 3) Admin aiProviders / operations Providers, Governance, BuildServer, Observability, AzureCostManagement — not hosted yet, see below
SocialMedia channels / campaigns LinkedIn, X, YouTube / Marketing (satellite)
Reinsurance modules / demo the insurance packages / ReinsuranceDemo (satellite)

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:

The gate

check_app_roster in validate-repos.py fails a pull request when:

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 PersonalApp, three sections new, built the same way
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 no shelf yet, so nothing is hosted there in this phase. Administration › Operations and AI providers arrive in phase 3 missing
SocialMedia no shelf yet missing (phase 3)
Reinsurance no shelf yet missing (phase 3)

Cornerstone (in this repo, category Insurance) is listed by the plan as absorbed by Reinsurance; this phase leaves it standing on its own because the Reinsurance host lives in a satellite repo.

After a deploy — in this order

A merge reaches an instance through the registry once main's settle-locks pull request lands. Then:

  1. 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 Personal or Games: they install nothing (Localize takes its NothingToInstall branch), and the hosted-tile purge runs on that activation anyway.

  2. Run RefreshAppTiles straight after: a Store/Maintenance node under Admin/Maintenance with task: RefreshAppTiles, requestedAction: Run. This step mints the hosts' tiles and fixes the rename:

    • AppTileRefresh.Missing mints a tile for every package that is an app, preInstalled and not hosted, which is exactly Personal and Games, in every home.
    • A tile copies its package's name at install, so this also renames the Developer tiles 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 AppDirectory removes the window, because the launcher stops reading records.

  3. Recycle the changed types: Developer/DeveloperApp, Edu/CourseCatalog, Personal/PersonalApp and Games/GamesApp, each with enqueue_recycle(path, reason). The reason is required and is recorded in the audit under Admin/_Recycle.

  4. Verify on a real home (get @{user}/_App/*). Personal and Games are present; Google, iCloud, Home Assistant, Apple Music, Apple Weather, Learning Roadmap and the game tiles are gone; the Examples tile reads Examples. Personal/Home and Games/Home render their sections.