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

@ -0,0 +1,86 @@
#!/usr/bin/env node
/**
* Validate that no `LOCAL TIER PATCH` markers leak into the release.
*
* Background: tier downgrades during local dev are marked with a comment
* `// LOCAL TIER PATCH — revert to '<tier>' before release` so devs can
* temporarily expose alpha/beta modules to themselves on the guest tier.
* If those markers ship to prod every guest sees premium modules.
*
* This script is informational by default it lists every marker so the
* release engineer sees them. Set MANA_TIER_PATCH_STRICT=1 to fail the
* build instead (use this in the release / RC pipeline, NOT in local
* validate:all where the markers are intentional).
*
* Zero deps runs as plain Node ESM. Uses `git ls-files` so it
* automatically respects .gitignore.
*/
import { execSync } from 'node:child_process';
import { readFileSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import { dirname, join } from 'node:path';
const __dirname = dirname(fileURLToPath(import.meta.url));
const REPO_ROOT = join(__dirname, '..');
const STRICT = process.env.MANA_TIER_PATCH_STRICT === '1';
const MARKER = 'LOCAL TIER PATCH';
function listTrackedFiles() {
const out = execSync('git ls-files "*.ts" "*.tsx" "*.js" "*.mjs" "*.svelte" "*.json" "*.md"', {
cwd: REPO_ROOT,
encoding: 'utf8',
maxBuffer: 32 * 1024 * 1024,
});
return out
.split('\n')
.map((p) => p.trim())
.filter(Boolean);
}
function scan() {
const hits = [];
for (const rel of listTrackedFiles()) {
const abs = join(REPO_ROOT, rel);
let body;
try {
body = readFileSync(abs, 'utf8');
} catch {
continue;
}
if (!body.includes(MARKER)) continue;
const lines = body.split('\n');
for (let i = 0; i < lines.length; i++) {
if (lines[i].includes(MARKER)) {
hits.push({ file: rel, line: i + 1, text: lines[i].trim() });
}
}
}
return hits;
}
const hits = scan();
if (hits.length === 0) {
console.log('✓ No LOCAL TIER PATCH markers found.');
process.exit(0);
}
console.log(`Found ${hits.length} LOCAL TIER PATCH marker(s):\n`);
for (const h of hits) {
console.log(` ${h.file}:${h.line}`);
console.log(` ${h.text}`);
}
if (STRICT) {
console.error(
'\n✗ MANA_TIER_PATCH_STRICT=1 — refusing to ship while LOCAL TIER PATCH markers are present.\n' +
' Revert each marker to the documented production tier before tagging the release.'
);
process.exit(1);
}
console.log(
'\n (informational — not failing. Set MANA_TIER_PATCH_STRICT=1 in release CI to gate.)'
);