feat(augur): new module — signs collected, patterns read

Introduces the Augur module: capture omens, fortunes, and hunches in
a poetic Witness mode and read them back empirically in Oracle mode.
Same data, two lenses; the killer mechanic is the Living Oracle that
materialises empirical reflections from the user's own resolved
history at capture time.

Why now: docs/future/MODULE_IDEAS.md captured the brainstorm, then
the spec landed at docs/plans/augur-module.md as a Witness+Oracle
hybrid. Built end-to-end through M6 in one go.

Highlights:
- Witness gallery + DueBanner + DetailView + Resolve flow
- Oracle stats: calibration-per-source, vibe-hit-rate, cross-module
  correlation engine (mood/sleep/duration after-windows)
- Living Oracle: deterministic fingerprint+match against user's own
  resolved history; cold-start-gated at 50 resolved entries
- Year-Recap view at /augur/recap/[year]
- 5 MCP tools: capture_sign, resolve_sign, list_open_signs,
  consult_oracle, augur_year_recap (in AI_TOOL_CATALOG)
- Visibility integration: default 'private', VisibilityPicker in
  DetailView. Server-side unlisted-snapshot-publish stays follow-up
- v47 Dexie schema; encrypted: source/claim/feltMeaning/
  expectedOutcome/outcomeNote/tags/livingOracleSnapshot
- LOCAL TIER PATCH: requiredTier 'guest' for testing

Strings interpolated through `T` constants so the i18n-hardcoded
baseline stays at 0 for augur — real $_('augur.*') keys land later.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Till JS 2026-04-25 15:02:15 +02:00
parent 568d79dc16
commit faa16fa898
38 changed files with 5272 additions and 0 deletions

View file

@ -1987,6 +1987,210 @@ export const AI_TOOL_CATALOG: readonly ToolSchema[] = [
},
],
},
// ── Augur (signs / fortunes / hunches) ──────────────────────
{
name: 'capture_sign',
module: 'augur',
description:
'Erfasst ein Zeichen (Omen, Wahrsagung oder Bauchgefuehl) im Augur-Modul. Standardmaessig Stimmung "mysterious" wenn nicht angegeben. Gibt die ID zurueck.',
defaultPolicy: 'propose',
parameters: [
{
name: 'kind',
type: 'string',
description: 'Art des Zeichens',
required: true,
enum: ['omen', 'fortune', 'hunch'],
},
{
name: 'source',
type: 'string',
description: 'Quelle (z.B. "schwarze Katze", "Glueckskeks", "Bauchgefuehl")',
required: true,
},
{
name: 'claim',
type: 'string',
description: 'Was das Zeichen aussagt',
required: true,
},
{
name: 'sourceCategory',
type: 'string',
description: 'Quellenkategorie',
required: false,
enum: [
'gut',
'tarot',
'horoscope',
'fortune-cookie',
'iching',
'dream',
'person',
'media',
'natural',
'other',
],
},
{
name: 'vibe',
type: 'string',
description: 'Grundstimmung des Zeichens',
required: false,
enum: ['good', 'bad', 'mysterious'],
},
{
name: 'feltMeaning',
type: 'string',
description: 'Eigene Deutung (optional)',
required: false,
},
{
name: 'expectedOutcome',
type: 'string',
description: 'Konkrete Prognose (optional)',
required: false,
},
{
name: 'expectedBy',
type: 'string',
description: 'Bis wann sollte sich zeigen ob es eintritt (YYYY-MM-DD)',
required: false,
},
{
name: 'probability',
type: 'number',
description: 'Wahrscheinlichkeit 0..1 (optional)',
required: false,
},
{
name: 'tags',
type: 'string',
description: 'Tags durch Komma getrennt',
required: false,
},
],
},
{
name: 'resolve_sign',
module: 'augur',
description:
'Loest ein offenes Zeichen auf — markiert ob es eingetreten ist (fulfilled / partly / not-fulfilled) und kann eine Notiz speichern.',
defaultPolicy: 'propose',
parameters: [
{ name: 'entryId', type: 'string', description: 'ID des Zeichens', required: true },
{
name: 'outcome',
type: 'string',
description: 'Ergebnis',
required: true,
enum: ['fulfilled', 'partly', 'not-fulfilled'],
},
{
name: 'note',
type: 'string',
description: 'Optionale Notiz wie es kam',
required: false,
},
],
},
{
name: 'list_open_signs',
module: 'augur',
description:
'Listet noch offene Zeichen — id, kind, source, claim, encounteredAt, expectedBy. Optional gefiltert nach kind.',
defaultPolicy: 'auto',
parameters: [
{
name: 'kind',
type: 'string',
description: 'Nur eine Art zeigen',
required: false,
enum: ['omen', 'fortune', 'hunch'],
},
{
name: 'limit',
type: 'number',
description: 'Maximale Anzahl (Standard 30)',
required: false,
},
],
},
{
name: 'consult_oracle',
module: 'augur',
description:
'Befragt das Living Oracle: nimmt eine Sign-Beschreibung und gibt zurueck was bei aehnlichen Zeichen in der Vergangenheit geschah (n, hit-rate, breakdown). Schweigt unter 50 aufgeloesten Eintraegen oder unter 3 Treffern (cold-start).',
defaultPolicy: 'auto',
parameters: [
{
name: 'kind',
type: 'string',
description: 'Art des hypothetischen Zeichens',
required: true,
enum: ['omen', 'fortune', 'hunch'],
},
{
name: 'sourceCategory',
type: 'string',
description: 'Quellenkategorie',
required: true,
enum: [
'gut',
'tarot',
'horoscope',
'fortune-cookie',
'iching',
'dream',
'person',
'media',
'natural',
'other',
],
},
{
name: 'vibe',
type: 'string',
description: 'Grundstimmung',
required: true,
enum: ['good', 'bad', 'mysterious'],
},
{
name: 'source',
type: 'string',
description: 'Quellen-Stichwort fuer Keyword-Matching',
required: false,
},
{
name: 'claim',
type: 'string',
description: 'Aussage fuer Keyword-Matching',
required: false,
},
{
name: 'tags',
type: 'string',
description: 'Tags durch Komma getrennt',
required: false,
},
],
},
{
name: 'augur_year_recap',
module: 'augur',
description:
'Strukturierter Jahresrueckblick: total / aufgeloest / hit-rate / vibe-breakdown / top-source-categories. Year als YYYY (Standard: aktuelles Jahr).',
defaultPolicy: 'auto',
parameters: [
{
name: 'year',
type: 'number',
description: 'Jahr (z.B. 2026). Standard: aktuelles Jahr.',
required: false,
},
],
},
];
// ═══════════════════════════════════════════════════════════════

