feat(app-registry): wire up 4 modules + 7 routes + tier-patch validator

Resolves the cross-cutting drift that the app-registry sanity-test was
silently catching but BRANDING_ONLY exceptions papered over.

App-registry wiring:
- Register augur, broadcasts, invoices, timeline as workbench cards.
- Resolve agents↔ai-agents naming drift: workbench id is now `agents`
  (matches MANA_APPS + the /agents route URL); folder stays `ai-agents`
  for grouping with other ai-* modules.

Broadcast→broadcasts unification:
- module.config appId, MANA_APPS id, APP_ICONS key, all route appIds,
  and the redundant APP_URL_OVERRIDES entry — all aligned with the
  earlier folder rename so nothing diverges anymore.

Top-level routes for workbench-only modules:
- /goals, /myday, /kontext, /rituals, /automations, /activity — thin
  RoutePage wrappers around the existing module ListViews.
- /timeline becomes a real module (ListView extracted from the route),
  route shrinks to a 12-line wrapper.

Food unarchive:
- packages/shared-branding/src/mana-apps.ts: remove `archived: true`
  from food entry. The module is fully wired (registered, synced,
  routed, with AI tools); the flag was outdated.

i18n cleanup:
- Rename ai-agents → agents key in all 5 apps locales.
- Drop dead "observatory" key from all 5 nav locales (route folder was
  removed in 7bca16dfa).

New CI guard — scripts/validate-tier-patches.mjs:
- Scans for `LOCAL TIER PATCH — revert before release` markers.
- Default: informational list (does not fail).
- Strict mode (MANA_TIER_PATCH_STRICT=1) for release/RC pipeline.
- Wired into validate:all.

Spec update:
- registry.spec.ts WORKBENCH_ONLY/BRANDING_ONLY: documented Settings
  family + AI Studio surfaces + intentionally-internal modules so the
  drift guard fires only on real drift.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Till JS 2026-04-28 22:21:41 +02:00
parent 8a5fad34df
commit fa299e3bf9
41 changed files with 812 additions and 556 deletions

View file

@ -276,7 +276,7 @@ export const APP_ICONS = {
// Emerald→teal sits next to finance green in the Arbeit & Finanzen row.
`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><linearGradient id="iv" x1="0%" y1="0%" x2="100%" y2="100%"><stop offset="0%" style="stop-color:#059669"/><stop offset="100%" style="stop-color:#14b8a6"/></linearGradient></defs><rect width="100" height="100" rx="22" fill="url(#iv)"/><path d="M28 22h34l14 14v42a4 4 0 0 1-4 4H28a4 4 0 0 1-4-4V26a4 4 0 0 1 4-4z" fill="white" fill-opacity="0.95"/><path d="M62 22v10a4 4 0 0 0 4 4h10" fill="none" stroke="#059669" stroke-width="2" stroke-opacity="0.35"/><rect x="32" y="44" width="24" height="3" rx="1" fill="#059669" fill-opacity="0.6"/><rect x="32" y="52" width="20" height="3" rx="1" fill="#059669" fill-opacity="0.45"/><rect x="32" y="60" width="28" height="3" rx="1" fill="#059669" fill-opacity="0.6"/><rect x="60" y="58" width="14" height="14" rx="1" fill="#059669"/><rect x="62" y="60" width="3" height="3" fill="white"/><rect x="69" y="60" width="3" height="3" fill="white"/><rect x="62" y="67" width="3" height="3" fill="white"/><rect x="66" y="64" width="2" height="2" fill="white"/><rect x="69" y="67" width="3" height="3" fill="white"/></svg>`
),
broadcast: svgToDataUrl(
broadcasts: svgToDataUrl(
// Megaphone / loudspeaker with three radiating sound arcs.
// Indigo→cyan gradient sets it apart from mail (blue) and invoices
// (emerald) while staying in the "communication" colour family.

View file

@ -255,7 +255,6 @@ export const MANA_APPS: ManaApp[] = [
comingSoon: false,
status: 'development',
requiredTier: 'guest',
archived: true,
},
{
id: 'contacts',
@ -1106,7 +1105,7 @@ export const MANA_APPS: ManaApp[] = [
requiredTier: 'guest', // LOCAL TIER PATCH — revert to 'beta' before release
},
{
id: 'broadcast',
id: 'broadcasts',
name: 'Broadcasts',
description: {
de: 'Newsletter & Kampagnen',
@ -1116,7 +1115,7 @@ export const MANA_APPS: ManaApp[] = [
de: 'Newsletter und Ankündigungen an Kontaktgruppen versenden — mit Rich-Text-Editor, Open/Click-Tracking, DSGVO-konformem Unsubscribe und Kampagnen-Statistik.',
en: 'Send newsletters and announcements to contact segments — with a rich-text editor, open/click tracking, GDPR-compliant unsubscribe, and per-campaign stats.',
},
icon: APP_ICONS.broadcast,
icon: APP_ICONS.broadcasts,
color: '#6366f1',
comingSoon: false,
status: 'development',
@ -1315,9 +1314,6 @@ const APP_URL_OVERRIDES: Partial<Record<AppIconId, { dev: string; prod: string }
mana: { dev: 'http://localhost:5173', prod: 'https://mana.how' },
// Standalone apps on their own subdomain / port.
arcade: { dev: 'http://localhost:5201', prod: 'https://arcade.mana.how' },
// The broadcast module's route is `/broadcasts` (plural) but the icon
// + id stay singular to match the `lib/modules/broadcast/` folder.
broadcast: { dev: 'http://localhost:5173/broadcasts', prod: 'https://mana.how/broadcasts' },
};
export const APP_URLS: Record<AppIconId, { dev: string; prod: string }> = Object.fromEntries(