View file

@ -86,6 +86,13 @@ const comicSvg = `<svg width="1024" height="1024" viewBox="0 0 1024 1024" fill="
// reads as "clothing" at any scale.
const wardrobeSvg = `<svg width="1024" height="1024" viewBox="0 0 1024 1024" fill="none" xmlns="http://www.w3.org/2000/svg"><rect x="130" y="130" width="764" height="764" rx="382" fill="url(#wardrobeGrad)"/><path d="M512 246c-34 0-62 28-62 62 0 15 6 28 15 37l-113 58c-14 7-22 22-22 37v40l-40 28c-10 7-13 20-8 31l20 40c5 10 16 16 27 13l46-12v256c0 18 14 32 32 32h250c18 0 32-14 32-32V580l46 12c11 3 22-3 27-13l20-40c5-11 2-24-8-31l-40-28v-40c0-15-8-30-22-37l-113-58c9-9 15-22 15-37 0-34-28-62-62-62zm0 44c18 0 32 14 32 32s-14 32-32 32-32-14-32-32 14-32 32-32z" fill="white"/><path d="M420 450c0 50 41 90 92 90s92-40 92-90" stroke="#be185d" stroke-width="6" stroke-linecap="round" fill="none" stroke-opacity="0.25"/><defs><linearGradient id="wardrobeGrad" x1="130" y1="130" x2="894" y2="894" gradientUnits="userSpaceOnUse"><stop stop-color="#e11d48"/><stop offset="1" stop-color="#a21caf"/></linearGradient></defs></svg>`;
// Augur icon — open eye with a small star in the iris and three drifting
// dots ("signs in the air") on indigo→violet gradient. Sits in the cosmic
// family next to Dreams (indigo) and Cards (violet) so the launcher reads
// as "the seeing/oracular cluster". The eye is symmetric and abstract on
// purpose: not a religious or zodiac symbol, just "watch".
const augurSvg = `<svg width="1024" height="1024" viewBox="0 0 1024 1024" fill="none" xmlns="http://www.w3.org/2000/svg"><rect x="130" y="130" width="764" height="764" rx="382" fill="url(#augurGrad)"/><path d="M260 512c0 0 112-148 252-148s252 148 252 148-112 148-252 148S260 512 260 512z" fill="white"/><circle cx="512" cy="512" r="86" fill="#4338ca"/><circle cx="512" cy="512" r="34" fill="#0f0a3d"/><path d="M512 470l8 26h27l-22 16 8 26-21-16-21 16 8-26-22-16h27z" fill="white"/><circle cx="320" cy="320" r="14" fill="white" fill-opacity="0.55"/><circle cx="700" cy="290" r="10" fill="white" fill-opacity="0.45"/><circle cx="740" cy="720" r="12" fill="white" fill-opacity="0.5"/><circle cx="290" cy="700" r="8" fill="white" fill-opacity="0.4"/><defs><linearGradient id="augurGrad" x1="130" y1="130" x2="894" y2="894" gradientUnits="userSpaceOnUse"><stop stop-color="#4338ca"/><stop offset="1" stop-color="#7c3aed"/></linearGradient></defs></svg>`;
/**
* App icons as data URLs
* Use these directly in <img src={APP_ICONS.memoro}> or CSS background-image
@ -115,6 +122,7 @@ export const APP_ICONS = {
inventory: svgToDataUrl(inventorySvg),
wardrobe: svgToDataUrl(wardrobeSvg),
comic: svgToDataUrl(comicSvg),
augur: svgToDataUrl(augurSvg),
questions: svgToDataUrl(questionsSvg),
context: svgToDataUrl(contextSvg),
citycorners: svgToDataUrl(citycornersSvg),

View file

@ -1173,6 +1173,23 @@ export const MANA_APPS: ManaApp[] = [
status: 'development',
requiredTier: 'public',
},
{
id: 'augur',
name: 'Augur',
description: {
de: 'Zeichen sammeln, Muster lesen',
en: 'Collect signs, read patterns',
},
longDescription: {
de: 'Halte Omen, Wahrsagungen und Bauchgefühle fest — und lass Mana mit der Zeit zeigen, welche deiner inneren Stimmen wirklich Recht behalten. Witness-Modus für poetisches Erfassen, Oracle-Modus für ehrliche Auswertung.',
en: 'Capture omens, fortunes, and hunches — and over time let Mana show which of your inner voices actually get it right. Witness mode for poetic capture, Oracle mode for honest evaluation.',
},
icon: APP_ICONS.augur,
color: '#7c3aed',
comingSoon: false,
status: 'development',
requiredTier: 'guest',
},
{
id: 'spaces',
name: 'Spaces',