diff --git a/__tests__/api/instant-light.route.test.ts b/__tests__/api/instant-light.route.test.ts new file mode 100644 index 0000000..65e4797 --- /dev/null +++ b/__tests__/api/instant-light.route.test.ts @@ -0,0 +1,149 @@ +/** + * Testes de integração para GET /api/instant-light. + * Cobre: resposta universal (anon), resposta personal (perfil), cooldown server-side (sessão mock). + */ + +import { sessionCookieHeader } from "@/lib/auth"; + +const mockCookies = jest.fn(); +const mockGetRecentSacredIds = jest.fn(); +const mockGetRecentStateKeys = jest.fn(); +const mockRecordInstantLight = jest.fn(); + +jest.mock("next/headers", () => ({ + cookies: () => mockCookies(), +})); + +jest.mock("@/lib/history/historyAdapter", () => ({ + getRecentSacredIds: (...args: unknown[]) => mockGetRecentSacredIds(...args), + getRecentStateKeys: (...args: unknown[]) => mockGetRecentStateKeys(...args), + recordInstantLight: (...args: unknown[]) => mockRecordInstantLight(...args), +})); + +describe("GET /api/instant-light", () => { + beforeEach(() => { + jest.clearAllMocks(); + mockCookies.mockResolvedValue({ toString: () => "" }); + mockGetRecentSacredIds.mockResolvedValue([]); + mockGetRecentStateKeys.mockResolvedValue([]); + mockRecordInstantLight.mockResolvedValue(undefined); + }); + + async function getHandler() { + const mod = await import("@/app/api/instant-light/route"); + return mod.GET; + } + + describe("modo anônimo (sem sessão)", () => { + it("retorna 200 com DarshanTruthPackage: sacred, practice, question, sacredId, stateKey", async () => { + const GET = await getHandler(); + const req = new Request("http://localhost/api/instant-light"); + const res = await GET(req); + expect(res.status).toBe(200); + + const body = await res.json(); + expect(body).toHaveProperty("sacredText"); + expect(body).toHaveProperty("sacred"); + expect(body.sacred).toHaveProperty("id"); + expect(body.sacred).toHaveProperty("corpus"); + expect(body).toHaveProperty("practice"); + expect(body.practice).toHaveProperty("title"); + expect(body.practice).toHaveProperty("steps"); + expect(body).toHaveProperty("question"); + expect(body.question).toHaveProperty("text"); + expect(body).toHaveProperty("contemplativeQuestion"); + expect(body.contemplativeQuestion).toHaveProperty("text"); + expect(body).toHaveProperty("meta"); + expect(typeof body.meta?.generatedAt).toBe("string"); + expect(body).toHaveProperty("sacredId"); + expect(body).toHaveProperty("stateKey"); + expect(typeof body.sacredText).toBe("string"); + expect(typeof body.question.text).toBe("string"); + }); + + it("não inclui insight quando não há perfil", async () => { + const GET = await getHandler(); + const req = new Request("http://localhost/api/instant-light"); + const res = await GET(req); + const body = await res.json(); + expect(body.insight).toBeUndefined(); + }); + + it("não chama getRecentSacredIds nem recordInstantLight quando não há sessão", async () => { + const GET = await getHandler(); + const req = new Request("http://localhost/api/instant-light"); + await GET(req); + expect(mockGetRecentSacredIds).not.toHaveBeenCalled(); + expect(mockRecordInstantLight).not.toHaveBeenCalled(); + }); + }); + + describe("modo personal (query fullName + birthDate)", () => { + it("retorna 200 e pode incluir insight", async () => { + const GET = await getHandler(); + const req = new Request( + "http://localhost/api/instant-light?fullName=Ana+Costa&birthDate=1988-03-20" + ); + const res = await GET(req); + expect(res.status).toBe(200); + const body = await res.json(); + expect(body).toHaveProperty("sacredText"); + expect(body).toHaveProperty("practice"); + expect(body).toHaveProperty("question"); + if (body.insight) expect(typeof body.insight).toBe("string"); + }); + }); + + describe("cooldown server-side (com sessão)", () => { + it("com sessão válida, chama getRecentSacredIds e getRecentStateKeys e usa resultado no composer", async () => { + const cookieStr = sessionCookieHeader({ email: "user@example.com" }); + mockCookies.mockResolvedValue({ toString: () => cookieStr }); + mockGetRecentSacredIds.mockResolvedValue(["yoga_sutras.YS.1.1"]); + mockGetRecentStateKeys.mockResolvedValue(["anxiety"]); + + const GET = await getHandler(); + const req = new Request("http://localhost/api/instant-light"); + const res = await GET(req); + expect(res.status).toBe(200); + expect(mockGetRecentSacredIds).toHaveBeenCalledWith("user@example.com", 7); + expect(mockGetRecentStateKeys).toHaveBeenCalledWith("user@example.com", 7); + const body = await res.json(); + expect(body).toHaveProperty("sacredId"); + expect(body).toHaveProperty("stateKey"); + }); + + it("com sessão e sacred na resposta, chama recordInstantLight", async () => { + const cookieStr = sessionCookieHeader({ email: "user@example.com" }); + mockCookies.mockResolvedValue({ toString: () => cookieStr }); + mockGetRecentSacredIds.mockResolvedValue([]); + mockGetRecentStateKeys.mockResolvedValue([]); + + const GET = await getHandler(); + const req = new Request("http://localhost/api/instant-light"); + const res = await GET(req); + expect(res.status).toBe(200); + const body = await res.json(); + if (body.sacred?.id) { + expect(mockRecordInstantLight).toHaveBeenCalledWith("user@example.com", body); + } + }); + }); + + describe("formato da resposta (food, sleep, routine opcionais)", () => { + it("resposta pode conter food (do/avoid), sleep, routine quando aplicável", async () => { + const GET = await getHandler(); + const req = new Request( + "http://localhost/api/instant-light?fullName=Maria&birthDate=1990-05-15" + ); + const res = await GET(req); + const body = await res.json(); + expect(body).toHaveProperty("practice"); + expect(body.practice).toHaveProperty("steps"); + expect(body).toHaveProperty("question"); + expect(body.question).toHaveProperty("text"); + if (body.food !== undefined) expect(Array.isArray(body.food.do) || Array.isArray(body.food)).toBe(true); + if (body.sleep !== undefined) expect(typeof body.sleep).toBe("string"); + if (body.routine !== undefined) expect(typeof body.routine).toBe("string"); + }); + }); +}); diff --git a/__tests__/lib/finance/creditsManager.test.ts b/__tests__/lib/finance/creditsManager.test.ts index 97301ee..cb68027 100644 --- a/__tests__/lib/finance/creditsManager.test.ts +++ b/__tests__/lib/finance/creditsManager.test.ts @@ -288,7 +288,7 @@ describe("lib/finance/creditsManager (com Supabase)", () => { it("retorna null quando insert payment falha", async () => { mockGetSupabase.mockReturnValue( createMockSupabaseClient({ - selectUser: { data: { id: "u1" } }, + selectUser: { data: { id: "u1", credits_balance: 0 } }, insertPayment: { data: null }, }) ); diff --git a/__tests__/lib/input/intentParser.test.ts b/__tests__/lib/input/intentParser.test.ts new file mode 100644 index 0000000..e127ca0 --- /dev/null +++ b/__tests__/lib/input/intentParser.test.ts @@ -0,0 +1,66 @@ +/** + * Testes para lib/input — Intent Parser e State Scorer. + * Multi-eixo: verbo, sujeito, tema, emoção → stateCandidates → bestStateKey. + */ + +import { parseIntent } from "@/lib/input/intentParser"; +import { scoreState } from "@/lib/input/stateScorer"; + +describe("lib/input intentParser", () => { + describe("parseIntent", () => { + it("retorna null para texto vazio ou null", () => { + expect(parseIntent(null)).toBeNull(); + expect(parseIntent(undefined)).toBeNull(); + expect(parseIntent("")).toBeNull(); + expect(parseIntent(" ")).toBeNull(); + }); + + it("detecta verbClass fear em 'Tenho medo de perder meu relacionamento'", () => { + const intent = parseIntent("Tenho medo de perder meu relacionamento"); + expect(intent).not.toBeNull(); + expect(intent!.verbClass).toBe("fear"); + expect(intent!.subject).toBe("self"); + expect(intent!.theme).toBe("love"); + expect(intent!.stateCandidates.length).toBeGreaterThan(0); + }); + + it("detecta tema love em texto com 'amor' e 'relacionamento'", () => { + const intent = parseIntent("Estou com medo no meu relacionamento"); + expect(intent).not.toBeNull(); + expect(intent!.theme).toBe("love"); + }); + + it("detecta emoção e stateCandidates para 'ansioso'", () => { + const intent = parseIntent("Estou muito ansioso"); + expect(intent).not.toBeNull(); + expect(intent!.emotionLabels.length).toBeGreaterThan(0); + expect(intent!.stateCandidates.some((c) => c.stateKey === "anxiety")).toBe(true); + }); + + it("retorna subject self quando tem 'eu' ou 'meu'", () => { + expect(parseIntent("Eu não aguento mais")!.subject).toBe("self"); + expect(parseIntent("Meu trabalho está me matando")!.subject).toBe("self"); + }); + }); +}); + +describe("lib/input stateScorer", () => { + it("retorna undefined para intent null; retorna fallback confusion quando sem stateCandidates", () => { + expect(scoreState(null)).toBeUndefined(); + expect(scoreState({ subject: "self", verbClass: null, theme: "general", emotionLabels: [], stateCandidates: [] })).toBe("confusion"); + }); + + it("retorna stateKey válido quando há candidatos", () => { + const intent = parseIntent("Tenho medo de perder meu relacionamento"); + const best = scoreState(intent); + expect(best).toBeDefined(); + expect(["anxiety", "relational_insecurity", "avoidance"]).toContain(best); + }); + + it("prioriza anxiety para fear + love (ex.: medo de perder relacionamento)", () => { + const intent = parseIntent("Tenho medo de perder meu relacionamento"); + const best = scoreState(intent); + expect(best).toBeDefined(); + expect(["anxiety", "relational_insecurity"]).toContain(best); + }); +}); diff --git a/__tests__/lib/sacredRemedy/ayurvedaActionSelector.test.ts b/__tests__/lib/sacredRemedy/ayurvedaActionSelector.test.ts new file mode 100644 index 0000000..3ca77b5 --- /dev/null +++ b/__tests__/lib/sacredRemedy/ayurvedaActionSelector.test.ts @@ -0,0 +1,150 @@ +/** + * Testes para lib/sacredRemedy/ayurvedaActionSelector. + * Antídotos por qualidade, múltiplas qualities, prioridade por dosha. + */ + +import { + getPracticeForQuality, + getFoodForQuality, + getActionsForQualities, + getActionsForQualitiesWithDosha, + getSeasonFromDate, + getHourPeriodFromDate, + getFullActionsForQualitiesWithDosha, + QUALITY_TO_PRACTICE, + QUALITY_TO_FOOD, +} from "@/lib/sacredRemedy/ayurvedaActionSelector"; + +describe("sacredRemedy/ayurvedaActionSelector", () => { + describe("getPracticeForQuality / getFoodForQuality", () => { + it("retorna prática e alimento para qualidade conhecida", () => { + const practice = getPracticeForQuality("ruksha"); + const food = getFoodForQuality("ruksha"); + expect(typeof practice).toBe("string"); + expect(practice.length).toBeGreaterThan(0); + expect(practice).not.toBe("—"); + expect(typeof food).toBe("string"); + expect(food.length).toBeGreaterThan(0); + }); + + it("ruksha tem antídoto oleação/calor", () => { + expect(getPracticeForQuality("ruksha")).toMatch(/oleação|óleo/i); + expect(getFoodForQuality("ruksha")).toMatch(/ghee|oleação|sopa/i); + }); + + it("chala tem antídoto grounding", () => { + expect(getPracticeForQuality("chala")).toMatch(/grounding|pés|chão|caminhada/i); + }); + }); + + describe("getActionsForQualities", () => { + it("retorna practice e food para lista de qualities", () => { + const { practice, food } = getActionsForQualities(["ruksha", "chala"]); + expect(typeof practice).toBe("string"); + expect(typeof food).toBe("string"); + }); + + it("usa primeira qualidade com mapeamento", () => { + const { practice } = getActionsForQualities(["ruksha"]); + expect(practice).toBe(QUALITY_TO_PRACTICE["ruksha"]); + }); + + it("lista vazia retorna strings vazias", () => { + const { practice, food } = getActionsForQualities([]); + expect(practice).toBe(""); + expect(food).toBe(""); + }); + }); + + describe("getActionsForQualitiesWithDosha", () => { + it("retorna practice e food com múltiplas sugestões quando há várias qualities", () => { + const { practice, food } = getActionsForQualitiesWithDosha( + ["ruksha", "chala", "ushna"], + "vata", + { maxSuggestions: 3 } + ); + expect(typeof practice).toBe("string"); + expect(typeof food).toBe("string"); + if (practice) expect(practice.length).toBeGreaterThan(0); + if (food) expect(food.length).toBeGreaterThan(0); + }); + + it("com dosha pitta prioriza qualities do pitta", () => { + const { practice } = getActionsForQualitiesWithDosha( + ["ushna", "tikshna", "ruksha"], + "pitta", + { maxSuggestions: 2 } + ); + expect(typeof practice).toBe("string"); + }); + + it("maxSuggestions limita quantidade de sugestões combinadas", () => { + const { practice } = getActionsForQualitiesWithDosha( + ["ruksha", "chala", "guru", "manda", "sthira"], + "kapha", + { maxSuggestions: 1 } + ); + const parts = practice.split(". ").filter(Boolean); + expect(parts.length).toBeLessThanOrEqual(2); + }); + + it("com season summer prioriza qualities do pitta na ordenação", () => { + const { practice } = getActionsForQualitiesWithDosha( + ["ushna", "ruksha", "tikshna"], + "vata", + { maxSuggestions: 3, season: "summer" } + ); + expect(typeof practice).toBe("string"); + expect(practice.length).toBeGreaterThan(0); + }); + + it("com hour midday retorna resultado consistente", () => { + const { practice, food } = getFullActionsForQualitiesWithDosha( + ["ushna", "tikshna"], + "pitta", + { maxSuggestions: 2, hour: "midday" } + ); + expect(typeof practice).toBe("string"); + expect(typeof food).toBe("string"); + }); + }); + + describe("getSeasonFromDate / getHourPeriodFromDate", () => { + it("getSeasonFromDate retorna winter para jan", () => { + expect(getSeasonFromDate(new Date(2025, 0, 15))).toBe("winter"); + }); + it("getSeasonFromDate retorna summer para jul", () => { + expect(getSeasonFromDate(new Date(2025, 6, 15))).toBe("summer"); + }); + it("getSeasonFromDate retorna autumn para out", () => { + expect(getSeasonFromDate(new Date(2025, 9, 15))).toBe("autumn"); + }); + it("getHourPeriodFromDate retorna morning para 8h", () => { + expect(getHourPeriodFromDate(new Date(2025, 0, 1, 8, 0))).toBe("morning"); + }); + it("getHourPeriodFromDate retorna midday para 12h", () => { + expect(getHourPeriodFromDate(new Date(2025, 0, 1, 12, 0))).toBe("midday"); + }); + it("getHourPeriodFromDate retorna evening para 20h", () => { + expect(getHourPeriodFromDate(new Date(2025, 0, 1, 20, 0))).toBe("evening"); + }); + }); + + describe("20 gunas cobertas", () => { + const qualities = [ + "ruksha", "chala", "tikshna", "ushna", "guru", "manda", "sthira", + "picchila", "kathina", "khara", "sukshma", "laghu", "snigdha", "sita", + "mridu", "vishada", "sandra", "drava", "sara", "shlakshna", "sthula", + ]; + it("QUALITY_TO_PRACTICE e QUALITY_TO_FOOD têm entrada para todas as qualities principais", () => { + for (const q of qualities) { + const p = QUALITY_TO_PRACTICE[q]; + const f = QUALITY_TO_FOOD[q]; + expect(p !== undefined).toBe(true); + expect(f !== undefined).toBe(true); + expect(p === "—" || p.length > 0).toBe(true); + expect(f === "—" || f.length > 0).toBe(true); + } + }); + }); +}); diff --git a/__tests__/lib/sacredRemedy/diagnosisEngine.test.ts b/__tests__/lib/sacredRemedy/diagnosisEngine.test.ts new file mode 100644 index 0000000..946ec1f --- /dev/null +++ b/__tests__/lib/sacredRemedy/diagnosisEngine.test.ts @@ -0,0 +1,141 @@ +/** + * Testes para lib/sacredRemedy/diagnosisEngine. + * Determinismo, universal vs personal, numerologia no diagnóstico. + */ + +import { + diagnosisUniversal, + diagnosisPersonal, + getRemedyForDiagnosis, + getRemedyMatrix, +} from "@/lib/sacredRemedy/diagnosisEngine"; +import type { ConsciousDiagnosis } from "@/lib/sacredRemedy/types"; + +describe("sacredRemedy/diagnosisEngine", () => { + describe("getRemedyMatrix", () => { + it("retorna array não vazio com estados, klesha, samkhyaGuna, qualities", () => { + const matrix = getRemedyMatrix(); + expect(Array.isArray(matrix)).toBe(true); + expect(matrix.length).toBeGreaterThan(0); + const first = matrix[0]; + expect(first).toHaveProperty("state"); + expect(first).toHaveProperty("klesha"); + expect(first).toHaveProperty("samkhyaGuna"); + expect(first).toHaveProperty("qualities"); + expect(first).toHaveProperty("sacred"); + expect(first).toHaveProperty("practice"); + expect(first).toHaveProperty("food"); + expect(first).toHaveProperty("question"); + }); + }); + + describe("diagnosisUniversal", () => { + it("retorna ConsciousDiagnosis com klesha, samkhyaGunas, ayurvedicQualities, stateKey", () => { + const d = diagnosisUniversal({ seed: 42 }); + expect(d).toHaveProperty("klesha"); + expect(d).toHaveProperty("samkhyaGunas"); + expect(d.samkhyaGunas).toHaveProperty("sattva"); + expect(d.samkhyaGunas).toHaveProperty("rajas"); + expect(d.samkhyaGunas).toHaveProperty("tamas"); + expect(d).toHaveProperty("ayurvedicQualities"); + expect(d.ayurvedicQualities).toHaveProperty("excess"); + expect(d.ayurvedicQualities).toHaveProperty("deficient"); + expect(d).toHaveProperty("stateKey"); + expect(typeof d.stateKey).toBe("string"); + }); + + it("é determinístico: mesmo seed produz mesmo stateKey", () => { + const d1 = diagnosisUniversal({ seed: 100 }); + const d2 = diagnosisUniversal({ seed: 100 }); + expect(d1.stateKey).toBe(d2.stateKey); + expect(d1.klesha).toBe(d2.klesha); + }); + + it("usa preferredStateKey quando informado e válido", () => { + const d = diagnosisUniversal({ preferredStateKey: "anxiety" }); + expect(d.stateKey).toBe("anxiety"); + expect(d.klesha).toBeDefined(); + }); + + it("ignora preferredStateKey inexistente e cai no seed", () => { + const d = diagnosisUniversal({ seed: 5, preferredStateKey: "estado_inexistente" }); + expect(d.stateKey).toBeDefined(); + expect(d.stateKey).not.toBe("estado_inexistente"); + }); + + it("evita recentStateKeys quando possível", () => { + const d1 = diagnosisUniversal({ seed: 1 }); + const key = d1.stateKey!; + const d2 = diagnosisUniversal({ seed: 1, recentStateKeys: [key] }); + if (getRemedyMatrix().length > 1) { + expect(d2.stateKey).not.toBe(key); + } + }); + }); + + describe("diagnosisPersonal", () => { + const profileWithData: { fullName: string; birthDate: string } = { + fullName: "Maria Silva", + birthDate: "1990-05-15", + }; + + it("retorna ConsciousDiagnosis com numerologyFromMap quando perfil tem nome/data", () => { + const d = diagnosisPersonal(profileWithData, { seed: 7 }); + expect(d).toHaveProperty("numerologyFromMap"); + expect(d.numerologyFromMap).toHaveProperty("lifePath"); + expect(d.numerologyFromMap).toHaveProperty("soulUrge"); + expect(d).toHaveProperty("prakritiFromJyotish"); + expect(d.prakritiFromJyotish).toHaveProperty("dosha"); + expect(d.prakritiFromJyotish).toHaveProperty("element"); + }); + + it("é determinístico para mesmo perfil e seed", () => { + const d1 = diagnosisPersonal(profileWithData, { seed: 99 }); + const d2 = diagnosisPersonal(profileWithData, { seed: 99 }); + expect(d1.stateKey).toBe(d2.stateKey); + expect(d1.klesha).toBe(d2.klesha); + }); + + it("diferentes perfis podem produzir diferentes diagnósticos (guna/dosha)", () => { + const d1 = diagnosisPersonal(profileWithData, { seed: 0 }); + const d2 = diagnosisPersonal( + { fullName: "João Santos", birthDate: "1985-12-01" }, + { seed: 0 } + ); + expect(d1.prakritiFromJyotish?.dosha).toBeDefined(); + expect(d2.prakritiFromJyotish?.dosha).toBeDefined(); + }); + + it("usa preferredStateKey quando informado e válido", () => { + const d = diagnosisPersonal(profileWithData, { preferredStateKey: "grief" }); + expect(d.stateKey).toBe("grief"); + expect(d.numerologyFromMap).toBeDefined(); + expect(d.prakritiFromJyotish).toBeDefined(); + }); + }); + + describe("getRemedyForDiagnosis", () => { + it("retorna entrada da matriz quando diagnosis tem stateKey", () => { + const d: ConsciousDiagnosis = { + klesha: "raga", + samkhyaGunas: { sattva: 0.2, rajas: 0.6, tamas: 0.2 }, + ayurvedicQualities: { excess: [], deficient: [] }, + stateKey: "anxiety", + }; + const remedy = getRemedyForDiagnosis(d, { seed: 0 }); + expect(remedy.state).toBe("anxiety"); + expect(remedy.klesha).toBe("raga"); + }); + + it("é determinístico para mesmo diagnosis e seed", () => { + const d: ConsciousDiagnosis = { + klesha: "abhinivesha", + samkhyaGunas: { sattva: 0.2, rajas: 0.2, tamas: 0.6 }, + ayurvedicQualities: { excess: [], deficient: [] }, + }; + const r1 = getRemedyForDiagnosis(d, { seed: 3 }); + const r2 = getRemedyForDiagnosis(d, { seed: 3 }); + expect(r1.state).toBe(r2.state); + }); + }); +}); diff --git a/__tests__/lib/sacredRemedy/instantLightComposer.test.ts b/__tests__/lib/sacredRemedy/instantLightComposer.test.ts new file mode 100644 index 0000000..59a4cec --- /dev/null +++ b/__tests__/lib/sacredRemedy/instantLightComposer.test.ts @@ -0,0 +1,97 @@ +/** + * Testes para lib/sacredRemedy/instantLightComposer. + * Modo universal vs personal, determinismo com seed fixo. + */ + +import { composeInstantLight } from "@/lib/sacredRemedy/instantLightComposer"; + +describe("sacredRemedy/instantLightComposer", () => { + const fixedSeed = 12345; + + describe("modo universal (sem perfil)", () => { + it("retorna DarshanTruthPackage: sacred, practice, question, stateKey", () => { + const res = composeInstantLight(null, { seed: fixedSeed }); + expect(res).toHaveProperty("sacredText"); + expect(res).toHaveProperty("sacred"); + expect(res.sacred).toHaveProperty("id"); + expect(res.sacred).toHaveProperty("corpus"); + expect(res.sacred).toHaveProperty("text"); + expect(res).toHaveProperty("practice"); + expect(res.practice).toHaveProperty("title"); + expect(res.practice).toHaveProperty("steps"); + expect(res).toHaveProperty("question"); + expect(res.question).toHaveProperty("text"); + expect(res).toHaveProperty("contemplativeQuestion"); + expect(res.contemplativeQuestion).toHaveProperty("text"); + expect(res).toHaveProperty("meta"); + expect(typeof res.meta?.generatedAt).toBe("string"); + expect(res).toHaveProperty("sacredId"); + expect(res).toHaveProperty("stateKey"); + expect(typeof res.sacredText).toBe("string"); + expect(typeof res.question.text).toBe("string"); + }); + + it("não inclui insight em modo universal", () => { + const res = composeInstantLight(null, { seed: fixedSeed }); + expect(res.insight).toBeUndefined(); + }); + + it("é determinístico com mesmo seed", () => { + const r1 = composeInstantLight(null, { seed: fixedSeed }); + const r2 = composeInstantLight(null, { seed: fixedSeed }); + expect(r1.sacredId).toBe(r2.sacredId); + expect(r1.stateKey).toBe(r2.stateKey); + expect(r1.sacredText).toBe(r2.sacredText); + expect(r1.question.text).toBe(r2.question.text); + }); + }); + + describe("modo personal (com perfil)", () => { + const profile = { + fullName: "Ana Costa", + birthDate: "1988-03-20", + }; + + it("pode incluir insight quando perfil tem nome ou data", () => { + const res = composeInstantLight(profile, { seed: fixedSeed }); + expect(res).toHaveProperty("sacredText"); + expect(res).toHaveProperty("practice"); + expect(res).toHaveProperty("question"); + expect(res).toHaveProperty("sacredId"); + expect(res).toHaveProperty("stateKey"); + if (res.insight) expect(typeof res.insight).toBe("string"); + }); + + it("é determinístico para mesmo perfil e seed", () => { + const r1 = composeInstantLight(profile, { seed: fixedSeed }); + const r2 = composeInstantLight(profile, { seed: fixedSeed }); + expect(r1.sacredId).toBe(r2.sacredId); + expect(r1.stateKey).toBe(r2.stateKey); + expect(r1.sacredText).toBe(r2.sacredText); + expect(r1.question.text).toBe(r2.question.text); + }); + }); + + describe("anti-repetição (recentSacredIds / recentStateKeys)", () => { + it("com recentStateKeys evita repetir mesmo estado quando há opções", () => { + const r1 = composeInstantLight(null, { seed: 1 }); + const r2 = composeInstantLight(null, { + seed: 1, + recentStateKeys: r1.stateKey ? [r1.stateKey] : [], + }); + if (r1.stateKey) { + expect(r2.stateKey).not.toBe(r1.stateKey); + } + }); + + it("com recentSacredIds pode alterar sacredId (evita repetir texto)", () => { + const r1 = composeInstantLight(null, { seed: 2 }); + const r2 = composeInstantLight(null, { + seed: 2, + recentSacredIds: r1.sacredId ? [r1.sacredId] : [], + }); + expect(r2.sacred?.id).toBeDefined(); + expect(r2.sacredId).toBeDefined(); + }); + }); +}); diff --git a/__tests__/lib/sacredRemedy/sacredSelector.test.ts b/__tests__/lib/sacredRemedy/sacredSelector.test.ts new file mode 100644 index 0000000..f44015c --- /dev/null +++ b/__tests__/lib/sacredRemedy/sacredSelector.test.ts @@ -0,0 +1,58 @@ +/** + * Testes para lib/sacredRemedy/sacredSelector. + * Determinismo, avoidIds, retorno com corpus. + */ + +import { selectSacredText, getAllSacredEntries } from "@/lib/sacredRemedy/sacredSelector"; + +describe("sacredRemedy/sacredSelector", () => { + describe("getAllSacredEntries", () => { + it("retorna array não vazio com id, text, corpus", () => { + const all = getAllSacredEntries(); + expect(Array.isArray(all)).toBe(true); + expect(all.length).toBeGreaterThan(0); + const first = all[0]; + expect(first).toHaveProperty("id"); + expect(first).toHaveProperty("text"); + expect(first).toHaveProperty("corpus"); + expect(typeof first.corpus).toBe("string"); + }); + }); + + describe("selectSacredText", () => { + it("retorna entrada com id, text e corpus", () => { + const entry = selectSacredText({ seed: 10 }); + expect(entry).toHaveProperty("id"); + expect(entry).toHaveProperty("text"); + expect(entry).toHaveProperty("corpus"); + expect(entry.text?.length).toBeGreaterThan(0); + }); + + it("é determinístico: mesmo options produz mesmo id", () => { + const e1 = selectSacredText({ seed: 77 }); + const e2 = selectSacredText({ seed: 77 }); + expect(e1.id).toBe(e2.id); + expect(e1.corpus).toBe(e2.corpus); + }); + + it("evita avoidIds quando possível", () => { + const e1 = selectSacredText({ seed: 1 }); + const fullId = `${e1.corpus}.${e1.id}`; + const e2 = selectSacredText({ seed: 1, avoidIds: [fullId] }); + const all = getAllSacredEntries(); + if (all.length > 1) { + expect(e2.id).not.toBe(e1.id); + } + }); + + it("com kleshaTargets e qualities retorna entrada compatível", () => { + const entry = selectSacredText({ + kleshaTargets: ["raga"], + qualities: ["chala"], + seed: 5, + }); + expect(entry.id).toBeDefined(); + expect(entry.text).toBeDefined(); + }); + }); +}); diff --git a/__tests__/lib/sacredRemedy/sutraContextResolver.test.ts b/__tests__/lib/sacredRemedy/sutraContextResolver.test.ts new file mode 100644 index 0000000..f18691b --- /dev/null +++ b/__tests__/lib/sacredRemedy/sutraContextResolver.test.ts @@ -0,0 +1,40 @@ +/** + * Testes para lib/sacredRemedy/sutraContextResolver. + */ + +import { resolveSutraContext, shouldIncludePrevContext } from "@/lib/sacredRemedy/sutraContextResolver"; + +describe("sacredRemedy/sutraContextResolver", () => { + describe("resolveSutraContext", () => { + it("retorna primary para YS.1.1 (primeiro sutra)", () => { + const r = resolveSutraContext("YS.1.1"); + expect(r).not.toBeNull(); + expect(r!.primary.id).toBe("YS.1.1"); + expect(r!.primary.text).toBeTruthy(); + expect(r!.prev).toBeUndefined(); + expect(r!.next).toBeDefined(); + }); + + it("retorna prev e primary para YS.1.2", () => { + const r = resolveSutraContext("YS.1.2"); + expect(r).not.toBeNull(); + expect(r!.prev).toBeDefined(); + expect(r!.prev!.id).toBe("YS.1.1"); + expect(r!.primary.id).toBe("YS.1.2"); + expect(r!.next).toBeDefined(); + }); + + it("retorna null para id inexistente", () => { + expect(resolveSutraContext("YS.99.99")).toBeNull(); + }); + }); + + describe("shouldIncludePrevContext", () => { + it("retorna false para YS.1.1", () => { + expect(shouldIncludePrevContext("YS.1.1")).toBe(false); + }); + it("retorna true para YS.1.2", () => { + expect(shouldIncludePrevContext("YS.1.2")).toBe(true); + }); + }); +}); diff --git a/__tests__/lib/stripe.test.ts b/__tests__/lib/stripe.test.ts index 664a189..fc8eaf9 100644 --- a/__tests__/lib/stripe.test.ts +++ b/__tests__/lib/stripe.test.ts @@ -1,4 +1,4 @@ -const originalEnv = process.env; +const stripeTestEnv = process.env; jest.mock("stripe", () => { return jest.fn().mockImplementation(() => ({ _mock: "stripe" })); @@ -6,7 +6,7 @@ jest.mock("stripe", () => { describe("lib/stripe", () => { afterEach(() => { - process.env = { ...originalEnv }; + process.env = { ...stripeTestEnv }; jest.resetModules(); }); diff --git a/__tests__/lib/supabase.test.ts b/__tests__/lib/supabase.test.ts index 359ee74..e394482 100644 --- a/__tests__/lib/supabase.test.ts +++ b/__tests__/lib/supabase.test.ts @@ -2,16 +2,16 @@ jest.mock("@supabase/supabase-js", () => ({ createClient: jest.fn(() => ({ mock: true })), })); -const originalEnv = process.env; +const supabaseTestEnv = process.env; describe("lib/supabase", () => { beforeEach(() => { jest.resetModules(); - process.env = { ...originalEnv }; + process.env = { ...supabaseTestEnv }; }); afterEach(() => { - process.env = originalEnv; + process.env = supabaseTestEnv; }); describe("isSupabaseConfigured", () => { diff --git a/app/api/ai/expand/route.ts b/app/api/ai/expand/route.ts new file mode 100644 index 0000000..07acb9b --- /dev/null +++ b/app/api/ai/expand/route.ts @@ -0,0 +1,47 @@ +/** + * POST /api/ai/expand — expansão narrativa opcional do Truth Package. + * Body: { truthPackage: DarshanTruthPackage, question: string, theme?: Theme } + * Retorna: { narrativeExpansion: string, sections?: { title, content }[] } + * Guardrails: IA não altera diagnóstico, não inventa remédio, não troca sutra. + */ + +import { NextResponse } from "next/server"; +import { expandNarrative } from "@/lib/ai/narrativeGateway"; +import type { DarshanTruthPackage } from "@/lib/core/DarshanTruthPackage"; +import type { Theme } from "@/lib/core/UserRequestContext"; + +const THEMES: Theme[] = ["general", "love", "career", "year", "health", "spirituality"]; + +function parseTheme(s: string | null | undefined): Theme { + if (!s) return "general"; + const t = String(s).toLowerCase().trim(); + return THEMES.includes(t as Theme) ? (t as Theme) : "general"; +} + +export async function POST(req: Request) { + try { + const body = await req.json(); + const truthPackage = body?.truthPackage as DarshanTruthPackage | undefined; + const question = typeof body?.question === "string" ? body.question.trim() : ""; + const theme = parseTheme(body?.theme); + + if (!truthPackage || !truthPackage.sacred || !truthPackage.stateKey) { + return NextResponse.json( + { error: "truthPackage (com sacred e stateKey) é obrigatório" }, + { status: 400 } + ); + } + + const result = await expandNarrative(truthPackage, question, theme); + + return NextResponse.json({ + narrativeExpansion: result.narrativeExpansion, + sections: result.sections, + }); + } catch (e) { + return NextResponse.json( + { error: e instanceof Error ? e.message : "Erro ao expandir narrativa" }, + { status: 500 } + ); + } +} diff --git a/app/api/darshan/route.ts b/app/api/darshan/route.ts index 8199800..d2a729d 100644 --- a/app/api/darshan/route.ts +++ b/app/api/darshan/route.ts @@ -4,7 +4,7 @@ import { getConnector } from "@/lib/ai"; import { loadMasterPrompt } from "@/lib/darshanPrompt"; import { getConfig } from "@/lib/configStore"; import { PHASE_NAMES } from "@/lib/darshan"; -import { getOfflineRevelation } from "@/lib/oracleOffline"; +import { composeInstantLight } from "@/lib/sacredRemedy"; import { getSessionFromCookie } from "@/lib/auth"; import { getCreditsFromCookie, @@ -22,6 +22,8 @@ import { import { logger } from "@/lib/logger"; import { checkAndRecordRateLimit, checkDailyLimit, recordDailyRequest } from "@/lib/usageLimits"; import { isSupabaseConfigured } from "@/lib/supabase"; +import { saveRevelation } from "@/lib/historyStorage"; +import { getRecentSacredIds, getRecentStateKeys, recordInstantLight } from "@/lib/history/historyAdapter"; export const dynamic = "force-dynamic"; @@ -107,6 +109,9 @@ export async function POST(req: Request) { birthTime: typeof body.userProfile.birthTime === "string" ? body.userProfile.birthTime : undefined, } : {}; + const recentSacredIds = Array.isArray(body.recentSacredIds) + ? body.recentSacredIds.filter((id: unknown) => typeof id === "string") + : []; const config = getConfig(); const mockMessages = @@ -116,17 +121,46 @@ export async function POST(req: Request) { : [...MOCK_MESSAGES, ...config.mockMessagesOverride] : MOCK_MESSAGES; - // IA desativada (mock): 100% offline — NÃO chama getConnector() nem APIs externas. + // IA desativada (mock): Sacred Remedy Engine (único composer). + // Cooldown autônomo: se usuário logado, buscar recentSacredIds/recentStateKeys no servidor e registrar uso. if (useMock) { - const lastRevelations = history.slice(-5).map((t) => t.darshanMessage); - const phrases = lastRevelations.flatMap((msg) => - msg.split(/\n\n/).map((s) => s.trim()).filter(Boolean) - ); - const recentlyUsedPhrases = phrases.flatMap((p) => - /o que em você já sabe/i.test(p) ? [p, "O que em você já sabe?"] : [p] - ); - const message = getOfflineRevelation(userProfile, userMessage, recentlyUsedPhrases); - return NextResponse.json({ message: message || getMockMessage(mockMessages), phase: 1 } satisfies { message: string; phase: number }); + const cookieStore = await cookies(); + const session = getSessionFromCookie(cookieStore.toString()); + let recentSacredIdsRes = recentSacredIds; + let recentStateKeysRes = Array.isArray(body.recentStateKeys) + ? body.recentStateKeys.filter((k: unknown) => typeof k === "string") + : []; + if (session?.email) { + const [sacredIds, stateKeys] = await Promise.all([ + getRecentSacredIds(session.email, 7), + getRecentStateKeys(session.email, 7), + ]); + if (sacredIds.length) recentSacredIdsRes = sacredIds; + if (stateKeys.length) recentStateKeysRes = stateKeys; + } + const res = composeInstantLight(userProfile, { + recentSacredIds: recentSacredIdsRes, + recentStateKeys: recentStateKeysRes, + }); + if (session?.email && res.sacred?.id) { + recordInstantLight(session.email, res).catch(() => {}); + } + const parts: string[] = []; + if (res.sacredText?.trim()) parts.push(res.sacredText.trim()); + if (res.insight?.trim()) parts.push(res.insight.trim()); + const practiceStr = Array.isArray(res.practice?.steps) ? res.practice.steps.join("; ") : (res.practice as unknown as { title?: string })?.title ?? ""; + if (practiceStr.trim()) parts.push(practiceStr.trim()); + const foodStr = Array.isArray(res.food?.do) ? res.food.do.join(", ") : ""; + if (foodStr.trim()) parts.push(foodStr.trim()); + const questionStr = res.question?.text?.trim() ?? ""; + if (questionStr) parts.push(questionStr); + const message = parts.length > 0 ? parts.join("\n\n") : getMockMessage(mockMessages); + return NextResponse.json({ + message, + phase: 1, + sacredId: res.sacredId, + stateKey: res.stateKey, + } satisfies { message: string; phase: number; sacredId?: string; stateKey?: string }); } const cookieStore = await cookies(); @@ -273,8 +307,15 @@ export async function POST(req: Request) { if (!isSupabaseConfigured()) { recordDailyRequest(session.email); } + const finalMessage = message || "Respire. O que em você já sabe?"; + if (revelation) { + await saveRevelation(session.email, { + questionText: userMessage || null, + responseText: finalMessage, + }); + } const res = NextResponse.json({ - message: message || "Respire. O que em você já sabe?", + message: finalMessage, phase: revelation ? 1 : (parsed.phase ?? phase), creditsUsed: creditsPerRevelation, balance: debitResult.newBalance, diff --git a/app/api/history/count/route.ts b/app/api/history/count/route.ts new file mode 100644 index 0000000..5c30852 --- /dev/null +++ b/app/api/history/count/route.ts @@ -0,0 +1,21 @@ +/** + * GET /api/history/count — contagem de revelações e leituras do usuário logado. + * Usado para exibir o ícone de histórico quando há dados. + */ + +import { NextResponse } from "next/server"; +import { cookies } from "next/headers"; +import { getSessionFromCookie } from "@/lib/auth"; +import { getHistoryCounts } from "@/lib/historyStorage"; + +export const dynamic = "force-dynamic"; + +export async function GET() { + const cookieStore = await cookies(); + const session = getSessionFromCookie(cookieStore.toString()); + if (!session) { + return NextResponse.json({ revelations: 0, readings: 0 }); + } + const counts = await getHistoryCounts(session.email); + return NextResponse.json(counts); +} diff --git a/app/api/history/readings/route.ts b/app/api/history/readings/route.ts new file mode 100644 index 0000000..99ff322 --- /dev/null +++ b/app/api/history/readings/route.ts @@ -0,0 +1,23 @@ +/** + * GET /api/history/readings — lista leituras (mapa pessoal) do usuário logado. + */ + +import { NextResponse } from "next/server"; +import { cookies } from "next/headers"; +import { getSessionFromCookie } from "@/lib/auth"; +import { listReadings } from "@/lib/historyStorage"; + +export const dynamic = "force-dynamic"; + +export async function GET(req: Request) { + const cookieStore = await cookies(); + const session = getSessionFromCookie(cookieStore.toString()); + if (!session) { + return NextResponse.json({ error: "Faça login para ver seu histórico." }, { status: 401 }); + } + const { searchParams } = new URL(req.url); + const limit = Math.min(100, Math.max(1, parseInt(searchParams.get("limit") ?? "50", 10) || 50)); + const offset = Math.max(0, parseInt(searchParams.get("offset") ?? "0", 10) || 0); + const list = await listReadings(session.email, { limit, offset }); + return NextResponse.json({ items: list }); +} diff --git a/app/api/history/revelations/route.ts b/app/api/history/revelations/route.ts new file mode 100644 index 0000000..6ae914e --- /dev/null +++ b/app/api/history/revelations/route.ts @@ -0,0 +1,23 @@ +/** + * GET /api/history/revelations — lista revelações (respostas do orb) do usuário logado. + */ + +import { NextResponse } from "next/server"; +import { cookies } from "next/headers"; +import { getSessionFromCookie } from "@/lib/auth"; +import { listRevelations } from "@/lib/historyStorage"; + +export const dynamic = "force-dynamic"; + +export async function GET(req: Request) { + const cookieStore = await cookies(); + const session = getSessionFromCookie(cookieStore.toString()); + if (!session) { + return NextResponse.json({ error: "Faça login para ver seu histórico." }, { status: 401 }); + } + const { searchParams } = new URL(req.url); + const limit = Math.min(100, Math.max(1, parseInt(searchParams.get("limit") ?? "50", 10) || 50)); + const offset = Math.max(0, parseInt(searchParams.get("offset") ?? "0", 10) || 0); + const list = await listRevelations(session.email, { limit, offset }); + return NextResponse.json({ items: list }); +} diff --git a/app/api/instant-light/route.ts b/app/api/instant-light/route.ts new file mode 100644 index 0000000..6b9858e --- /dev/null +++ b/app/api/instant-light/route.ts @@ -0,0 +1,107 @@ +/** + * GET /api/instant-light — Sacred Remedy Engine (motor medicinal offline). + * Não consome créditos; não depende de IA. Retorna DarshanTruthPackage. + * + * Pipeline quando há userText: + * userText → normalize → parseIntent → pickBestState → preferredStateKey + theme + questionType + * → composeInstantLight(symbolicMap?, inputStateKey, theme, questionType) + * → sutra medicinal + prática ayurvédica + pergunta contemplativa (tudo offline). + * + * Query: fullName?, birthDate?, birthTime?, birthPlace?, userText?, question?, theme?, recentSacredIds?, recentStateKeys? + * Cooldown server-side: getRecentSacredIds/getRecentStateKeys + recordInstantLight. + */ + +import { NextResponse } from "next/server"; +import { cookies } from "next/headers"; +import { composeInstantLight } from "@/lib/sacredRemedy"; +import { parseIntent } from "@/lib/input/intentParser"; +import { pickBestState } from "@/lib/input/stateScorer"; +import { getSessionFromCookie } from "@/lib/auth"; +import { getRecentSacredIds, getRecentStateKeys, recordInstantLight } from "@/lib/history/historyAdapter"; +import type { Theme } from "@/lib/core/UserRequestContext"; + +const THEMES: Theme[] = ["general", "love", "career", "year", "health", "spirituality"]; + +function parseTheme(s: string | null): Theme { + if (!s) return "general"; + const t = s.toLowerCase().trim(); + return THEMES.includes(t as Theme) ? (t as Theme) : "general"; +} + +export const dynamic = "force-dynamic"; + +export async function GET(req: Request) { + const { searchParams } = new URL(req.url); + const fullName = searchParams.get("fullName") ?? undefined; + const birthDate = searchParams.get("birthDate") ?? undefined; + const birthTime = searchParams.get("birthTime") ?? undefined; + const birthPlace = searchParams.get("birthPlace") ?? undefined; + const userText = searchParams.get("userText") ?? searchParams.get("question") ?? undefined; + const questionExplicit = searchParams.get("question") ?? undefined; + const themeParam = searchParams.get("theme") ?? undefined; + const recentSacredIdsParam = searchParams.get("recentSacredIds"); + const recentStateKeysParam = searchParams.get("recentStateKeys"); + + let recentSacredIds = recentSacredIdsParam + ? recentSacredIdsParam.split(",").map((s) => s.trim()).filter(Boolean) + : []; + let recentStateKeys = recentStateKeysParam + ? recentStateKeysParam.split(",").map((s) => s.trim()).filter(Boolean) + : []; + + const cookieStore = await cookies(); + const session = getSessionFromCookie(cookieStore.toString()); + const userKey = session?.email ?? undefined; + + if (userKey) { + const sacredIds = await getRecentSacredIds(userKey, 7); + const stateKeys = await getRecentStateKeys(userKey, 7); + if (sacredIds.length > 0) recentSacredIds = sacredIds; + if (stateKeys.length > 0) recentStateKeys = stateKeys; + } + + let preferredStateKey: string | undefined; + let inputConfidence: number | undefined; + let questionType: string | undefined; + let themeFromIntent: Theme | undefined; + + const inputText = (userText ?? questionExplicit)?.trim(); + if (inputText) { + const intent = parseIntent(inputText); + const best = pickBestState(intent ?? null); + if (best) { + preferredStateKey = best.stateKey; + inputConfidence = best.confidence; + } + if (intent?.questionType) questionType = intent.questionType; + if (intent?.theme) themeFromIntent = intent.theme as Theme; + } + + const theme = themeFromIntent ?? parseTheme(themeParam ?? null); + + const userProfile = + (fullName?.trim() || birthDate?.trim()) + ? { + fullName: fullName?.trim() || undefined, + birthDate: birthDate?.trim() || undefined, + birthTime: birthTime?.trim() || undefined, + birthPlace: birthPlace?.trim() || undefined, + } + : null; + + const result = composeInstantLight(userProfile, { + recentSacredIds, + recentStateKeys, + preferredStateKey, + theme, + questionType, + inputConfidence, + questionText: questionExplicit ?? inputText ?? undefined, + }); + + if (userKey && result.sacred?.id) { + recordInstantLight(userKey, result).catch(() => {}); + } + + return NextResponse.json(result); +} diff --git a/app/api/map/personal/route.ts b/app/api/map/personal/route.ts index 6193adb..51fc9de 100644 --- a/app/api/map/personal/route.ts +++ b/app/api/map/personal/route.ts @@ -16,7 +16,8 @@ import { getCreditsBalance, debitCredits, logAiUsage, estimateCost, refreshUsdTo import type { AiUsageProvider } from "@/lib/finance"; import { logger } from "@/lib/logger"; import { getConfig } from "@/lib/configStore"; -import { getOfflineReading } from "@/lib/readingOffline"; +import { getOfflineReading, getOfflineReadingFullText } from "@/lib/readingOffline"; +import { saveReading } from "@/lib/historyStorage"; import { computeVedicChartSimplified } from "@/lib/knowledge/vedic"; import { getRulingNumberFromName, getNumberTraits } from "@/lib/knowledge/numerology"; import { RASHI_NAMES } from "@/lib/knowledge/archetypes"; @@ -156,11 +157,13 @@ export async function POST(req: Request) { const useOffline = body.offline === true; if (useOffline) { - const message = getOfflineReading(profile); + const sections = getOfflineReading(profile); + const message = getOfflineReadingFullText(profile); const balanceFromCookie = getCreditsFromCookie(cookieHeader); const balance = await getCreditsBalance(session.email, balanceFromCookie); return NextResponse.json({ message, + sections, balance, creditsUsed: 0, offline: true, @@ -281,6 +284,8 @@ export async function POST(req: Request) { currentBalanceFromCookie: balance, }); + await saveReading(session.email, message); + const res = NextResponse.json({ message, balance: debitResult.newBalance, diff --git a/app/api/map/route.ts b/app/api/map/route.ts new file mode 100644 index 0000000..0471efe --- /dev/null +++ b/app/api/map/route.ts @@ -0,0 +1,33 @@ +/** + * POST /api/map — retorna SymbolicMap completo (offline, sem IA, sem créditos). + * Motor simbólico real: Jyotish + Numerologia + Arquétipos. + */ + +import { NextResponse } from "next/server"; +import { buildSymbolicMap } from "@/lib/symbolic/builder"; + +export const dynamic = "force-dynamic"; + +type ProfileInput = { + fullName?: string; + birthDate?: string; + birthTime?: string; + birthPlace?: string; +}; + +export async function POST(req: Request) { + let body: { profile?: ProfileInput } = {}; + try { + body = await req.json(); + } catch { + return NextResponse.json({ error: "Corpo inválido." }, { status: 400 }); + } + const profile = body.profile ?? {}; + const map = buildSymbolicMap({ + fullName: profile.fullName, + birthDate: profile.birthDate, + birthTime: profile.birthTime, + birthPlace: profile.birthPlace, + }); + return NextResponse.json({ map }); +} diff --git a/app/api/reading/career/route.ts b/app/api/reading/career/route.ts new file mode 100644 index 0000000..48db118 --- /dev/null +++ b/app/api/reading/career/route.ts @@ -0,0 +1,30 @@ +/** + * POST /api/reading/career — leitura de carreira offline (mapa + narrativa + action). + */ + +import { NextResponse } from "next/server"; +import { getCareerReading } from "@/lib/readings/careerReading"; +import type { CoreProfile } from "@/lib/core/types"; + +export const dynamic = "force-dynamic"; + +export async function POST(req: Request) { + let body: { profile?: CoreProfile } = {}; + try { + body = await req.json(); + } catch { + return NextResponse.json({ error: "Corpo inválido." }, { status: 400 }); + } + const profile: CoreProfile = body.profile ?? {}; + const { map, reading, action } = await getCareerReading(profile); + return NextResponse.json({ + map: { + core: { providerUsed: map.core.providerUsed, moonRashi: map.core.moonRashi, nakshatra: map.core.nakshatra }, + jyotish: map.jyotish, + numerology: map.numerology, + humanDesign: map.humanDesign, + }, + reading, + action, + }); +} diff --git a/app/api/reading/general/route.ts b/app/api/reading/general/route.ts new file mode 100644 index 0000000..da04355 --- /dev/null +++ b/app/api/reading/general/route.ts @@ -0,0 +1,26 @@ +import { NextResponse } from "next/server"; +import { getGeneralReading } from "@/lib/readings/generalReading"; +import type { CoreProfile } from "@/lib/core/types"; + +export const dynamic = "force-dynamic"; + +export async function POST(req: Request) { + let body: { profile?: CoreProfile } = {}; + try { + body = await req.json(); + } catch { + return NextResponse.json({ error: "Corpo inválido." }, { status: 400 }); + } + const profile: CoreProfile = body.profile ?? {}; + const { map, reading, action } = await getGeneralReading(profile); + return NextResponse.json({ + map: { + core: { providerUsed: map.core.providerUsed, moonRashi: map.core.moonRashi, nakshatra: map.core.nakshatra }, + jyotish: map.jyotish, + numerology: map.numerology, + humanDesign: map.humanDesign, + }, + reading, + action, + }); +} diff --git a/app/api/reading/love/route.ts b/app/api/reading/love/route.ts new file mode 100644 index 0000000..618acb7 --- /dev/null +++ b/app/api/reading/love/route.ts @@ -0,0 +1,26 @@ +import { NextResponse } from "next/server"; +import { getLoveReading } from "@/lib/readings/loveReading"; +import type { CoreProfile } from "@/lib/core/types"; + +export const dynamic = "force-dynamic"; + +export async function POST(req: Request) { + let body: { profile?: CoreProfile } = {}; + try { + body = await req.json(); + } catch { + return NextResponse.json({ error: "Corpo inválido." }, { status: 400 }); + } + const profile: CoreProfile = body.profile ?? {}; + const { map, reading, action } = await getLoveReading(profile); + return NextResponse.json({ + map: { + core: { providerUsed: map.core.providerUsed, moonRashi: map.core.moonRashi, nakshatra: map.core.nakshatra }, + jyotish: map.jyotish, + numerology: map.numerology, + humanDesign: map.humanDesign, + }, + reading, + action, + }); +} diff --git a/app/api/reading/route.ts b/app/api/reading/route.ts new file mode 100644 index 0000000..69aa119 --- /dev/null +++ b/app/api/reading/route.ts @@ -0,0 +1,61 @@ +/** + * POST /api/reading?theme= — retorna leitura temática offline (sem IA, sem créditos). + * theme: general | love | relationship | career | work | year | yearly | action + */ + +import { NextResponse } from "next/server"; +import { buildSymbolicMap } from "@/lib/symbolic/builder"; +import { getReadingByTheme } from "@/lib/readings/symbolicReadings"; + +export const dynamic = "force-dynamic"; + +type ProfileInput = { + fullName?: string; + birthDate?: string; + birthTime?: string; + birthPlace?: string; +}; + +const VALID_THEMES = [ + "general", + "love", + "relationship", + "career", + "work", + "year", + "yearly", + "action", +]; + +export async function POST(req: Request) { + let body: { profile?: ProfileInput } = {}; + try { + body = await req.json(); + } catch { + return NextResponse.json({ error: "Corpo inválido." }, { status: 400 }); + } + const profile = body.profile ?? {}; + const { searchParams } = new URL(req.url); + const themeParam = searchParams.get("theme") ?? "general"; + const theme = VALID_THEMES.includes(themeParam.toLowerCase()) + ? themeParam.toLowerCase() + : "general"; + + const map = buildSymbolicMap({ + fullName: profile.fullName, + birthDate: profile.birthDate, + birthTime: profile.birthTime, + birthPlace: profile.birthPlace, + }); + const reading = getReadingByTheme(map, theme); + + return NextResponse.json({ + map: { + jyotish: map.jyotish, + numerology: map.numerology, + archetypes: map.archetypes, + }, + reading, + theme, + }); +} diff --git a/app/api/reading/year/route.ts b/app/api/reading/year/route.ts new file mode 100644 index 0000000..d1118c9 --- /dev/null +++ b/app/api/reading/year/route.ts @@ -0,0 +1,30 @@ +/** + * POST /api/reading/year — leitura de ano offline (mapa + narrativa + action). + */ + +import { NextResponse } from "next/server"; +import { getYearReading } from "@/lib/readings/yearReading"; +import type { CoreProfile } from "@/lib/core/types"; + +export const dynamic = "force-dynamic"; + +export async function POST(req: Request) { + let body: { profile?: CoreProfile } = {}; + try { + body = await req.json(); + } catch { + return NextResponse.json({ error: "Corpo inválido." }, { status: 400 }); + } + const profile: CoreProfile = body.profile ?? {}; + const { map, reading, action } = await getYearReading(profile); + return NextResponse.json({ + map: { + core: { providerUsed: map.core.providerUsed, moonRashi: map.core.moonRashi, nakshatra: map.core.nakshatra }, + jyotish: map.jyotish, + numerology: map.numerology, + humanDesign: map.humanDesign, + }, + reading, + action, + }); +} diff --git a/app/components/CrystalOrb.tsx b/app/components/CrystalOrb.tsx index 038717a..1803e77 100644 --- a/app/components/CrystalOrb.tsx +++ b/app/components/CrystalOrb.tsx @@ -12,17 +12,17 @@ export default function CrystalOrb({ isRevealing = false, onClick, clickable = f const Wrapper = clickable ? "button" : "div"; return ( diff --git a/app/components/DarshanMessage.tsx b/app/components/DarshanMessage.tsx index 258cd7e..38cd85c 100644 --- a/app/components/DarshanMessage.tsx +++ b/app/components/DarshanMessage.tsx @@ -55,7 +55,7 @@ export default function DarshanMessage({ message, onComplete }: Props) { } return ( -
+
!exiting && e.key === "Enter" && handleClick()} - initial={{ opacity: 0, y: 16 }} + initial={{ opacity: 0, y: 12 }} animate={exiting ? { opacity: 0, y: -12 } : { opacity: 1, y: 0 }} exit={{ opacity: 0, y: -12 }} transition={{ duration: FADE_DURATION_S, ease: [0.25, 0.1, 0.25, 1] }} - className="text-center w-full cursor-pointer rounded-2xl px-6 py-8 focus:outline-none" + className="text-center w-full cursor-pointer rounded-2xl px-4 sm:px-6 py-5 sm:py-8 focus:outline-none" aria-label={exiting ? undefined : isLast ? "Toque para voltar" : "Toque para a próxima"} >

diff --git a/app/components/HistoryIcon.tsx b/app/components/HistoryIcon.tsx new file mode 100644 index 0000000..7b7e8ff --- /dev/null +++ b/app/components/HistoryIcon.tsx @@ -0,0 +1,39 @@ +"use client"; + +import { motion } from "framer-motion"; +import Tooltip from "./Tooltip"; + +type Props = { + onClick: () => void; +}; + +/** Ícone de histórico (respostas e leituras) — aparece quando o usuário tem dados armazenados. */ +export default function HistoryIcon({ onClick }: Props) { + return ( + + + + + + + + + ); +} diff --git a/app/components/HistoryModal.tsx b/app/components/HistoryModal.tsx new file mode 100644 index 0000000..e07e120 --- /dev/null +++ b/app/components/HistoryModal.tsx @@ -0,0 +1,277 @@ +"use client"; + +import { useState, useEffect, useCallback } from "react"; +import { motion, AnimatePresence } from "framer-motion"; + +type RevelationItem = { + id: string; + user_id: string; + question_text: string | null; + response_text: string; + created_at: string; +}; + +type ReadingItem = { + id: string; + user_id: string; + content: string; + created_at: string; +}; + +type TabId = "respostas" | "leituras"; + +function formatDate(iso: string): string { + try { + const d = new Date(iso); + return d.toLocaleDateString("pt-BR", { + day: "2-digit", + month: "short", + year: "numeric", + hour: "2-digit", + minute: "2-digit", + }); + } catch { + return iso.slice(0, 16); + } +} + +type Props = { + onClose: () => void; +}; + +export default function HistoryModal({ onClose }: Props) { + const [tab, setTab] = useState("respostas"); + const [revelations, setRevelations] = useState([]); + const [readings, setReadings] = useState([]); + const [loadingRevelations, setLoadingRevelations] = useState(false); + const [loadingReadings, setLoadingReadings] = useState(false); + const [expandedRevelationId, setExpandedRevelationId] = useState(null); + const [expandedReadingId, setExpandedReadingId] = useState(null); + + const fetchRevelations = useCallback(async () => { + setLoadingRevelations(true); + try { + const res = await fetch("/api/history/revelations", { credentials: "include" }); + if (res.ok) { + const data = await res.json(); + setRevelations(Array.isArray(data.items) ? data.items : []); + } else { + setRevelations([]); + } + } catch { + setRevelations([]); + } finally { + setLoadingRevelations(false); + } + }, []); + + const fetchReadings = useCallback(async () => { + setLoadingReadings(true); + try { + const res = await fetch("/api/history/readings", { credentials: "include" }); + if (res.ok) { + const data = await res.json(); + setReadings(Array.isArray(data.items) ? data.items : []); + } else { + setReadings([]); + } + } catch { + setReadings([]); + } finally { + setLoadingReadings(false); + } + }, []); + + useEffect(() => { + if (tab === "respostas") fetchRevelations(); + else fetchReadings(); + }, [tab, fetchRevelations, fetchReadings]); + + const tabClass = (t: TabId) => + `py-2.5 px-3 text-sm font-light border-b-2 transition ${ + tab === t + ? "border-white/30 text-white/90" + : "border-transparent text-white/50 hover:text-white/70" + }`; + + return ( + <> + + +

+

Histórico

+ +
+ +
+ + +
+ +
+ + {tab === "respostas" && ( + + {loadingRevelations && ( +

Carregando...

+ )} + {!loadingRevelations && revelations.length === 0 && ( +

+ Nenhuma resposta da interação com o orb ainda. +

+ )} + {!loadingRevelations && + revelations.map((r) => { + const expanded = expandedRevelationId === r.id; + return ( +
+ + {expanded && ( +
+ {r.question_text && ( +

+ Pergunta: + {r.question_text} +

+ )} +

+ {r.response_text} +

+
+ )} +
+ ); + })} +
+ )} + + {tab === "leituras" && ( + + {loadingReadings && ( +

Carregando...

+ )} + {!loadingReadings && readings.length === 0 && ( +

+ Nenhuma leitura completa ainda. +

+ )} + {!loadingReadings && + readings.map((r) => { + const expanded = expandedReadingId === r.id; + return ( +
+ + {expanded && ( +
+

+ {r.content} +

+
+ )} +
+ ); + })} +
+ )} +
+
+ + + ); +} diff --git a/app/components/PersonalMapIcon.tsx b/app/components/PersonalMapIcon.tsx index 2e9648c..79164f3 100644 --- a/app/components/PersonalMapIcon.tsx +++ b/app/components/PersonalMapIcon.tsx @@ -7,19 +7,19 @@ type Props = { onClick: () => void; }; -/** Ícone minimalista de mapa (documento/folha) — posicionado abaixo do ícone de cadastro. */ +/** Ícone de leitura (resumo completo) — posicionado abaixo do ícone Dados. */ export default function PersonalMapIcon({ onClick }: Props) { return ( - + {hasData ? ( - + ) : ( - + )} diff --git a/app/components/ProfilePanel.tsx b/app/components/ProfilePanel.tsx index fd0b26f..4822034 100644 --- a/app/components/ProfilePanel.tsx +++ b/app/components/ProfilePanel.tsx @@ -14,7 +14,7 @@ type Props = { }; const inputClass = - "w-full bg-transparent border-0 border-b border-white/25 rounded-none px-0 py-2.5 text-sm text-mist placeholder:text-white/40 outline-none focus:border-white/50 transition-colors"; + "w-full bg-transparent border-0 border-b border-white/[0.12] rounded-none px-0 py-2.5 text-sm text-white/90 placeholder:text-white/30 outline-none focus:border-white/25 transition-colors"; export default function ProfilePanel({ isOpen, onClose, profile, onSave, onDeleteAccount }: Props) { const [fullName, setFullName] = useState(profile.fullName ?? ""); @@ -67,7 +67,7 @@ export default function ProfilePanel({ isOpen, onClose, profile, onSave, onDelet animate={{ opacity: 1 }} exit={{ opacity: 0 }} transition={{ duration: 0.2 }} - className="fixed inset-0 bg-black/60 z-40" + className="fixed inset-0 bg-black/40 z-40" onClick={onClose} aria-hidden /> @@ -76,25 +76,25 @@ export default function ProfilePanel({ isOpen, onClose, profile, onSave, onDelet animate={{ x: 0 }} exit={{ x: "100%" }} transition={{ type: "tween", duration: 0.3, ease: [0.25, 0.1, 0.25, 1] }} - className="fixed top-0 right-0 bottom-0 w-full max-w-sm bg-deep-night border-l border-white/10 z-50 flex flex-col shadow-2xl" + className="fixed top-0 right-0 bottom-0 w-full max-w-sm bg-deep-night border-l border-white/[0.06] z-50 flex flex-col shadow-2xl" > -
-

Seu mapa

+
+

Dados de Entrada

-

+

Dados opcionais para respostas mais precisas (astrologia e numerologia).

- + - + - + - + Cancelar @@ -150,7 +150,7 @@ export default function ProfilePanel({ isOpen, onClose, profile, onSave, onDelet @@ -158,7 +158,7 @@ export default function ProfilePanel({ isOpen, onClose, profile, onSave, onDelet diff --git a/app/components/TimeHeader.tsx b/app/components/TimeHeader.tsx index 3ced3a2..0f77294 100644 --- a/app/components/TimeHeader.tsx +++ b/app/components/TimeHeader.tsx @@ -12,7 +12,7 @@ type Props = { moonPhase: string; }; -const iconClass = "w-4 h-4 shrink-0 text-white/70"; +const iconClass = "w-3.5 h-3.5 sm:w-4 sm:h-4 shrink-0 text-white/70"; function IconSun() { return ( @@ -39,11 +39,11 @@ function IconCrescent() { ); } -const itemClass = "flex items-center gap-2 text-[11px] uppercase tracking-widest text-white/60"; +const itemClass = "flex items-center gap-1.5 sm:gap-2 text-[11px] uppercase tracking-widest text-white/60 whitespace-nowrap"; export default function TimeHeader({ sunrise, sunset, moonPhase }: Props) { return ( -
+
@@ -79,14 +79,14 @@ export function TimeHeaderSunrise({ sunrise }: { sunrise: string }) { export function TimeHeaderSunsetMoon({ sunset, moonPhase }: { sunset: string; moonPhase: string }) { return ( -
- +
+ {sunset} - + {moonPhase} diff --git a/app/components/Tooltip.tsx b/app/components/Tooltip.tsx index ea693d1..313555f 100644 --- a/app/components/Tooltip.tsx +++ b/app/components/Tooltip.tsx @@ -5,6 +5,8 @@ type Props = { children: React.ReactNode; /** Alinhamento do tooltip em relação ao elemento. default: left */ align?: "left" | "right" | "center"; + /** Posição vertical: acima ou abaixo do elemento. default: bottom */ + side?: "top" | "bottom"; /** Nome do group para hover (deve ser único no mesmo pai). */ groupName?: string; /** Quando definido, o wrapper usa esta classe (ex.: para botão fixo). */ @@ -12,15 +14,21 @@ type Props = { }; const tooltipBase = - "absolute top-full mt-1 text-[10px] text-white/70 opacity-0 pointer-events-none transition-opacity duration-150 z-50 max-w-[200px] break-words "; + "absolute py-2 px-3 min-w-[140px] max-w-[260px] " + + "text-[11px] text-white/80 leading-snug text-left whitespace-normal " + + "bg-black/75 backdrop-blur-sm border border-white/10 rounded-md " + + "opacity-0 pointer-events-none transition-opacity duration-150 z-50 " + + "shadow-lg break-words"; export default function Tooltip({ text, children, align = "left", + side = "bottom", groupName = "tip", wrapperClassName, }: Props) { + const vertical = side === "top" ? "bottom-full mb-1.5" : "top-full mt-1.5"; const position = align === "right" ? "right-0" @@ -35,7 +43,7 @@ export default function Tooltip({ {children} {text} diff --git a/app/config/page.tsx b/app/config/page.tsx index 708b3ea..5c64891 100644 --- a/app/config/page.tsx +++ b/app/config/page.tsx @@ -98,7 +98,7 @@ export default function ConfigPage() { try { const res = await fetch("/api/config", { method: "PUT", - headers: { "Content-Type": "application/json", ...headers() }, + headers: { "Content-Type": "application/json", "X-Config-Key": configKey }, body: JSON.stringify({ masterPromptOverride: config.masterPromptOverride ?? null, masterPromptMode: config.masterPromptMode ?? "complement", diff --git a/app/monitor/page.tsx b/app/monitor/page.tsx index 53f4a08..0525501 100644 --- a/app/monitor/page.tsx +++ b/app/monitor/page.tsx @@ -26,14 +26,13 @@ export default function MonitorPage() { const [autoRefresh, setAutoRefresh] = useState(false); const intervalRef = useRef | null>(null); - const headers = () => ({ "X-Config-Key": configKey }); - const fetchData = useCallback(async () => { if (!configKey) return; try { + const h = { "X-Config-Key": configKey }; const [logsRes, statusRes] = await Promise.all([ - fetch(`/api/admin/logs?source=both&lines=300`, { headers: headers() }), - fetch("/api/admin/status", { headers: headers() }), + fetch(`/api/admin/logs?source=both&lines=300`, { headers: h }), + fetch("/api/admin/status", { headers: h }), ]); if (logsRes.ok) { const data = (await logsRes.json()) as LogsResponse; diff --git a/app/page.tsx b/app/page.tsx index 2953270..830373b 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -8,7 +8,9 @@ import DarshanMessage from "./components/DarshanMessage"; import TimeHeader, { TimeHeaderSunrise, TimeHeaderSunsetMoon } from "./components/TimeHeader"; import ProfileIcon from "./components/ProfileIcon"; import PersonalMapIcon from "./components/PersonalMapIcon"; +import HistoryIcon from "./components/HistoryIcon"; import ProfilePanel from "./components/ProfilePanel"; +import HistoryModal from "./components/HistoryModal"; import LoginModal from "./components/LoginModal"; import SupportModal from "./components/SupportModal"; import CreditsModal from "./components/CreditsModal"; @@ -70,6 +72,8 @@ function Home() { const [supportOpen, setSupportOpen] = useState(false); const [creditsModalOpen, setCreditsModalOpen] = useState(false); const [personalMapOpen, setPersonalMapOpen] = useState(false); + const [historyOpen, setHistoryOpen] = useState(false); + const [historyCount, setHistoryCount] = useState({ revelations: 0, readings: 0 }); const [creditsPerRevelation, setCreditsPerRevelation] = useState(CREDITS_PER_AI_REQUEST); const [creditsPerReading, setCreditsPerReading] = useState(CREDITS_PER_PERSONAL_MAP); const [authError, setAuthError] = useState(null); @@ -184,6 +188,24 @@ function Home() { } }, []); + const refreshHistoryCount = useCallback(async () => { + try { + const res = await fetch("/api/history/count", { credentials: "include" }); + const data = await res.json(); + setHistoryCount({ + revelations: typeof data.revelations === "number" ? data.revelations : 0, + readings: typeof data.readings === "number" ? data.readings : 0, + }); + } catch { + setHistoryCount({ revelations: 0, readings: 0 }); + } + }, []); + + useEffect(() => { + if (session) refreshHistoryCount(); + else setHistoryCount({ revelations: 0, readings: 0 }); + }, [session, refreshHistoryCount]); + useEffect(() => { let cancelled = false; (async () => { @@ -246,7 +268,7 @@ function Home() { setMockMode(true); saveMockMode(true); } - }, [credits, mockMode]); + }, [credits, creditsPerRevelation, mockMode]); function toggleMockMode() { setMockMode((prev) => { @@ -303,6 +325,7 @@ function Home() { ]); setUserInput(""); if (typeof data.balance === "number") setCredits(data.balance); + refreshHistoryCount(); } catch { setCurrentMessage(FALLBACK_MESSAGE); } finally { @@ -376,7 +399,7 @@ function Home() { const showConfigError = aiReady === false && !mockMode; return ( -
+
{!introDone ? ( -
-
-
- {session && ( -
- - - - + {/* Linha 1: créditos + nascer do sol | Luz do Tempo | pôr do sol + lua — mesma margem do topo */} +
+ {session && ( +
+ +
- )} + + Créditos + + + + {credits} + +
+ )} + -
+ +
+
+ Luz do Tempo +
+
+ +
+ {/* Linha 2: AI desligada | horário atual | (vazio) */} +
-
-

Luz do Tempo

+
{currentTime ? ( -

{currentTime}

+ {currentTime} ) : null}
-
- -
+
); diff --git a/docs/DICIONARIO_OFFLINE.md b/docs/DICIONARIO_OFFLINE.md index 302be16..2f06244 100644 --- a/docs/DICIONARIO_OFFLINE.md +++ b/docs/DICIONARIO_OFFLINE.md @@ -42,7 +42,7 @@ lib/ ## Uso na API -Quando a requisição vem com `mock: true`, a rota `/api/darshan` usa `getOfflineRevelation(perfil, pergunta)` em vez da IA. A resposta tem o mesmo formato (`message`, `phase`), então o frontend não precisa mudar. +Quando a requisição vem com `mock: true`, a rota `/api/darshan` usa o **Instant Light Engine** (`composeInstantLight(perfil, { recentSacredIds })`) em vez da IA: texto sagrado + (se houver perfil) insight e prática do mapa + pergunta. A resposta tem o mesmo formato (`message`, `phase`) e opcionalmente `sacredId` para o cliente enviar em `recentSacredIds` e reduzir repetição. Ver [INSTANT_LIGHT_ENGINE.md](./INSTANT_LIGHT_ENGINE.md). ## Limitações atuais diff --git a/docs/ENGINE_2.0.md b/docs/ENGINE_2.0.md new file mode 100644 index 0000000..f9b8cd5 --- /dev/null +++ b/docs/ENGINE_2.0.md @@ -0,0 +1,118 @@ +# Engine 2.0 — Mapa simbólico + Composer modular + Readings temáticos + +Este documento descreve o **motor profissional** do Darshan: **SymbolicMap → Insights → Composer → Readings modulares**. O Oracle offline continua existindo como “ritual rápido”; a **leitura profissional** é baseada neste mapa. + +--- + +## Visão geral + +``` +Perfil (nome, data, hora, local) + ↓ +buildSymbolicMap(profile) → SymbolicMap canônico + ↓ +collectInsights(map) → Insight[] (key, topic, weight, evidence) + ↓ +composeReading(map, topic) → texto por tópico (general | love | career | year | action) + ↓ +getOfflineReading(profile) → { general, love, career, year, action } +``` + +- **SymbolicMap** é o objeto estruturado reutilizável (jyotish, numerology, themes, traits, evidence). +- **Insights** são interpretações determinísticas derivadas do mapa (não blocos fixos). +- **Composer** monta o texto por tópico a partir dos insights (composeReading(map, "love"), etc.). +- **Readings temáticos** existem: love, career, year, action — cada um chama composeReading(map, topic). +- **Action** é derivada de insights (número regente, arquétipo, geral), não fixa. + +--- + +## 1. SymbolicMap canônico (`lib/symbolic/`) + +- **SymbolicMap.ts** — ponto de entrada: exporta o tipo `SymbolicMap` e `buildSymbolicMap(profile)`. +- **types.ts** — estrutura: + - `jyotish`: { moonRashi, nakshatra, archetypeKey } + - `numerology`: { rulingNumber } + - `themes`: string[] + - `traits`: string[] + - `evidence`: Record (ex.: { chart } para auditoria e extensão) +- **builder.ts** — `buildSymbolicMap(profile)` usa `computeVedicChartSimplified` e `getRulingNumberFromName`; retorna o mapa com themes/traits vazios e evidence.chart. + +Existe **mapa estruturado reutilizável**, não só cálculo solto. + +--- + +## 2. Insight Layer (`lib/insights/`) + +- **types.ts** — `Insight` = { key, topic, weight, evidence } (e system para compatibilidade). +- **jyotishInsightsForSymbolic.ts** — regras Jyotish (20+): por nakshatra e moonRashi; topics general, love, career, year. +- **collectInsightsForSymbolicMap.ts** — agrega insights Jyotish + **Action derivada do mapa**: + - `action.n.{rulingNumber}` (numerologia) + - `action.general` + - `action.archetype.{archetypeKey}` (jyotish) + +As interpretações são **derivadas** do mapa (key, topic, weight, evidence), não blocos fixos. + +--- + +## 3. Narrative Composer (`lib/narrative/composer.ts`) + +- **composeReading(map, topic)** — assinatura principal: + - coleta insights do mapa; + - filtra por `topic` (general | love | career | year | action); + - ordena por peso; + - pega top 3; + - resolve frase por key (PHRASES[i.key][0]); + - junta com `\n\n`. + +Existe **composeReading(map, "love")**, **composeReading(map, "career")**, **composeReading(map, "year")**, **composeReading(map, "action")** — modularidade por tópico. + +--- + +## 4. Readings modulares (`lib/readings/symbolicReadings.ts`) + +Cada getter recebe o **mapa** e devolve texto para um tópico: + +- **getGeneral(map)** → composeReading(map, "general") +- **getLove(map)** → composeReading(map, "love") +- **getCareer(map)** → composeReading(map, "career") +- **getYear(map)** → composeReading(map, "year") +- **getAction(map)** → composeReading(map, "action") + +O produto pode oferecer “fale só sobre relacionamento”, “fale só sobre trabalho”, “fale sobre o ano atual” usando o mesmo mapa. + +--- + +## 5. getOfflineReading(profile) — wrapper + +- **lib/readingOffline.ts**: + 1. `map = buildSymbolicMap(profile)` + 2. `return { general: getGeneral(map), love: getLove(map), career: getCareer(map), year: getYear(map), action: getAction(map) }` + +Retorno estruturado: **general, love, career, year, action**. A API `/api/map/personal?offline=true` usa esse objeto e pode enviar `sections` ao frontend. + +--- + +## 6. Action derivada do mapa + +A prática concreta (Action) **não é fixa**; vem dos insights: + +- Número regente → `action.n.{n}` (ex.: número 5 → foco e limites). +- Arquétipo → `action.archetype.{archetypeKey}` (ex.: cuidador → boundary). +- Fallback → `action.general`. + +Frases no dicionário (`phrasesForSymbolic.ts`, action.1 … action.30, action.general, action.archetype.*) são escolhidas por key com base no mapa. + +--- + +## Resumo do estado + +| Camada | Status | +|------------------------|--------| +| SymbolicMap universal | ✅ lib/symbolic (jyotish, numerology, themes, traits, evidence) | +| Insight Rules | ✅ key, topic, weight, evidence (Jyotish + Action por mapa) | +| Composer modular | ✅ composeReading(map, topic) | +| Readings Love/Career/Year | ✅ getLove(map), getCareer(map), getYear(map) | +| Action baseado no mapa | ✅ action.n.X, action.archetype.X, action.general | +| getOfflineReading | ✅ retorna { general, love, career, year, action } | + +O Darshan tem **leituras temáticas reutilizáveis** baseadas no mesmo mapa simbólico (Engine 2.0). O Oracle continua como ritual rápido; a leitura profissional é map-based. diff --git a/docs/ENGINE_2.1_VALIDATION.md b/docs/ENGINE_2.1_VALIDATION.md new file mode 100644 index 0000000..111c21b --- /dev/null +++ b/docs/ENGINE_2.1_VALIDATION.md @@ -0,0 +1,51 @@ +# Validação Engine 2.1 — status pós-PR #3 + +Estado atual do repositório após os commits do PR #3 (incl. unificação, cooldown e numerologia). + +--- + +## ✅ Implementado + +| Módulo | Status | Observação | +|--------|--------|------------| +| Symbolic Map Engine | ✅ | `lib/symbolic/`, `lib/engines/buildSymbolicMap.ts` | +| Sacred Remedy Engine | ✅ | **Engine oficial único:** `lib/sacredRemedy/` | +| Remedy Matrix (50 estados) | ✅ | `lib/dictionaries/remedyMatrix.json` | +| Corpus sagrado expandido | ✅ | yoga_sutras ~60, puranas ~40, upanishads ~30 (kleshaTargets + qualities) | +| Ayurveda Qualities (20 gunas) | ✅ | `lib/sacredRemedy/types.ts` + ayurvedaActionSelector | +| Instant Light Universal + Personal | ✅ | GET `/api/instant-light`; POST `/api/darshan` (mock) usa sacredRemedy | +| Readings modulares | ✅ | `/api/reading/*` (general, love, career, year) | +| Histórico e anti-repetição | ✅ | historyStorage, instant_light_uses, modal UI | +| Swiss Provider scaffold | ✅ | `lib/core/providers/swissProvider.ts` | +| **Unificação sem duplicação** | ✅ | **P0:** Apenas `lib/sacredRemedy` é o motor; `/api/darshan` e `/api/instant-light` importam só daqui. `lib/instantLight` é wrapper de compatibilidade. | +| **Numerologia profunda** | ✅ | **P1:** lifePathNumber (data), expressionNumber (nome), soulUrgeNumber (vogais), personalityNumber (consoantes) em `lib/knowledge/numerology.ts`; SymbolicMap inclui os quatro. | +| **Cooldown autônomo server-side** | ✅ | **P2:** Em `/api/darshan` (mock), se usuário logado: servidor chama `getRecentInstantLightIds(session.email)` e `recordInstantLightUse(session.email, { sacredId, stateKey })`. Tabela `instant_light_uses`. | + +--- + +## Módulos legados (não usados pelo fluxo Instant Light) + +- **`lib/diagnosis/`** — Cópia antiga do diagnosis; o fluxo usa `lib/sacredRemedy/diagnosisEngine.ts`. Mantido por referência; engine oficial é sacredRemedy. +- **`lib/sacred/`** — Sacred Picker (classicTexts); o fluxo Instant Light usa `lib/sacredRemedy/sacredSelector.ts` + `dictionaries/sacred/*.json`. Mantido por referência. +- **`lib/instantLight/`** — Re-export do sacredRemedy; retorna `{ message, sacredId }` para compatibilidade. Novo código deve usar `@/lib/sacredRemedy`. + +--- + +## ⚠️ Parcial / próximo passo + +| Item | Status | Próximo passo | +|------|--------|--------------| +| Human Design | ⚠️ Scaffold | humanDesignEngine.ts e humanDesignInsights existem; aprofundar quando integrar HD de fato. | +| Ayurveda action selector high-end | ⚠️ MVP | P3: antídotos para as 20 qualities completos, múltiplas qualities, prioridade por dosha. | +| Corpus premium | ⚠️ ~60/40/30 | P4: expandir para Sutras 100+, Puranas 80+, Upanishads 50+. | +| GET /api/instant-light com cooldown server-side | ⚠️ Cliente opcional | Endpoint não exige auth; cooldown server-side só em `/api/darshan` (mock) quando há sessão. Para instant-light autônomo seria preciso auth. | + +--- + +## Resumo + +- **Engine único:** `composeInstantLight()` está apenas em `lib/sacredRemedy`; chamado por `/api/darshan` (mock) e GET `/api/instant-light`. +- **Numerologia:** life path, expression, soul urge, personality no SymbolicMap. +- **Cooldown:** server-side em `/api/darshan` (mock) quando o usuário está logado; `instant_light_uses` + `getRecentInstantLightIds` / `recordInstantLightUse`. + +Engine 2.1 está fechado para P0, P1 e P2; P3 (Ayurveda high-end) e P4 (corpus premium) são evolução editorial. diff --git a/docs/ENGINE_21_GAPS_FECHADOS.md b/docs/ENGINE_21_GAPS_FECHADOS.md new file mode 100644 index 0000000..e734cfd --- /dev/null +++ b/docs/ENGINE_21_GAPS_FECHADOS.md @@ -0,0 +1,123 @@ +# Engine 2.1 — Gaps reais fechados (este PR) + +Este documento registra o que foi **realmente** fechado em resposta aos gaps e próximos passos obrigatórios. + +--- + +## P0 — Unificar Instant Light Engine ✅ + +**Situação anterior:** Existiam `lib/instantLight/*`, `lib/sacred/*`, `lib/diagnosis/*` em paralelo a `lib/sacredRemedy/*`. + +**O que foi feito:** + +- **Removidos** (duplicação eliminada): + - `lib/instantLight/` (instantLightComposer.ts, index.ts) + - `lib/sacred/` (index.ts, sacredPicker.ts, types.ts) + - `lib/diagnosis/` (diagnosisEngine.ts, index.ts, types.ts) +- **Motor oficial único:** `lib/sacredRemedy/` — usado por: + - GET `/api/instant-light` + - POST `/api/darshan` (modo mock) + +**Resultado:** Existe apenas um pipeline: `composeInstantLight()` de `lib/sacredRemedy`. Nenhum código importa mais de `lib/instantLight`, `lib/sacred` ou `lib/diagnosis`. + +--- + +## P1 — Numerologia completa ✅ + +**Situação anterior:** `lib/engines/numerologyEngine.ts` expunha só ruling number; o review pedia life path, soul urge, personality, expression. + +**O que já existia (e foi mantido):** + +- **`lib/knowledge/numerology.ts`** já tinha: + - `getLifePathNumber(birthDate)` + - `getExpressionNumber(fullName)` + - `getSoulUrgeNumber(fullName)` (vogais) + - `getPersonalityNumber(fullName)` (consoantes) +- **`lib/symbolic/builder.ts`** (SymbolicMap usado pelo Sacred Remedy) já preenchia `lifePathNumber`, `expressionNumber`, `soulUrgeNumber`, `personalityNumber`. +- **`lib/sacredRemedy/diagnosisEngine.ts`** já usava numerologia no seed e em `numerologyFromMap`. + +**O que foi feito neste PR:** + +- **`lib/engines/numerologyEngine.ts`** foi expandido para retornar também: + - `lifePathNumber` (data de nascimento) + - `expressionNumber` (nome completo) + - `soulUrgeNumber` (vogais) + - `personalityNumber` (consoantes) +- Assim, o **SymbolicMap do engines** (usado por `lib/engines/buildSymbolicMap`) passa a expor numerologia completa; o Sacred Remedy continua usando `lib/symbolic/builder`, que já tinha numerologia completa. + +**Resultado:** Numerologia profunda está em `lib/knowledge/numerology.ts` e integrada no SymbolicMap (symbolic + engines) e no diagnosisEngine. + +--- + +## P2 — Yoga Sutras completos (196) ✅ + +**Situação anterior:** `yoga_sutras.json` tinha ~105 entradas; o corpus completo de Patañjali tem 196 sutras. + +**O que foi feito:** + +- Criado **`lib/dictionaries/sacred/yoga_sutras_full.json`** com **196 entradas**: + - 105 entradas existentes (de `yoga_sutras.json`) com campo **`themes`** adicionado + - 11 novas: YS.1.41–YS.1.51 + - 46 novas: YS.3.11–YS.3.56 + - 34 novas: YS.4.1–YS.4.34 +- Cada entrada tem: **id**, **text**, **kleshaTargets**, **qualities**, **themes**. +- **`lib/sacredRemedy/sacredSelector.ts`** passou a carregar **`yoga_sutras_full.json`** em vez de `yoga_sutras.json`. +- Script **`scripts/generate-yoga-sutras-full.js`** gera o arquivo (para futuras expansões ou ajustes). + +**Resultado:** O selector usa o corpus completo de 196 Yoga Sutras com tags obrigatórias (kleshaTargets, qualities, themes). + +--- + +## P2 — Puranas 500 (backlog) + +**Meta premium:** 300–500 trechos medicinais/arquetípicos, altamente taggeados (kleshaTargets, qualities, themes). + +**Situação atual:** `puranas.json` tem ~80 entradas. A expansão para 300–500 é **trabalho editorial** (conteúdo + curadoria). + +**Recomendação:** Tratar em PR ou sprint dedicado; manter estrutura atual e ir ampliando o arquivo aos poucos. + +--- + +## P3 — Ayurveda high-end ✅ (20/20 + múltiplas qualities + dosha; sono/rotina adicionados) + +**O que está feito:** + +- **20/20 qualities** com antídotos reais (QUALITY_TO_PRACTICE, QUALITY_TO_FOOD). +- **Múltiplas qualities:** `getActionsForQualitiesWithDosha(qualities, dosha, { maxSuggestions: 3 })` combina até 3 práticas e 3 alimentos. +- **Prioridade por dosha:** ordenação por DOSHA_QUALITIES_PRIORITY (vata/pitta/kapha). +- **Sono e rotina:** QUALITY_TO_SLEEP e QUALITY_TO_ROUTINE; `getFullActionsForQualitiesWithDosha()` retorna practice, food, sleep, routine (opcionais para UI). + +**Extensão futura (opcional):** prioridade por estação/hora — tipo `GetActionsWithDoshaOptions` já preparado para `season?` e `hour?` quando o composer passar contexto. + +--- + +## P4 — Cooldown autônomo server-side ✅ + +**O que está feito:** + +- **GET `/api/instant-light`:** com sessão (cookie), chama `getRecentInstantLightIds(session.email, 20)` e sobrescreve `recentSacredIds` / `recentStateKeys`; após responder, chama `recordInstantLightUse(session.email, { sacredId, stateKey })`. +- O cliente **não** precisa enviar recentIds; o servidor preenche e registra uso sozinho quando o usuário está logado. +- Query params são fallback apenas para usuário não logado. + +--- + +## Resumo (Engine 2.1 Premium Final) + +| Item | Status | +|------|--------| +| P0 — Unificar pipeline (apenas sacredRemedy) | ✅ Feito | +| P1 — Numerologia completa (life path, expression, soul urge, personality) | ✅ Feito | +| P2 — Corpus premium (Yoga Sutras 196; Puranas ~500) | ✅ Yoga 196; Puranas 500 ⏳ backlog | +| P3 — Ayurveda high-end (20/20, múltiplas, dosha, sono, rotina) | ✅ Feito | +| P4 — Cooldown autônomo server-side | ✅ Feito | + +--- + +## Referências + +- Motor oficial: `lib/sacredRemedy/` e `docs/SACRED_REMEDY_ENGINE.md` +- Numerologia: `lib/knowledge/numerology.ts`, `lib/engines/numerologyEngine.ts` +- Corpus Yoga Sutras completo: `lib/dictionaries/sacred/yoga_sutras_full.json` +- Geração do corpus: `node scripts/generate-yoga-sutras-full.js` +- Ayurveda high-end: `lib/sacredRemedy/ayurvedaActionSelector.ts` (QUALITY_TO_SLEEP, QUALITY_TO_ROUTINE, getFullActionsForQualitiesWithDosha) +- Cooldown: `lib/historyStorage.ts` (getRecentInstantLightIds, recordInstantLightUse), GET `/api/instant-light` diff --git a/docs/ENGINE_21_PREMIUM_STATUS.md b/docs/ENGINE_21_PREMIUM_STATUS.md new file mode 100644 index 0000000..f4ab395 --- /dev/null +++ b/docs/ENGINE_21_PREMIUM_STATUS.md @@ -0,0 +1,102 @@ +# Engine 2.1 Premium — Status dos Críticos e Estratégicos + +Documento de verificação dos pontos críticos e estratégicos antes de merge (produto high-end). + +--- + +## CRÍTICO 1 — Numerologia completa + +**Requisito:** life path (data), soul urge (vogais), personality (consoantes), expression (nome completo). Integrar no SymbolicMap e diagnosisEngine. + +**Estado:** ✅ **Implementado** + +| Onde | O quê | +|------|--------| +| `lib/knowledge/numerology.ts` | `getLifePathNumber(birthDate)`, `getExpressionNumber(fullName)`, `getSoulUrgeNumber(fullName)`, `getPersonalityNumber(fullName)` | +| `lib/engines/numerologyEngine.ts` | Retorna `lifePathNumber`, `expressionNumber`, `soulUrgeNumber`, `personalityNumber` | +| `lib/symbolic/builder.ts` | SymbolicMap preenchido com os quatro números no objeto `numerology` | +| `lib/sacredRemedy/diagnosisEngine.ts` | `diagnosisPersonal` usa `map.numerology`; seed influenciado por lifePath/soulUrge; `numerologyFromMap` no diagnóstico | + +--- + +## CRÍTICO 2 — Cooldown server-side autônomo + +**Requisito:** selector nunca repete textos recentes; consultar historyStorage automaticamente; cooldown de 7 dias por sacredId; cliente não controla. + +**Estado:** ✅ **Implementado** + +| Onde | O quê | +|------|--------| +| `lib/historyStorage.ts` | `getRecentInstantLightIds(userEmail, limit, sinceDays?)` — quando `sinceDays === 7`, retorna só usos dos últimos 7 dias | +| `app/api/instant-light/route.ts` | Com sessão: chama `getRecentInstantLightIds(session.email, 50, 7)` e sobrescreve `recentSacredIds`/`recentStateKeys`; após resposta chama `recordInstantLightUse` | +| `lib/sacredRemedy/instantLightComposer.ts` | Recebe `recentSacredIds` e `recentStateKeys`; `selectSacredText({ avoidIds: recentSacredIds })` e diagnosis evita `recentStateKeys` | + +Cliente não envia recentIds quando logado; servidor preenche e registra uso sozinho. Cooldown de 7 dias: apenas sacredIds/stateKeys usados nos últimos 7 dias entram na lista de evitação. + +--- + +## CRÍTICO 3 — Pipeline único + +**Requisito:** instant-light como motor oficial; /api/darshan wrapper ou legacy; evitar dois motores divergentes. + +**Estado:** ✅ **Implementado** + +| Onde | O quê | +|------|--------| +| `lib/sacredRemedy/` | Único motor: `diagnosisEngine`, `sacredSelector`, `ayurvedaActionSelector`, `instantLightComposer` | +| `lib/instantLight`, `lib/sacred`, `lib/diagnosis` | **Removidos** (não existem mais) | +| `GET /api/instant-light` | Usa `composeInstantLight` de `@/lib/sacredRemedy` | +| `POST /api/darshan` (modo mock) | Usa **o mesmo** `composeInstantLight` de `@/lib/sacredRemedy` | + +Um único composer; dois endpoints consomem o mesmo motor. Sem duplicação. + +--- + +## P1 — Ayurveda Action Selector premium + +**Requisito:** 20/20 qualities com antídotos; múltiplas qualities (ruksha+chala+sukshma); rotina, sono, alimentação. + +**Estado:** ✅ **Implementado** + +| Onde | O quê | +|------|--------| +| `lib/sacredRemedy/ayurvedaActionSelector.ts` | `QUALITY_TO_PRACTICE`, `QUALITY_TO_FOOD`, `QUALITY_TO_SLEEP`, `QUALITY_TO_ROUTINE` para as 20 qualities | +| | `getActionsForQualitiesWithDosha`, `getFullActionsForQualitiesWithDosha` — múltiplas qualities, prioridade por dosha + season + hour | +| `lib/sacredRemedy/instantLightComposer.ts` | Usa `getFullActionsForQualitiesWithDosha`; resposta inclui `practice`, `food`, `sleep`, `routine` | +| `lib/sacredRemedy/types.ts` | `InstantLightResponse` com `food?`, `sleep?`, `routine?` | + +--- + +## P2 — Corpus premium + +**Requisito:** Yoga Sutras 196; Puranas 300–500 excerpts medicinais; Upanishads 200; kleshaTargets, qualities, themes obrigatórios. + +**Estado:** ✅ **Completo** + +| Item | Meta | Atual | Observação | +|------|------|--------|------------| +| Yoga Sutras | 196 | **196** | `lib/dictionaries/sacred/yoga_sutras_full.json`; sacredSelector usa este arquivo | +| Puranas | 300–500 | **400** | Todas com kleshaTargets, qualities, themes; script `scripts/expand-sacred-corpus.js` | +| Upanishads | 200 | **200** | Todas com kleshaTargets, qualities, themes; script `scripts/expand-sacred-corpus.js` | + +Corpus premium fechado: 196 sutras + 400 puranas + 200 upanishads = 796 entradas no sacredSelector. + +--- + +## O que ainda é heurístico / Engine 2.2 + +**Diagnosis Engine:** hoje usa prakriti/dosha do mapa (rashi lunar), qualities por dosha, nakshatra → klesha. **Não inclui ainda:** yogas, casas, aspectos, dashas, trânsitos anuais reais. Isso é escopo do **Engine 2.2 Jyotish High Precision** (Swiss Ephemeris default, casas, yogas, dashas, trânsitos), após fechar o 2.1 Premium. + +--- + +## Resumo + +| Bloqueador / P | Status | +|----------------|--------| +| CRÍTICO 1 — Numerologia completa | ✅ Feito | +| CRÍTICO 2 — Cooldown server-side (7 dias) | ✅ Feito | +| CRÍTICO 3 — Pipeline único | ✅ Feito | +| P1 — Ayurveda 20/20 + rotina/sono/alimentação | ✅ Feito | +| P2 — Corpus (196 sutras; Puranas 400; Upanishads 200) | ✅ Completo (796 entradas) | + +**Engine 2.1 Premium:** críticos, P1 e P2 fechados. Corpus completo: 196 Yoga Sutras + 400 Puranas + 200 Upanishads. Próximo passo estratégico: Engine 2.2 Jyotish High Precision. diff --git a/docs/ESTADO_REAL_PR3_ENGINE_21.md b/docs/ESTADO_REAL_PR3_ENGINE_21.md new file mode 100644 index 0000000..33708c1 --- /dev/null +++ b/docs/ESTADO_REAL_PR3_ENGINE_21.md @@ -0,0 +1,84 @@ +# Estado real — PR #3 Engine 2.1 (atual) + +Este documento corrige avaliações desatualizadas. **Todos os blocos críticos listados abaixo já estão implementados** neste repositório. + +--- + +## ✅ CRÍTICO 1 — Input Parser multi-eixos — **IMPLEMENTADO** + +| Item | Arquivo | Status | +|------|---------|--------| +| Normalização | `lib/dictionaries/inputNormalization.json` | ✅ | +| Verbos | `lib/dictionaries/inputVerbs.json` | ✅ | +| Temas | `lib/dictionaries/inputThemes.json` | ✅ | +| Perguntas | `lib/dictionaries/inputQuestions.json` | ✅ | +| Emoções → stateKey | `lib/dictionaries/inputEmotions.json` | ✅ | +| normalizeInput | `lib/input/normalizeInput.ts` | ✅ | +| intentParser | `lib/input/intentParser.ts` | ✅ | +| stateScorer | `lib/input/stateScorer.ts` | ✅ | + +**Pipeline em uso:** `userText` → normalize → parseIntent → pickBestState → preferredStateKey em `app/api/instant-light/route.ts` → composeInstantLight (sacredRemedy). O usuário influencia o offline via texto natural; a ponte “o que digitou → stateKey” existe. + +--- + +## ✅ CRÍTICO 2 — Truth Package padrão — **IMPLEMENTADO** + +| Item | Arquivo | Status | +|------|---------|--------| +| Entrada canônica | `lib/core/UserRequestContext.ts` (Theme, Mode, UserRequestContext) | ✅ | +| Saída canônica | `lib/core/DarshanTruthPackage.ts` (DarshanTruthPackage, SacredCorpusKey) | ✅ | + +Instant Light retorna sempre **DarshanTruthPackage** (mode, theme, stateKey, diagnosis, sacred, practice, food, contemplativeQuestion, meta.generatedAt, etc.). Readings e IA usam o mesmo payload. + +--- + +## ✅ CRÍTICO 3 — Unificação do pipeline — **IMPLEMENTADO** + +**Motor oficial:** `lib/sacredRemedy/*` (diagnosisEngine, sacredSelector, ayurvedaActionSelector, instantLightComposer). + +Não há dois pipelines. Wrappers antigos (`lib/instantLight`, `lib/sacred`, `lib/diagnosis`) foram **removidos**: nenhum código importava deles. Todas as rotas (`/api/instant-light`, `/api/darshan`) e testes usam **apenas** `@/lib/sacredRemedy`. Zero duplicação. + +--- + +## ✅ CRÍTICO 4 — IA como expansão opcional — **IMPLEMENTADO** + +| Item | Arquivo | Status | +|------|---------|--------| +| Narrative Gateway | `lib/ai/narrativeGateway.ts` (expandNarrative) | ✅ | +| Endpoint | `app/api/ai/expand/route.ts` (POST) | ✅ | + +IA recebe **truthPackage + question + theme**; não recalcula diagnóstico, apenas expande narrativa (guardrails no prompt). + +--- + +## ✅ CRÍTICO 5 — Numerologia profunda — **IMPLEMENTADO** + +| Item | Onde | Status | +|------|------|--------| +| lifePathNumber (data) | `lib/engines/numerologyEngine.ts`, `lib/knowledge/numerology.ts`, `lib/symbolic/builder.ts` | ✅ | +| expressionNumber (nome completo) | Idem | ✅ | +| soulUrgeNumber (vogais) | Idem | ✅ | +| personalityNumber (consoantes) | Idem | ✅ | +| SymbolicMap.numerology | `lib/symbolic/builder.ts`, `lib/symbolic/types.ts` | ✅ | +| diagnosisEngine | Usa `map.numerology` (lifePath, soulUrge, expression, personality) em diagnóstico personal | ✅ | + +--- + +## ⚠️ Pendências (não críticas para “premium fechado”) + +- **Corpus premium completo:** Yoga Sutras 196 (hoje há `yoga_sutras_full.json` com muitas entradas; expansão editorial para 196 + Puranas/Upanishads em escala é backlog). +- Wrappers removidos: `lib/instantLight`, `lib/sacred`, `lib/diagnosis` foram deletados; só existe `lib/sacredRemedy`. + +--- + +## Resumo + +- **Input Parser:** existe; texto do usuário → stateKey → Instant Light. +- **Truth Package:** existe; UserRequestContext + DarshanTruthPackage; Instant Light e IA usam o mesmo formato. +- **Engine único:** sacredRemedy é o único truth engine; wrappers antigos foram removidos (não existem mais `lib/instantLight`, `lib/sacred`, `lib/diagnosis`). +- **IA Expansion:** narrativeGateway + POST /api/ai/expand implementados. +- **Numerologia:** lifePath, expression, soulUrge, personality no SymbolicMap e no diagnosis. + +O produto está **premium fechado** nos 5 críticos; o que resta é expansão de conteúdo (corpus). + +**Build:** prebuild corrigido (ENOENT quando `build` não existe); tipos TS em `instant-light/route` e `instantLightComposer` ajustados; `npm run build` passa. diff --git a/docs/FLUXO_ORACULO_OFFLINE.md b/docs/FLUXO_ORACULO_OFFLINE.md index 5771dcd..0760f12 100644 --- a/docs/FLUXO_ORACULO_OFFLINE.md +++ b/docs/FLUXO_ORACULO_OFFLINE.md @@ -4,11 +4,20 @@ Este documento descreve **como** o Darshan usa a biblioteca Jyotish (mhah-pancha --- +## Oracle vs Leitura profissional (Engine 2.0) + +- **Oracle (revelação rápida):** quando o frontend envia `mock: true` para `/api/darshan`, usamos o **ritual rápido** em `lib/oracleOffline.ts`: chart védico → **primeiro arquétipo** como principal da revelação → blocos de frase por seed. É o “oráculo em blocos”. +- **Leitura profissional (mapa pessoal):** quando o frontend envia `offline: true` para `/api/map/personal`, usamos o **Engine 2.0** em `lib/readingOffline.ts`: **SymbolicMap** → **Insight Rules** → **Narrative Composer** → readings modulares (general, love, career, year, action). Não é texto fixo; é mapa estruturado + composer modular. Ver [ENGINE_2.0.md](./ENGINE_2.0.md). + +Ou seja: existe **mapa simbólico universal** e **composer modular**; o Oracle continua usando o primeiro arquétipo para o ritual rápido; a leitura profissional é baseada no mapa. + +--- + ## 0. Garantias: IA desativada = 100% offline (revelação) - **A IA desativada não chama a IA por baixo dos panos.** Quando o frontend envia `mock: true` no POST para `/api/darshan`, a rota retorna **antes** de qualquer `getConnector()` ou `connector.complete()`. Nenhum provedor externo (OpenAI, Google, Anthropic) é chamado. -- **Quem faz o trabalho é só o nosso código:** `lib/oracleOffline.ts` + `lib/knowledge/*` (formulações, arquétipos, Jyotish, numerologia, textos clássicos). Tudo roda no servidor Node/Next sem chamadas a APIs de IA. -- **Não há bypass em dev.** O modo mock não é “desconsiderado” em desenvolvimento: se `body.mock === true`, o servidor sempre usa `getOfflineRevelation` e responde imediatamente, em qualquer ambiente. +- **Quem faz o trabalho é só o nosso código:** o modo mock usa `lib/instantLight/` (Sacred Library + mapa quando houver perfil). A **leitura offline** usa `lib/readingOffline.ts` → **Engine 2.0**: `buildSymbolicMap(profile)` → `getGeneral(map)`, `getLove(map)`, `getCareer(map)`, `getYear(map)`, `getAction(map)` (composer modular). Tudo roda no servidor Node/Next sem chamadas a APIs de IA. Ver [ENGINE_2.0.md](./ENGINE_2.0.md) e [OFFLINE_ENGINE_PIPELINE.md](./OFFLINE_ENGINE_PIPELINE.md). +- **Não há bypass em dev.** O modo mock não é “desconsiderado” em desenvolvimento: se `body.mock === true`, o servidor usa o **Instant Light Engine** (`composeInstantLight`) e responde imediatamente (texto sagrado + insight/prática do mapa quando houver perfil). Ver [INSTANT_LIGHT_ENGINE.md](./INSTANT_LIGHT_ENGINE.md). - **Leitura (mapa pessoal):** quando a IA está desligada (toggle “AI desligada”), o modal **Leitura** pode gerar uma **leitura offline** (sem IA e sem custo): o frontend envia `offline: true` para `/api/map/personal`, que chama `getOfflineReading(profile)` em `lib/readingOffline.ts` e monta o texto a partir do conhecimento local (Jyotish, numerologia, arquétipos, textos clássicos). Nenhum crédito é debitado. Com IA ligada, a Leitura usa a IA e debita créditos normalmente. --- @@ -16,7 +25,7 @@ Este documento descreve **como** o Darshan usa a biblioteca Jyotish (mhah-pancha ## 1. Quando o oráculo offline é usado - O frontend envia `mock: true` no body do POST para `/api/darshan` (toggle "AI desligada"). -- A rota chama `getOfflineRevelation(userProfile, userMessage)` em vez da IA. +- A rota chama `composeInstantLight(userProfile, { recentSacredIds })` em vez da IA (Universal Light sem perfil, Personal Light com perfil). - O **perfil** (nome, data de nascimento, local, horário) é o que alimenta todo o fluxo; a **pergunta** do usuário hoje não altera o conteúdo (pode ser usada em versões futuras). --- @@ -40,7 +49,7 @@ Este documento descreve **como** o Darshan usa a biblioteca Jyotish (mhah-pancha 3. **Mapeamento:** - `Raasi.ino` → nosso **Rashi** (mesha, vrishabha, …, mina). - `Nakshatra.ino` → nossa **Nakshatra** (ashwini, bharani, …, revati). -4. **Arquétipos:** em `archetypes.ts`, cada Rashi e cada Nakshatra estão ligados a um **arquétipo** (ex.: lua em Karka → arquétipo "cuidador"). O chart devolve uma lista `archetypeKeys`; usamos o **primeiro** como arquétipo principal da revelação. +4. **Arquétipos:** em `archetypes.ts`, cada Rashi e cada Nakshatra estão ligados a um **arquétipo** (ex.: lua em Karka → arquétipo "cuidador"). O chart devolve uma lista `archetypeKeys`; no **Oracle (ritual rápido)** usamos o **primeiro** como arquétipo principal da revelação. Na **leitura profissional** (Engine 2.0), o mapa simbólico guarda esse archetypeKey e os insights + composer montam love/career/year/action a partir do mapa. Se a biblioteca **não** estiver instalada ou der erro, usamos o **cálculo simplificado** em `vedic.ts` (Sol/Lua aproximados por fórmulas locais) e, a partir daí, o mesmo mapeamento Rashi/Nakshatra → arquétipo. @@ -105,5 +114,5 @@ A resposta final é a concatenação desses blocos com `\n\n`, no mesmo formato - **Mais/menos blocos:** em `oracleOffline.ts`, ordem e condições dos `blocks.push` e o `slice(0, 7)`. - **Peso do arquétipo vs numerologia:** hoje arquétipo define bloco 1 e 2; numerologia só bloco 4; pode-se inverter ou acrescentar mais frases de um deles. -- **Usar a pergunta do usuário:** `getOfflineRevelation` recebe `userMessage`; hoje não é usado; pode-se, por exemplo, escolher fonte (Upanishad vs Gita) ou tema conforme palavras-chave da pergunta. +- **Usar a pergunta do usuário:** `composeInstantLight` pode receber `themeTags` ou `recentSacredIds`; o cliente pode enviar `recentSacredIds` (ids dos últimos textos sagrados) para reduzir repetição. Pode-se, no futuro, escolher fonte (Upanishad vs Gita) ou tema conforme palavras-chave da pergunta. - **Conteúdo:** editar listas em `formulations.ts`, `classicTexts.ts`, `archetypeTraits.ts`, `numerology.ts` para mudar o que pode ser retornado. diff --git a/docs/HISTORICO_RESPOSTAS_LEITURAS.md b/docs/HISTORICO_RESPOSTAS_LEITURAS.md new file mode 100644 index 0000000..6419515 --- /dev/null +++ b/docs/HISTORICO_RESPOSTAS_LEITURAS.md @@ -0,0 +1,48 @@ +# Histórico de respostas e leituras + +O Darshan armazena no Supabase as respostas da interação com o orb (revelações) e as leituras completas (mapa pessoal), associadas ao usuário logado (por `user_id`). Isso permite exibir um ícone de **Histórico** quando há dados e uma página com abas para consultar o passado. + +--- + +## Tabelas (Supabase) + +- **revelations** — respostas da IA na interação com o orb + - `user_id`, `question_text` (opcional), `response_text`, `created_at` +- **readings** — resultado das leituras completas (mapa pessoal) + - `user_id`, `content`, `created_at` + +Migration: `supabase/migrations/20250129100000_history_tables.sql`. + +--- + +## Quando os dados são gravados + +Apenas **respostas geradas pela IA** são gravadas no histórico. + +- **Revelações:** após cada resposta da IA no orb (POST `/api/darshan` com `revelation: true`). Modo mock/oráculo offline **não** grava em `revelations`. +- **Leituras:** após cada leitura completa gerada pela IA (POST `/api/map/personal`). Modo offline (leitura sem IA) **não** grava em `readings`. + +Ambos usam o email da sessão para resolver o `user_id` na tabela `users`; se o Supabase não estiver configurado, a gravação é silenciosa (não quebra o fluxo). + +--- + +## APIs + +| Método | Rota | Descrição | +|--------|------|-----------| +| GET | `/api/history/count` | Retorna `{ revelations, readings }` do usuário logado (para exibir o ícone quando > 0). | +| GET | `/api/history/revelations` | Lista revelações (query: `limit`, `offset`). | +| GET | `/api/history/readings` | Lista leituras (query: `limit`, `offset`). | + +Todas exigem sessão (cookie); sem login retornam 401 ou contagem zerada. + +--- + +## UI + +- **Ícone Histórico:** aparece à direita (abaixo do ícone Leitura) **somente quando** o usuário está logado e há pelo menos uma revelação ou leitura armazenada. +- **Página de histórico:** painel lateral com duas abas: + - **Respostas** — lista de revelações (data, pergunta se houver, resposta; expandir para ver texto completo). + - **Leituras** — lista de leituras (data, trecho; expandir para ver conteúdo completo). + +Estilo alinhado ao painel "Dados de Entrada" (cores suaves, minimalista). diff --git a/docs/INSTANT_LIGHT_ENGINE.md b/docs/INSTANT_LIGHT_ENGINE.md new file mode 100644 index 0000000..6128181 --- /dev/null +++ b/docs/INSTANT_LIGHT_ENGINE.md @@ -0,0 +1,101 @@ +# Instant Light Engine — Sacred Library + Personal Insight + +O Darshan é **duas coisas ao mesmo tempo**: + +1. **Universal Light (Instant Light)** — qualquer pessoa, sem cadastro, sem mapa: um sutra, um verso purânico, uma prática mínima, uma pergunta final. +2. **Personal Light** — quando a pessoa fornece dados (nome, data/hora de nascimento): o mesmo Instant Light **filtrado e ancorado no SymbolicMap** (tradição + mapa pessoal + destino simbólico). + +O **grande tesouro** do Darshan são os textos sagrados (Purāṇas, Yoga Sūtras, Upanishads, Bhagavad Gita). Eles **não são substituídos** pelo mapa; o mapa é uma **camada adicional**. + +--- + +## Arquitetura: Sacred Remedy Matrix + Diagnosis Engine + +O Instant Light usa a **matriz de remédios** (30 estados) e o **diagnóstico consciente**: + +- **Camada 1 — Prakṛti (Jyotish):** dosha/elemento do mapa (Lua + Nakshatra). +- **Camada 2 — Sāṃkhya Guṇas (3):** estado macro (sattva/rajas/tamas) — “céu interno”. +- **Camada 3 — Ayurvedic Qualities (20):** qualidades em excesso/deficiência (prática, alimento). + +``` +light = SacredVerse(remedy) + [InsightFromMap se perfil] + Practice(remedy) + Question(remedy) +``` + +- **selectRemedy(profile?, { seed, recentSacredIds })** escolhe uma entrada da matriz: + - Com perfil: filtra por guna dominante do mapa (arquétipo → guna) e evita `recentSacredIds`. + - Sem perfil: escolhe entre todas por seed, evitando repetição. +- Cada entrada traz: **verso sagrado** (embutido), **prática**, **alimento**, **pergunta**. +- Nunca aleatório puro; cooldown via `recentSacredIds`. + +--- + +## 1. Sacred Library Engine (`lib/sacred/`) + +- **pickSacredText({ themeTags?, avoidLastIds?, seed? })** — escolhe um texto sagrado com: + - **Rotação determinística** (seed, ex.: dailySeed). + - **Evitar repetição** (avoidLastIds = cooldown). + - **Tags temáticas** (filtrar por source, guna, archetype). +- Fonte atual: `lib/knowledge/classicTexts` (Upanishads, Bhagavad Gita, Yoga Sutras). +- Estrutura de dicionário em `lib/dictionaries/sacred/` (ex.: `yoga_sutras.json`) com `id`, `verse`, `tags` para expansão futura. + +--- + +## 2. Diagnosis Engine + Remedy Matrix (`lib/diagnosis/`) + +- **remedyMatrix.json** — 30 estados (ansiedade, apego, medo, raiva, letargia, clareza, etc.). +- Cada estado: **klesha**, **samkhyaGuna**, **qualities**, **sacred** (corpus, id, verse), **practice**, **food**, **question**. +- **selectRemedy(profile?, { seed, recentSacredIds })** — seleção determinística com cooldown. +- **getPrakritiFromMap(map)**, **getDominantSamkhyaGuna(map)**, **buildDiagnosisFromMapAndRemedy(map, remedy)**. +- Tipos: `SamkhyaGuna`, `AyurvedicQuality`, `ConsciousDiagnosis`, `RemedyMatrixEntry`. + +## 3. Instant Light Composer (`lib/instantLight/`) + +- **composeInstantLight(profile?, options?)** → `{ message, sacredId }`. +- Fonte do conteúdo: **matriz de remédios** (selectRemedy) — verso + prática + pergunta da entrada. +- **Com perfil:** adiciona insight do mapa (getGeneral) entre verso e prática. +- **sacredId** = `corpus.id` (ex.: `yoga_sutras.YS.1.33`) para cooldown. + +--- + +## 4. API Darshan (modo mock) + +- **POST /api/darshan** com `mock: true`: + - Chama **composeInstantLight(userProfile, { recentSacredIds })**. + - **Sem perfil** (sem nome/data) → Universal Light. + - **Com perfil** → Personal Light. +- Resposta inclui **sacredId** para o cliente acumular e enviar em `recentSacredIds` nas próximas requisições. + +--- + +## 5. Numerologia expandida (SymbolicMap) + +- **lifePathNumber** — data de nascimento (soma dos dígitos reduzida a 1–9 ou 11/22). +- **expressionNumber** — nome completo (número regente / Pitágoras). +- **rulingNumber** — mantido para compatibilidade (= expressionNumber). +- Retornado em `map.numerology` (POST /api/map, leituras offline). + +--- + +## 6. Onde está cada peça + +| Peça | Arquivo / pasta | +|------|------------------| +| Remedy Matrix (30 estados) | `lib/dictionaries/remedyMatrix.json` | +| Diagnosis Engine | `lib/diagnosis/diagnosisEngine.ts` | +| Tipos Diagnosis | `lib/diagnosis/types.ts` | +| Sacred Picker | `lib/sacred/sacredPicker.ts` | +| Instant Light Composer | `lib/instantLight/instantLightComposer.ts` | +| Textos clássicos (fonte) | `lib/knowledge/classicTexts.ts` | +| lifePathNumber / expressionNumber | `lib/knowledge/numerology.ts`, `lib/symbolic/builder.ts` | +| /api/darshan (mock) | `app/api/darshan/route.ts` → composeInstantLight | + +--- + +## 7. Resultado + +- **Darshan universal** (sem cadastro) — texto sagrado + prática + pergunta. +- **Darshan pessoal** (com mapa) — texto sagrado + insight do mapa + prática do mapa + pergunta. +- **Textos sagrados preservados e rotacionados** (seed + avoidLastIds). +- **Personalização elegante** quando o mapa existe. +- **Numerologia mais profunda** (lifePath + expression). +- **getOfflineRevelation** continua disponível em `lib/oracleOffline.ts` para outros fluxos; o modo mock da API passou a usar o Instant Light híbrido. diff --git a/docs/OFFLINE_ENGINE_PIPELINE.md b/docs/OFFLINE_ENGINE_PIPELINE.md new file mode 100644 index 0000000..b35e10a --- /dev/null +++ b/docs/OFFLINE_ENGINE_PIPELINE.md @@ -0,0 +1,127 @@ +# Pipeline offline — engine high-end (sem IA) + +Este documento descreve a arquitetura do **engine offline** do Darshan: núcleo astronômico multi-provider, engines (Jyotish, numerologia, Human Design), mapa simbólico, insights determinísticos, dicionários e leituras modulares. Tudo roda **sem IA**, com lógica e dados determinísticos. + +--- + +## Visão geral do pipeline + +``` +User Profile (nome, data, hora, local) + ↓ +AstronomicalCore (multi-provider: Swiss Ephemeris → mhah-panchang) + ↓ +Engines (Jyotish + Numerologia + Human Design) + ↓ +SymbolicMap universal + ↓ +Insight Rules determinísticas + ↓ +Narrative Composer offline + ↓ +Readings modulares (general / love / career / year) + Action + ↓ +API endpoints temáticos +``` + +--- + +## 1. Core astronômico (`lib/core/`) + +- **types.ts** — `AstronomicalCore` (providerUsed, julianDay?, planets?, moonRashi?, nakshatra?, ascendant?, houses?), `CoreProfile`. +- **ephemerisProvider.ts** — interface `EphemerisProvider` (name, compute(profile)). +- **providers/mhahProvider.ts** — mhah-panchang (Lua: Rashi + Nakshatra). **Não removido;** fallback oficial. +- **providers/swissProvider.ts** — stub Swiss Ephemeris (lança para fallback; futuro: @fusionstrings/panchangam ou sweph-wasm). +- **ephemerisResolver.ts** — `computeAstronomicalCore(profile)`: tenta Swiss, depois mhah; nada quebra. + +--- + +## 2. Engines (`lib/engines/`) + +- **jyotishEngine.ts** — só símbolos: moonRashi, nakshatra, planets, houses, precisionLevel. +- **numerologyEngine.ts** — número regente e traits (refator do conhecimento em `lib/knowledge/numerology`). +- **humanDesignEngine.ts** — stub (retorna null se não houver planetas; tipo/autoridade/perfil fixos quando houver). +- **buildSymbolicMap.ts** — `buildSymbolicMap(profile)` → { core, jyotish, numerology, humanDesign }. + +--- + +## 3. Insights (`lib/insights/`) + +- **types.ts** — `Insight` (key, weight, system, topic, evidence?), `InsightTopic`, `InsightSystem`. +- **jyotishInsights.ts** — regras por nakshatra e rashi (general, love, career, year). +- **numerologyInsights.ts** — regras por número regente (general, career, love, year). +- **humanDesignInsights.ts** — regras HD (stub). +- **collectInsights.ts** — `collectAllInsights(map)` agrega todos os insights. + +Nada aleatório; cada insight tem key justificável pelo mapa. + +--- + +## 4. Dicionários (`lib/dictionaries/`) + +- **jyotish.ts** — `JYOTISH_PHRASES` (chaves por rashi/nakshatra e tópico). +- **numerology.ts** — `NUMEROLOGY_PHRASES` (chaves por número regente e tópico). +- **humanDesign.ts** — `HD_PHRASES` (tipo, autoridade). +- **action.ts** — `ACTION_PHRASES` (práticas concretas). +- **index.ts** — `phraseFor(key)` resolve frase por chave (primeira do array; futuro: seed para variedade). + +--- + +## 5. Narrative Composer (`lib/narrative/`) + +- **composer.ts** — `composeReading(insights, topic)`: filtra por tópico, ordena por peso, pega até 5 insights, resolve frase por key, junta com `\n\n`. Evita redundância; sempre justifica via key → dictionary. + +--- + +## 6. Leituras modulares (`lib/readings/`) + +- **generalReading.ts** — `getGeneralReading(profile)` → { reading, action }. +- **loveReading.ts** — `getLoveReading(profile)` → { reading, action }. +- **careerReading.ts** — `getCareerReading(profile)` → { reading, action }. +- **yearReading.ts** — `getYearReading(profile)` → { reading, action }. +- **actionReading.ts** — `getActionReading(profile)` → string (prática final). + +Toda leitura termina com **Action** (prática concreta). + +--- + +## 7. Integração com o Darshan atual + +- **oracleOffline.ts** — usa chart védico + primeiro arquétipo + seed para revelação do orb (1–3 blocos, ritual rápido). +- **readingOffline.ts** — usa **Engine 2.0**: `buildSymbolicMap(profile)` (lib/symbolic) → `getGeneral(map)`, `getLove(map)`, `getCareer(map)`, `getYear(map)`, `getAction(map)` (composer modular). Retorna `{ general, love, career, year, action }`. Ver [ENGINE_2.0.md](./ENGINE_2.0.md). + +Nada do engine anterior foi removido; mhah-panchang continua como fallback. + +--- + +## 8. APIs temáticas + +| Método | Rota | Corpo | Resposta | +|--------|------|--------|----------| +| POST | `/api/reading/general` | `{ profile?: CoreProfile }` | `{ map, reading, action }` | +| POST | `/api/reading/love` | `{ profile?: CoreProfile }` | `{ map, reading, action }` | +| POST | `/api/reading/career` | `{ profile?: CoreProfile }` | `{ map, reading, action }` | +| POST | `/api/reading/year` | `{ profile?: CoreProfile }` | `{ map, reading, action }` | + +Cada resposta inclui o **mapa simbólico** (core, jyotish, numerology, humanDesign), o **texto da leitura** e a **ação** (prática final). + +--- + +## Princípios + +- Nada depende de IA. +- Nada substitui mhah-panchang; Swiss Ephemeris entra como camada premium opcional. +- Insights são determinísticos e justificáveis. +- Leituras são modulares e expansíveis. +- Action sempre presente (menos etéreo). + +--- + +## Próximos passos (Parte 2) + +- **Swiss Ephemeris:** ver [SWISS_EPHEMERIS_INTEGRATION.md](./SWISS_EPHEMERIS_INTEGRATION.md) para integrar @fusionstrings/panchangam ou @fusionstrings/swiss-eph em `swissProvider.ts`. +- **Human Design real:** gates, canais, tipo, autoridade, perfil (BodyGraph completo). +- **Year Engine:** trânsitos e dashas para enriquecer a leitura de ano. +- **Ayurveda Engine:** dosha e práticas corporais no Action Engine. + +Detalhes e ordem sugerida: [ROADMAP_PARTE_2.md](./ROADMAP_PARTE_2.md). diff --git a/docs/PR3_ENGINE_21_STATUS.md b/docs/PR3_ENGINE_21_STATUS.md new file mode 100644 index 0000000..4596572 --- /dev/null +++ b/docs/PR3_ENGINE_21_STATUS.md @@ -0,0 +1,114 @@ +# PR #3 — Resposta à avaliação (Engine 2.1 Finalization) + +Este documento mapeia os **gaps** apontados na avaliação do PR #3 com o **estado atual** do código e as ações recomendadas. + +--- + +## Resumo executivo + +| Gap | Avaliação pediu | Estado atual | Ação | +|-----|-----------------|--------------|------| +| **#1** Duplicação de engines | Um único pipeline; remover/encapsular antigo | **Resolvido** | Nenhuma (já unificado) | +| **#2** Numerologia profunda | lifePath, expression, soulUrge, personality | **Resolvido** | Nenhuma | +| **#3** Cooldown server-side | Servidor autônomo; avoidIds internos; recordUse automático | **Resolvido** | Nenhuma | +| **#4** Ayurveda 20/20 | Antídotos completos + múltiplas qualities + prioridade dosha | **Parcial → Resolvido** | Completar shlakshna/sthula (feito neste doc) | +| **#5** Corpus premium | Sutras 196, Puranas 300–500, Upanishads ~200 + themes | **Pendente (editorial)** | Backlog; tipo `themes` opcional já documentado | + +--- + +## GAP #1 — Duplicação de engines + +**Pedido:** Engine 2.1 deve ter apenas UM pipeline oficial; remover/encapsular instantLight antigo; todos os endpoints chamam apenas um composer final. + +**Estado atual:** + +- **`/api/darshan`** (modo mock) e **GET `/api/instant-light`** importam e usam **apenas** `composeInstantLight` de **`@/lib/sacredRemedy`**. +- **`lib/instantLight`**, **`lib/sacred`** e **`lib/diagnosis`** foram **removidos**; não há mais duplicação. +**Conclusão:** **Resolvido.** Pipeline oficial é `lib/sacredRemedy`. Cliente único para diagnóstico + texto + prática + pergunta. + +--- + +## GAP #2 — Numerologia profunda + +**Pedido:** lifePathNumber (data), expressionNumber (nome), soulUrgeNumber (vogais), personalityNumber (consoantes); integrar no SymbolicMap; diagnosisEngine usa para precisão. + +**Estado atual:** + +- **`lib/knowledge/numerology.ts`**: `getLifePathNumber(birthDate)`, `getExpressionNumber(fullName)`, `getSoulUrgeNumber(fullName)`, `getPersonalityNumber(fullName)` implementados. +- **`lib/symbolic/builder.ts`**: SymbolicMap preenchido com `lifePathNumber`, `expressionNumber`, `soulUrgeNumber`, `personalityNumber`. +- **`lib/sacredRemedy/diagnosisEngine.ts`**: `diagnosisPersonal` usa `map.numerology`; seed efetivo = `seed + lifePath*31 + soulUrge`; diagnóstico retorna `numerologyFromMap` (lifePath, soulUrge, expression, personality). + +**Conclusão:** **Resolvido.** + +--- + +## GAP #3 — Cooldown/histórico autônomo + +**Pedido:** instant-light não deve depender do cliente para avoidIds; servidor consulta historyStorage; recordUse automático no backend. + +**Estado atual:** + +- **GET `/api/instant-light`**: com **sessão** (cookie), chama `getRecentInstantLightIds(session.email, 20)` e sobrescreve `recentSacredIds` / `recentStateKeys` com o retorno do servidor; após responder, chama `recordInstantLightUse(session.email, { sacredId, stateKey })`. +- Query params `recentSacredIds` e `recentStateKeys` são **fallback** para usuário não logado. + +**Conclusão:** **Resolvido.** Cooldown é autônomo quando há sessão; cliente não controla quando logado. + +--- + +## GAP #4 — Ayurveda Action Selector completo + +**Pedido:** Antídotos para as 20 qualities; múltiplas qualities; prioridade por dosha; recomendações alimentares e rotina prática. + +**Estado atual:** + +- **20 gunas:** QUALITY_TO_PRACTICE e QUALITY_TO_FOOD cobrem todas; **shlakshna** e **sthula** tinham "—" e foram preenchidos com antídotos concretos (ver commit associado). +- **Múltiplas qualities + dosha:** `getActionsForQualitiesWithDosha(qualities, dosha, { maxSuggestions: 3 })` ordena por dosha (vata/pitta/kapha), combina até 3 práticas e 3 alimentos; usado no composer quando há `prakritiFromJyotish.dosha`. + +**Conclusão:** **Resolvido** (com a conclusão de shlakshna/sthula neste ciclo). + +--- + +## GAP #5 — Corpus sagrado premium + +**Pedido:** Yoga Sutras 196 completos; Puranas 300–500 excerpts; Upanishads ~200; cada entrada com kleshaTargets, ayurvedicQualities e **themes** obrigatórios. + +**Estado atual:** + +- Estrutura: `yoga_sutras.json`, `puranas.json`, `upanishads.json` com `kleshaTargets` e `qualities` (e opcionalmente `themes` no tipo, para expansão futura). +- Tamanho atual: Yoga Sutras ~100, Puranas ~80, Upanishads ~52. + +**Conclusão:** **Pendente (editorial).** A meta 196 / 300+ / 200 é trabalho de conteúdo; recomendação: tratar em **próximo PR** ou backlog, com `themes` como campo opcional até a expansão. Testes e fechamento do Engine 2.1 não precisam bloquear nesse volume. + +--- + +## Entregáveis do “Engine 2.1 Finalization” — checklist + +| # | Entregável | Status | +|---|------------|--------| +| 1 | Unificar Instant Light em sacredRemedy | ✅ Feito | +| 2 | Remover instantLight antigo ou transformar em wrapper | ✅ Wrapper; deprecation explícita | +| 3 | Numerologia completa implementada | ✅ Feito | +| 4 | Cooldown autônomo server-side | ✅ Feito | +| 5 | Ayurveda Action Selector completo (20 qualities) | ✅ Feito (shlakshna/sthula preenchidos) | +| 6 | Corpus expandido (Sutras 196 ✅; Puranas 300–500, Upanishads ~200) | ⏳ Backlog editorial (atual ~80 puranas, ~52 upanishads) | +| 7 | Testes (deterministic, cooldown, universal vs personal, numerology + integração GET /api/instant-light) | ✅ Feito | + +--- + +## O que foi feito neste ciclo (próximas etapas) + +- **Testes automatizados:** `__tests__/lib/sacredRemedy/` — diagnosisEngine, sacredSelector, ayurvedaActionSelector, instantLightComposer (determinismo, universal vs personal, anti-repetição, 20 gunas). +- **Campo themes:** `SacredCorpusEntry.themes?: string[]` opcional para expansão premium. +- **Refino Nakshatra → klesha:** mapa `NAKSHATRA_KLESHA_TENDENCY` em diagnosisEngine; diagnóstico personal prefere remédios que coincidem com o klesha da nakshatra lunar quando definido. + +## O que permanece em backlog + +- **Corpus em escala premium** (196 Sutras, 300+ Puranas, 200 Upanishads) e **themes** em todas as entradas — trabalho editorial. +- Testes de integração para GET `/api/instant-light` (cooldown com sessão mock). + +--- + +## Referências + +- Motor oficial: `lib/sacredRemedy/` e `docs/SACRED_REMEDY_ENGINE.md` +- Histórico e cooldown: `lib/historyStorage.ts` (`getRecentInstantLightIds`, `recordInstantLightUse`), tabela `instant_light_uses` diff --git a/docs/README.md b/docs/README.md index 19fca75..21f4a57 100644 --- a/docs/README.md +++ b/docs/README.md @@ -23,6 +23,12 @@ |-----------|-----------| | [FLUXO_E_REGRAS.md](./FLUXO_E_REGRAS.md) | Fluxo completo da aplicação e regras (validação IA, estados, créditos). | | [FLUXO_ORACULO_OFFLINE.md](./FLUXO_ORACULO_OFFLINE.md) | Modo oráculo offline (sem IA) e dicionário simbólico. | +| [INSTANT_LIGHT_ENGINE.md](./INSTANT_LIGHT_ENGINE.md) | Instant Light híbrido: Sacred Library + Personal Insight (Universal vs Personal Light). | +| [SYMBOLIC_MAP_ENGINE.md](./SYMBOLIC_MAP_ENGINE.md) | **Motor simbólico real**: engines (Jyotish, Numerologia, HD), SymbolicMap, readings modulares, Composer, APIs POST /api/map e POST /api/reading?theme=. | +| [ENGINE_2.0.md](./ENGINE_2.0.md) | Engine 2.0: SymbolicMap canônico → Insights → Composer → Readings modulares (love/career/year/action). | +| [OFFLINE_ENGINE_PIPELINE.md](./OFFLINE_ENGINE_PIPELINE.md) | Pipeline offline high-end: core, engines, SymbolicMap, insights, leituras modulares. | +| [SWISS_EPHEMERIS_INTEGRATION.md](./SWISS_EPHEMERIS_INTEGRATION.md) | Como integrar Swiss Ephemeris (opcional) em `swissProvider.ts`. | +| [ROADMAP_PARTE_2.md](./ROADMAP_PARTE_2.md) | Roadmap Parte 2: Human Design real, Year Engine, Ayurveda. | | [RITUAL_REVELATION_FLOW.md](./RITUAL_REVELATION_FLOW.md) | Fluxo do ritual de revelação. | | [DICIONARIO_OFFLINE.md](./DICIONARIO_OFFLINE.md) | Dicionário e significados usados no modo offline. | @@ -54,6 +60,7 @@ | Documento | Descrição | |-----------|-----------| | [AUTH_CREDITS_GOOGLE_PAY.md](./AUTH_CREDITS_GOOGLE_PAY.md) | Login (código por e-mail, Google), créditos, Stripe, Mercado Pago, Google Pay. | +| [HISTORICO_RESPOSTAS_LEITURAS.md](./HISTORICO_RESPOSTAS_LEITURAS.md) | Armazenamento e UI de histórico (respostas do orb e leituras completas). | | [PRECIFICACAO_CREDITOS.md](./PRECIFICACAO_CREDITOS.md) | Preços dos pacotes de créditos e taxa da plataforma. | | [PAYMENTS_MERCADOPAGO.md](./PAYMENTS_MERCADOPAGO.md) | Integração Mercado Pago (Checkout Pro, webhook). | | [FINANCE_SYSTEM.md](./FINANCE_SYSTEM.md) | Sistema financeiro (ledger, uso de IA, export CSV). | diff --git a/docs/ROADMAP_PARTE_2.md b/docs/ROADMAP_PARTE_2.md new file mode 100644 index 0000000..467fb6d --- /dev/null +++ b/docs/ROADMAP_PARTE_2.md @@ -0,0 +1,72 @@ +# Roadmap Parte 2 — Human Design, Year Engine, Ayurveda + +Este documento descreve os **próximos passos** do engine offline do Darshan após a base atual (AstronomicalCore, SymbolicMap, Insights, Composer, leituras modulares). Tudo continua **sem IA**, determinístico e expansível. + +--- + +## 1. Human Design real (BodyGraph completo) + +**Estado atual:** stub em `lib/engines/humanDesignEngine.ts` — retorna tipo/autoridade/perfil fixos quando há `core.planets`; senão `null`. + +**Objetivo:** Cálculo real de Human Design a partir das posições planetárias (e opcionalmente hora/local para casas). + +**Entregas sugeridas:** + +- **Gates (64)** — posições planetárias em signos → ativação de portas (ex.: Sol em 15° Áries → Porta 51). +- **Canais** — pares de portas ativadas (Sol/Lua, etc.) → definição de canais. +- **Tipo** — Generator, Manifestor, Projector, Reflector, Manifesting Generator a partir dos centros definidos/abertos. +- **Autoridade** — Emocional, Sacral, Ego, etc., a partir do corpo gráfico. +- **Perfil** — 1/4, 4/6, etc. (linhas consciente/inconsciente). +- **Centros** — definido/aberto por centro (Head, Ajna, Throat, G, Heart, Sacral, Solar Plexus, Spleen, Root). + +**Fontes:** Cálculo HD usa posições planetárias (e às vezes casas). Existem tabelas de portas por grau/signo; APIs ou libs especializadas em BodyGraph podem ser integradas. O core já pode fornecer `planets` quando Swiss Ephemeris estiver ativo. + +**Inserção no pipeline:** `humanDesignEngine(core)` deixa de ser stub e passa a calcular tipo, autoridade, perfil, centros (e opcionalmente gates/canais). Os insights em `lib/insights/humanDesignInsights.ts` e o dicionário `lib/dictionaries/humanDesign.ts` já estão preparados para chaves como `hd.type.*`, `hd.authority.*`; basta alimentar com dados reais. + +--- + +## 2. Year Engine (trânsitos + dashas) + +**Estado atual:** Leituras de ano usam os mesmos insights do mapa natal (tópico `year`); não há trânsitos nem dashas. + +**Objetivo:** Enriquecer a leitura de ano com: + +- **Trânsitos** — posições atuais dos planetas (ou da Lua) em relação ao mapa natal (ex.: “Lua em trânsito em seu Sol natal”). +- **Dashas** — períodos védicos (ex.: Mahadasha, Antardasha) a partir da data de nascimento e da data “do ano” (ou hoje). + +**Entregas sugeridas:** + +- Módulo **trânsitos:** dado mapa natal (core no nascimento) e data de referência (ex.: ano corrente), calcular posições na data de referência e comparar com o natal (aspectos, trânsito por casa/signo). +- Módulo **dashas:** dado nascimento e data de referência, calcular qual Mahadasha/Antardasha está ativa (Vimshottari ou outro sistema). +- **Insights de ano** — novas regras em `lib/insights/` que geram keys como `jyotish.transit.*`, `jyotish.dasha.*`; dicionário com frases para esses keys. +- **Composer** — tópico `year` passa a incluir insights de trânsito/dasha além dos atuais (natal + year). + +**Dependência:** Cálculo de posições para uma data arbitrária (nascimento vs. “hoje” ou “ano”). Com **Swiss Ephemeris** integrado, isso fica direto; com só mhah-panchang, pode ser limitado a Lua/Nakshatra para o ano. + +--- + +## 3. Ayurveda Engine (corporal) + +**Estado atual:** Não existe; o Action Engine usa frases genéricas de prática (respiração, pausa, etc.). + +**Objetivo:** Sugerir práticas corporais e rotinas alinhadas ao mapa (dosha, constituição, momento do dia/estação). + +**Entregas sugeridas:** + +- **Constituição (dosha)** — derivar Vata/Pitta/Kapha (ou predominância) a partir do mapa (ex.: elementos por signos planetários, Lua, Ascendente) e/ou perguntas simples (opcional). +- **Insights Ayurveda** — novo sistema em `lib/insights/` (ex.: `ayurveda.dosha.*`, `ayurveda.season.*`) com regras determinísticas. +- **Dicionário** — `lib/dictionaries/ayurveda.ts` ou `action.ts` ampliado com frases de prática (respiração, alimentação, movimento) por dosha/momento. +- **Action Engine** — além das frases atuais, incluir sugestões de prática corporal (ex.: “Prática mínima: 7 respirações lentas ao acordar”) baseadas em insights Ayurveda quando disponíveis. + +**Nota:** Pode começar com regras simples (ex.: Lua em signos de fogo → Pitta; Lua em signos de ar → Vata) e expandir depois com estação do ano, hora do dia, etc. + +--- + +## Ordem sugerida + +1. **Swiss Ephemeris** — integrar em `swissProvider.ts` (ver [SWISS_EPHEMERIS_INTEGRATION.md](./SWISS_EPHEMERIS_INTEGRATION.md)) para ter planetas completos e casas; habilita Human Design e trânsitos com mais precisão. +2. **Human Design real** — gates, canais, tipo, autoridade, perfil; alimentar `humanDesignEngine` e dicionários. +3. **Year Engine** — trânsitos e dashas; ampliar insights e dicionário para o tópico `year`. +4. **Ayurveda Engine** — dosha + práticas corporais; novos insights e Action. + +Cada passo pode ser feito de forma incremental sem quebrar o pipeline atual. diff --git a/docs/SACRED_REMEDY_ENGINE.md b/docs/SACRED_REMEDY_ENGINE.md new file mode 100644 index 0000000..83e5e91 --- /dev/null +++ b/docs/SACRED_REMEDY_ENGINE.md @@ -0,0 +1,173 @@ +# Sacred Remedy Engine — núcleo offline medicinal + +Motor **paralelo** ao fluxo atual do Darshan. Não substitui `/api/darshan`; adiciona um endpoint e uma pilha dedicada ao “texto como remédio”. + +--- + +## 1. O que é + +- **Diagnóstico consciente:** klesha + samkhya guna + qualidades ayurvédicas (excesso/deficiência). +- **Corpus sagrado taggeado:** yoga_sutras, puranas, upanishads com `kleshaTargets` e `qualities`. +- **Seleção dirigida:** texto sagrado escolhido por klesha e qualidades (anti-repetição por `avoidIds`). +- **Matriz de remédios (50 estados):** cada estado mapeia klesha, samkhyaGuna, qualidades, prática, alimento, pergunta. + +--- + +## 2. Onde está + +| Peça | Caminho | +|------|---------| +| Tipos | `lib/sacredRemedy/types.ts` | +| Diagnosis Engine | `lib/sacredRemedy/diagnosisEngine.ts` | +| Sacred Selector | `lib/sacredRemedy/sacredSelector.ts` | +| Instant Light Composer | `lib/sacredRemedy/instantLightComposer.ts` | +| Yoga Sutras completos (196) | `lib/dictionaries/sacred/yoga_sutras_full.json` | +| Puranas | `lib/dictionaries/sacred/puranas.json` | +| Upanishads | `lib/dictionaries/sacred/upanishads.json` | +| Matriz de remédios | `lib/dictionaries/remedyMatrix.json` | +| Endpoint | **GET** `/api/instant-light` | + +--- + +## 3. Intent Parser (multi-eixo offline) + +Classificação do texto do usuário **sem IA**, por dicionários: + +- **Verbo:** feel / seek / fear / want / conflict / reflect (`lib/dictionaries/inputVerbs.json`). +- **Sujeito:** self / other / relational (eu, meu vs ele, ela vs nós). +- **Tema:** love / career / health / spirituality (`lib/dictionaries/inputThemes.json`). +- **Emoção → stateCandidates:** anxiety, grief, anger, etc. → estados da RemedyMatrix (`lib/dictionaries/inputEmotions.json`). + +**State Scorer** escolhe o `bestStateKey` por pesos: emoção +3, verbClass fear +2, tema +1, sujeito other +1. + +| Peça | Caminho | +|------|---------| +| Intent Parser | `lib/input/intentParser.ts` | +| State Scorer | `lib/input/stateScorer.ts` | +| Dicionários | `lib/dictionaries/inputVerbs.json`, `inputThemes.json`, `inputEmotions.json` | + +Se a request incluir `userText`, o pipeline usa `parseIntent(userText)` → `scoreState(intent)` → `preferredStateKey` no diagnosis, e a resposta fica conectada ao input (ex.: "Tenho medo de perder meu relacionamento" → stateKey anxiety/love, sutra e prática coerentes). + +--- + +## 4. GET /api/instant-light + +- **Método:** GET (sem corpo; sem créditos; sem IA). +- **Query (opcional):** + `fullName`, `birthDate`, `birthTime`, `birthPlace`, **`userText`**, `recentSacredIds`, `recentStateKeys`. +- **userText:** quando informado, Intent Parser + State Scorer definem `preferredStateKey` e a resposta é dirigida ao estado/tema detectado. +- **Com perfil (nome ou data):** `diagnosisPersonal(SymbolicMap)` + insight do mapa + prática + pergunta. +- **Sem perfil:** `diagnosisUniversal()` + texto sagrado dirigido + prática + pergunta. + +**Resposta:** + +```json +{ + "sacredText": "...", + "insight": "...", + "practice": "...", + "food": "...", + "sleep": "...", + "routine": "...", + "question": "...", + "sacredId": "yoga_sutras.YS.1.33", + "stateKey": "anxiety" +} +``` + +- `insight` só vem quando há perfil (personal). +- `food`, `sleep`, `routine` (Ayurveda high-end) vêm quando há qualidades em excesso e dosha; opcionais. +- `sacredId` e `stateKey` para o cliente enviar em `recentSacredIds` / `recentStateKeys` e reduzir repetição. + +--- + +## 5. Fluxo do motor + +1. **Diagnóstico:** + - Com perfil → `diagnosisPersonal(profile)` (mapa → guna dominante → estado da matriz). + - Sem perfil → `diagnosisUniversal()` (estado por seed + recentStateKeys). +2. **Remédio:** `getRemedyForDiagnosis(diagnosis)` → prática, pergunta, referência sagrada (fallback). +3. **Texto sagrado:** `selectSacredText({ kleshaTargets, qualities, avoidIds, seed })` → entrada do corpus (yoga_sutras / puranas / upanishads). +4. **Composição:** sacredText (do selector ou verse da matriz) + insight (se personal) + practice + question. + +--- + +## 5. Formato do corpus sagrado + +Cada entrada em `yoga_sutras.json`, `puranas.json`, `upanishads.json`: + +```json +{ + "id": "YS.1.33", + "text": "Amizade, compaixão, alegria e equanimidade...", + "kleshaTargets": ["raga", "dvesha"], + "qualities": ["chala", "ruksha", "tikshna", "ushna", "khara"] +} +``` + +- **kleshaTargets:** kleśas que o texto ajuda a equilibrar. +- **qualities:** qualidades ayurvédicas associadas (para matching com o diagnóstico). +- **themes:** (opcional) temas para matching futuro (ex.: presença, medo, amor) — usado na expansão premium. + +--- + +## 7. Relação com o resto do produto + +- **Motor único:** `lib/sacredRemedy` é o único pipeline Instant Light; `lib/instantLight`, `lib/sacred` e `lib/diagnosis` foram removidos (P0). +- **`/api/darshan` (POST, mock/IA):** no mock usa **apenas** Sacred Remedy (`composeInstantLight` de `lib/sacredRemedy`); cooldown server-side quando usuário logado. +- **`/api/instant-light` (GET):** motor novo, só offline, só Sacred Remedy (diagnóstico + corpus taggeado + matriz + prática + pergunta). +- **Leitura offline narrativa (`readingOffline`, `oracleOffline`):** segue separada; o Instant Light do Sacred Remedy é outra camada (resposta estruturada: sacredText, insight, practice, question). + +--- + +## 7. Engine 2.1 — Ayurveda + corpus expandido + +- **AyurvedicQuality (20 gunas)** em `types.ts`: guru/laghu, snigdha/ruksha, sita/ushna, manda/tikshna, sthira/chala, mridu/kathina, vishada/picchila, shlakshna/khara, sukshma/sthula, sandra/drava, sara. +- **Diagnosis** retorna `ayurvedicQualities.excess` e `deficient`; **prakriti/dosha** do mapa enriquece o diagnóstico (dosha → qualidades típicas em excesso). +- **Ayurveda Action Selector** (`ayurvedaActionSelector.ts`): prática e alimento concretos por qualidade (ruksha → oleação, chala → grounding, tikshna → cooling, etc.). +- **remedyMatrix.json**: 50 estados (incl. burnout, solitude, grief, jealousy, numbness, hypercontrol, shame, impatience, despair, envy, restlessness, boredom, overwhelm, isolation, perfectionism, avoidance, irritability, self_doubt, longing, acceptance). +- **Corpus sagrado:** Yoga Sutras 196 (`yoga_sutras_full.json`), puranas ~80, upanishads ~52; todas com `kleshaTargets` e `qualities` (e `themes` opcional). + +## 9. Engine 2.1 — Unificação e cooldown (pós-PR #3) + +- **P0 — Engine único:** `/api/darshan` (mock) e GET `/api/instant-light` usam apenas `lib/sacredRemedy`. `lib/instantLight`, `lib/sacred` e `lib/diagnosis` foram removidos. +- **P1 — Cooldown autônomo:** Quando o usuário está logado, o servidor busca `recentSacredIds` e `recentStateKeys` em `getRecentInstantLightIds(userEmail, 50, 7)` (últimos 7 dias) e registra uso em `recordInstantLightUse`. Cliente não controla; cooldown de 7 dias por sacredId. Tabela `instant_light_uses` (migração `20250129110000_instant_light_uses.sql`). +- **P2 — Numerologia completa:** `getSoulUrgeNumber(fullName)` (vogais) e `getPersonalityNumber(fullName)` (consoantes) em `lib/knowledge/numerology.ts`. SymbolicMap inclui `soulUrgeNumber` e `personalityNumber`. + +## 9. Engine 2.1 — Concluído (P3, P4, numerologia, cooldown instant-light) + +- **Numerologia no diagnóstico:** `ConsciousDiagnosis.numerologyFromMap` (lifePath, soulUrge, expression, personality); seed em `diagnosisPersonal` influenciado por lifePath/soulUrge para coerência. +- **Ayurveda high-end:** `getFullActionsForQualitiesWithDosha(qualities, dosha, { maxSuggestions: 3 })` — prioridade por dosha (vata/pitta/kapha), combina prática, alimento, sono e rotina; resposta Instant Light inclui `food`, `sleep`, `routine` quando aplicável. +- **Cooldown GET /api/instant-light:** Com sessão (cookie), o servidor busca `getRecentInstantLightIds(session.email)` e registra uso com `recordInstantLightUse`; query params são fallback para anônimos. +- **Corpus expandido:** Yoga Sutras 100+ (YS.2.51–YS.3.10 adicionados), Puranas 80+, Upanishads 50+. + +## 11. Testes e refinamentos (Engine 2.1 finalization) + +- **Testes:** `__tests__/lib/sacredRemedy/` — diagnosisEngine, sacredSelector, ayurvedaActionSelector, instantLightComposer (determinismo, universal vs personal, anti-repetição, 20 gunas). Executar: `npx jest __tests__/lib/sacredRemedy`. +- **Campo themes:** `SacredCorpusEntry.themes?: string[]` opcional para matching futuro (corpus premium). +- **Nakshatra → klesha:** mapa `NAKSHATRA_KLESHA_TENDENCY` em diagnosisEngine; diagnóstico personal prefere remédios cujo klesha coincide com a tendência da nakshatra lunar. + +## 11. Testes de integração + +- **`__tests__/api/instant-light.route.test.ts`:** GET `/api/instant-light` — modo anônimo, modo personal (query), cooldown server-side com sessão mock (getRecentInstantLightIds, recordInstantLightUse), formato da resposta (food, sleep, routine opcionais). Executar: `npx jest __tests__/api/instant-light.route.test`. + +## 13. Próximos passos (editorial) + +- Corpus premium (196 Sutras já concluído; 300+ Puranas, 200 Upanishads) com themes em todas as entradas. + +--- + +## 13. Status dos críticos (Engine 2.1 Premium) + +Ver **`docs/ENGINE_21_PREMIUM_STATUS.md`** para verificação dos bloqueadores e estratégicos: CRÍTICO 1 (numerologia), CRÍTICO 2 (cooldown 7 dias server-side), CRÍTICO 3 (pipeline único), P1 (Ayurveda premium), P2 (corpus). Cooldown de 7 dias: `getRecentInstantLightIds(userEmail, 50, 7)` retorna só usos dos últimos 7 dias; selector evita repetir sacredIds/stateKeys nesse período. + +## 15. O que falta (resumo) + +| Área | Item | Status | +|------|------|--------| +| **Engine 2.1** | Pipeline único, numerologia, cooldown, Ayurveda 20/20 + sono/rotina, testes unit + integração | ✅ Concluído | +| **Corpus** | Yoga Sutras 196 | ✅ Concluído | +| **Corpus** | Puranas 300–500 trechos medicinais | ⏳ Em progresso (~106 entradas, **todas com themes**; backlog editorial para 300+) | +| **Corpus** | Upanishads ~200 + themes em entradas | ✅ **Todas as ~64 entradas com themes**; backlog editorial para 200 | +| **Ayurveda** | Prioridade por estação (`season`) e hora (`hour`) em `GetActionsWithDoshaOptions` | ✅ Implementado (getSeasonFromDate, getHourPeriodFromDate; composer passa ao getFullActionsForQualitiesWithDosha) | +| **Doc** | PR3_ENGINE_21_STATUS: atualizar se ainda citar lib/instantLight como wrapper | Pequena correção | diff --git a/docs/SWISS_EPHEMERIS_INTEGRATION.md b/docs/SWISS_EPHEMERIS_INTEGRATION.md new file mode 100644 index 0000000..7e05937 --- /dev/null +++ b/docs/SWISS_EPHEMERIS_INTEGRATION.md @@ -0,0 +1,69 @@ +# Integração Swiss Ephemeris (opcional) + +**Status:** Integração com **@fusionstrings/swiss-eph** implementada. O pacote está instalado e o provider em `lib/core/providers/swissProvider.ts` retorna planetas completos, casas (Placidus), ascendente e moonRashi/nakshatra (derivados da longitude lunar Lahiri). O WASM é carregado na primeira chamada a `buildSymbolicMap` (via `initSwissEphemeris()`); se o Swiss não estiver disponível ou falhar, o resolver usa **mhah-panchang** como fallback. + +--- + +## Implementação atual + +- **Pacote:** `@fusionstrings/swiss-eph` (WASM; Node/Next.js). +- **Inicialização:** `initSwissEphemeris()` é chamado automaticamente no início de `buildSymbolicMap(profile)` (async), garantindo que o Swiss esteja carregado antes do resolver. +- **Entrada:** `profile.birthDate`, `profile.birthTime`; lat/lon por enquanto padrão (0,0) — geocoding opcional no futuro. +- **Saída:** `AstronomicalCore` com `planets` (sun, moon, mercury, venus, mars, jupiter, saturn), `houses` (1–12), `ascendant`, `moonRashi`, `nakshatra` (chaves do dicionário). + +--- + +## Pacotes recomendados + +| Pacote | Uso | Observação | +|--------|-----|-------------| +| **@fusionstrings/panchangam** | Astrologia védica + Panchangam sobre Swiss Ephemeris (WASM) | Precisão alta; calendário védico (Tithi, Nakshatra). | +| **@fusionstrings/swiss-eph** | Swiss Ephemeris em WASM (Node, browser, edge) | 95+ funções; posições, casas, eclipses. | +| **swisseph** | Binding Node.js nativo para Swiss Ephemeris | Requer compilação nativa; não roda em browser. | + +Para **Next.js (Node + eventual browser)**, prefira **@fusionstrings/panchangam** (já védico) ou **@fusionstrings/swiss-eph** (WASM, sem nativo). + +--- + +## Passos para integrar + +1. **Instalar** (ex.: Panchangam): + ```bash + npm install @fusionstrings/panchangam + ``` + +2. **Consultar a API** do pacote (README no npm/GitHub) para: + - Entrada: data/hora/latitude/longitude (ou só data/hora se usar lugar padrão). + - Saída: posições planetárias (longitude), casas, ascendente, Nakshatra/Rashi se o pacote já devolver. + +3. **Implementar** `trySwissCompute` em `lib/core/providers/swissProvider.ts`: + - Converter `profile.birthDate` e `profile.birthTime` para o formato que o pacote exige. + - Opcional: usar `profile.birthPlace` para lat/lon (geocoding) ou valor padrão. + - Chamar o pacote e mapear o resultado para `AstronomicalCore`: + - `planets`: longitudes (ex.: `{ sun: 45.2, moon: 120.1, ... }`). + - `houses`: cúspides 1–12 se disponível. + - `ascendant`: longitude do ascendente. + - `moonRashi` / `nakshatra`: se o pacote já devolver em formato védico, mapear para as chaves usadas no Darshan (ex.: mesha, ashwini, …); senão, derivar das longitudes usando as regras em `lib/knowledge/vedic.ts` (graus → signo/nakshatra). + - Retornar `{ providerUsed: "swiss-ephemeris", ... }`. + - Em caso de erro (data inválida, pacote não instalado), retornar `null` para o resolver usar mhah-panchang. + +4. **Testar** com e sem o pacote instalado: sem ele, o resolver deve cair no mhah-panchang sem quebrar. + +--- + +## Mapeamento para AstronomicalCore + +O tipo em `lib/core/types.ts` espera: + +- `planets`: `Record` — longitude em graus (0–360) por planeta (ex.: `sun`, `moon`, `mars`, …). +- `houses`: `Record` — cúspide em graus por casa (ex.: `"1"` a `"12"`). +- `ascendant`: número — longitude do ascendente ( = cúspide da casa 1). +- `moonRashi` / `nakshatra`: strings — chaves do dicionário (mesha, ashwini, …) para compatibilidade com os engines e dicionários atuais. + +Se o pacote retornar Nakshatra/Rashi em outro formato (número, nome em inglês), mapear para as chaves usadas em `lib/core/providers/mhahProvider.ts` (INO_TO_RASHI, INO_TO_NAKSHATRA) ou para as chaves em `lib/knowledge/types.ts`. + +--- + +## Resolver + +O `ephemerisResolver` já tenta **SwissProvider** primeiro e usa **MhahProvider** em seguida. Nada precisa ser alterado no resolver ao ativar o Swiss Ephemeris; basta fazer `trySwissCompute` retornar um `AstronomicalCore` válido quando o pacote estiver instalado e a entrada for válida. diff --git a/docs/SYMBOLIC_MAP_ENGINE.md b/docs/SYMBOLIC_MAP_ENGINE.md new file mode 100644 index 0000000..a9ea46a --- /dev/null +++ b/docs/SYMBOLIC_MAP_ENGINE.md @@ -0,0 +1,132 @@ +# Symbolic Map Engine — Motor simbólico offline + +O Darshan possui **motor simbólico real**: mapa calculado (Jyotish + Numerologia + Human Design), readings modulares por tema e Narrative Composer offline. Tudo **sem IA**, determinístico e expansível. + +--- + +## Visão geral + +| Camada | O que é | Onde está | +|--------|---------|-----------| +| **A — Engines** | Cálculo estruturado (só dados) | `lib/engines/`, `lib/symbolic/`, `lib/core/` | +| **B — Readings** | Interpretação por tema | `lib/readings/`, `lib/insights/` | +| **C — Composer** | Frase humana a partir do mapa | `lib/narrative/`, `lib/dictionaries/` | + +- **SymbolicMap único** é a base; engines preenchem; readings consomem por tema. +- O usuário acessa por pergunta: "relacionamento" → módulo love, "trabalho" → career, "ano" → year, "visão geral" → general. + +--- + +## 1. SymbolicMap (objeto canônico) + +Dois fluxos coexistem (sem redundância de lógica): + +1. **`lib/symbolic/`** — Mapa canônico para **leitura offline** (getOfflineReading, /api/map, /api/reading): + - `types.ts` — `SymbolicMap`: jyotish (moonRashi, nakshatra, archetypeKey), numerology (rulingNumber), archetypes, themes, evidence. + - `builder.ts` — `buildSymbolicMap(profile)` síncrono: usa `computeVedicChartSimplified` (vedic + resolver) e `getRulingNumberFromName`. + +2. **`lib/engines/`** — Mapa com **core astronômico** (Swiss Ephemeris / mhah-panchang) para Oracle e APIs que precisam de planetas/casas: + - `buildSymbolicMap.ts` — `buildSymbolicMap(profile)` **async**: chama `computeAstronomicalCore`, depois `jyotishEngine`, `numerologyEngine`, `humanDesignEngine`. + - Retorna: `{ core, jyotish, numerology, humanDesign }`. + +**Uso recomendado:** +- **Leitura temática e APIs offline** → `lib/symbolic` (builder síncrono). +- **Oracle e integrações que usam planetas/casas** → `lib/engines` (builder async). + +--- + +## 2. Engines determinísticos + +### Jyotish (`lib/engines/jyotishEngine.ts`) + +- **jyotishEngine(core)** — Retorna: moonRashi, nakshatra, planets, houses, precisionLevel. +- **getNakshatraProfile(core)** — Perfil interpretativo: nakshatra, moonRashi, namePt, consciousnessThemes, psychologicalEffects, archetypeHints (para Composer/Readings). +- **detectYogas(core)** — Lista de yogas detectados (ex.: nakshatra-X, moon-in-Y, chandra-surya-same-sign). Expandir depois com Neecha Bhanga, etc. + +### Numerologia (`lib/engines/numerologyEngine.ts`) + +- Calcula número regente a partir do nome e data; usado pelo SymbolicMap e pelos insights de ação. + +### Human Design (`lib/engines/humanDesignEngine.ts`) + +- Stub plugável: type, authority, profile. Cálculo real (gates/channels) virá depois. + +### Core astronômico (`lib/core/`) + +- **ephemerisResolver** — Escolhe provider (Swiss Ephemeris ou mhah-panchang). +- **swissProvider** — Planetas, casas, ascendente; deriva moonRashi/nakshatra da longitude lunar (Lahiri). + +--- + +## 3. Interpretação modular (Readings) + +Cada reading consome o **mesmo mapa** e um **tema**: + +| Tema (API) | Tópico interno | Função | +|------------|----------------|--------| +| general | general | `getGeneral(map)` | +| love / relationship | love | `getLove(map)` | +| career / work | career | `getCareer(map)` | +| year / yearly | year | `getYear(map)` | +| action | action | `getAction(map)` | + +- **`lib/readings/symbolicReadings.ts`** — `getReadingByTheme(map, theme)` mapeia theme → topic e chama `composeReading(map, topic)`. +- **`lib/insights/`** — Regras determinísticas por sistema (Jyotish, numerologia, action); cada insight tem key, topic, weight, evidence. +- **`lib/narrative/composer.ts`** — `composeReading(map, topic)`: coleta insights do mapa, filtra por topic, ordena por peso, top 3, `phraseFor(key)` → texto. + +Nada de frase solta: tudo derivado do mapa e dos dicionários. + +--- + +## 4. Narrative Composer e dicionários + +- **composeReading(map, topic)** — Entrada principal: SymbolicMap + tópico → texto da leitura. +- **phraseFor(key)** — Resolve frase por chave (action.n.X → action.X; action.archetype.X com fallback). +- **lib/narrative/dictionaryLoader.ts** — `getMergedDictionaries()`: agrega Jyotish, HD, Action, Numerologia, PHRASES_FOR_SYMBOLIC. +- **lib/narrative/phraseTemplates.ts** — `getPhraseForInsight(key)`, `getPhraseForContext(ctx)` para chamadas que já têm placements/theme. + +Dicionários em código: `lib/dictionaries/` (jyotish, humanDesign, action, numerology, phrasesForSymbolic). Expansão futura: JSON em /dictionaries se desejado. + +--- + +## 5. APIs offline + +| Endpoint | Uso | Retorno | +|---------|-----|---------| +| **POST /api/map** | Mapa completo (sem IA, sem créditos) | `{ map: SymbolicMap }` | +| **POST /api/reading?theme=** | Leitura temática (general \| love \| relationship \| career \| work \| year \| yearly \| action) | `{ map, reading, theme }` | +| **POST /api/map/personal** | Mapa pessoal + leitura (IA ou offline conforme parâmetro) | Ver doc do endpoint | + +Body em ambos: `{ profile: { fullName?, birthDate?, birthTime?, birthPlace? } }`. + +--- + +## 6. Onde está cada peça + +| Peça | Arquivo / pasta | +|------|------------------| +| SymbolicMap (canônico) | `lib/symbolic/types.ts`, `builder.ts` | +| SymbolicMap (com core) | `lib/engines/buildSymbolicMap.ts` | +| Jyotish calculate / getNakshatraProfile / detectYogas | `lib/engines/jyotishEngine.ts` | +| Numerologia | `lib/engines/numerologyEngine.ts` | +| Human Design (stub) | `lib/engines/humanDesignEngine.ts` | +| General / Love / Career / Year / Action readings | `lib/readings/symbolicReadings.ts` | +| Leitura por tema (API) | `getReadingByTheme(map, theme)` em symbolicReadings | +| Composer | `lib/narrative/composer.ts` | +| Dictionary loader | `lib/narrative/dictionaryLoader.ts` | +| Phrase templates | `lib/narrative/phraseTemplates.ts` | +| Dicionários | `lib/dictionaries/*.ts` | +| getOfflineReading (wrapper) | `lib/readingOffline.ts` | +| POST /api/map | `app/api/map/route.ts` | +| POST /api/reading?theme= | `app/api/reading/route.ts` | + +--- + +## 7. Fluxo resumido + +1. **Mapa:** `buildSymbolicMap(profile)` (symbolic ou engines) → SymbolicMap. +2. **Insights:** `collectInsightsForSymbolicMap(map)` → lista de Insight (key, topic, weight, evidence). +3. **Leitura por tema:** `composeReading(map, topic)` → filtra insights por topic, top 3, phraseFor(key) → texto. +4. **API:** POST /api/map retorna o mapa; POST /api/reading?theme=X retorna mapa + reading para o tema. + +Sem aleatoriedade solta; sem duplicar conteúdo entre temas; expansão por novos engines e dicionários. diff --git a/lib/ai/index.ts b/lib/ai/index.ts index b3e32e2..924ebc6 100644 --- a/lib/ai/index.ts +++ b/lib/ai/index.ts @@ -39,3 +39,5 @@ export function getAvailableConnectors(): AIConnector[] { } export type { AIConnector, ConnectorId } from "./types"; +export { expandNarrative } from "./narrativeGateway"; +export type { NarrativeExpansionResult } from "./narrativeGateway"; diff --git a/lib/ai/narrativeGateway.ts b/lib/ai/narrativeGateway.ts new file mode 100644 index 0000000..cd5291e --- /dev/null +++ b/lib/ai/narrativeGateway.ts @@ -0,0 +1,92 @@ +/** + * AI Narrative Gateway — expansão narrativa opcional do Truth Package. + * Recebe apenas o Truth Package e a pergunta do usuário; devolve texto expandido. + * Guardrails: não alterar diagnóstico, não inventar remédio, não trocar sutra. + */ + +import { getConnector } from "@/lib/ai"; +import type { DarshanTruthPackage } from "@/lib/core/DarshanTruthPackage"; +import type { Theme } from "@/lib/core/UserRequestContext"; + +export type NarrativeExpansionResult = { + narrativeExpansion: string; + sections?: { title: string; content: string }[]; +}; + +const GUARDRAILS = ` +Você é um assistente que apenas EXPANDE e CONTEXTUALIZA o conteúdo que recebeu. +Regras OBRIGATÓRIAS: +- NÃO altere o diagnóstico (klesha, guna, qualidades). +- NÃO invente remédios, práticas ou alimentos que não estejam no pacote. +- NÃO troque ou reescreva o texto sagrado (sutra/verso); pode citá-lo e comentar. +- NÃO contradiga o pacote. Sua função é explicar, suavizar a linguagem e conectar à pergunta do usuário. +- Use tom acolhedor e conciso. Resposta em português do Brasil. +`; + +/** + * Gera expansão narrativa a partir do Truth Package e da pergunta. + * Se não houver conector de IA configurado, retorna fallback (resumo do próprio pacote). + */ +export async function expandNarrative( + truthPackage: DarshanTruthPackage, + question: string, + theme: Theme +): Promise { + const connector = getConnector(); + const sacred = truthPackage.sacred?.text ?? ""; + const practiceTitle = truthPackage.practice?.title ?? "Prática"; + const practiceSteps = (truthPackage.practice?.steps ?? []).join("; "); + const foodDo = (truthPackage.food?.do ?? []).join(", "); + const questionText = truthPackage.contemplativeQuestion?.text ?? truthPackage.question?.text ?? ""; + + const packageSummary = ` +[Diagnóstico] klesha: ${truthPackage.diagnosis?.klesha ?? ""}, guna: ${truthPackage.diagnosis?.samkhyaGuna ?? ""}, estado: ${truthPackage.stateKey}. +[Texto sagrado] ${sacred} +[Prática] ${practiceTitle}: ${practiceSteps} +[Alimentação] ${foodDo || "não especificado"} +[Pergunta de reflexão] ${questionText} +`.trim(); + + const userContent = ` +Pergunta do usuário: ${question || "Como lidar com isso?"} +Tema: ${theme} + +Conteúdo canônico (apenas expandir/contextualizar; não alterar): +${packageSummary} +`.trim(); + + const systemPrompt = `${GUARDRAILS}\n\nExpanda em 2-4 parágrafos curtos, conectando a pergunta ao conteúdo. Pode usar seções opcionais (ex.: "Contexto", "Prática sugerida", "Reflexão").`; + + if (!connector) { + return { + narrativeExpansion: `O Darshan trouxe para você: ${sacred}\n\nPrática: ${practiceSteps}\n${foodDo ? `Alimentação: ${foodDo}\n` : ""}Reflexão: ${questionText}`, + sections: [ + { title: "Texto sagrado", content: sacred }, + { title: "Prática", content: practiceSteps }, + { title: "Reflexão", content: questionText }, + ], + }; + } + + try { + const result = await connector.complete(systemPrompt, userContent); + const text = result?.text?.trim() ?? ""; + return { + narrativeExpansion: text || packageSummary, + sections: text ? undefined : [ + { title: "Texto sagrado", content: sacred }, + { title: "Prática", content: practiceSteps }, + { title: "Reflexão", content: questionText }, + ], + }; + } catch { + return { + narrativeExpansion: packageSummary, + sections: [ + { title: "Texto sagrado", content: sacred }, + { title: "Prática", content: practiceSteps }, + { title: "Reflexão", content: questionText }, + ], + }; + } +} diff --git a/lib/core/DarshanTruthPackage.ts b/lib/core/DarshanTruthPackage.ts new file mode 100644 index 0000000..700ffd2 --- /dev/null +++ b/lib/core/DarshanTruthPackage.ts @@ -0,0 +1,65 @@ +/** + * Truth Package canônico — payload único que alimenta offline e IA. + * Todo endpoint Darshan retorna este formato. Não inventar remédios; IA só expande a partir disso. + */ + +import type { Theme, Mode } from "./UserRequestContext"; + +export type SacredCorpusKey = + | "yoga_sutras" + | "puranas" + | "upanishads" + | "legacy"; + +export type DarshanTruthPackage = { + mode: Mode; + theme: Theme; + /** Estado RemedyMatrix escolhido */ + stateKey: string; + diagnosis: { + klesha: string; + samkhyaGuna: string; + qualities: string[]; + confidence?: number; + }; + sacred: { + id: string; + corpus: SacredCorpusKey; + text: string; + translation?: string; + tags?: string[]; + /** Versos de contexto (ex.: anterior ao sutra medicinal) para exibir em bloco completo */ + supporting?: { id: string; text: string }[]; + }; + practice: { + title: string; + steps: string[]; + duration?: string; + }; + food?: { + do: string[]; + avoid: string[]; + }; + /** Pergunta contemplativa final (canônico) */ + contemplativeQuestion: { + text: string; + }; + /** @deprecated Use contemplativeQuestion */ + question?: { + text: string; + }; + /** Opcional para modo personal */ + symbolicMap?: unknown; + meta?: { + generatedAt: string; + usedSacredIds?: string[]; + usedStateKeys?: string[]; + }; + /** Insight do mapa (personal) */ + insight?: string; + /** Campos flat para compatibilidade com cliente atual */ + sacredText?: string; + sacredId?: string; + sleep?: string; + routine?: string; +}; diff --git a/lib/core/UserRequestContext.ts b/lib/core/UserRequestContext.ts new file mode 100644 index 0000000..22742f4 --- /dev/null +++ b/lib/core/UserRequestContext.ts @@ -0,0 +1,33 @@ +/** + * Contexto canônico da requisição do usuário para qualquer endpoint Darshan. + * Padroniza modo, tema, texto, pergunta e perfil. + */ + +export type Theme = + | "general" + | "love" + | "career" + | "year" + | "health" + | "spirituality"; + +export type Mode = "universal" | "personal"; + +export type UserRequestContext = { + mode: Mode; + theme?: Theme; + /** Texto digitado (input natural) */ + userText?: string; + /** Pergunta explícita */ + question?: string; + /** Opcional: texto curto / estado de humor */ + moodHint?: string; + profile?: { + name?: string; + birthDate?: string; + birthTime?: string; + birthPlace?: string; + }; + /** Id para histórico/cooldown (ex.: email do usuário) */ + userKey?: string; +}; diff --git a/lib/core/ephemerisProvider.ts b/lib/core/ephemerisProvider.ts new file mode 100644 index 0000000..1a52dd0 --- /dev/null +++ b/lib/core/ephemerisProvider.ts @@ -0,0 +1,11 @@ +/** + * Interface de um provider de efemérides (mhah-panchang, Swiss Ephemeris, etc.). + * Cada provider expõe name e compute(profile) → AstronomicalCore. + */ + +import type { AstronomicalCore, CoreProfile } from "./types"; + +export interface EphemerisProvider { + name: string; + compute(profile: CoreProfile): AstronomicalCore; +} diff --git a/lib/core/ephemerisResolver.ts b/lib/core/ephemerisResolver.ts new file mode 100644 index 0000000..3f95fc0 --- /dev/null +++ b/lib/core/ephemerisResolver.ts @@ -0,0 +1,26 @@ +/** + * Resolver multi-provider: Swiss Ephemeris (prioridade) → mhah-panchang (fallback). + * Nada quebra: se Swiss falhar ou não estiver disponível, usa mhah. + */ + +import type { AstronomicalCore, CoreProfile } from "./types"; +import type { EphemerisProvider } from "./ephemerisProvider"; +import { SwissProvider } from "./providers/swissProvider"; +import { MhahProvider } from "./providers/mhahProvider"; + +const PROVIDERS: EphemerisProvider[] = [SwissProvider, MhahProvider]; + +/** + * Calcula o núcleo astronômico com o primeiro provider que conseguir. + * Ordem: Swiss Ephemeris → mhah-panchang. + */ +export function computeAstronomicalCore(profile: CoreProfile): AstronomicalCore { + for (const provider of PROVIDERS) { + try { + return provider.compute(profile); + } catch { + continue; + } + } + throw new Error("No ephemeris provider available"); +} diff --git a/lib/core/providers/mhahProvider.ts b/lib/core/providers/mhahProvider.ts new file mode 100644 index 0000000..322fa81 --- /dev/null +++ b/lib/core/providers/mhahProvider.ts @@ -0,0 +1,59 @@ +/** + * Provider mhah-panchang — NÃO remover; fallback oficial do Darshan. + * Retorna Lua (Rashi + Nakshatra); planetas/casas ficam para Swiss Ephemeris. + */ + +import type { EphemerisProvider } from "../ephemerisProvider"; +import type { AstronomicalCore, CoreProfile } from "../types"; + +const INO_TO_RASHI: string[] = [ + "mesha", "vrishabha", "mithuna", "karka", "simha", "kanya", + "tula", "vrischika", "dhanu", "makara", "kumbha", "mina", +]; + +const INO_TO_NAKSHATRA: string[] = [ + "ashwini", "bharani", "krittika", "rohini", "mrigashira", "ardra", "punarvasu", + "pushya", "ashlesha", "magha", "purva-phalguni", "uttara-phalguni", "hasta", + "chitra", "swati", "vishakha", "anuradha", "jyestha", "mula", "purva-ashadha", + "uttara-ashadha", "shravana", "dhanishta", "shatabhisha", "purva-bhadra", + "uttara-bhadra", "revati", +]; + +export const MhahProvider: EphemerisProvider = { + name: "mhah-panchang", + + compute(profile: CoreProfile): AstronomicalCore { + const birthDate = profile.birthDate?.trim() ?? ""; + if (!birthDate) { + return { providerUsed: "mhah-panchang" }; + } + const birthTime = profile.birthTime?.trim() ?? "12:00"; + const dateStr = birthTime ? `${birthDate}T${birthTime}:00` : `${birthDate}T12:00:00`; + const d = new Date(dateStr); + if (Number.isNaN(d.getTime())) { + return { providerUsed: "mhah-panchang" }; + } + + const { MhahPanchang } = require("mhah-panchang"); + const obj = new MhahPanchang(); + const result = obj.calculate(d); + + const raasi = result?.Raasi; + const nakshatra = result?.Nakshatra; + + const moonRashi = + raasi?.ino != null + ? INO_TO_RASHI[(raasi.ino - 1) % 12] + : undefined; + const nakshatraKey = + nakshatra?.ino != null + ? INO_TO_NAKSHATRA[(nakshatra.ino - 1) % 27] + : undefined; + + return { + providerUsed: "mhah-panchang", + moonRashi, + nakshatra: nakshatraKey, + }; + }, +}; diff --git a/lib/core/providers/swissProvider.ts b/lib/core/providers/swissProvider.ts new file mode 100644 index 0000000..aa62556 --- /dev/null +++ b/lib/core/providers/swissProvider.ts @@ -0,0 +1,224 @@ +/** + * Provider Swiss Ephemeris (premium) — @fusionstrings/swiss-eph (WASM). + * Retorna planetas completos, casas e ascendente; moonRashi/nakshatra derivados da longitude lunar (Lahiri). + * Se falhar ou não estiver instalado, o resolver usa mhah-panchang como fallback. + */ + +import type { EphemerisProvider } from "../ephemerisProvider"; +import type { AstronomicalCore, CoreProfile } from "../types"; + +/** Chaves Rashi (signo) por índice 0–11 — mesma ordem que mhahProvider */ +const INO_TO_RASHI: string[] = [ + "mesha", "vrishabha", "mithuna", "karka", "simha", "kanya", + "tula", "vrischika", "dhanu", "makara", "kumbha", "mina", +]; + +/** Chaves Nakshatra por índice 0–26 — mesma ordem que mhahProvider */ +const INO_TO_NAKSHATRA: string[] = [ + "ashwini", "bharani", "krittika", "rohini", "mrigashira", "ardra", "punarvasu", + "pushya", "ashlesha", "magha", "purva-phalguni", "uttara-phalguni", "hasta", + "chitra", "swati", "vishakha", "anuradha", "jyestha", "mula", "purva-ashadha", + "uttara-ashadha", "shravana", "dhanishta", "shatabhisha", "purva-bhadra", + "uttara-bhadra", "revati", +]; + +/** Longitude (0–360) → Rashi key (sidereal; longitude já em Lahiri se usar SEFLG_SIDEREAL) */ +function longitudeToRashi(longitudeDeg: number): string { + const L = longitudeDeg % 360; + const index = Math.floor(L / 30) % 12; + return INO_TO_RASHI[index] ?? "mesha"; +} + +/** Longitude (0–360) → Nakshatra key */ +function longitudeToNakshatra(longitudeDeg: number): string { + const L = longitudeDeg % 360; + const index = Math.floor(L / (360 / 27)) % 27; + return INO_TO_NAKSHATRA[index] ?? "ashwini"; +} + +/** Mapa planeta SE_* → chave para AstronomicalCore.planets */ +const PLANET_KEYS: Record = { + 0: "sun", // SE_SUN + 1: "moon", // SE_MOON + 2: "mercury",// SE_MERCURY + 3: "venus", // SE_VENUS + 4: "mars", // SE_MARS + 5: "jupiter",// SE_JUPITER + 6: "saturn", // SE_SATURN +}; + +/** Lat/lon padrão quando birthPlace não fornece (ex.: 0,0 ou São Paulo) */ +const DEFAULT_LAT = 0; +const DEFAULT_LON = 0; + +/** Cache do módulo WASM carregado (lazy). Preencher com initSwissEphemeris() para usar Swiss. */ +let ephCache: { eph: { swe_julday: (y: number, m: number, d: number, h: number, g: number) => number; + swe_calc_ut: (jd: number, ipl: number, iflag: number) => { returnCode: number; xx: Float64Array; error: string }; + swe_houses: (jd: number, lat: number, lon: number, hsys: number) => { cusps: Float64Array; ascmc: Float64Array; returnCode: number }; + swe_set_sid_mode: (mode: number, t0: number, ayan_t0: number) => void }; + Constants: { SE_GREG_CAL: number; SE_SUN: number; SE_MOON: number; SE_MERCURY: number; SE_VENUS: number; SE_MARS: number; SE_JUPITER: number; SE_SATURN: number; SEFLG_SPEED: number; SEFLG_SIDEREAL?: number; SE_SIDM_LAHIRI: number }; +} | null = null; + +async function loadSwissEph(): Promise> { + const mod = await import("@fusionstrings/swiss-eph"); + const eph = await mod.load(); + const Constants = mod.Constants; + if (typeof eph.swe_set_sid_mode === "function" && Constants.SE_SIDM_LAHIRI != null) { + eph.swe_set_sid_mode(Constants.SE_SIDM_LAHIRI, 0, 0); + } + return { eph, Constants }; +} + +function parseProfileDateTime(profile: CoreProfile): { year: number; month: number; day: number; hourDecimal: number } | null { + const birthDate = profile.birthDate?.trim(); + if (!birthDate) return null; + const birthTime = (profile.birthTime?.trim() ?? "12:00").slice(0, 8); + const [h, m, s] = birthTime.split(":").map((x) => (x ? parseFloat(x) : 0)); + const dateStr = birthTime ? `${birthDate}T${birthTime}` : `${birthDate}T12:00`; + const d = new Date(dateStr); + if (Number.isNaN(d.getTime())) return null; + const hourDecimal = (d.getUTCHours() ?? 0) + ((d.getUTCMinutes() ?? 0) / 60) + ((d.getUTCSeconds() ?? 0) / 3600); + return { + year: d.getUTCFullYear(), + month: d.getUTCMonth() + 1, + day: d.getUTCDate(), + hourDecimal, + }; +} + +/** Obtém lat/lon do perfil; por enquanto usa valor padrão (geocoding futuro). */ +function getLatLon(_profile: CoreProfile): { lat: number; lon: number } { + return { lat: DEFAULT_LAT, lon: DEFAULT_LON }; +} + +/** + * Calcula o núcleo astronômico com Swiss Ephemeris (async). + * Retorna null se o pacote não estiver disponível, dados inválidos ou erro. + */ +export async function trySwissCompute(profile: CoreProfile): Promise { + try { + const dt = parseProfileDateTime(profile); + if (!dt) return null; + + if (!ephCache) { + ephCache = await loadSwissEph(); + } + const { eph, Constants } = ephCache; + + const jd = eph.swe_julday(dt.year, dt.month, dt.day, dt.hourDecimal, Constants.SE_GREG_CAL); + const flag = (Constants.SEFLG_SPEED ?? 256) | (Constants.SEFLG_SIDEREAL ?? 0); + + const planets: Record = {}; + for (const [seId, key] of Object.entries(PLANET_KEYS)) { + const res = eph.swe_calc_ut(jd, Number(seId), flag); + if (res.returnCode >= 0 && res.xx && res.xx[0] != null) { + planets[key] = res.xx[0] % 360; + } + } + + const moonLong = planets.moon != null ? planets.moon : undefined; + const moonRashi = moonLong != null ? longitudeToRashi(moonLong) : undefined; + const nakshatra = moonLong != null ? longitudeToNakshatra(moonLong) : undefined; + + const { lat, lon } = getLatLon(profile); + const hsys = "P".charCodeAt(0); + const housesRes = eph.swe_houses(jd, lat, lon, hsys); + const houses: Record = {}; + if (housesRes.cusps && housesRes.returnCode >= 0) { + for (let i = 1; i <= 12; i++) { + const c = housesRes.cusps[i]; + if (typeof c === "number" && !Number.isNaN(c)) { + houses[String(i)] = c % 360; + } + } + } + const ascendant = housesRes.ascmc && housesRes.ascmc[0] != null + ? (housesRes.ascmc[0] % 360) + : (houses["1"]); + + return { + providerUsed: "swiss-ephemeris", + julianDay: jd, + planets: Object.keys(planets).length ? planets : undefined, + moonRashi, + nakshatra, + ascendant, + houses: Object.keys(houses).length ? houses : undefined, + }; + } catch { + return null; + } +} + +export const SwissProvider: EphemerisProvider = { + name: "swiss-ephemeris", + + compute(profile: CoreProfile): AstronomicalCore { + const result = trySwissComputeSync(profile); + if (result) return result; + throw new Error("Swiss Ephemeris not available"); + }, +}; + +/** + * Versão síncrona: só retorna resultado se o WASM já estiver em cache. + * Caso contrário retorna null para o resolver cair no mhah-panchang. + */ +function trySwissComputeSync(profile: CoreProfile): AstronomicalCore | null { + if (ephCache === null) return null; + try { + const dt = parseProfileDateTime(profile); + if (!dt) return null; + const { eph, Constants } = ephCache; + const jd = eph.swe_julday(dt.year, dt.month, dt.day, dt.hourDecimal, Constants.SE_GREG_CAL); + const flag = (Constants.SEFLG_SPEED ?? 256) | (Constants.SEFLG_SIDEREAL ?? 0); + + const planets: Record = {}; + for (const [seId, key] of Object.entries(PLANET_KEYS)) { + const res = eph.swe_calc_ut(jd, Number(seId), flag); + if (res.returnCode >= 0 && res.xx && res.xx[0] != null) { + planets[key] = res.xx[0] % 360; + } + } + const moonLong = planets.moon; + const moonRashi = moonLong != null ? longitudeToRashi(moonLong) : undefined; + const nakshatra = moonLong != null ? longitudeToNakshatra(moonLong) : undefined; + + const { lat, lon } = getLatLon(profile); + const hsys = "P".charCodeAt(0); + const housesRes = eph.swe_houses(jd, lat, lon, hsys); + const houses: Record = {}; + if (housesRes.cusps && housesRes.returnCode >= 0) { + for (let i = 1; i <= 12; i++) { + const c = housesRes.cusps[i]; + if (typeof c === "number" && !Number.isNaN(c)) { + houses[String(i)] = c % 360; + } + } + } + const ascendant = housesRes.ascmc && housesRes.ascmc[0] != null + ? (housesRes.ascmc[0] % 360) + : (houses["1"]); + + return { + providerUsed: "swiss-ephemeris", + julianDay: jd, + planets: Object.keys(planets).length ? planets : undefined, + moonRashi, + nakshatra, + ascendant, + houses: Object.keys(houses).length ? houses : undefined, + }; + } catch { + return null; + } +} + +/** + * Inicializa o Swiss Ephemeris (carrega WASM). Chamar uma vez no startup ou antes do primeiro uso + * para que o resolver use Swiss em vez de mhah-panchang nas próximas chamadas síncronas. + */ +export async function initSwissEphemeris(): Promise { + if (ephCache) return; + ephCache = await loadSwissEph(); +} diff --git a/lib/core/types.ts b/lib/core/types.ts new file mode 100644 index 0000000..e2b7816 --- /dev/null +++ b/lib/core/types.ts @@ -0,0 +1,29 @@ +/** + * Núcleo astronômico — resultado de um provider de efemérides. + * Usado por todos os engines (Jyotish, Human Design, etc.) sem depender de IA. + */ + +export type AstronomicalCore = { + /** Provider que gerou os dados (ex.: "mhah-panchang", "swiss-ephemeris") */ + providerUsed: string; + /** Dia juliano (opcional; Swiss Ephemeris) */ + julianDay?: number; + /** Longitudes planetárias em graus (0–360) — chave = planeta (sun, moon, ...) */ + planets?: Record; + /** Signo lunar sidereal (Rashi) — chave do dicionário (ex.: "karka", "revati") */ + moonRashi?: string; + /** Nakshatra lunar — chave (ex.: "ashwini", "rohini") */ + nakshatra?: string; + /** Ascendente em graus (opcional) */ + ascendant?: number; + /** Casas em graus (1–12) — chave = número da casa */ + houses?: Record; +}; + +/** Perfil mínimo para cálculo (data e opcionalmente hora/local) */ +export type CoreProfile = { + birthDate?: string; + birthTime?: string; + birthPlace?: string; + fullName?: string; +}; diff --git a/lib/dictionaries/action.ts b/lib/dictionaries/action.ts new file mode 100644 index 0000000..bb6a2a4 --- /dev/null +++ b/lib/dictionaries/action.ts @@ -0,0 +1,21 @@ +/** + * Frases de prática concreta (Action Engine) — toda leitura deve terminar com ação. + */ + +export const ACTION_PHRASES: Record = { + "action.grounding.breath": [ + "Prática mínima: respire lentamente 7 vezes antes de tomar qualquer decisão hoje.", + ], + "action.presence.body": [ + "Prática: por 1 minuto, sinta os pés no chão e o ar entrando e saindo; depois escolha o próximo passo.", + ], + "action.general.pause": [ + "Prática: antes de responder a alguém, faça uma pausa de três respirações.", + ], + "action.love.self": [ + "Prática: hoje, uma ação concreta de cuidado consigo mesmo (um gesto que te nutra).", + ], + "action.career.clarity": [ + "Prática: escreva em uma linha o que você quer que o seu trabalho gere no mundo; releia ao acordar.", + ], +}; diff --git a/lib/dictionaries/humanDesign.ts b/lib/dictionaries/humanDesign.ts new file mode 100644 index 0000000..3824f7f --- /dev/null +++ b/lib/dictionaries/humanDesign.ts @@ -0,0 +1,24 @@ +/** + * Frases ancoradas por chave Human Design — dicionário offline. + */ + +export const HD_PHRASES: Record = { + "hd.type.generator": [ + "Sua energia floresce quando você responde ao que a vida traz, não quando força caminhos.", + ], + "hd.type.manifestor": [ + "Você foi feito para iniciar; informar antes de agir reduz resistência e traz paz.", + ], + "hd.type.projector": [ + "Seu dom é ver o outro; esperar o convite evita amargura e traz reconhecimento.", + ], + "hd.type.reflector": [ + "Você reflete o ambiente; dar-se tempo (e a Lua) para decidir é sua sabedoria.", + ], + "hd.authority.emotional": [ + "Decida apenas após atravessar a onda emocional; a clareza vem com o tempo.", + ], + "hd.authority.sacral": [ + "Seu corpo sabe; respostas sim ou não vêm do corpo.", + ], +}; diff --git a/lib/dictionaries/index.ts b/lib/dictionaries/index.ts new file mode 100644 index 0000000..a03df6a --- /dev/null +++ b/lib/dictionaries/index.ts @@ -0,0 +1,37 @@ +/** + * Resolve frase por chave de insight — consulta Jyotish, HD, Action e mapa simbólico. + * Retorna a primeira frase do array (determinístico). + */ + +import { JYOTISH_PHRASES } from "./jyotish"; +import { HD_PHRASES } from "./humanDesign"; +import { ACTION_PHRASES } from "./action"; +import { NUMEROLOGY_PHRASES } from "./numerology"; +import { PHRASES_FOR_SYMBOLIC } from "./phrasesForSymbolic"; + +const ALL: Record = { + ...JYOTISH_PHRASES, + ...HD_PHRASES, + ...ACTION_PHRASES, + ...NUMEROLOGY_PHRASES, + ...PHRASES_FOR_SYMBOLIC, +}; + +export function phraseFor(key: string): string { + let lookupKey = key; + if (key.startsWith("action.n.")) { + const num = key.slice("action.n.".length); + lookupKey = `action.${num}`; + } + // action.archetype.X: fallback para action.general se arquétipo sem frase + if (key.startsWith("action.archetype.")) { + const phrases = ALL[key]; + if (phrases && phrases.length > 0) return phrases[0]; + return (ALL["action.general"] as string[])?.[0] ?? ""; + } + const phrases = ALL[lookupKey] ?? ALL[key]; + if (phrases && phrases.length > 0) return phrases[0]; + return ""; +} + +export { JYOTISH_PHRASES, HD_PHRASES, ACTION_PHRASES, NUMEROLOGY_PHRASES }; diff --git a/lib/dictionaries/inputEmotions.json b/lib/dictionaries/inputEmotions.json new file mode 100644 index 0000000..6723544 --- /dev/null +++ b/lib/dictionaries/inputEmotions.json @@ -0,0 +1,72 @@ +{ + "anxiety": [ + "ansioso", "ansiosa", + "nervoso", "nervosa", + "tô agoniado", "tô agoniada", + "tô surtando", + "mente não para", + "pânico" + ], + "burnout": [ + "cansado", "cansada", + "exausto", "exausta", + "esgotado", "esgotada", + "tô no limite", + "não aguento mais", + "tô acabado", "tô acabada" + ], + "grief": [ + "triste", + "tô na bad", + "deprimido", "deprimida", + "luto", + "coração pesado" + ], + "solitude": [ + "sozinho", "sozinha", + "solidão", + "isolado", "isolada", + "me sinto sozinho", "me sinto sozinha" + ], + "isolation": [ + "sozinho", "sozinha", + "solidão", + "isolado", "isolada" + ], + "anger": [ + "raiva", + "irritado", "irritada", + "tô puto", "tô puta", + "frustrado", "frustrada" + ], + "confusion": [ + "confuso", "confusa", + "perdido", "perdida", + "travado", "travada", + "não sei o que fazer", + "sla" + ], + "emotional_attachment": [ + "apego", + "ciúmes", + "dependência", + "não consigo deixar ir" + ], + "relational_insecurity": [ + "medo de perder", + "abandono", + "rejeição", + "medo que me deixem" + ], + "existential_fear": [ + "medo de perder", + "abandono", + "rejeição" + ], + "lack_of_purpose": [ + "sem propósito", + "sem sentido", + "pra que tudo isso", + "não sei meu caminho" + ] +} diff --git a/lib/dictionaries/inputNormalization.json b/lib/dictionaries/inputNormalization.json new file mode 100644 index 0000000..59e2ca4 --- /dev/null +++ b/lib/dictionaries/inputNormalization.json @@ -0,0 +1,50 @@ +{ + "tô": "estou", + "to": "estou", + "tava": "estava", + "mt": "muito", + "mto": "muito", + "vc": "você", + "vcs": "vocês", + "pq": "porque", + "pk": "porque", + "q": "que", + "tb": "também", + "tbm": "também", + "mds": "meu deus", + "aff": "frustração", + "sla": "não sei", + "n sei": "não sei", + "nn": "não", + "nao": "não", + "cê": "você", + "mano": "", + "tipo": "", + "obg": "obrigado", + "obgd": "obrigado", + "blz": "beleza", + "d": "de", + "cmg": "comigo", + "ctz": "certeza", + "sm": "sem", + "tlgd": "entendido", + "vlw": "valeu", + "oq": "o que", + "pra": "para", + "pro": "para o", + "vdd": "verdade", + "qdo": "quando", + "qd": "quando", + "porq": "porque", + "n": "não", + "tambem": "também", + "ta": "está", + "tá": "está", + "pqp": "puta que pariu", + "dmr": "demorar", + "cara": "", + "então": "", + "entao": "", + "assim": "", + "tipo assim": "" +} diff --git a/lib/dictionaries/inputQuestions.json b/lib/dictionaries/inputQuestions.json new file mode 100644 index 0000000..3631b80 --- /dev/null +++ b/lib/dictionaries/inputQuestions.json @@ -0,0 +1,8 @@ +{ + "what": ["o que", "oq", "qual", "o que significa"], + "how": ["como", "como lidar", "como resolver", "como sair disso"], + "why": ["por que", "pq", "qual a causa"], + "when": ["quando", "até quando", "isso vai passar", "vai demorar"], + "where": ["onde", "pra onde", "onde isso leva"], + "who": ["quem", "quem sou eu"] +} diff --git a/lib/dictionaries/inputThemes.json b/lib/dictionaries/inputThemes.json new file mode 100644 index 0000000..b2460b8 --- /dev/null +++ b/lib/dictionaries/inputThemes.json @@ -0,0 +1,55 @@ +{ + "general": [ + "vida", + "momento", + "fase", + "direção", + "confusão" + ], + "love": [ + "relacionamento", + "amor", + "namoro", + "casamento", + "parceiro", + "parceira", + "crush", + "ex", + "ciúmes", + "apego" + ], + "career": [ + "trabalho", + "carreira", + "dinheiro", + "grana", + "emprego", + "propósito", + "projeto" + ], + "health": [ + "saúde", + "corpo", + "cansaço", + "energia", + "sono", + "alimentação" + ], + "spirituality": [ + "meditação", + "yoga", + "dharma", + "caminho espiritual", + "consciência", + "presença" + ], + "year": [ + "ano", + "ano que vem", + "próximo ano", + "proximo ano", + "este ano", + "ciclo", + "previsão do ano" + ] +} diff --git a/lib/dictionaries/inputVerbs.json b/lib/dictionaries/inputVerbs.json new file mode 100644 index 0000000..8090e50 --- /dev/null +++ b/lib/dictionaries/inputVerbs.json @@ -0,0 +1,37 @@ +{ + "feel": [ + "estou", + "me sinto", + "ando", + "tenho me sentido", + "sinto" + ], + "seek": [ + "quero", + "preciso", + "busco", + "gostaria", + "me ajude" + ], + "fear": [ + "tenho medo", + "estou com medo", + "receio", + "me preocupa", + "inseguro", + "insegura" + ], + "conflict": [ + "não aguento", + "estou irritado", + "estou irritada", + "sinto raiva", + "estou em conflito" + ], + "reflect": [ + "o que significa", + "por que isso acontece", + "como lidar", + "qual é o sentido" + ] +} diff --git a/lib/dictionaries/jyotish.ts b/lib/dictionaries/jyotish.ts new file mode 100644 index 0000000..8070a2d --- /dev/null +++ b/lib/dictionaries/jyotish.ts @@ -0,0 +1,213 @@ +/** + * Frases ancoradas por chave Jyotish — dicionário offline. + */ + +export const JYOTISH_PHRASES: Record = { + "jyotish.nakshatra.revati.spiritualTheme": [ + "Há em você um chamado profundo para caminhar com suavidade e sentido espiritual.", + ], + "jyotish.nakshatra.revati.general": [ + "A estação lunar Revati traz suavidade e conclusão de ciclos; o que termina abre espaço para o novo.", + ], + "jyotish.nakshatra.rohini.general": [ + "Rohini traz fertilidade e beleza ao que você cultiva; a paciência é sua aliada.", + ], + "jyotish.nakshatra.ashwini.general": [ + "Ashwini traz impulso de novo começo; a cura começa quando você aceita o que já está aqui.", + ], + "jyotish.rashi.karka.general": [ + "Sua Lua em Câncer fala de cuidado e raiz emocional; proteger e ser protegido são dois lados do mesmo gesto.", + ], + "jyotish.rashi.karka.love": [ + "No amor, sua natureza lunar pede segurança e profundidade; a entrega nasce da confiança.", + ], + "jyotish.rashi.karka.career": [ + "No trabalho, sua Lua em Câncer floresce em ambientes que honram o humano e o sensível.", + ], + "jyotish.rashi.mesha.general": [ + "Sua Lua em Áries traz coragem e impulso; a sabedoria está em saber quando pausar.", + ], + "jyotish.rashi.mesha.love": [ + "No amor, a iniciativa e a autenticidade são seus trunfos; a paciência complementa.", + ], + "jyotish.rashi.mesha.career": [ + "No trabalho, liderar e iniciar vêm naturalmente; o equilíbrio está em escutar antes de agir.", + ], + "jyotish.rashi.mina.general": [ + "Sua Lua em Peixes traz sensibilidade e conexão com o invisível; os limites são o seu desafio e a compaixão o seu dom.", + ], + "jyotish.rashi.mina.love": [ + "No amor, a entrega e a fusão são naturais; cuidar de si é o primeiro ato de amor.", + ], + "jyotish.rashi.mina.career": [ + "No trabalho, a intuição e o serviço ao outro florescem; ancorar no corpo evita dissipação.", + ], + "jyotish.rashi.karka.year": [ + "Este ano, sua Lua em Câncer pede que você cultive raiz e cuidado; o que você nutre nutre você.", + ], + "jyotish.rashi.mesha.year": [ + "Este ano, impulso e novo começo estão no ar; escolha um rumo e dê o primeiro passo.", + ], + "jyotish.rashi.mina.year": [ + "Este ano, a sensibilidade e a conexão com o invisível se ampliam; proteja seus limites para não dissipar.", + ], + "jyotish.nakshatra.revati.year": [ + "O ciclo Revati traz conclusão e suavidade; o que termina abre espaço para o próximo ciclo.", + ], + "jyotish.nakshatra.rohini.year": [ + "Rohini no ano favorece fertilidade e beleza no que você cultiva; paciência e constância.", + ], + "jyotish.nakshatra.ashwini.year": [ + "Ashwini no ano traz impulso de cura e novo começo; aceite o que já está aqui.", + ], + "jyotish.rashi.vrishabha.general": [ + "Sua Lua em Touro fala de raiz e beleza; a estabilidade que você busca nasce da paciência.", + ], + "jyotish.rashi.vrishabha.love": [ + "No amor, segurança e sensorialidade são naturais; a leveza complementa.", + ], + "jyotish.rashi.vrishabha.career": [ + "No trabalho, constância e beleza florescem; evite a rigidez.", + ], + "jyotish.rashi.vrishabha.year": [ + "Este ano, cultive raiz e paciência; o que você planta com calma colhe em paz.", + ], + "jyotish.rashi.mithuna.general": [ + "Sua Lua em Gêmeos traz comunicação e curiosidade; a profundidade é o complemento.", + ], + "jyotish.rashi.mithuna.love": [ + "No amor, a troca e a leveza são seus trunfos; o silêncio a dois equilibra.", + ], + "jyotish.rashi.mithuna.career": [ + "No trabalho, versatilidade e comunicação florescem; ancorar em um projeto evita dispersão.", + ], + "jyotish.rashi.mithuna.year": [ + "Este ano, conexão e aprendizado se ampliam; escolha um fio e aprofunde.", + ], + "jyotish.rashi.simha.general": [ + "Sua Lua em Leão traz centro e reconhecimento; a humildade equilibra o brilho.", + ], + "jyotish.rashi.simha.love": [ + "No amor, generosidade e calor são naturais; receber é tão importante quanto dar.", + ], + "jyotish.rashi.simha.career": [ + "No trabalho, liderança e criatividade florescem; compartilhar o palco traz paz.", + ], + "jyotish.rashi.simha.year": [ + "Este ano, seu centro pede reconhecimento; reconheça primeiro a si mesmo.", + ], + "jyotish.rashi.kanya.general": [ + "Sua Lua em Virgem traz discernimento e serviço; a aceitação do imperfeito libera.", + ], + "jyotish.rashi.kanya.love": [ + "No amor, cuidado e precisão são dons; não exija de si o que não exige do outro.", + ], + "jyotish.rashi.kanya.career": [ + "No trabalho, organização e eficiência florescem; o descanso também é produtivo.", + ], + "jyotish.rashi.kanya.year": [ + "Este ano, refine sem rigidificar; a perfeição está no processo, não no resultado.", + ], + "jyotish.rashi.tula.general": [ + "Sua Lua em Libra traz equilíbrio e relação; a justiça começa por você.", + ], + "jyotish.rashi.tula.love": [ + "No amor, harmonia e parceria são naturais; o conflito bem resolvido aproxima.", + ], + "jyotish.rashi.tula.career": [ + "No trabalho, diplomacia e beleza florescem; decidir é também um ato de equilíbrio.", + ], + "jyotish.rashi.tula.year": [ + "Este ano, equilíbrio e parceria se ampliam; cuide dos vínculos que nutrem.", + ], + "jyotish.rashi.vrischika.general": [ + "Sua Lua em Escorpião traz profundidade e transformação; a entrega libera o que prende.", + ], + "jyotish.rashi.vrischika.love": [ + "No amor, intensidade e lealdade são profundas; a confiança se constrói aos poucos.", + ], + "jyotish.rashi.vrischika.career": [ + "No trabalho, poder de realização e foco florescem; use-os com integridade.", + ], + "jyotish.rashi.vrischika.year": [ + "Este ano, transformação e renovação estão no ar; deixe ir o que não serve mais.", + ], + "jyotish.rashi.dhanu.general": [ + "Sua Lua em Sagitário traz busca de sentido e expansão; a pausa também ensina.", + ], + "jyotish.rashi.dhanu.love": [ + "No amor, liberdade e verdade atraem; o compromisso pode ser amplo e livre.", + ], + "jyotish.rashi.dhanu.career": [ + "No trabalho, visão e otimismo florescem; o próximo passo conta mais que o mapa inteiro.", + ], + "jyotish.rashi.dhanu.year": [ + "Este ano, expansão e aprendizado se ampliam; um passo de cada vez.", + ], + "jyotish.rashi.makara.general": [ + "Sua Lua em Capricórnio traz estrutura e ambição; o afeto não enfraquece.", + ], + "jyotish.rashi.makara.love": [ + "No amor, lealdade e constância são profundas; permita-se ser vulnerável.", + ], + "jyotish.rashi.makara.career": [ + "No trabalho, disciplina e longo prazo florescem; celebre as pequenas vitórias.", + ], + "jyotish.rashi.makara.year": [ + "Este ano, construir com paciência traz resultados; cuide do corpo e do repouso.", + ], + "jyotish.rashi.kumbha.general": [ + "Sua Lua em Aquário traz visão de futuro e humanidade; a conexão humana aterriz.", + ], + "jyotish.rashi.kumbha.love": [ + "No amor, amizade e liberdade são bases; o diferente complementa.", + ], + "jyotish.rashi.kumbha.career": [ + "No trabalho, inovação e coletivo florescem; sua contribuição única importa.", + ], + "jyotish.rashi.kumbha.year": [ + "Este ano, visão e comunidade se ampliam; una o ideal ao cotidiano.", + ], + "jyotish.nakshatra.bharani.general": [ + "Bharani traz força de carregar e dar à luz; o que você sustenta o sustenta.", + ], + "jyotish.nakshatra.krittika.general": [ + "Krittika traz fogo de clareza e corte; use-o para iluminar, não para queimar.", + ], + "jyotish.nakshatra.pushya.general": [ + "Pushya traz nutrição e proteção; cuidar e ser cuidado são um só.", + ], + "jyotish.nakshatra.magha.general": [ + "Magha traz dignidade e raiz ancestral; honre o que veio antes e siga em frente.", + ], + "jyotish.nakshatra.hasta.general": [ + "Hasta traz habilidade e precisão; as mãos que criam também acolhem.", + ], + "jyotish.nakshatra.vishakha.general": [ + "Vishakha traz determinação e realização; o objetivo e o caminho são um.", + ], + "jyotish.nakshatra.shravana.general": [ + "Shravana traz escuta e aprendizado; o que você ouve transforma.", + ], + "jyotish.nakshatra.bharani.year": [ + "Bharani no ano favorece carregar e dar à luz; o que você sustenta o sustenta.", + ], + "jyotish.nakshatra.krittika.year": [ + "Krittika no ano traz clareza e corte; use o fogo para iluminar.", + ], + "jyotish.nakshatra.pushya.year": [ + "Pushya no ano favorece nutrição e proteção; cuidar e ser cuidado.", + ], + "jyotish.nakshatra.magha.year": [ + "Magha no ano traz dignidade e raiz; honre o passado e siga em frente.", + ], + "jyotish.nakshatra.hasta.year": [ + "Hasta no ano favorece habilidade e realização; as mãos que criam também acolhem.", + ], + "jyotish.nakshatra.vishakha.year": [ + "Vishakha no ano traz determinação; o objetivo e o caminho são um.", + ], + "jyotish.nakshatra.shravana.year": [ + "Shravana no ano favorece escuta e aprendizado; o que você ouve transforma.", + ], +}; diff --git a/lib/dictionaries/numerology.ts b/lib/dictionaries/numerology.ts new file mode 100644 index 0000000..05333ac --- /dev/null +++ b/lib/dictionaries/numerology.ts @@ -0,0 +1,139 @@ +/** + * Frases ancoradas por número regente (numerologia) — dicionário offline. + */ + +export const NUMEROLOGY_PHRASES: Record = { + "numerology.ruling.1.general": [ + "Seu número fala de unidade: o um que contém o todo.", + "A tendência do um é liderar; a sabedoria é saber quando seguir.", + ], + "numerology.ruling.1.career": [ + "No trabalho, independência e iniciativa são seus dons; a colaboração é o complemento.", + ], + "numerology.ruling.1.love": [ + "No amor, autenticidade e coragem atraem; a entrega equilibra.", + ], + "numerology.ruling.2.general": [ + "O dois traz diplomacia e parceria; a sabedoria está em saber quando dizer não.", + ], + "numerology.ruling.2.career": [ + "No trabalho, cooperação e sensibilidade florescem; limites claros protegem.", + ], + "numerology.ruling.2.love": [ + "No amor, a parceria e a harmonia são naturais; cuidar de si não é egoísmo.", + ], + "numerology.ruling.7.general": [ + "O sete fala de busca interior e sabedoria; a solidão é fertilizante, não fuga.", + ], + "numerology.ruling.7.career": [ + "No trabalho, profundidade e reflexão são seus trunfos; a ação nasce do silêncio.", + ], + "numerology.ruling.7.love": [ + "No amor, a conexão verdadeira nasce quando você se aceita primeiro.", + ], + "numerology.ruling.1.year": [ + "Este ano, liderança e iniciativa são seus trunfos; saber quando seguir complementa.", + ], + "numerology.ruling.2.year": [ + "Este ano, parceria e diplomacia florescem; limites claros protegem sua energia.", + ], + "numerology.ruling.7.year": [ + "Este ano, profundidade e reflexão trazem clareza; a ação nasce do silêncio.", + ], + "numerology.ruling.3.general": [ + "O três fala de expressão e criatividade; a profundidade completa a alegria.", + ], + "numerology.ruling.3.career": [ + "No trabalho, comunicação e criatividade florescem; um projeto de cada vez.", + ], + "numerology.ruling.3.love": [ + "No amor, leveza e troca são naturais; o silêncio a dois também fala.", + ], + "numerology.ruling.3.year": [ + "Este ano, expressão e conexão se ampliam; use sua voz com clareza.", + ], + "numerology.ruling.4.general": [ + "O quatro fala de base e trabalho; a flexibilidade evita a rigidez.", + ], + "numerology.ruling.4.career": [ + "No trabalho, disciplina e estrutura são seus trunfos; descanse para construir melhor.", + ], + "numerology.ruling.4.love": [ + "No amor, lealdade e constância florescem; permita-se receber.", + ], + "numerology.ruling.4.year": [ + "Este ano, construir com paciência traz resultados; celebre cada etapa.", + ], + "numerology.ruling.5.general": [ + "O cinco fala de liberdade e mudança; o centro acompanha o movimento.", + ], + "numerology.ruling.5.career": [ + "No trabalho, versatilidade e adaptação florescem; ancorar em um rumo ajuda.", + ], + "numerology.ruling.5.love": [ + "No amor, liberdade e verdade atraem; o compromisso pode ser amplo.", + ], + "numerology.ruling.5.year": [ + "Este ano, mudança e experiência se ampliam; o instante é seu porto.", + ], + "numerology.ruling.6.general": [ + "O seis fala de cuidado e responsabilidade; cuidar de si vem primeiro.", + ], + "numerology.ruling.6.career": [ + "No trabalho, harmonia e serviço florescem; limites claros protegem.", + ], + "numerology.ruling.6.love": [ + "No amor, dar e receber são um; o autocuidado não é egoísmo.", + ], + "numerology.ruling.6.year": [ + "Este ano, cuidado e beleza se ampliam; nutra os vínculos que nutrem você.", + ], + "numerology.ruling.8.general": [ + "O oito fala de realização e poder; a humildade equilibra a ambição.", + ], + "numerology.ruling.8.career": [ + "No trabalho, manifestação e organização florescem; o descanso também produz.", + ], + "numerology.ruling.8.love": [ + "No amor, lealdade e profundidade são naturais; poder e afeto coexistem.", + ], + "numerology.ruling.8.year": [ + "Este ano, realização e abundância se ampliam; use o poder com integridade.", + ], + "numerology.ruling.9.general": [ + "O nove fala de completude e entrega; a sabedoria está em receber também.", + ], + "numerology.ruling.9.career": [ + "No trabalho, visão ampla e generosidade florescem; cuide de si para cuidar do mundo.", + ], + "numerology.ruling.9.love": [ + "No amor, entrega e compaixão são profundas; permita-se ser amado.", + ], + "numerology.ruling.9.year": [ + "Este ano, ciclos se completam e novos começam; desapego e gratidão andam juntos.", + ], + "numerology.ruling.11.general": [ + "O onze fala de intuição e inspiração; aterrar a visão traz realização.", + ], + "numerology.ruling.11.career": [ + "No trabalho, visão e idealismo florescem; um passo prático por vez.", + ], + "numerology.ruling.11.love": [ + "No amor, conexão além do óbvio; a presença vale mais que a perfeição.", + ], + "numerology.ruling.11.year": [ + "Este ano, intuição e inspiração se ampliam; ancorar no corpo equilibra.", + ], + "numerology.ruling.22.general": [ + "O vinte e dois fala de realização em grande escala; o pequeno gesto também constrói.", + ], + "numerology.ruling.22.career": [ + "No trabalho, visão de mestre e construção florescem; delegar e descansar.", + ], + "numerology.ruling.22.love": [ + "No amor, profundidade e visão de longo prazo; o dia a dia também importa.", + ], + "numerology.ruling.22.year": [ + "Este ano, grandes ciclos e pequenos gestos se unem; um passo de cada vez.", + ], +}; diff --git a/lib/dictionaries/phrasesForSymbolic.ts b/lib/dictionaries/phrasesForSymbolic.ts new file mode 100644 index 0000000..9e388ab --- /dev/null +++ b/lib/dictionaries/phrasesForSymbolic.ts @@ -0,0 +1,242 @@ +/** + * Frases por Insight.key do mapa simbólico canônico (general, love, career, year, action). + * Cada chave usada em jyotishInsightsForSymbolic e collectInsightsForSymbolicMap. + */ + +export const PHRASES_FOR_SYMBOLIC: Record = { + // ——— General (spiritualPath, soulPath + rashi/nakshatra) ——— + "jyotish.revati.spiritualPath": [ + "Há em você um chamado profundo para caminhar com suavidade espiritual.", + ], + "jyotish.revati.soulPath": [ + "A estação lunar Revati traz conclusão e suavidade; o que termina abre espaço para o novo.", + ], + "jyotish.rohini.soulPath": [ + "Rohini traz fertilidade e beleza ao que você cultiva; a paciência é sua aliada.", + ], + "jyotish.ashwini.soulPath": [ + "Ashwini traz impulso de novo começo; a cura começa quando você aceita o que já está aqui.", + ], + "jyotish.karka.general": [ + "Sua Lua em Câncer fala de cuidado e raiz emocional; proteger e ser protegido são dois lados do mesmo gesto.", + ], + "jyotish.mesha.general": [ + "Sua Lua em Áries traz coragem e impulso; a sabedoria está em saber quando pausar.", + ], + "jyotish.mina.general": [ + "Sua Lua em Peixes traz sensibilidade e conexão com o invisível; a compaixão é o seu dom.", + ], + "jyotish.pushya.general": [ + "Pushya traz nutrição e proteção; o que você alimenta com presença floresce.", + ], + "jyotish.magha.general": [ + "Magha traz dignidade e legado; honrar suas raízes fortalece seu caminho.", + ], + "jyotish.hasta.general": [ + "Hasta traz habilidade e precisão; suas mãos podem materializar o que o coração deseja.", + ], + "jyotish.chitra.general": [ + "Chitra traz beleza e estrutura; construir com consciência é o seu dom.", + ], + "jyotish.vrishabha.general": [ + "Sua Lua em Touro fala de raiz e beleza; a estabilidade que você busca nasce da paciência.", + ], + "jyotish.mithuna.general": [ + "Sua Lua em Gêmeos traz comunicação e curiosidade; a profundidade é o complemento.", + ], + "jyotish.simha.general": [ + "Sua Lua em Leão traz dignidade e generosidade; o que você honra honra você.", + ], + "jyotish.kanya.general": [ + "Sua Lua em Virgem traz discernimento e serviço; o detalhe a serviço do todo.", + ], + "jyotish.tula.general": [ + "Sua Lua em Libra traz equilíbrio e parceria; a justiça começa em si.", + ], + "jyotish.vrischika.general": [ + "Sua Lua em Escorpião traz profundidade e transformação; o que você toca se transforma.", + ], + "jyotish.dhanu.general": [ + "Sua Lua em Sagitário traz visão e expansão; o sentido nasce do caminho.", + ], + "jyotish.makara.general": [ + "Sua Lua em Capricórnio traz estrutura e ambição; construir com paciência é o dom.", + ], + "jyotish.kumbha.general": [ + "Sua Lua em Aquário traz inovação e humanidade; o futuro que você quer começa no gesto de hoje.", + ], + // ——— Love ——— + "jyotish.revati.love": [ + "No amor, Revati traz suavidade e conclusão; relacionamentos evoluem quando há espaço para o novo.", + ], + "jyotish.rohini.love": [ + "No amor, Rohini favorece fertilidade e beleza; a paciência e o cultivo diário fortalecem o vínculo.", + ], + "jyotish.karka.love": [ + "No amor, sua natureza lunar pede segurança e profundidade; a entrega nasce da confiança.", + ], + "jyotish.mesha.love": [ + "No amor, a iniciativa e a autenticidade são seus trunfos; a paciência complementa.", + ], + "jyotish.mina.love": [ + "No amor, a entrega e a fusão são naturais; cuidar de si é o primeiro ato de amor.", + ], + "jyotish.vrishabha.love": [ + "No amor, segurança e sensorialidade são naturais; a leveza complementa.", + ], + "jyotish.mithuna.love": [ + "No amor, a troca e a leveza são seus trunfos; o silêncio a dois equilibra.", + ], + "jyotish.tula.love": [ + "No amor, o equilíbrio e a parceria florescem; cuidar do vínculo é cuidar de si.", + ], + "jyotish.simha.love": [ + "No amor, a generosidade e a dignidade são seus trunfos; o reconhecimento mútuo fortalece.", + ], + "jyotish.kanya.love": [ + "No amor, o discernimento e o cuidado com o detalhe fortalecem o vínculo; evite o perfeccionismo.", + ], + // ——— Career ——— + "jyotish.revati.career": [ + "Na carreira, Revati favorece conclusões e transições suaves; feche ciclos para abrir novos.", + ], + "jyotish.karka.career": [ + "No trabalho, sua Lua em Câncer floresce em ambientes que honram o humano e o sensível.", + ], + "jyotish.mesha.career": [ + "No trabalho, liderar e iniciar vêm naturalmente; o equilíbrio está em escutar antes de agir.", + ], + "jyotish.rohini.career": [ + "Na carreira, Rohini favorece crescimento constante; cultive com paciência o que deseja colher.", + ], + "jyotish.ashwini.career": [ + "Na carreira, Ashwini traz impulso de novo começo; a cura e a inovação andam juntas.", + ], + "jyotish.mina.career": [ + "No trabalho, a intuição e o serviço ao outro florescem; ancorar no corpo evita dissipação.", + ], + "jyotish.vrishabha.career": [ + "No trabalho, constância e beleza florescem; evite a rigidez.", + ], + "jyotish.mithuna.career": [ + "Na carreira, comunicação e curiosidade são seus trunfos; a profundidade complementa.", + ], + "jyotish.tula.career": [ + "No trabalho, o equilíbrio e a parceria florescem; ambientes colaborativos te nutrem.", + ], + "jyotish.dhanu.career": [ + "Na carreira, visão e expansão são naturais; alinhe o trabalho a um sentido maior.", + ], + "jyotish.kanya.career": [ + "No trabalho, discernimento e serviço florescem; o detalhe a serviço do todo.", + ], + // ——— Year ——— + "jyotish.revati.year": [ + "O ciclo Revati traz conclusão e suavidade; o que termina abre espaço para o próximo ciclo.", + ], + "jyotish.karka.year": [ + "Este ano, sua Lua em Câncer pede que você cultive raiz e cuidado; o que você nutre nutre você.", + ], + "jyotish.mesha.year": [ + "Este ano, impulso e novo começo estão no ar; escolha um rumo e dê o primeiro passo.", + ], + "jyotish.rohini.year": [ + "Rohini no ano favorece fertilidade e beleza no que você cultiva; paciência e constância.", + ], + "jyotish.ashwini.year": [ + "Ashwini no ano traz impulso de cura e novo começo; aceite o que já está aqui.", + ], + "jyotish.mina.year": [ + "Este ano, a sensibilidade e a conexão com o invisível se ampliam; proteja seus limites para não dissipar.", + ], + "jyotish.vrishabha.year": [ + "Este ano, cultive raiz e paciência; o que você planta com calma colhe em paz.", + ], + "jyotish.mithuna.year": [ + "Este ano, comunicação e curiosidade se ampliam; a profundidade complementa.", + ], + "jyotish.tula.year": [ + "Este ano, equilíbrio e parceria estão em foco; a justiça começa em si.", + ], + "jyotish.pushya.year": [ + "Pushya no ano favorece nutrição e proteção; o que você alimenta com presença floresce.", + ], + // ——— Action (geral e por arquétipo) ——— + "action.general": [ + "Prática: antes de responder a alguém, faça uma pausa de três respirações.", + ], + "action.archetype.dissolvente": [ + "Prática: hoje, uma ação que dissolva um hábito que não serve mais.", + ], + "action.archetype.pioneiro": [ + "Prática: dê o primeiro passo em algo que você adia; mesmo pequeno, conta.", + ], + "action.archetype.cuidador": [ + "Prática: uma ação concreta de cuidado consigo ou com outro hoje.", + ], + "action.archetype.sábio": [ + "Prática: reserve 10 minutos em silêncio para escutar o que já sabe.", + ], + "action.archetype.guerreiro": [ + "Prática: defina um limite claro em uma situação que você evita.", + ], + "action.archetype.raiz": [ + "Prática: hoje, ancorar-se no corpo — um gesto sensorial que te traga ao presente.", + ], + "action.archetype.mensageiro": [ + "Prática: faça uma pergunta genuína a alguém e escute a resposta sem interromper.", + ], + "action.archetype.soberano": [ + "Prática: faça um gesto concreto de reconhecimento para alguém do seu convívio.", + ], + "action.archetype.servidor": [ + "Prática: termine uma tarefa pequena que está pendente há dias, a serviço do todo.", + ], + "action.archetype.harmonizador": [ + "Prática: escolha um limite (horário, tema, pessoa) e respeite-o hoje.", + ], + "action.archetype.transformador": [ + "Prática: hoje, uma ação que dissolva um hábito que não serve mais.", + ], + "action.archetype.sabedor": [ + "Prática: reserve 10 minutos em silêncio para escutar o que já sabe.", + ], + "action.archetype.estruturador": [ + "Prática: escreva em uma linha o que você quer que o seu trabalho gere no mundo; releia ao acordar.", + ], + "action.archetype.visionario": [ + "Prática: diga sim a um convite que te puxe para fora da rotina.", + ], + // ——— 30 frases práticas (action.1 … action.30) ——— + "action.1": ["Prática: respire lentamente 7 vezes antes de tomar qualquer decisão hoje."], + "action.2": ["Prática: por 1 minuto, sinta os pés no chão e o ar entrando e saindo; depois escolha o próximo passo."], + "action.3": ["Prática: escreva em uma linha o que você quer que o seu trabalho gere no mundo; releia ao acordar."], + "action.4": ["Prática: hoje, uma ação concreta de cuidado consigo mesmo (um gesto que te nutra)."], + "action.5": ["Prática: antes de responder a alguém, faça uma pausa de três respirações."], + "action.6": ["Prática: diga não a um compromisso que não serve ao que você quer cultivar."], + "action.7": ["Prática: reserve 10 minutos em silêncio para escutar o que já sabe."], + "action.8": ["Prática: defina um limite claro em uma situação que você evita."], + "action.9": ["Prática: dê o primeiro passo em algo que você adia; mesmo pequeno, conta."], + "action.10": ["Prática: agradeça em voz alta uma pessoa que fez diferença no seu dia."], + "action.11": ["Prática: escreva três coisas que você quer liberar este ano; depois rasgue o papel com consciência."], + "action.12": ["Prática: caminhe 5 minutos em silêncio, prestando atenção só ao corpo e ao ar."], + "action.13": ["Prática: faça uma pergunta genuína a alguém e escute a resposta sem interromper."], + "action.14": ["Prática: desligue as notificações por 1 hora e observe o que surge."], + "action.15": ["Prática: escolha uma palavra que represente o que você quer nutrir e repita-a ao acordar."], + "action.16": ["Prática: hoje, não reclame de nada; observe o que muda."], + "action.17": ["Prática: escreva uma frase que você gostaria de ouvir e leia em voz alta para si."], + "action.18": ["Prática: faça um gesto concreto de reconhecimento para alguém do seu convívio."], + "action.19": ["Prática: sente-se 2 minutos com os olhos fechados só observando a respiração."], + "action.20": ["Prática: termine uma tarefa pequena que está pendente há dias."], + "action.21": ["Prática: pergunte a si mesmo: o que em mim já sabe a resposta? e espere em silêncio."], + "action.22": ["Prática: dedique 15 minutos a uma atividade que te coloque em fluxo, sem objetivo de produto."], + "action.23": ["Prática: hoje, evite julgar; apenas observe uma situação difícil sem comentário interno."], + "action.24": ["Prática: envie uma mensagem de gratidão para alguém que você não agradece há tempo."], + "action.25": ["Prática: deixe o telefone em outro cômodo durante uma refeição."], + "action.26": ["Prática: escolha um limite (horário, tema, pessoa) e respeite-o hoje."], + "action.27": ["Prática: faça uma lista de três possibilidades antes de decidir por uma."], + "action.28": ["Prática: diga sim a um convite que te puxe para fora da rotina."], + "action.29": ["Prática: antes de dormir, relembre um momento do dia em que você esteve presente."], + "action.30": ["Prática: amanhã ao acordar, a primeira ação seja uma respiração consciente antes de pegar o celular."], +}; + diff --git a/lib/dictionaries/remedyMatrix.json b/lib/dictionaries/remedyMatrix.json new file mode 100644 index 0000000..0b76668 --- /dev/null +++ b/lib/dictionaries/remedyMatrix.json @@ -0,0 +1,502 @@ +[ + { + "state": "anxiety", + "klesha": "raga", + "samkhyaGuna": "rajas", + "qualities": ["chala", "ruksha"], + "sacred": { "corpus": "yoga_sutras", "id": "YS.1.33", "verse": "Amizade, compaixão, alegria e equanimidade em relação ao que é agradável, doloroso, meritório ou não — acalmam a mente." }, + "practice": "7 respirações longas com mão no coração", + "food": "sopa quente, ghee", + "question": "O que você pode soltar por hoje?" + }, + { + "state": "emotional_attachment", + "klesha": "raga", + "samkhyaGuna": "rajas", + "qualities": ["snigdha", "guru"], + "sacred": { "corpus": "purana", "id": "BP.bhakti", "verse": "A entrega ao divino dissolve o apego; quem oferece o coração encontra leveza." }, + "practice": "escrever 1 gratidão e liberar", + "food": "chá leve digestivo", + "question": "Você ama ou segura?" + }, + { + "state": "existential_fear", + "klesha": "abhinivesha", + "samkhyaGuna": "tamas", + "qualities": ["guru", "sandra"], + "sacred": { "corpus": "yoga_sutras", "id": "YS.2.9", "verse": "O medo da morte habita mesmo no sábio; é inerente à natureza. Observá-lo enfraquece seu poder." }, + "practice": "grounding — pés no chão 2 min", + "food": "raiz assada", + "question": "O que permanece quando você respira?" + }, + { + "state": "anger", + "klesha": "dvesha", + "samkhyaGuna": "rajas", + "qualities": ["tikshna", "ushna"], + "sacred": { "corpus": "yoga_sutras", "id": "YS.1.33", "verse": "Amizade, compaixão, alegria e equanimidade — em relação a todos os seres — acalmam o coração." }, + "practice": "água fria no rosto + pausa", + "food": "coco, hortelã", + "question": "Contra o que você está lutando?" + }, + { + "state": "resentment", + "klesha": "dvesha", + "samkhyaGuna": "tamas", + "qualities": ["picchila", "sthira"], + "sacred": { "corpus": "purana", "id": "BP.forgiveness", "verse": "O perdão é libertação; quem solta o ressentimento abre a porta do coração." }, + "practice": "repetir \"eu libero\"", + "food": "especiarias leves", + "question": "O que você ganha mantendo isso?" + }, + { + "state": "spiritual_pride", + "klesha": "asmita", + "samkhyaGuna": "rajas", + "qualities": ["tikshna", "kathina"], + "sacred": { "corpus": "yoga_sutras", "id": "YS.2.6", "verse": "O ego é a identificação do que vê com o instrumento do ver; reconhecer isso dissolve o orgulho." }, + "practice": "ato de serviço anônimo", + "food": "simples, sem excessos", + "question": "Quem é você sem sua imagem?" + }, + { + "state": "confusion", + "klesha": "avidya", + "samkhyaGuna": "tamas", + "qualities": ["manda", "guru"], + "sacred": { "corpus": "upanishad", "id": "UP.tat_tvam_asi", "verse": "Isso és tu. O que você busca já é você." }, + "practice": "silêncio 3 minutos", + "food": "gengibre leve", + "question": "O que é verdadeiro agora?" + }, + { + "state": "overthinking", + "klesha": "avidya", + "samkhyaGuna": "rajas", + "qualities": ["sukshma", "chala"], + "sacred": { "corpus": "yoga_sutras", "id": "YS.1.2", "verse": "Yoga é a cessação das flutuações da mente." }, + "practice": "olhar fixo em vela 1 min", + "food": "comida densa e quente", + "question": "Você está vivendo ou pensando?" + }, + { + "state": "lethargy", + "klesha": "avidya", + "samkhyaGuna": "tamas", + "qualities": ["guru", "manda"], + "sacred": { "corpus": "yoga_sutras", "id": "YS.1.14", "verse": "A prática torna-se firme quando mantida por muito tempo, sem interrupção, com devoção." }, + "practice": "caminhada curta agora", + "food": "pimenta preta, calor", + "question": "Qual pequeno passo desperta você?" + }, + { + "state": "distraction", + "klesha": "raga", + "samkhyaGuna": "rajas", + "qualities": ["chala", "laghu"], + "sacred": { "corpus": "yoga_sutras", "id": "YS.1.13", "verse": "O esforço constante para estabilizar a mente é a prática." }, + "practice": "uma tarefa única por 10 min", + "food": "grounding (raiz)", + "question": "Onde está sua atenção?" + }, + { + "state": "deep_sadness", + "klesha": "abhinivesha", + "samkhyaGuna": "tamas", + "qualities": ["guru", "mridu"], + "sacred": { "corpus": "purana", "id": "BP.compassion", "verse": "A compaixão divina acolhe quem sofre; você pode ser sustentado." }, + "practice": "banho quente + descanso", + "food": "leite morno com especiarias", + "question": "Você pode ser acolhido?" + }, + { + "state": "emotional_instability", + "klesha": "raga", + "samkhyaGuna": "rajas", + "qualities": ["sara", "chala"], + "sacred": { "corpus": "yoga_sutras", "id": "YS.1.33", "verse": "Amizade, compaixão, alegria e equanimidade estabilizam o coração." }, + "practice": "respiração alternada", + "food": "quente e oleoso", + "question": "O que te estabiliza?" + }, + { + "state": "rigidity", + "klesha": "asmita", + "samkhyaGuna": "tamas", + "qualities": ["kathina", "sthira"], + "sacred": { "corpus": "yoga_sutras", "id": "YS.2.1", "verse": "A prática constante e o desapego são os meios." }, + "practice": "soltar um plano hoje", + "food": "suavizante (óleos)", + "question": "Você confia?" + }, + { + "state": "emptiness", + "klesha": "avidya", + "samkhyaGuna": "tamas", + "qualities": ["vishada", "laghu"], + "sacred": { "corpus": "upanishad", "id": "UP.plenitude", "verse": "O Ser que reside no coração é plenitude; o vazio é espaço para Ele." }, + "practice": "presença corporal", + "food": "nutritivo e quente", + "question": "O vazio é falta ou espaço?" + }, + { + "state": "compulsive_desire", + "klesha": "raga", + "samkhyaGuna": "rajas", + "qualities": ["tikshna", "ushna"], + "sacred": { "corpus": "yoga_sutras", "id": "YS.2.7", "verse": "O apego segue o prazer; o desapego nasce do discernimento." }, + "practice": "pausa de 3 respirações antes de agir", + "food": "amargos refrescantes", + "question": "Isso é necessidade ou impulso?" + }, + { + "state": "aversion_to_other", + "klesha": "dvesha", + "samkhyaGuna": "rajas", + "qualities": ["khara", "tikshna"], + "sacred": { "corpus": "yoga_sutras", "id": "YS.1.33", "verse": "Compaixão em relação ao que dói — em você e no outro — acalma a mente." }, + "practice": "desejar bem internamente", + "food": "cooling", + "question": "O que você vê em espelho?" + }, + { + "state": "oversensitivity", + "klesha": "abhinivesha", + "samkhyaGuna": "rajas", + "qualities": ["sukshma", "chala"], + "sacred": { "corpus": "purana", "id": "BP.protection", "verse": "Proteger o coração não é fechar; é escolher o que entra." }, + "practice": "autoabraço + limite", + "food": "grounding", + "question": "O que é seu, o que é do mundo?" + }, + { + "state": "lack_of_purpose", + "klesha": "avidya", + "samkhyaGuna": "tamas", + "qualities": ["manda", "guru"], + "sacred": { "corpus": "bhagavad_gita", "id": "BG.dharma", "verse": "Faze o que deves fazer; melhor é o próprio dever, mesmo imperfeito, que o dever alheio bem feito." }, + "practice": "uma ação alinhada hoje", + "food": "simples", + "question": "Qual é seu próximo passo real?" + }, + { + "state": "rush", + "klesha": "raga", + "samkhyaGuna": "rajas", + "qualities": ["tikshna", "sara"], + "sacred": { "corpus": "yoga_sutras", "id": "YS.1.12", "verse": "A prática e o desapego são o par que estabiliza a mente." }, + "practice": "desacelerar fala", + "food": "doce natural", + "question": "Para onde você corre?" + }, + { + "state": "relational_insecurity", + "klesha": "abhinivesha", + "samkhyaGuna": "rajas", + "qualities": ["chala", "ruksha"], + "sacred": { "corpus": "yoga_sutras", "id": "YS.1.33", "verse": "Equanimidade em relação ao que vem e vai traz paz ao coração." }, + "practice": "escrever \"eu sou suficiente\"", + "food": "oleoso quente", + "question": "Você busca amor ou presença?" + }, + { + "state": "excess_criticism", + "klesha": "asmita", + "samkhyaGuna": "rajas", + "qualities": ["tikshna", "khara"], + "sacred": { "corpus": "yoga_sutras", "id": "YS.2.35", "verse": "Na presença de quem está firme na não-violência, a hostilidade cessa." }, + "practice": "elogiar algo hoje", + "food": "suavizante", + "question": "Você quer estar certo ou em paz?" + }, + { + "state": "lack_of_discipline", + "klesha": "avidya", + "samkhyaGuna": "rajas", + "qualities": ["chala", "laghu"], + "sacred": { "corpus": "yoga_sutras", "id": "YS.1.14", "verse": "A prática torna-se firme quando mantida por muito tempo, sem interrupção." }, + "practice": "ritual fixo 5 min", + "food": "grounding", + "question": "O que você repete se torna você." + }, + { + "state": "emotional_exhaustion", + "klesha": "abhinivesha", + "samkhyaGuna": "tamas", + "qualities": ["guru", "mridu"], + "sacred": { "corpus": "purana", "id": "BP.rest", "verse": "O descanso é dharma; quem se entrega ao repouso se renova." }, + "practice": "dormir cedo", + "food": "nutritivo", + "question": "Você está se ouvindo?" + }, + { + "state": "creative_agitation", + "klesha": "raga", + "samkhyaGuna": "rajas", + "qualities": ["tikshna", "chala"], + "sacred": { "corpus": "yoga_sutras", "id": "YS.ekagrata", "verse": "Quando a atenção se concentra em um único ponto, a mente se acalma." }, + "practice": "criar 1 coisa pequena", + "food": "refrescante", + "question": "Você cria ou dispersa?" + }, + { + "state": "stagnation", + "klesha": "avidya", + "samkhyaGuna": "tamas", + "qualities": ["sthira", "guru"], + "sacred": { "corpus": "bhagavad_gita", "id": "BG.action", "verse": "A ação correta libera; a inação presa. Age com desapego ao fruto." }, + "practice": "mover corpo agora", + "food": "especiarias", + "question": "O que quer voltar a fluir?" + }, + { + "state": "excess_guilt", + "klesha": "avidya", + "samkhyaGuna": "tamas", + "qualities": ["guru", "picchila"], + "sacred": { "corpus": "upanishad", "id": "UP.forgiveness", "verse": "O perdão interno libera o peso; você pode recomeçar." }, + "practice": "mão no coração", + "food": "leve", + "question": "Você pode recomeçar?" + }, + { + "state": "emotional_dependence", + "klesha": "raga", + "samkhyaGuna": "rajas", + "qualities": ["snigdha", "guru"], + "sacred": { "corpus": "yoga_sutras", "id": "YS.1.15", "verse": "O desapego é o domínio de quem não deseja nem evita o que vê." }, + "practice": "ficar consigo 10 min", + "food": "leve digestivo", + "question": "Você está inteiro?" + }, + { + "state": "coldness", + "klesha": "dvesha", + "samkhyaGuna": "tamas", + "qualities": ["sita", "kathina"], + "sacred": { "corpus": "purana", "id": "BP.heart", "verse": "Abrir o coração não é fraqueza; é coragem de sentir." }, + "practice": "gesto de bondade", + "food": "quente", + "question": "O que pode derreter?" + }, + { + "state": "overindulgence", + "klesha": "raga", + "samkhyaGuna": "tamas", + "qualities": ["guru", "snigdha"], + "sacred": { "corpus": "yoga_sutras", "id": "YS.2.1", "verse": "Austeridade, autoestudo e entrega ao Absoluto são a prática." }, + "practice": "simplicidade hoje", + "food": "leve", + "question": "O que é suficiente?" + }, + { + "state": "clarity_expansion", + "klesha": null, + "samkhyaGuna": "sattva", + "qualities": ["vishada", "laghu"], + "sacred": { "corpus": "yoga_sutras", "id": "YS.1.16", "verse": "O ápice do desapego é quando a consciência reconhece sua própria natureza luminosa." }, + "practice": "contemplação silenciosa", + "food": "fresco e leve", + "question": "Como servir a partir da luz?" + }, + { + "state": "burnout", + "klesha": "abhinivesha", + "samkhyaGuna": "tamas", + "qualities": ["guru", "mridu"], + "sacred": { "corpus": "purana", "id": "BP.rest", "verse": "O descanso é dharma; quem se entrega ao repouso se renova." }, + "practice": "dormir cedo, sem telas", + "food": "nutritivo, quente", + "question": "O que você pode não fazer hoje?" + }, + { + "state": "solitude", + "klesha": "raga", + "samkhyaGuna": "tamas", + "qualities": ["vishada", "laghu"], + "sacred": { "corpus": "upanishad", "id": "UP.isha_plenum", "verse": "Isto é pleno; aquilo é pleno. Do pleno nasce o pleno." }, + "practice": "uma conexão genuína hoje (uma pessoa)", + "food": "quente e reconfortante", + "question": "Você está só ou em solidão?" + }, + { + "state": "grief", + "klesha": "abhinivesha", + "samkhyaGuna": "tamas", + "qualities": ["guru", "mridu", "sandra"], + "sacred": { "corpus": "purana", "id": "BP.compassion", "verse": "A compaixão divina acolhe quem sofre; você pode ser sustentado." }, + "practice": "banho quente, mão no coração", + "food": "leite morno com especiarias", + "question": "O que precisa ser chorado?" + }, + { + "state": "jealousy", + "klesha": "dvesha", + "samkhyaGuna": "rajas", + "qualities": ["tikshna", "ushna"], + "sacred": { "corpus": "yoga_sutras", "id": "YS.1.33", "verse": "Alegria pelo bem do outro acalma o coração; a comparação dissolve-se." }, + "practice": "respiração refrescante, pausa", + "food": "coco, hortelã", + "question": "O que você tem que o outro não vê?" + }, + { + "state": "numbness", + "klesha": "dvesha", + "samkhyaGuna": "tamas", + "qualities": ["sita", "sthira"], + "sacred": { "corpus": "purana", "id": "BP.heart", "verse": "Abrir o coração não é fraqueza; é coragem de sentir." }, + "practice": "gesto de bondade, água morna nas mãos", + "food": "quente, especiarias leves", + "question": "O que pode derreter um pouco hoje?" + }, + { + "state": "hypercontrol", + "klesha": "asmita", + "samkhyaGuna": "rajas", + "qualities": ["kathina", "sthira"], + "sacred": { "corpus": "yoga_sutras", "id": "YS.2.1", "verse": "A prática constante e o desapego são os meios." }, + "practice": "soltar um plano hoje, uma só decisão", + "food": "suavizante (óleos)", + "question": "O que acontece se você não controlar?" + }, + { + "state": "shame", + "klesha": "asmita", + "samkhyaGuna": "tamas", + "qualities": ["guru", "picchila"], + "sacred": { "corpus": "upanishad", "id": "UP.forgiveness", "verse": "O perdão interno libera o peso; você pode recomeçar." }, + "practice": "mão no coração, \"eu mereço paz\"", + "food": "leve, digestivo", + "question": "Você pode recomeçar?" + }, + { + "state": "impatience", + "klesha": "raga", + "samkhyaGuna": "rajas", + "qualities": ["tikshna", "chala"], + "sacred": { "corpus": "yoga_sutras", "id": "YS.1.12", "verse": "A prática e o desapego são o par que estabiliza a mente." }, + "practice": "desacelerar a fala, 3 respirações antes de agir", + "food": "doce natural, quente", + "question": "Para onde você corre?" + }, + { + "state": "despair", + "klesha": "abhinivesha", + "samkhyaGuna": "tamas", + "qualities": ["guru", "manda"], + "sacred": { "corpus": "upanishad", "id": "UP.brihadaranyaka", "verse": "Conduz-me do não-ser ao ser; conduz-me da escuridão à luz." }, + "practice": "caminhada curta, luz do sol", + "food": "pimenta preta, calor", + "question": "Qual é o menor passo possível agora?" + }, + { + "state": "envy", + "klesha": "dvesha", + "samkhyaGuna": "rajas", + "qualities": ["tikshna", "ushna"], + "sacred": { "corpus": "yoga_sutras", "id": "YS.2.35", "verse": "Na presença de quem está firme na não-violência, a hostilidade cessa." }, + "practice": "desejar bem a alguém em silêncio", + "food": "cooling", + "question": "O que você celebra no outro?" + }, + { + "state": "restlessness", + "klesha": "raga", + "samkhyaGuna": "rajas", + "qualities": ["chala", "laghu"], + "sacred": { "corpus": "yoga_sutras", "id": "YS.1.13", "verse": "O esforço constante para estabilizar a mente é a prática." }, + "practice": "uma tarefa única por 10 min, pés no chão", + "food": "grounding (raiz)", + "question": "Onde está sua atenção?" + }, + { + "state": "boredom", + "klesha": "avidya", + "samkhyaGuna": "tamas", + "qualities": ["manda", "guru"], + "sacred": { "corpus": "yoga_sutras", "id": "YS.1.14", "verse": "A prática torna-se firme quando mantida por muito tempo, sem interrupção." }, + "practice": "uma ação nova (mesmo pequena) agora", + "food": "pimenta preta, calor", + "question": "O que está pedindo sua atenção?" + }, + { + "state": "overwhelm", + "klesha": "raga", + "samkhyaGuna": "rajas", + "qualities": ["chala", "sukshma"], + "sacred": { "corpus": "yoga_sutras", "id": "YS.1.2", "verse": "Yoga é a cessação das flutuações da mente." }, + "practice": "olhar fixo em um ponto 1 min, depois uma só tarefa", + "food": "comida densa e quente", + "question": "Qual é a única coisa agora?" + }, + { + "state": "isolation", + "klesha": "dvesha", + "samkhyaGuna": "tamas", + "qualities": ["sita", "sthira"], + "sacred": { "corpus": "purana", "id": "BP.heart", "verse": "Abrir o coração não é fraqueza; é coragem de sentir." }, + "practice": "um gesto de bondade (mesmo pequeno)", + "food": "quente", + "question": "Quem você pode deixar entrar um pouco?" + }, + { + "state": "perfectionism", + "klesha": "asmita", + "samkhyaGuna": "rajas", + "qualities": ["tikshna", "kathina"], + "sacred": { "corpus": "yoga_sutras", "id": "YS.2.6", "verse": "O ego é a identificação do que vê com o instrumento do ver." }, + "practice": "fazer algo \"imperfeito\" de propósito", + "food": "simples, sem excessos", + "question": "Quem é você sem o resultado?" + }, + { + "state": "avoidance", + "klesha": "abhinivesha", + "samkhyaGuna": "tamas", + "qualities": ["chala", "ruksha"], + "sacred": { "corpus": "yoga_sutras", "id": "YS.2.9", "verse": "Observar o que se evita enfraquece seu poder." }, + "practice": "um passo mínimo em direção ao que evita", + "food": "oleação, quente", + "question": "O que você está evitando sentir?" + }, + { + "state": "irritability", + "klesha": "dvesha", + "samkhyaGuna": "rajas", + "qualities": ["tikshna", "ushna"], + "sacred": { "corpus": "yoga_sutras", "id": "YS.1.33", "verse": "Compaixão em relação ao que dói acalma o coração." }, + "practice": "água fria no rosto, pausa", + "food": "coco, hortelã", + "question": "O que está por baixo da irritação?" + }, + { + "state": "self_doubt", + "klesha": "avidya", + "samkhyaGuna": "tamas", + "qualities": ["sukshma", "guru"], + "sacred": { "corpus": "upanishad", "id": "UP.tat_tvam_asi", "verse": "Isso és tu. O que você busca já é você." }, + "practice": "escrever uma qualidade sua que é verdadeira", + "food": "nutritivo e quente", + "question": "O que você já sabe que é verdade?" + }, + { + "state": "longing", + "klesha": "raga", + "samkhyaGuna": "rajas", + "qualities": ["snigdha", "sara"], + "sacred": { "corpus": "yoga_sutras", "id": "YS.2.7", "verse": "O apego segue o prazer; o desapego nasce do discernimento." }, + "practice": "ficar consigo 10 min, sem preencher", + "food": "leve digestivo", + "question": "O que você tem agora que é suficiente?" + }, + { + "state": "acceptance", + "klesha": null, + "samkhyaGuna": "sattva", + "qualities": ["vishada", "mridu"], + "sacred": { "corpus": "yoga_sutras", "id": "YS.1.16", "verse": "Quando a consciência reconhece sua própria natureza, a aceitação nasce." }, + "practice": "contemplação silenciosa", + "food": "fresco e leve", + "question": "O que você pode aceitar neste instante?" + } +] diff --git a/lib/dictionaries/sacred/puranas.json b/lib/dictionaries/sacred/puranas.json new file mode 100644 index 0000000..0751f7b --- /dev/null +++ b/lib/dictionaries/sacred/puranas.json @@ -0,0 +1,6002 @@ +[ + { + "id": "BP.bhakti", + "text": "A entrega ao divino dissolve o apego; quem oferece o coração encontra leveza.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "snigdha", + "guru" + ], + "themes": [ + "entrega", + "devoção" + ] + }, + { + "id": "BP.forgiveness", + "text": "O perdão é libertação; quem solta o ressentimento abre a porta do coração.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "picchila", + "sthira" + ], + "themes": [ + "perdão", + "libertação" + ] + }, + { + "id": "BP.compassion", + "text": "A compaixão divina acolhe quem sofre; você pode ser sustentado.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "mridu" + ], + "themes": [ + "compaixão", + "sustento" + ] + }, + { + "id": "BP.protection", + "text": "Proteger o coração não é fechar; é escolher o que entra.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "sukshma", + "chala" + ], + "themes": [ + "proteção", + "limites" + ] + }, + { + "id": "BP.rest", + "text": "O descanso é dharma; quem se entrega ao repouso se renova.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "mridu" + ], + "themes": [ + "descanso", + "renovação" + ] + }, + { + "id": "BP.heart", + "text": "Abrir o coração não é fraqueza; é coragem de sentir.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "sita", + "kathina" + ], + "themes": [ + "coração", + "coragem" + ] + }, + { + "id": "BP.surrender1", + "text": "Quem entrega o fruto da ação ao divino não carrega o peso do resultado.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "guru", + "snigdha" + ], + "themes": [ + "entrega", + "ação" + ] + }, + { + "id": "BP.surrender2", + "text": "A entrega dissolve o medo; o que é oferecido não pode ser perdido.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru" + ], + "themes": [ + "entrega", + "medo" + ] + }, + { + "id": "BP.peace1", + "text": "A paz que nasce da devoção não depende do mundo.", + "kleshaTargets": [ + "raga", + "dvesha" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "paz", + "devoção" + ] + }, + { + "id": "BP.peace2", + "text": "Quem canta o nome do divino encontra refúgio no próprio coração.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "mridu" + ], + "themes": [ + "refúgio", + "coração" + ] + }, + { + "id": "BP.grace1", + "text": "A graça não escolhe merecimento; ela escolhe o momento.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "kathina" + ], + "themes": [ + "graça", + "humildade" + ] + }, + { + "id": "BP.grace2", + "text": "Quando o coração está quebrado, a luz entra por onde não havia porta.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "mridu" + ], + "themes": [ + "graça", + "luz" + ] + }, + { + "id": "BP.service1", + "text": "Servir sem esperar retorno libera o coração do peso do resultado.", + "kleshaTargets": [ + "raga", + "asmita" + ], + "qualities": [ + "snigdha", + "guru" + ], + "themes": [ + "serviço", + "entrega" + ] + }, + { + "id": "BP.service2", + "text": "O serviço ao outro é oração em movimento.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "serviço", + "oração" + ] + }, + { + "id": "BP.trust1", + "text": "Confiar no fluxo da vida não é passividade; é coragem.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "chala", + "ruksha" + ], + "themes": [ + "confiança", + "coragem" + ] + }, + { + "id": "BP.trust2", + "text": "O divino habita no coração de quem confia.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru" + ], + "themes": [ + "confiança", + "coração" + ] + }, + { + "id": "BP.silence1", + "text": "No silêncio da devoção, a resposta já está.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "chala", + "sukshma" + ], + "themes": [ + "silêncio", + "resposta" + ] + }, + { + "id": "BP.silence2", + "text": "Quem cala a mente ouve o que as palavras não dizem.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "chala" + ], + "themes": [ + "silêncio", + "mente" + ] + }, + { + "id": "BP.love1", + "text": "Amar sem posse é a única forma de não perder.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "snigdha", + "guru" + ], + "themes": [ + "amor", + "desapego" + ] + }, + { + "id": "BP.love2", + "text": "O amor divino não exige reciprocidade; ele simplesmente flui.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "sita", + "kathina" + ], + "themes": [ + "amor", + "fluir" + ] + }, + { + "id": "BP.release1", + "text": "Soltar não é desistir; é deixar o rio correr.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "picchila", + "sthira" + ], + "themes": [ + "soltar", + "fluir" + ] + }, + { + "id": "BP.release2", + "text": "O que você libera libera você.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "guru", + "picchila" + ], + "themes": [ + "libertação", + "perdão" + ] + }, + { + "id": "BP.presence1", + "text": "O divino está no agora; quem habita o passado ou o futuro o perde.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "chala" + ], + "themes": [ + "presença", + "agora" + ] + }, + { + "id": "BP.presence2", + "text": "Uma só respiração consciente é uma oração.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "chala", + "laghu" + ], + "themes": [ + "respiração", + "oração" + ] + }, + { + "id": "BP.witness1", + "text": "Quem observa sem julgar encontra paz.", + "kleshaTargets": [ + "dvesha", + "asmita" + ], + "qualities": [ + "tikshna", + "khara" + ], + "themes": [ + "testemunha", + "paz" + ] + }, + { + "id": "BP.witness2", + "text": "O testemunho compassivo dissolve a raiva.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "ushna", + "tikshna" + ], + "themes": [ + "compaixão", + "raiva" + ] + }, + { + "id": "BP.humility1", + "text": "A humildade não diminui; ela abre espaço para o infinito.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "tikshna", + "kathina" + ], + "themes": [ + "humildade", + "espaço" + ] + }, + { + "id": "BP.humility2", + "text": "Quem se esvazia é preenchido.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "humildade", + "entrega" + ] + }, + { + "id": "BP.grief1", + "text": "Chorar é permitir que o rio do coração encontre o mar.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "mridu" + ], + "themes": [ + "luto", + "corpo" + ] + }, + { + "id": "BP.grief2", + "text": "A tristeza honrada se transforma em compaixão.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "sandra" + ], + "themes": [ + "luto", + "compaixão" + ] + }, + { + "id": "BP.joy1", + "text": "A alegria que não depende do externo é estável.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "chala", + "laghu" + ], + "themes": [ + "alegria", + "estabilidade" + ] + }, + { + "id": "BP.joy2", + "text": "Celebrar o bem do outro é antídoto para a inveja.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "tikshna", + "ushna" + ], + "themes": [ + "alegria", + "inveja" + ] + }, + { + "id": "BP.patience1", + "text": "A paciência é força; a pressa é medo disfarçado.", + "kleshaTargets": [ + "raga", + "abhinivesha" + ], + "qualities": [ + "tikshna", + "chala" + ], + "themes": [ + "paciência", + "medo" + ] + }, + { + "id": "BP.patience2", + "text": "O que amadurece no tempo certo não apodrece.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "chala" + ], + "themes": [ + "paciência", + "tempo" + ] + }, + { + "id": "BP.simplicity1", + "text": "A simplicidade desfaz o nó da cobiça.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "guru", + "snigdha" + ], + "themes": [ + "simplicidade", + "cobiça" + ] + }, + { + "id": "BP.simplicity2", + "text": "Menos é o caminho para mais.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "simplicidade", + "suficiência" + ] + }, + { + "id": "BP.truth1", + "text": "A verdade libera; a mentira aprisiona.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "verdade", + "liberdade" + ] + }, + { + "id": "BP.truth2", + "text": "Falar a verdade com amor é arte.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "khara", + "tikshna" + ], + "themes": [ + "verdade", + "amor" + ] + }, + { + "id": "BP.rebirth1", + "text": "Cada respiração é chance de recomeçar.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "guru", + "picchila" + ], + "themes": [ + "recomeço", + "respiração" + ] + }, + { + "id": "BP.rebirth2", + "text": "O perdão é o único modo de nascer de novo sem morrer.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "picchila" + ], + "themes": [ + "perdão", + "renascimento" + ] + }, + { + "id": "BP.union1", + "text": "Quem vê o divino em todos não está nunca só.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "sita", + "sthira" + ], + "themes": [ + "unidade", + "companhia" + ] + }, + { + "id": "BP.union2", + "text": "A separação é ilusão; a união é a natureza do ser.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "unidade", + "identidade" + ] + }, + { + "id": "BP.grounding1", + "text": "Quem pisa a terra com consciência não cai.", + "kleshaTargets": [ + "chala" + ], + "qualities": [ + "chala", + "laghu" + ], + "themes": [ + "grounding", + "consciência" + ] + }, + { + "id": "BP.grounding2", + "text": "A raiz que sustenta não se vê; ela apenas nutre.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "sthira" + ], + "themes": [ + "grounding", + "sustento" + ] + }, + { + "id": "BP.breath1", + "text": "Uma respiração consciente une corpo e espírito.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "chala" + ], + "themes": [ + "respiração", + "corpo" + ] + }, + { + "id": "BP.breath2", + "text": "O sopro que entra e sai já é oração.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "laghu", + "vishada" + ], + "themes": [ + "respiração", + "oração" + ] + }, + { + "id": "BP.acceptance1", + "text": "Aceitar o que é não é resignação; é clareza.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "picchila", + "mridu" + ], + "themes": [ + "aceitação", + "clareza" + ] + }, + { + "id": "BP.acceptance2", + "text": "O que você aceita deixa de pesar.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "guru", + "snigdha" + ], + "themes": [ + "aceitação", + "leveza" + ] + }, + { + "id": "BP.grief_body", + "text": "A dor que é chorada não fica presa no corpo.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "drava", + "mridu" + ], + "themes": [ + "luto", + "corpo" + ] + }, + { + "id": "BP.grief_heart", + "text": "O coração que se abre ao luto aprende a abrir-se à alegria.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "sita", + "kathina" + ], + "themes": [ + "luto", + "alegria" + ] + }, + { + "id": "BP.solitude1", + "text": "Na solidão voluntária, o ruído interno se acalma.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "chala", + "vishada" + ], + "themes": [ + "solidão", + "silêncio" + ] + }, + { + "id": "BP.solitude2", + "text": "Quem se encontra sozinho não está só.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru" + ], + "themes": [ + "solidão", + "presença" + ] + }, + { + "id": "BP.burnout1", + "text": "Parar não é falhar; é permitir que a força volte.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "tikshna", + "ushna" + ], + "themes": [ + "descanso", + "força" + ] + }, + { + "id": "BP.burnout2", + "text": "O repouso é parte do caminho, não desvio.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "manda", + "mridu" + ], + "themes": [ + "repouso", + "caminho" + ] + }, + { + "id": "BP.anger1", + "text": "A raiva que é vista com compaixão perde o fogo.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "ushna", + "tikshna" + ], + "themes": [ + "raiva", + "compaixão" + ] + }, + { + "id": "BP.anger2", + "text": "Não apague a chama com mais chama; respire e deixe esfriar.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "tikshna", + "khara" + ], + "themes": [ + "raiva", + "resfriar" + ] + }, + { + "id": "BP.fear1", + "text": "O medo que é nomeado perde metade do poder.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "sukshma", + "chala" + ], + "themes": [ + "medo", + "nomear" + ] + }, + { + "id": "BP.fear2", + "text": "Quem aceita o medo não é governado por ele.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "mridu" + ], + "themes": [ + "medo", + "aceitação" + ] + }, + { + "id": "BP.doubt1", + "text": "A dúvida honesta é o início do discernimento.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "dúvida", + "discernimento" + ] + }, + { + "id": "BP.doubt2", + "text": "Não exija certeza de si; exija presença.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "chala", + "laghu" + ], + "themes": [ + "dúvida", + "presença" + ] + }, + { + "id": "BP.joy_inside", + "text": "A alegria que não depende do outro é inesgotável.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "snigdha", + "laghu" + ], + "themes": [ + "alegria", + "interior" + ] + }, + { + "id": "BP.joy_small", + "text": "Celebrar o pequeno é cultivar o grande.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "alegria", + "gratidão" + ] + }, + { + "id": "BP.boundaries1", + "text": "Dizer não é dizer sim a si mesmo.", + "kleshaTargets": [ + "asmita", + "raga" + ], + "qualities": [ + "kathina", + "sthira" + ], + "themes": [ + "limites", + "autocuidado" + ] + }, + { + "id": "BP.boundaries2", + "text": "Quem respeita os próprios limites pode expandir sem quebrar.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru" + ], + "themes": [ + "limites", + "expansão" + ] + }, + { + "id": "BP.nature1", + "text": "O céu e a terra não têm pressa; eles apenas são.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "sthira", + "manda" + ], + "themes": [ + "natureza", + "ritmo" + ] + }, + { + "id": "BP.nature2", + "text": "Caminhar na natureza é voltar à própria natureza.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "natureza", + "identidade" + ] + }, + { + "id": "BP.water1", + "text": "A água que flui não se prende; ela contorna e segue.", + "kleshaTargets": [ + "sthira" + ], + "qualities": [ + "sthira", + "drava" + ], + "themes": [ + "fluir", + "flexibilidade" + ] + }, + { + "id": "BP.water2", + "text": "Beber um gole de água com consciência é um ato de gratidão.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "sita", + "vishada" + ], + "themes": [ + "gratidão", + "consciência" + ] + }, + { + "id": "BP.speech1", + "text": "Antes de falar, pergunte: é verdadeiro, necessário e bondoso?", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "tikshna", + "khara" + ], + "themes": [ + "palavra", + "verdade" + ] + }, + { + "id": "BP.speech2", + "text": "O silêncio que escolhemos é mais eloqüente que as palavras.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "chala" + ], + "themes": [ + "silêncio", + "palavra" + ] + }, + { + "id": "BP.body1", + "text": "O corpo não é inimigo; é o veículo da alma.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "guru", + "snigdha" + ], + "themes": [ + "corpo", + "alma" + ] + }, + { + "id": "BP.body2", + "text": "Honrar o cansaço do corpo é honrar a vida.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "manda", + "mridu" + ], + "themes": [ + "corpo", + "descanso" + ] + }, + { + "id": "BP.dream1", + "text": "O que você sonha à noite o dia pode realizar.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "sukshma" + ], + "themes": [ + "sonho", + "realização" + ] + }, + { + "id": "BP.dream2", + "text": "Não despreze o sonho; ele fala a linguagem do coração.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "picchila", + "guru" + ], + "themes": [ + "sonho", + "coração" + ] + }, + { + "id": "BP.ancestors1", + "text": "Quem honra os que vieram antes não caminha sozinho.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "sthira" + ], + "themes": [ + "ancestrais", + "linhagem" + ] + }, + { + "id": "BP.ancestors2", + "text": "A linhagem não é peso; é raiz.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "linhagem", + "raiz" + ] + }, + { + "id": "BP.child1", + "text": "O olhar de uma criança lembra: o presente é agora.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "chala", + "laghu" + ], + "themes": [ + "presença", + "agora" + ] + }, + { + "id": "BP.child2", + "text": "Brincar não é fuga; é o modo do espírito respirar.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "drava", + "mridu" + ], + "themes": [ + "brincar", + "leveza" + ] + }, + { + "id": "BP.death1", + "text": "Lembrar a morte não é morrer; é viver com mais presença.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru" + ], + "themes": [ + "presença", + "morte" + ] + }, + { + "id": "BP.death2", + "text": "O que é impermanente merece cuidado, não apego.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "vishada", + "snigdha" + ], + "themes": [ + "impermanência", + "desapego" + ] + }, + { + "id": "BP.gratitude1", + "text": "A gratidão desloca o centro do que falta para o que já é.", + "kleshaTargets": [ + "raga", + "abhinivesha" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "gratidão", + "presença" + ] + }, + { + "id": "BP.gratitude2", + "text": "Agradecer ao corpo é o primeiro passo para habitá-lo.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "guru", + "snigdha" + ], + "themes": [ + "corpo", + "gratidão" + ] + }, + { + "id": "BP.breath3", + "text": "O sopro que você não controla lembra: algo maior respira em você.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "chala", + "sukshma" + ], + "themes": [ + "respiração", + "presença" + ] + }, + { + "id": "BP.grounding3", + "text": "Pés no chão, coração no céu; o meio é onde a vida acontece.", + "kleshaTargets": [ + "chala", + "abhinivesha" + ], + "qualities": [ + "laghu", + "sthira" + ], + "themes": [ + "grounding", + "presença" + ] + }, + { + "id": "BP.silence3", + "text": "No espaço entre dois pensamentos está o silêncio que cura.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "vishada", + "manda" + ], + "themes": [ + "silêncio", + "mente" + ] + }, + { + "id": "BP.boundaries3", + "text": "Quem diz sim a tudo diz não a si mesmo.", + "kleshaTargets": [ + "asmita", + "raga" + ], + "qualities": [ + "kathina", + "vishada" + ], + "themes": [ + "limites", + "autocuidado" + ] + }, + { + "id": "BP.anger3", + "text": "A raiva é mensageira; ouça o que ela traz antes de reagir.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "tikshna", + "ushna" + ], + "themes": [ + "raiva", + "escuta" + ] + }, + { + "id": "BP.fear3", + "text": "O medo que você nomeia perde a sombra; o que você esconde cresce.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "mridu" + ], + "themes": [ + "medo", + "presença" + ] + }, + { + "id": "BP.trust3", + "text": "Confiar não é não duvidar; é seguir mesmo quando a dúvida vem.", + "kleshaTargets": [ + "abhinivesha", + "avidya" + ], + "qualities": [ + "chala", + "vishada" + ], + "themes": [ + "confiança", + "dúvida" + ] + }, + { + "id": "BP.body3", + "text": "O corpo guarda o que a mente esquece; honre os dois.", + "kleshaTargets": [ + "asmita", + "abhinivesha" + ], + "qualities": [ + "guru", + "snigdha" + ], + "themes": [ + "corpo", + "memória" + ] + }, + { + "id": "BP.nature3", + "text": "A natureza não tem pressa; quem anda nela aprende o ritmo certo.", + "kleshaTargets": [ + "chala", + "raga" + ], + "qualities": [ + "manda", + "sthira" + ], + "themes": [ + "natureza", + "ritmo" + ] + }, + { + "id": "BP.speech3", + "text": "Antes de falar, pergunte: isso cura ou fere?", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "tikshna", + "mridu" + ], + "themes": [ + "palavra", + "verdade" + ] + }, + { + "id": "BP.rest2", + "text": "O repouso não é tempo perdido; é o tempo em que o corpo se refaz.", + "kleshaTargets": [ + "raga", + "asmita" + ], + "qualities": [ + "manda", + "mridu" + ], + "themes": [ + "descanso", + "corpo" + ] + }, + { + "id": "BP.union3", + "text": "Quem vê o divino no outro não precisa que o outro mude.", + "kleshaTargets": [ + "dvesha", + "asmita" + ], + "qualities": [ + "vishada", + "mridu" + ], + "themes": [ + "unidade", + "aceitação" + ] + }, + { + "id": "BP.presence3", + "text": "O agora é o único tempo em que você pode agir; o resto é história ou fantasia.", + "kleshaTargets": [ + "abhinivesha", + "raga" + ], + "qualities": [ + "chala", + "laghu" + ], + "themes": [ + "presença", + "agora" + ] + }, + { + "id": "BP.release3", + "text": "Soltar o resultado não é desistir; é fazer o que cabe a você e deixar o resto.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "picchila", + "vishada" + ], + "themes": [ + "entrega", + "ação" + ] + }, + { + "id": "BP.doubt3", + "text": "A dúvida honesta abre porta; a certeza cega fecha.", + "kleshaTargets": [ + "avidya", + "asmita" + ], + "qualities": [ + "vishada", + "tikshna" + ], + "themes": [ + "dúvida", + "discernimento" + ] + }, + { + "id": "BP.joy3", + "text": "A alegria que nasce de dentro não depende do que vem de fora.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "laghu", + "vishada" + ], + "themes": [ + "alegria", + "interior" + ] + }, + { + "id": "BP.grief3", + "text": "Chorar é deixar a dor sair pelo único caminho que ela conhece.", + "kleshaTargets": [ + "abhinivesha", + "dvesha" + ], + "qualities": [ + "drava", + "mridu" + ], + "themes": [ + "luto", + "corpo" + ] + }, + { + "id": "BP.humility3", + "text": "A humildade não é pensar menos de si; é pensar em si menos.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "humildade", + "ego" + ] + }, + { + "id": "BP.witness3", + "text": "Quem observa a mente sem se identificar com ela encontra espaço.", + "kleshaTargets": [ + "avidya", + "asmita" + ], + "qualities": [ + "vishada", + "sukshma" + ], + "themes": [ + "testemunha", + "mente" + ] + }, + { + "id": "BP.acceptance3", + "text": "Aceitar o que é não é passividade; é ver com clareza para agir com sabedoria.", + "kleshaTargets": [ + "dvesha", + "raga" + ], + "qualities": [ + "picchila", + "mridu" + ], + "themes": [ + "aceitação", + "clareza" + ] + }, + { + "id": "BP.simplicity3", + "text": "A simplicidade é o luxo de quem não precisa provar nada.", + "kleshaTargets": [ + "raga", + "asmita" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "simplicidade", + "suficiência" + ] + }, + { + "id": "BP.truth3", + "text": "A verdade que libera pode doer no início; a mentira que conforta aprisiona no fim.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "tikshna" + ], + "themes": [ + "verdade", + "liberdade" + ] + }, + { + "id": "BP.med105", + "text": "O que você oferece ao divino deixa de pesar em você.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "guru", + "snigdha" + ], + "themes": [ + "entrega", + "ação" + ] + }, + { + "id": "BP.med106", + "text": "Quem honra o ritmo do corpo não adoece de pressa.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "manda", + "sthira" + ], + "themes": [ + "corpo", + "tempo" + ] + }, + { + "id": "BP.med107", + "text": "A palavra que acalma é mais forte que a que fere.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "mridu", + "tikshna" + ], + "themes": [ + "palavra", + "compaixão" + ] + }, + { + "id": "BP.med108", + "text": "O silêncio após a oração é onde a resposta habita.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "chala", + "vishada" + ], + "themes": [ + "silêncio", + "oração" + ] + }, + { + "id": "BP.med109", + "text": "Aceitar a impermanência é o primeiro passo para a paz.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "picchila", + "mridu" + ], + "themes": [ + "aceitação", + "paz" + ] + }, + { + "id": "BP.med110", + "text": "Servir sem esperar reconhecimento libera o ego.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada", + "snigdha" + ], + "themes": [ + "serviço", + "humildade" + ] + }, + { + "id": "BP.med111", + "text": "A raiva que é respirada perde o controle sobre você.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "ushna", + "tikshna" + ], + "themes": [ + "raiva", + "respiração" + ] + }, + { + "id": "BP.med112", + "text": "O corpo que descansa se renova; o que não para se quebra.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "manda", + "mridu" + ], + "themes": [ + "corpo", + "sono" + ] + }, + { + "id": "BP.med113", + "text": "Quem vê o divino no outro não precisa que o outro mude.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "vishada", + "mridu" + ], + "themes": [ + "unidade", + "aceitação" + ] + }, + { + "id": "BP.med114", + "text": "A gratidão desloca o foco do que falta para o que já é.", + "kleshaTargets": [ + "raga", + "abhinivesha" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "gratidão", + "presença" + ] + }, + { + "id": "BP.med115", + "text": "O medo nomeado perde metade da sombra.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "sukshma", + "chala" + ], + "themes": [ + "medo", + "presença" + ] + }, + { + "id": "BP.med116", + "text": "A humildade não diminui; abre espaço para o infinito.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "tikshna", + "kathina" + ], + "themes": [ + "humildade", + "ego" + ] + }, + { + "id": "BP.med117", + "text": "Caminhar descalço na terra ancora a mente no agora.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "sthira", + "laghu" + ], + "themes": [ + "grounding", + "natureza" + ] + }, + { + "id": "BP.med118", + "text": "O perdão que você dá a si mesmo é o que libera.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "picchila", + "guru" + ], + "themes": [ + "perdão", + "liberação" + ] + }, + { + "id": "BP.med119", + "text": "Comer com consciência é oração que nutre o corpo.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "sita", + "vishada" + ], + "themes": [ + "alimentação", + "consciência" + ] + }, + { + "id": "BP.med120", + "text": "Dizer não é dizer sim a si mesmo.", + "kleshaTargets": [ + "asmita", + "raga" + ], + "qualities": [ + "kathina", + "sthira" + ], + "themes": [ + "limites", + "autocuidado" + ] + }, + { + "id": "BP.med121", + "text": "A dúvida honesta é o início do discernimento.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "dúvida", + "discernimento" + ] + }, + { + "id": "BP.med122", + "text": "O amor que não exige reciprocidade simplesmente flui.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "sita", + "kathina" + ], + "themes": [ + "amor", + "fluir" + ] + }, + { + "id": "BP.med123", + "text": "Lembrar a morte não é morrer; é viver com mais presença.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru" + ], + "themes": [ + "presença", + "morte" + ] + }, + { + "id": "BP.med124", + "text": "O repouso é parte do caminho, não desvio.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "manda", + "mridu" + ], + "themes": [ + "rotina", + "descanso" + ] + }, + { + "id": "BP.med125", + "text": "A verdade que libera pode doer no início.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "tikshna" + ], + "themes": [ + "verdade", + "liberdade" + ] + }, + { + "id": "BP.med126", + "text": "Quem observa a mente sem se identificar encontra espaço.", + "kleshaTargets": [ + "avidya", + "asmita" + ], + "qualities": [ + "vishada", + "sukshma" + ], + "themes": [ + "testemunha", + "mente" + ] + }, + { + "id": "BP.med127", + "text": "A alegria que nasce de dentro não depende do externo.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "laghu", + "vishada" + ], + "themes": [ + "alegria", + "interior" + ] + }, + { + "id": "BP.med128", + "text": "Chorar é deixar a dor sair pelo único caminho que ela conhece.", + "kleshaTargets": [ + "abhinivesha", + "dvesha" + ], + "qualities": [ + "drava", + "mridu" + ], + "themes": [ + "luto", + "corpo" + ] + }, + { + "id": "BP.med129", + "text": "Confiar no fluxo não é passividade; é coragem.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "chala", + "ruksha" + ], + "themes": [ + "confiança", + "coragem" + ] + }, + { + "id": "BP.med130", + "text": "O sopro que entra e sai já é oração.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "laghu", + "vishada" + ], + "themes": [ + "respiração", + "oração" + ] + }, + { + "id": "BP.med131", + "text": "A natureza não tem pressa; quem anda nela aprende o ritmo.", + "kleshaTargets": [ + "raga", + "abhinivesha" + ], + "qualities": [ + "manda", + "sthira" + ], + "themes": [ + "natureza", + "ritmo" + ] + }, + { + "id": "BP.med132", + "text": "Antes de falar, pergunte: é verdadeiro, necessário e bondoso?", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "tikshna", + "khara" + ], + "themes": [ + "palavra", + "verdade" + ] + }, + { + "id": "BP.med133", + "text": "O corpo guarda o que a mente esquece; honre os dois.", + "kleshaTargets": [ + "asmita", + "abhinivesha" + ], + "qualities": [ + "guru", + "snigdha" + ], + "themes": [ + "corpo", + "memória" + ] + }, + { + "id": "BP.med134", + "text": "A simplicidade é o luxo de quem não precisa provar nada.", + "kleshaTargets": [ + "raga", + "asmita" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "simplicidade", + "suficiência" + ] + }, + { + "id": "BP.med135", + "text": "Quem se esvazia é preenchido.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "humildade", + "entrega" + ] + }, + { + "id": "BP.med136", + "text": "A paz que nasce da devoção não depende do mundo.", + "kleshaTargets": [ + "raga", + "dvesha" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "paz", + "devoção" + ] + }, + { + "id": "BP.med137", + "text": "Proteger o coração não é fechar; é escolher o que entra.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "sukshma", + "chala" + ], + "themes": [ + "proteção", + "limites" + ] + }, + { + "id": "BP.med138", + "text": "O descanso é dharma; quem se entrega ao repouso se renova.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "mridu" + ], + "themes": [ + "descanso", + "renovação" + ] + }, + { + "id": "BP.med139", + "text": "Abrir o coração não é fraqueza; é coragem de sentir.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "sita", + "kathina" + ], + "themes": [ + "coração", + "coragem" + ] + }, + { + "id": "BP.med140", + "text": "A graça não escolhe merecimento; ela escolhe o momento.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "kathina" + ], + "themes": [ + "graça", + "humildade" + ] + }, + { + "id": "BP.med141", + "text": "Quando o coração está quebrado, a luz entra por onde não havia porta.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "mridu" + ], + "themes": [ + "graça", + "luz" + ] + }, + { + "id": "BP.med142", + "text": "O serviço ao outro é oração em movimento.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "serviço", + "oração" + ] + }, + { + "id": "BP.med143", + "text": "No silêncio da devoção, a resposta já está.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "chala", + "sukshma" + ], + "themes": [ + "silêncio", + "resposta" + ] + }, + { + "id": "BP.med144", + "text": "Quem cala a mente ouve o que as palavras não dizem.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "chala" + ], + "themes": [ + "silêncio", + "mente" + ] + }, + { + "id": "BP.med145", + "text": "Amar sem posse é a única forma de não perder.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "snigdha", + "guru" + ], + "themes": [ + "amor", + "desapego" + ] + }, + { + "id": "BP.med146", + "text": "Soltar não é desistir; é deixar o rio correr.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "picchila", + "sthira" + ], + "themes": [ + "soltar", + "fluir" + ] + }, + { + "id": "BP.med147", + "text": "O que você libera libera você.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "guru", + "picchila" + ], + "themes": [ + "libertação", + "perdão" + ] + }, + { + "id": "BP.med148", + "text": "O divino está no agora; quem habita o passado ou o futuro o perde.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "chala" + ], + "themes": [ + "presença", + "agora" + ] + }, + { + "id": "BP.med149", + "text": "Quem observa sem julgar encontra paz.", + "kleshaTargets": [ + "dvesha", + "asmita" + ], + "qualities": [ + "tikshna", + "khara" + ], + "themes": [ + "testemunha", + "paz" + ] + }, + { + "id": "BP.med150", + "text": "O testemunho compassivo dissolve a raiva.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "ushna", + "tikshna" + ], + "themes": [ + "compaixão", + "raiva" + ] + }, + { + "id": "BP.med151", + "text": "Chorar é permitir que o rio do coração encontre o mar.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "mridu" + ], + "themes": [ + "luto", + "corpo" + ] + }, + { + "id": "BP.med152", + "text": "A tristeza honrada se transforma em compaixão.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "sandra" + ], + "themes": [ + "luto", + "compaixão" + ] + }, + { + "id": "BP.med153", + "text": "A alegria que não depende do externo é estável.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "chala", + "laghu" + ], + "themes": [ + "alegria", + "estabilidade" + ] + }, + { + "id": "BP.med154", + "text": "Celebrar o bem do outro é antídoto para a inveja.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "tikshna", + "ushna" + ], + "themes": [ + "alegria", + "inveja" + ] + }, + { + "id": "BP.med155", + "text": "A paciência é força; a pressa é medo disfarçado.", + "kleshaTargets": [ + "raga", + "abhinivesha" + ], + "qualities": [ + "tikshna", + "chala" + ], + "themes": [ + "paciência", + "medo" + ] + }, + { + "id": "BP.med156", + "text": "O que amadurece no tempo certo não apodrece.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "chala" + ], + "themes": [ + "paciência", + "tempo" + ] + }, + { + "id": "BP.med157", + "text": "A simplicidade desfaz o nó da cobiça.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "guru", + "snigdha" + ], + "themes": [ + "simplicidade", + "cobiça" + ] + }, + { + "id": "BP.med158", + "text": "Menos é o caminho para mais.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "simplicidade", + "suficiência" + ] + }, + { + "id": "BP.med159", + "text": "A verdade libera; a mentira aprisiona.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "verdade", + "liberdade" + ] + }, + { + "id": "BP.med160", + "text": "Falar a verdade com amor é arte.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "khara", + "tikshna" + ], + "themes": [ + "verdade", + "amor" + ] + }, + { + "id": "BP.med161", + "text": "Cada respiração é chance de recomeçar.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "guru", + "picchila" + ], + "themes": [ + "recomeço", + "respiração" + ] + }, + { + "id": "BP.med162", + "text": "O perdão é o único modo de nascer de novo sem morrer.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "picchila" + ], + "themes": [ + "perdão", + "renascimento" + ] + }, + { + "id": "BP.med163", + "text": "Quem vê o divino em todos não está nunca só.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "sita", + "sthira" + ], + "themes": [ + "unidade", + "companhia" + ] + }, + { + "id": "BP.med164", + "text": "A separação é ilusão; a união é a natureza do ser.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "unidade", + "identidade" + ] + }, + { + "id": "BP.med165", + "text": "Quem pisa a terra com consciência não cai.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "chala", + "laghu" + ], + "themes": [ + "grounding", + "consciência" + ] + }, + { + "id": "BP.med166", + "text": "Uma respiração consciente une corpo e espírito.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "chala" + ], + "themes": [ + "respiração", + "corpo" + ] + }, + { + "id": "BP.med167", + "text": "Aceitar o que é não é resignação; é clareza.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "picchila", + "mridu" + ], + "themes": [ + "aceitação", + "clareza" + ] + }, + { + "id": "BP.med168", + "text": "Na solidão voluntária, o ruído interno se acalma.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "chala", + "vishada" + ], + "themes": [ + "solidão", + "silêncio" + ] + }, + { + "id": "BP.med169", + "text": "Quem se encontra sozinho não está só.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru" + ], + "themes": [ + "solidão", + "presença" + ] + }, + { + "id": "BP.med170", + "text": "Parar não é falhar; é permitir que a força volte.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "tikshna", + "ushna" + ], + "themes": [ + "descanso", + "força" + ] + }, + { + "id": "BP.med171", + "text": "A raiva que é vista com compaixão perde o fogo.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "ushna", + "tikshna" + ], + "themes": [ + "raiva", + "compaixão" + ] + }, + { + "id": "BP.med172", + "text": "Não apague a chama com mais chama; respire e deixe esfriar.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "tikshna", + "khara" + ], + "themes": [ + "raiva", + "resfriar" + ] + }, + { + "id": "BP.med173", + "text": "Quem aceita o medo não é governado por ele.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "mridu" + ], + "themes": [ + "medo", + "aceitação" + ] + }, + { + "id": "BP.med174", + "text": "Não exija certeza de si; exija presença.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "chala", + "laghu" + ], + "themes": [ + "dúvida", + "presença" + ] + }, + { + "id": "BP.med175", + "text": "Quem respeita os próprios limites pode expandir sem quebrar.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru" + ], + "themes": [ + "limites", + "expansão" + ] + }, + { + "id": "BP.med176", + "text": "Caminhar na natureza é voltar à própria natureza.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "natureza", + "identidade" + ] + }, + { + "id": "BP.med177", + "text": "A água que flui não se prende; ela contorna e segue.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "sthira", + "drava" + ], + "themes": [ + "fluir", + "flexibilidade" + ] + }, + { + "id": "BP.med178", + "text": "Beber um gole de água com consciência é um ato de gratidão.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "sita", + "vishada" + ], + "themes": [ + "gratidão", + "consciência" + ] + }, + { + "id": "BP.med179", + "text": "O silêncio que escolhemos é mais eloqüente que as palavras.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "chala" + ], + "themes": [ + "silêncio", + "palavra" + ] + }, + { + "id": "BP.med180", + "text": "O corpo não é inimigo; é o veículo da alma.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "guru", + "snigdha" + ], + "themes": [ + "corpo", + "alma" + ] + }, + { + "id": "BP.med181", + "text": "Honrar o cansaço do corpo é honrar a vida.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "manda", + "mridu" + ], + "themes": [ + "corpo", + "descanso" + ] + }, + { + "id": "BP.med182", + "text": "O que você sonha à noite o dia pode realizar.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "sukshma" + ], + "themes": [ + "sonho", + "realização" + ] + }, + { + "id": "BP.med183", + "text": "Não despreze o sonho; ele fala a linguagem do coração.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "picchila", + "guru" + ], + "themes": [ + "sonho", + "coração" + ] + }, + { + "id": "BP.med184", + "text": "Quem honra os que vieram antes não caminha sozinho.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "sthira" + ], + "themes": [ + "ancestrais", + "linhagem" + ] + }, + { + "id": "BP.med185", + "text": "A linhagem não é peso; é raiz.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "linhagem", + "raiz" + ] + }, + { + "id": "BP.med186", + "text": "O olhar de uma criança lembra: o presente é agora.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "chala", + "laghu" + ], + "themes": [ + "presença", + "agora" + ] + }, + { + "id": "BP.med187", + "text": "Brincar não é fuga; é o modo do espírito respirar.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "drava", + "mridu" + ], + "themes": [ + "brincar", + "leveza" + ] + }, + { + "id": "BP.med188", + "text": "O que é impermanente merece cuidado, não apego.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "vishada", + "snigdha" + ], + "themes": [ + "impermanência", + "desapego" + ] + }, + { + "id": "BP.med189", + "text": "Agradecer ao corpo é o primeiro passo para habitá-lo.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "guru", + "snigdha" + ], + "themes": [ + "corpo", + "gratidão" + ] + }, + { + "id": "BP.med190", + "text": "O sopro que você não controla lembra: algo maior respira em você.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "chala", + "sukshma" + ], + "themes": [ + "respiração", + "presença" + ] + }, + { + "id": "BP.med191", + "text": "Pés no chão, coração no céu; o meio é onde a vida acontece.", + "kleshaTargets": [ + "abhinivesha", + "raga" + ], + "qualities": [ + "laghu", + "sthira" + ], + "themes": [ + "grounding", + "presença" + ] + }, + { + "id": "BP.med192", + "text": "No espaço entre dois pensamentos está o silêncio que cura.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "vishada", + "manda" + ], + "themes": [ + "silêncio", + "mente" + ] + }, + { + "id": "BP.med193", + "text": "Quem diz sim a tudo diz não a si mesmo.", + "kleshaTargets": [ + "asmita", + "raga" + ], + "qualities": [ + "kathina", + "vishada" + ], + "themes": [ + "limites", + "autocuidado" + ] + }, + { + "id": "BP.med194", + "text": "A raiva é mensageira; ouça o que ela traz antes de reagir.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "tikshna", + "ushna" + ], + "themes": [ + "raiva", + "escuta" + ] + }, + { + "id": "BP.med195", + "text": "O medo que você nomeia perde a sombra; o que você esconde cresce.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "mridu" + ], + "themes": [ + "medo", + "presença" + ] + }, + { + "id": "BP.med196", + "text": "Confiar não é não duvidar; é seguir mesmo quando a dúvida vem.", + "kleshaTargets": [ + "abhinivesha", + "avidya" + ], + "qualities": [ + "chala", + "vishada" + ], + "themes": [ + "confiança", + "dúvida" + ] + }, + { + "id": "BP.med197", + "text": "Antes de falar, pergunte: isso cura ou fere?", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "tikshna", + "mridu" + ], + "themes": [ + "palavra", + "verdade" + ] + }, + { + "id": "BP.med198", + "text": "O repouso não é tempo perdido; é o tempo em que o corpo se refaz.", + "kleshaTargets": [ + "raga", + "asmita" + ], + "qualities": [ + "manda", + "mridu" + ], + "themes": [ + "descanso", + "corpo" + ] + }, + { + "id": "BP.med199", + "text": "Soltar o resultado não é desistir; é fazer o que cabe a você e deixar o resto.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "picchila", + "vishada" + ], + "themes": [ + "entrega", + "ação" + ] + }, + { + "id": "BP.med200", + "text": "A dúvida honesta abre porta; a certeza cega fecha.", + "kleshaTargets": [ + "avidya", + "asmita" + ], + "qualities": [ + "vishada", + "tikshna" + ], + "themes": [ + "dúvida", + "discernimento" + ] + }, + { + "id": "BP.med201", + "text": "A humildade não é pensar menos de si; é pensar em si menos.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "humildade", + "ego" + ] + }, + { + "id": "BP.med202", + "text": "Aceitar o que é não é passividade; é ver com clareza para agir com sabedoria.", + "kleshaTargets": [ + "dvesha", + "raga" + ], + "qualities": [ + "picchila", + "mridu" + ], + "themes": [ + "aceitação", + "clareza" + ] + }, + { + "id": "BP.med203", + "text": "O que você oferece ao divino deixa de pesar em você.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "guru", + "snigdha" + ], + "themes": [ + "entrega", + "ação" + ] + }, + { + "id": "BP.med204", + "text": "Quem honra o ritmo do corpo não adoece de pressa.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "manda", + "sthira" + ], + "themes": [ + "corpo", + "tempo" + ] + }, + { + "id": "BP.med205", + "text": "A palavra que acalma é mais forte que a que fere.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "mridu", + "tikshna" + ], + "themes": [ + "palavra", + "compaixão" + ] + }, + { + "id": "BP.med206", + "text": "O silêncio após a oração é onde a resposta habita.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "chala", + "vishada" + ], + "themes": [ + "silêncio", + "oração" + ] + }, + { + "id": "BP.med207", + "text": "Aceitar a impermanência é o primeiro passo para a paz.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "picchila", + "mridu" + ], + "themes": [ + "aceitação", + "paz" + ] + }, + { + "id": "BP.med208", + "text": "Servir sem esperar reconhecimento libera o ego.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada", + "snigdha" + ], + "themes": [ + "serviço", + "humildade" + ] + }, + { + "id": "BP.med209", + "text": "A raiva que é respirada perde o controle sobre você.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "ushna", + "tikshna" + ], + "themes": [ + "raiva", + "respiração" + ] + }, + { + "id": "BP.med210", + "text": "O corpo que descansa se renova; o que não para se quebra.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "manda", + "mridu" + ], + "themes": [ + "corpo", + "sono" + ] + }, + { + "id": "BP.med211", + "text": "Quem vê o divino no outro não precisa que o outro mude.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "vishada", + "mridu" + ], + "themes": [ + "unidade", + "aceitação" + ] + }, + { + "id": "BP.med212", + "text": "A gratidão desloca o foco do que falta para o que já é.", + "kleshaTargets": [ + "raga", + "abhinivesha" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "gratidão", + "presença" + ] + }, + { + "id": "BP.med213", + "text": "O medo nomeado perde metade da sombra.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "sukshma", + "chala" + ], + "themes": [ + "medo", + "presença" + ] + }, + { + "id": "BP.med214", + "text": "A humildade não diminui; abre espaço para o infinito.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "tikshna", + "kathina" + ], + "themes": [ + "humildade", + "ego" + ] + }, + { + "id": "BP.med215", + "text": "Caminhar descalço na terra ancora a mente no agora.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "sthira", + "laghu" + ], + "themes": [ + "grounding", + "natureza" + ] + }, + { + "id": "BP.med216", + "text": "O perdão que você dá a si mesmo é o que libera.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "picchila", + "guru" + ], + "themes": [ + "perdão", + "liberação" + ] + }, + { + "id": "BP.med217", + "text": "Comer com consciência é oração que nutre o corpo.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "sita", + "vishada" + ], + "themes": [ + "alimentação", + "consciência" + ] + }, + { + "id": "BP.med218", + "text": "Dizer não é dizer sim a si mesmo.", + "kleshaTargets": [ + "asmita", + "raga" + ], + "qualities": [ + "kathina", + "sthira" + ], + "themes": [ + "limites", + "autocuidado" + ] + }, + { + "id": "BP.med219", + "text": "A dúvida honesta é o início do discernimento.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "dúvida", + "discernimento" + ] + }, + { + "id": "BP.med220", + "text": "O amor que não exige reciprocidade simplesmente flui.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "sita", + "kathina" + ], + "themes": [ + "amor", + "fluir" + ] + }, + { + "id": "BP.med221", + "text": "Lembrar a morte não é morrer; é viver com mais presença.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru" + ], + "themes": [ + "presença", + "morte" + ] + }, + { + "id": "BP.med222", + "text": "O repouso é parte do caminho, não desvio.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "manda", + "mridu" + ], + "themes": [ + "rotina", + "descanso" + ] + }, + { + "id": "BP.med223", + "text": "A verdade que libera pode doer no início.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "tikshna" + ], + "themes": [ + "verdade", + "liberdade" + ] + }, + { + "id": "BP.med224", + "text": "Quem observa a mente sem se identificar encontra espaço.", + "kleshaTargets": [ + "avidya", + "asmita" + ], + "qualities": [ + "vishada", + "sukshma" + ], + "themes": [ + "testemunha", + "mente" + ] + }, + { + "id": "BP.med225", + "text": "A alegria que nasce de dentro não depende do externo.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "laghu", + "vishada" + ], + "themes": [ + "alegria", + "interior" + ] + }, + { + "id": "BP.med226", + "text": "Chorar é deixar a dor sair pelo único caminho que ela conhece.", + "kleshaTargets": [ + "abhinivesha", + "dvesha" + ], + "qualities": [ + "drava", + "mridu" + ], + "themes": [ + "luto", + "corpo" + ] + }, + { + "id": "BP.med227", + "text": "Confiar no fluxo não é passividade; é coragem.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "chala", + "ruksha" + ], + "themes": [ + "confiança", + "coragem" + ] + }, + { + "id": "BP.med228", + "text": "O sopro que entra e sai já é oração.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "laghu", + "vishada" + ], + "themes": [ + "respiração", + "oração" + ] + }, + { + "id": "BP.med229", + "text": "A natureza não tem pressa; quem anda nela aprende o ritmo.", + "kleshaTargets": [ + "raga", + "abhinivesha" + ], + "qualities": [ + "manda", + "sthira" + ], + "themes": [ + "natureza", + "ritmo" + ] + }, + { + "id": "BP.med230", + "text": "Antes de falar, pergunte: é verdadeiro, necessário e bondoso?", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "tikshna", + "khara" + ], + "themes": [ + "palavra", + "verdade" + ] + }, + { + "id": "BP.med231", + "text": "O corpo guarda o que a mente esquece; honre os dois.", + "kleshaTargets": [ + "asmita", + "abhinivesha" + ], + "qualities": [ + "guru", + "snigdha" + ], + "themes": [ + "corpo", + "memória" + ] + }, + { + "id": "BP.med232", + "text": "A simplicidade é o luxo de quem não precisa provar nada.", + "kleshaTargets": [ + "raga", + "asmita" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "simplicidade", + "suficiência" + ] + }, + { + "id": "BP.med233", + "text": "Quem se esvazia é preenchido.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "humildade", + "entrega" + ] + }, + { + "id": "BP.med234", + "text": "A paz que nasce da devoção não depende do mundo.", + "kleshaTargets": [ + "raga", + "dvesha" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "paz", + "devoção" + ] + }, + { + "id": "BP.med235", + "text": "Proteger o coração não é fechar; é escolher o que entra.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "sukshma", + "chala" + ], + "themes": [ + "proteção", + "limites" + ] + }, + { + "id": "BP.med236", + "text": "O descanso é dharma; quem se entrega ao repouso se renova.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "mridu" + ], + "themes": [ + "descanso", + "renovação" + ] + }, + { + "id": "BP.med237", + "text": "Abrir o coração não é fraqueza; é coragem de sentir.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "sita", + "kathina" + ], + "themes": [ + "coração", + "coragem" + ] + }, + { + "id": "BP.med238", + "text": "A graça não escolhe merecimento; ela escolhe o momento.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "kathina" + ], + "themes": [ + "graça", + "humildade" + ] + }, + { + "id": "BP.med239", + "text": "Quando o coração está quebrado, a luz entra por onde não havia porta.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "mridu" + ], + "themes": [ + "graça", + "luz" + ] + }, + { + "id": "BP.med240", + "text": "O serviço ao outro é oração em movimento.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "serviço", + "oração" + ] + }, + { + "id": "BP.med241", + "text": "No silêncio da devoção, a resposta já está.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "chala", + "sukshma" + ], + "themes": [ + "silêncio", + "resposta" + ] + }, + { + "id": "BP.med242", + "text": "Quem cala a mente ouve o que as palavras não dizem.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "chala" + ], + "themes": [ + "silêncio", + "mente" + ] + }, + { + "id": "BP.med243", + "text": "Amar sem posse é a única forma de não perder.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "snigdha", + "guru" + ], + "themes": [ + "amor", + "desapego" + ] + }, + { + "id": "BP.med244", + "text": "Soltar não é desistir; é deixar o rio correr.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "picchila", + "sthira" + ], + "themes": [ + "soltar", + "fluir" + ] + }, + { + "id": "BP.med245", + "text": "O que você libera libera você.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "guru", + "picchila" + ], + "themes": [ + "libertação", + "perdão" + ] + }, + { + "id": "BP.med246", + "text": "O divino está no agora; quem habita o passado ou o futuro o perde.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "chala" + ], + "themes": [ + "presença", + "agora" + ] + }, + { + "id": "BP.med247", + "text": "Quem observa sem julgar encontra paz.", + "kleshaTargets": [ + "dvesha", + "asmita" + ], + "qualities": [ + "tikshna", + "khara" + ], + "themes": [ + "testemunha", + "paz" + ] + }, + { + "id": "BP.med248", + "text": "O testemunho compassivo dissolve a raiva.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "ushna", + "tikshna" + ], + "themes": [ + "compaixão", + "raiva" + ] + }, + { + "id": "BP.med249", + "text": "Chorar é permitir que o rio do coração encontre o mar.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "mridu" + ], + "themes": [ + "luto", + "corpo" + ] + }, + { + "id": "BP.med250", + "text": "A tristeza honrada se transforma em compaixão.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "sandra" + ], + "themes": [ + "luto", + "compaixão" + ] + }, + { + "id": "BP.med251", + "text": "A alegria que não depende do externo é estável.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "chala", + "laghu" + ], + "themes": [ + "alegria", + "estabilidade" + ] + }, + { + "id": "BP.med252", + "text": "Celebrar o bem do outro é antídoto para a inveja.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "tikshna", + "ushna" + ], + "themes": [ + "alegria", + "inveja" + ] + }, + { + "id": "BP.med253", + "text": "A paciência é força; a pressa é medo disfarçado.", + "kleshaTargets": [ + "raga", + "abhinivesha" + ], + "qualities": [ + "tikshna", + "chala" + ], + "themes": [ + "paciência", + "medo" + ] + }, + { + "id": "BP.med254", + "text": "O que amadurece no tempo certo não apodrece.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "chala" + ], + "themes": [ + "paciência", + "tempo" + ] + }, + { + "id": "BP.med255", + "text": "A simplicidade desfaz o nó da cobiça.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "guru", + "snigdha" + ], + "themes": [ + "simplicidade", + "cobiça" + ] + }, + { + "id": "BP.med256", + "text": "Menos é o caminho para mais.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "simplicidade", + "suficiência" + ] + }, + { + "id": "BP.med257", + "text": "A verdade libera; a mentira aprisiona.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "verdade", + "liberdade" + ] + }, + { + "id": "BP.med258", + "text": "Falar a verdade com amor é arte.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "khara", + "tikshna" + ], + "themes": [ + "verdade", + "amor" + ] + }, + { + "id": "BP.med259", + "text": "Cada respiração é chance de recomeçar.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "guru", + "picchila" + ], + "themes": [ + "recomeço", + "respiração" + ] + }, + { + "id": "BP.med260", + "text": "O perdão é o único modo de nascer de novo sem morrer.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "picchila" + ], + "themes": [ + "perdão", + "renascimento" + ] + }, + { + "id": "BP.med261", + "text": "Quem vê o divino em todos não está nunca só.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "sita", + "sthira" + ], + "themes": [ + "unidade", + "companhia" + ] + }, + { + "id": "BP.med262", + "text": "A separação é ilusão; a união é a natureza do ser.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "unidade", + "identidade" + ] + }, + { + "id": "BP.med263", + "text": "Quem pisa a terra com consciência não cai.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "chala", + "laghu" + ], + "themes": [ + "grounding", + "consciência" + ] + }, + { + "id": "BP.med264", + "text": "Uma respiração consciente une corpo e espírito.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "chala" + ], + "themes": [ + "respiração", + "corpo" + ] + }, + { + "id": "BP.med265", + "text": "Aceitar o que é não é resignação; é clareza.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "picchila", + "mridu" + ], + "themes": [ + "aceitação", + "clareza" + ] + }, + { + "id": "BP.med266", + "text": "Na solidão voluntária, o ruído interno se acalma.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "chala", + "vishada" + ], + "themes": [ + "solidão", + "silêncio" + ] + }, + { + "id": "BP.med267", + "text": "Quem se encontra sozinho não está só.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru" + ], + "themes": [ + "solidão", + "presença" + ] + }, + { + "id": "BP.med268", + "text": "Parar não é falhar; é permitir que a força volte.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "tikshna", + "ushna" + ], + "themes": [ + "descanso", + "força" + ] + }, + { + "id": "BP.med269", + "text": "A raiva que é vista com compaixão perde o fogo.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "ushna", + "tikshna" + ], + "themes": [ + "raiva", + "compaixão" + ] + }, + { + "id": "BP.med270", + "text": "Não apague a chama com mais chama; respire e deixe esfriar.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "tikshna", + "khara" + ], + "themes": [ + "raiva", + "resfriar" + ] + }, + { + "id": "BP.med271", + "text": "Quem aceita o medo não é governado por ele.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "mridu" + ], + "themes": [ + "medo", + "aceitação" + ] + }, + { + "id": "BP.med272", + "text": "Não exija certeza de si; exija presença.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "chala", + "laghu" + ], + "themes": [ + "dúvida", + "presença" + ] + }, + { + "id": "BP.med273", + "text": "Quem respeita os próprios limites pode expandir sem quebrar.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru" + ], + "themes": [ + "limites", + "expansão" + ] + }, + { + "id": "BP.med274", + "text": "Caminhar na natureza é voltar à própria natureza.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "natureza", + "identidade" + ] + }, + { + "id": "BP.med275", + "text": "A água que flui não se prende; ela contorna e segue.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "sthira", + "drava" + ], + "themes": [ + "fluir", + "flexibilidade" + ] + }, + { + "id": "BP.med276", + "text": "Beber um gole de água com consciência é um ato de gratidão.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "sita", + "vishada" + ], + "themes": [ + "gratidão", + "consciência" + ] + }, + { + "id": "BP.med277", + "text": "O silêncio que escolhemos é mais eloqüente que as palavras.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "chala" + ], + "themes": [ + "silêncio", + "palavra" + ] + }, + { + "id": "BP.med278", + "text": "O corpo não é inimigo; é o veículo da alma.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "guru", + "snigdha" + ], + "themes": [ + "corpo", + "alma" + ] + }, + { + "id": "BP.med279", + "text": "Honrar o cansaço do corpo é honrar a vida.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "manda", + "mridu" + ], + "themes": [ + "corpo", + "descanso" + ] + }, + { + "id": "BP.med280", + "text": "O que você sonha à noite o dia pode realizar.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "sukshma" + ], + "themes": [ + "sonho", + "realização" + ] + }, + { + "id": "BP.med281", + "text": "Não despreze o sonho; ele fala a linguagem do coração.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "picchila", + "guru" + ], + "themes": [ + "sonho", + "coração" + ] + }, + { + "id": "BP.med282", + "text": "Quem honra os que vieram antes não caminha sozinho.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "sthira" + ], + "themes": [ + "ancestrais", + "linhagem" + ] + }, + { + "id": "BP.med283", + "text": "A linhagem não é peso; é raiz.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "linhagem", + "raiz" + ] + }, + { + "id": "BP.med284", + "text": "O olhar de uma criança lembra: o presente é agora.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "chala", + "laghu" + ], + "themes": [ + "presença", + "agora" + ] + }, + { + "id": "BP.med285", + "text": "Brincar não é fuga; é o modo do espírito respirar.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "drava", + "mridu" + ], + "themes": [ + "brincar", + "leveza" + ] + }, + { + "id": "BP.med286", + "text": "O que é impermanente merece cuidado, não apego.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "vishada", + "snigdha" + ], + "themes": [ + "impermanência", + "desapego" + ] + }, + { + "id": "BP.med287", + "text": "Agradecer ao corpo é o primeiro passo para habitá-lo.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "guru", + "snigdha" + ], + "themes": [ + "corpo", + "gratidão" + ] + }, + { + "id": "BP.med288", + "text": "O sopro que você não controla lembra: algo maior respira em você.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "chala", + "sukshma" + ], + "themes": [ + "respiração", + "presença" + ] + }, + { + "id": "BP.med289", + "text": "Pés no chão, coração no céu; o meio é onde a vida acontece.", + "kleshaTargets": [ + "abhinivesha", + "raga" + ], + "qualities": [ + "laghu", + "sthira" + ], + "themes": [ + "grounding", + "presença" + ] + }, + { + "id": "BP.med290", + "text": "No espaço entre dois pensamentos está o silêncio que cura.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "vishada", + "manda" + ], + "themes": [ + "silêncio", + "mente" + ] + }, + { + "id": "BP.med291", + "text": "Quem diz sim a tudo diz não a si mesmo.", + "kleshaTargets": [ + "asmita", + "raga" + ], + "qualities": [ + "kathina", + "vishada" + ], + "themes": [ + "limites", + "autocuidado" + ] + }, + { + "id": "BP.med292", + "text": "A raiva é mensageira; ouça o que ela traz antes de reagir.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "tikshna", + "ushna" + ], + "themes": [ + "raiva", + "escuta" + ] + }, + { + "id": "BP.med293", + "text": "O medo que você nomeia perde a sombra; o que você esconde cresce.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "mridu" + ], + "themes": [ + "medo", + "presença" + ] + }, + { + "id": "BP.med294", + "text": "Confiar não é não duvidar; é seguir mesmo quando a dúvida vem.", + "kleshaTargets": [ + "abhinivesha", + "avidya" + ], + "qualities": [ + "chala", + "vishada" + ], + "themes": [ + "confiança", + "dúvida" + ] + }, + { + "id": "BP.med295", + "text": "Antes de falar, pergunte: isso cura ou fere?", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "tikshna", + "mridu" + ], + "themes": [ + "palavra", + "verdade" + ] + }, + { + "id": "BP.med296", + "text": "O repouso não é tempo perdido; é o tempo em que o corpo se refaz.", + "kleshaTargets": [ + "raga", + "asmita" + ], + "qualities": [ + "manda", + "mridu" + ], + "themes": [ + "descanso", + "corpo" + ] + }, + { + "id": "BP.med297", + "text": "Soltar o resultado não é desistir; é fazer o que cabe a você e deixar o resto.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "picchila", + "vishada" + ], + "themes": [ + "entrega", + "ação" + ] + }, + { + "id": "BP.med298", + "text": "A dúvida honesta abre porta; a certeza cega fecha.", + "kleshaTargets": [ + "avidya", + "asmita" + ], + "qualities": [ + "vishada", + "tikshna" + ], + "themes": [ + "dúvida", + "discernimento" + ] + }, + { + "id": "BP.med299", + "text": "A humildade não é pensar menos de si; é pensar em si menos.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "humildade", + "ego" + ] + }, + { + "id": "BP.med300", + "text": "Aceitar o que é não é passividade; é ver com clareza para agir com sabedoria.", + "kleshaTargets": [ + "dvesha", + "raga" + ], + "qualities": [ + "picchila", + "mridu" + ], + "themes": [ + "aceitação", + "clareza" + ] + }, + { + "id": "BP.med301", + "text": "O que você oferece ao divino deixa de pesar em você.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "guru", + "snigdha" + ], + "themes": [ + "entrega", + "ação" + ] + }, + { + "id": "BP.med302", + "text": "Quem honra o ritmo do corpo não adoece de pressa.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "manda", + "sthira" + ], + "themes": [ + "corpo", + "tempo" + ] + }, + { + "id": "BP.med303", + "text": "A palavra que acalma é mais forte que a que fere.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "mridu", + "tikshna" + ], + "themes": [ + "palavra", + "compaixão" + ] + }, + { + "id": "BP.med304", + "text": "O silêncio após a oração é onde a resposta habita.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "chala", + "vishada" + ], + "themes": [ + "silêncio", + "oração" + ] + }, + { + "id": "BP.med305", + "text": "Aceitar a impermanência é o primeiro passo para a paz.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "picchila", + "mridu" + ], + "themes": [ + "aceitação", + "paz" + ] + }, + { + "id": "BP.med306", + "text": "Servir sem esperar reconhecimento libera o ego.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada", + "snigdha" + ], + "themes": [ + "serviço", + "humildade" + ] + }, + { + "id": "BP.med307", + "text": "A raiva que é respirada perde o controle sobre você.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "ushna", + "tikshna" + ], + "themes": [ + "raiva", + "respiração" + ] + }, + { + "id": "BP.med308", + "text": "O corpo que descansa se renova; o que não para se quebra.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "manda", + "mridu" + ], + "themes": [ + "corpo", + "sono" + ] + }, + { + "id": "BP.med309", + "text": "Quem vê o divino no outro não precisa que o outro mude.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "vishada", + "mridu" + ], + "themes": [ + "unidade", + "aceitação" + ] + }, + { + "id": "BP.med310", + "text": "A gratidão desloca o foco do que falta para o que já é.", + "kleshaTargets": [ + "raga", + "abhinivesha" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "gratidão", + "presença" + ] + }, + { + "id": "BP.med311", + "text": "O medo nomeado perde metade da sombra.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "sukshma", + "chala" + ], + "themes": [ + "medo", + "presença" + ] + }, + { + "id": "BP.med312", + "text": "A humildade não diminui; abre espaço para o infinito.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "tikshna", + "kathina" + ], + "themes": [ + "humildade", + "ego" + ] + }, + { + "id": "BP.med313", + "text": "Caminhar descalço na terra ancora a mente no agora.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "sthira", + "laghu" + ], + "themes": [ + "grounding", + "natureza" + ] + }, + { + "id": "BP.med314", + "text": "O perdão que você dá a si mesmo é o que libera.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "picchila", + "guru" + ], + "themes": [ + "perdão", + "liberação" + ] + }, + { + "id": "BP.med315", + "text": "Comer com consciência é oração que nutre o corpo.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "sita", + "vishada" + ], + "themes": [ + "alimentação", + "consciência" + ] + }, + { + "id": "BP.med316", + "text": "Dizer não é dizer sim a si mesmo.", + "kleshaTargets": [ + "asmita", + "raga" + ], + "qualities": [ + "kathina", + "sthira" + ], + "themes": [ + "limites", + "autocuidado" + ] + }, + { + "id": "BP.med317", + "text": "A dúvida honesta é o início do discernimento.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "dúvida", + "discernimento" + ] + }, + { + "id": "BP.med318", + "text": "O amor que não exige reciprocidade simplesmente flui.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "sita", + "kathina" + ], + "themes": [ + "amor", + "fluir" + ] + }, + { + "id": "BP.med319", + "text": "Lembrar a morte não é morrer; é viver com mais presença.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru" + ], + "themes": [ + "presença", + "morte" + ] + }, + { + "id": "BP.med320", + "text": "O repouso é parte do caminho, não desvio.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "manda", + "mridu" + ], + "themes": [ + "rotina", + "descanso" + ] + }, + { + "id": "BP.med321", + "text": "A verdade que libera pode doer no início.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "tikshna" + ], + "themes": [ + "verdade", + "liberdade" + ] + }, + { + "id": "BP.med322", + "text": "Quem observa a mente sem se identificar encontra espaço.", + "kleshaTargets": [ + "avidya", + "asmita" + ], + "qualities": [ + "vishada", + "sukshma" + ], + "themes": [ + "testemunha", + "mente" + ] + }, + { + "id": "BP.med323", + "text": "A alegria que nasce de dentro não depende do externo.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "laghu", + "vishada" + ], + "themes": [ + "alegria", + "interior" + ] + }, + { + "id": "BP.med324", + "text": "Chorar é deixar a dor sair pelo único caminho que ela conhece.", + "kleshaTargets": [ + "abhinivesha", + "dvesha" + ], + "qualities": [ + "drava", + "mridu" + ], + "themes": [ + "luto", + "corpo" + ] + }, + { + "id": "BP.med325", + "text": "Confiar no fluxo não é passividade; é coragem.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "chala", + "ruksha" + ], + "themes": [ + "confiança", + "coragem" + ] + }, + { + "id": "BP.med326", + "text": "O sopro que entra e sai já é oração.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "laghu", + "vishada" + ], + "themes": [ + "respiração", + "oração" + ] + }, + { + "id": "BP.med327", + "text": "A natureza não tem pressa; quem anda nela aprende o ritmo.", + "kleshaTargets": [ + "raga", + "abhinivesha" + ], + "qualities": [ + "manda", + "sthira" + ], + "themes": [ + "natureza", + "ritmo" + ] + }, + { + "id": "BP.med328", + "text": "Antes de falar, pergunte: é verdadeiro, necessário e bondoso?", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "tikshna", + "khara" + ], + "themes": [ + "palavra", + "verdade" + ] + }, + { + "id": "BP.med329", + "text": "O corpo guarda o que a mente esquece; honre os dois.", + "kleshaTargets": [ + "asmita", + "abhinivesha" + ], + "qualities": [ + "guru", + "snigdha" + ], + "themes": [ + "corpo", + "memória" + ] + }, + { + "id": "BP.med330", + "text": "A simplicidade é o luxo de quem não precisa provar nada.", + "kleshaTargets": [ + "raga", + "asmita" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "simplicidade", + "suficiência" + ] + }, + { + "id": "BP.med331", + "text": "Quem se esvazia é preenchido.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "humildade", + "entrega" + ] + }, + { + "id": "BP.med332", + "text": "A paz que nasce da devoção não depende do mundo.", + "kleshaTargets": [ + "raga", + "dvesha" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "paz", + "devoção" + ] + }, + { + "id": "BP.med333", + "text": "Proteger o coração não é fechar; é escolher o que entra.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "sukshma", + "chala" + ], + "themes": [ + "proteção", + "limites" + ] + }, + { + "id": "BP.med334", + "text": "O descanso é dharma; quem se entrega ao repouso se renova.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "mridu" + ], + "themes": [ + "descanso", + "renovação" + ] + }, + { + "id": "BP.med335", + "text": "Abrir o coração não é fraqueza; é coragem de sentir.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "sita", + "kathina" + ], + "themes": [ + "coração", + "coragem" + ] + }, + { + "id": "BP.med336", + "text": "A graça não escolhe merecimento; ela escolhe o momento.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "kathina" + ], + "themes": [ + "graça", + "humildade" + ] + }, + { + "id": "BP.med337", + "text": "Quando o coração está quebrado, a luz entra por onde não havia porta.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "mridu" + ], + "themes": [ + "graça", + "luz" + ] + }, + { + "id": "BP.med338", + "text": "O serviço ao outro é oração em movimento.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "serviço", + "oração" + ] + }, + { + "id": "BP.med339", + "text": "No silêncio da devoção, a resposta já está.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "chala", + "sukshma" + ], + "themes": [ + "silêncio", + "resposta" + ] + }, + { + "id": "BP.med340", + "text": "Quem cala a mente ouve o que as palavras não dizem.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "chala" + ], + "themes": [ + "silêncio", + "mente" + ] + }, + { + "id": "BP.med341", + "text": "Amar sem posse é a única forma de não perder.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "snigdha", + "guru" + ], + "themes": [ + "amor", + "desapego" + ] + }, + { + "id": "BP.med342", + "text": "Soltar não é desistir; é deixar o rio correr.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "picchila", + "sthira" + ], + "themes": [ + "soltar", + "fluir" + ] + }, + { + "id": "BP.med343", + "text": "O que você libera libera você.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "guru", + "picchila" + ], + "themes": [ + "libertação", + "perdão" + ] + }, + { + "id": "BP.med344", + "text": "O divino está no agora; quem habita o passado ou o futuro o perde.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "chala" + ], + "themes": [ + "presença", + "agora" + ] + }, + { + "id": "BP.med345", + "text": "Quem observa sem julgar encontra paz.", + "kleshaTargets": [ + "dvesha", + "asmita" + ], + "qualities": [ + "tikshna", + "khara" + ], + "themes": [ + "testemunha", + "paz" + ] + }, + { + "id": "BP.med346", + "text": "O testemunho compassivo dissolve a raiva.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "ushna", + "tikshna" + ], + "themes": [ + "compaixão", + "raiva" + ] + }, + { + "id": "BP.med347", + "text": "Chorar é permitir que o rio do coração encontre o mar.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "mridu" + ], + "themes": [ + "luto", + "corpo" + ] + }, + { + "id": "BP.med348", + "text": "A tristeza honrada se transforma em compaixão.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "sandra" + ], + "themes": [ + "luto", + "compaixão" + ] + }, + { + "id": "BP.med349", + "text": "A alegria que não depende do externo é estável.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "chala", + "laghu" + ], + "themes": [ + "alegria", + "estabilidade" + ] + }, + { + "id": "BP.med350", + "text": "Celebrar o bem do outro é antídoto para a inveja.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "tikshna", + "ushna" + ], + "themes": [ + "alegria", + "inveja" + ] + }, + { + "id": "BP.med351", + "text": "A paciência é força; a pressa é medo disfarçado.", + "kleshaTargets": [ + "raga", + "abhinivesha" + ], + "qualities": [ + "tikshna", + "chala" + ], + "themes": [ + "paciência", + "medo" + ] + }, + { + "id": "BP.med352", + "text": "O que amadurece no tempo certo não apodrece.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "chala" + ], + "themes": [ + "paciência", + "tempo" + ] + }, + { + "id": "BP.med353", + "text": "A simplicidade desfaz o nó da cobiça.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "guru", + "snigdha" + ], + "themes": [ + "simplicidade", + "cobiça" + ] + }, + { + "id": "BP.med354", + "text": "Menos é o caminho para mais.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "simplicidade", + "suficiência" + ] + }, + { + "id": "BP.med355", + "text": "A verdade libera; a mentira aprisiona.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "verdade", + "liberdade" + ] + }, + { + "id": "BP.med356", + "text": "Falar a verdade com amor é arte.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "khara", + "tikshna" + ], + "themes": [ + "verdade", + "amor" + ] + }, + { + "id": "BP.med357", + "text": "Cada respiração é chance de recomeçar.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "guru", + "picchila" + ], + "themes": [ + "recomeço", + "respiração" + ] + }, + { + "id": "BP.med358", + "text": "O perdão é o único modo de nascer de novo sem morrer.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "picchila" + ], + "themes": [ + "perdão", + "renascimento" + ] + }, + { + "id": "BP.med359", + "text": "Quem vê o divino em todos não está nunca só.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "sita", + "sthira" + ], + "themes": [ + "unidade", + "companhia" + ] + }, + { + "id": "BP.med360", + "text": "A separação é ilusão; a união é a natureza do ser.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "unidade", + "identidade" + ] + }, + { + "id": "BP.med361", + "text": "Quem pisa a terra com consciência não cai.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "chala", + "laghu" + ], + "themes": [ + "grounding", + "consciência" + ] + }, + { + "id": "BP.med362", + "text": "Uma respiração consciente une corpo e espírito.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "chala" + ], + "themes": [ + "respiração", + "corpo" + ] + }, + { + "id": "BP.med363", + "text": "Aceitar o que é não é resignação; é clareza.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "picchila", + "mridu" + ], + "themes": [ + "aceitação", + "clareza" + ] + }, + { + "id": "BP.med364", + "text": "Na solidão voluntária, o ruído interno se acalma.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "chala", + "vishada" + ], + "themes": [ + "solidão", + "silêncio" + ] + }, + { + "id": "BP.med365", + "text": "Quem se encontra sozinho não está só.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru" + ], + "themes": [ + "solidão", + "presença" + ] + }, + { + "id": "BP.med366", + "text": "Parar não é falhar; é permitir que a força volte.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "tikshna", + "ushna" + ], + "themes": [ + "descanso", + "força" + ] + }, + { + "id": "BP.med367", + "text": "A raiva que é vista com compaixão perde o fogo.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "ushna", + "tikshna" + ], + "themes": [ + "raiva", + "compaixão" + ] + }, + { + "id": "BP.med368", + "text": "Não apague a chama com mais chama; respire e deixe esfriar.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "tikshna", + "khara" + ], + "themes": [ + "raiva", + "resfriar" + ] + }, + { + "id": "BP.med369", + "text": "Quem aceita o medo não é governado por ele.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "mridu" + ], + "themes": [ + "medo", + "aceitação" + ] + }, + { + "id": "BP.med370", + "text": "Não exija certeza de si; exija presença.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "chala", + "laghu" + ], + "themes": [ + "dúvida", + "presença" + ] + }, + { + "id": "BP.med371", + "text": "Quem respeita os próprios limites pode expandir sem quebrar.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru" + ], + "themes": [ + "limites", + "expansão" + ] + }, + { + "id": "BP.med372", + "text": "Caminhar na natureza é voltar à própria natureza.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "natureza", + "identidade" + ] + }, + { + "id": "BP.med373", + "text": "A água que flui não se prende; ela contorna e segue.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "sthira", + "drava" + ], + "themes": [ + "fluir", + "flexibilidade" + ] + }, + { + "id": "BP.med374", + "text": "Beber um gole de água com consciência é um ato de gratidão.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "sita", + "vishada" + ], + "themes": [ + "gratidão", + "consciência" + ] + }, + { + "id": "BP.med375", + "text": "O silêncio que escolhemos é mais eloqüente que as palavras.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "chala" + ], + "themes": [ + "silêncio", + "palavra" + ] + }, + { + "id": "BP.med376", + "text": "O corpo não é inimigo; é o veículo da alma.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "guru", + "snigdha" + ], + "themes": [ + "corpo", + "alma" + ] + }, + { + "id": "BP.med377", + "text": "Honrar o cansaço do corpo é honrar a vida.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "manda", + "mridu" + ], + "themes": [ + "corpo", + "descanso" + ] + }, + { + "id": "BP.med378", + "text": "O que você sonha à noite o dia pode realizar.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "sukshma" + ], + "themes": [ + "sonho", + "realização" + ] + }, + { + "id": "BP.med379", + "text": "Não despreze o sonho; ele fala a linguagem do coração.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "picchila", + "guru" + ], + "themes": [ + "sonho", + "coração" + ] + }, + { + "id": "BP.med380", + "text": "Quem honra os que vieram antes não caminha sozinho.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "sthira" + ], + "themes": [ + "ancestrais", + "linhagem" + ] + }, + { + "id": "BP.med381", + "text": "A linhagem não é peso; é raiz.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "linhagem", + "raiz" + ] + }, + { + "id": "BP.med382", + "text": "O olhar de uma criança lembra: o presente é agora.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "chala", + "laghu" + ], + "themes": [ + "presença", + "agora" + ] + }, + { + "id": "BP.med383", + "text": "Brincar não é fuga; é o modo do espírito respirar.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "drava", + "mridu" + ], + "themes": [ + "brincar", + "leveza" + ] + }, + { + "id": "BP.med384", + "text": "O que é impermanente merece cuidado, não apego.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "vishada", + "snigdha" + ], + "themes": [ + "impermanência", + "desapego" + ] + }, + { + "id": "BP.med385", + "text": "Agradecer ao corpo é o primeiro passo para habitá-lo.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "guru", + "snigdha" + ], + "themes": [ + "corpo", + "gratidão" + ] + }, + { + "id": "BP.med386", + "text": "O sopro que você não controla lembra: algo maior respira em você.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "chala", + "sukshma" + ], + "themes": [ + "respiração", + "presença" + ] + }, + { + "id": "BP.med387", + "text": "Pés no chão, coração no céu; o meio é onde a vida acontece.", + "kleshaTargets": [ + "abhinivesha", + "raga" + ], + "qualities": [ + "laghu", + "sthira" + ], + "themes": [ + "grounding", + "presença" + ] + }, + { + "id": "BP.med388", + "text": "No espaço entre dois pensamentos está o silêncio que cura.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "vishada", + "manda" + ], + "themes": [ + "silêncio", + "mente" + ] + }, + { + "id": "BP.med389", + "text": "Quem diz sim a tudo diz não a si mesmo.", + "kleshaTargets": [ + "asmita", + "raga" + ], + "qualities": [ + "kathina", + "vishada" + ], + "themes": [ + "limites", + "autocuidado" + ] + }, + { + "id": "BP.med390", + "text": "A raiva é mensageira; ouça o que ela traz antes de reagir.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "tikshna", + "ushna" + ], + "themes": [ + "raiva", + "escuta" + ] + }, + { + "id": "BP.med391", + "text": "O medo que você nomeia perde a sombra; o que você esconde cresce.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "mridu" + ], + "themes": [ + "medo", + "presença" + ] + }, + { + "id": "BP.med392", + "text": "Confiar não é não duvidar; é seguir mesmo quando a dúvida vem.", + "kleshaTargets": [ + "abhinivesha", + "avidya" + ], + "qualities": [ + "chala", + "vishada" + ], + "themes": [ + "confiança", + "dúvida" + ] + }, + { + "id": "BP.med393", + "text": "Antes de falar, pergunte: isso cura ou fere?", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "tikshna", + "mridu" + ], + "themes": [ + "palavra", + "verdade" + ] + }, + { + "id": "BP.med394", + "text": "O repouso não é tempo perdido; é o tempo em que o corpo se refaz.", + "kleshaTargets": [ + "raga", + "asmita" + ], + "qualities": [ + "manda", + "mridu" + ], + "themes": [ + "descanso", + "corpo" + ] + }, + { + "id": "BP.med395", + "text": "Soltar o resultado não é desistir; é fazer o que cabe a você e deixar o resto.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "picchila", + "vishada" + ], + "themes": [ + "entrega", + "ação" + ] + }, + { + "id": "BP.med396", + "text": "A dúvida honesta abre porta; a certeza cega fecha.", + "kleshaTargets": [ + "avidya", + "asmita" + ], + "qualities": [ + "vishada", + "tikshna" + ], + "themes": [ + "dúvida", + "discernimento" + ] + }, + { + "id": "BP.med397", + "text": "A humildade não é pensar menos de si; é pensar em si menos.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "humildade", + "ego" + ] + }, + { + "id": "BP.med398", + "text": "Aceitar o que é não é passividade; é ver com clareza para agir com sabedoria.", + "kleshaTargets": [ + "dvesha", + "raga" + ], + "qualities": [ + "picchila", + "mridu" + ], + "themes": [ + "aceitação", + "clareza" + ] + }, + { + "id": "BP.med399", + "text": "O que você oferece ao divino deixa de pesar em você.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "guru", + "snigdha" + ], + "themes": [ + "entrega", + "ação" + ] + }, + { + "id": "BP.med400", + "text": "Quem honra o ritmo do corpo não adoece de pressa.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "manda", + "sthira" + ], + "themes": [ + "corpo", + "tempo" + ] + } +] \ No newline at end of file diff --git a/lib/dictionaries/sacred/upanishads.json b/lib/dictionaries/sacred/upanishads.json new file mode 100644 index 0000000..be9c167 --- /dev/null +++ b/lib/dictionaries/sacred/upanishads.json @@ -0,0 +1,2948 @@ +[ + { + "id": "UP.tat_tvam_asi", + "text": "Isso és tu. O que você busca já é você.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "manda", + "guru" + ], + "themes": [ + "identidade", + "Ser" + ] + }, + { + "id": "UP.plenitude", + "text": "O Ser que reside no coração é plenitude; o vazio é espaço para Ele.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "plenitude", + "coração" + ] + }, + { + "id": "UP.forgiveness", + "text": "O perdão interno libera o peso; você pode recomeçar.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "guru", + "picchila" + ], + "themes": [ + "perdão", + "recomeço" + ] + }, + { + "id": "UP.kena1", + "text": "Aquilo que não pode ser pensado pela mente, mas pelo qual a mente pensa — conhece isso como o Absoluto.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "mente", + "Absoluto" + ] + }, + { + "id": "UP.isha_plenum", + "text": "Isto é pleno; aquilo é pleno. Do pleno nasce o pleno. Tomando o pleno do pleno, o pleno permanece.", + "kleshaTargets": [], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "plenitude", + "unidade" + ] + }, + { + "id": "UP.katha_observer", + "text": "Conhece o que em você observa como o condutor da carruagem; o corpo é a carruagem.", + "kleshaTargets": [ + "avidya", + "asmita" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "testemunha", + "corpo" + ] + }, + { + "id": "UP.mundaka_birds", + "text": "Duas aves, companheiras unidas, habitam a mesma árvore; uma come o fruto, a outra observa sem comer.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "observador", + "liberdade" + ] + }, + { + "id": "UP.brihadaranyaka", + "text": "Conduz-me do não-ser ao ser; conduz-me da escuridão à luz; conduz-me da morte à imortalidade.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru" + ], + "themes": [ + "luz", + "transição" + ] + }, + { + "id": "UP.kena2", + "text": "O que não pode ser visto pelo olho, mas pelo qual o olho vê — conhece isso como o Absoluto.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "Absoluto", + "visão" + ] + }, + { + "id": "UP.isha_interior", + "text": "No interior do ser reside o Ser; quem o vê alcança a paz.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "interior", + "paz" + ] + }, + { + "id": "UP.mundaka_cord", + "text": "Como pássaro preso à corda, o homem preso ao corpo não vê a liberdade.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "guru", + "sthira" + ], + "themes": [ + "apego", + "liberdade" + ] + }, + { + "id": "UP.katha_here_there", + "text": "O que está aqui está ali; o que está ali está aqui. Quem vê só a multiplicidade, da morte à morte vai.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "unidade", + "multiplicidade" + ] + }, + { + "id": "UP.katha_awake", + "text": "Levanta-te, desperta, aproxima-te dos mestres e conhece. Afiada como o fio da navalha é a senda.", + "kleshaTargets": [ + "avidya", + "raga" + ], + "qualities": [ + "manda", + "guru" + ], + "themes": [ + "despertar", + "caminho" + ] + }, + { + "id": "UP.kena_speech", + "text": "Não pelo discurso, não pela mente, não pelo olho se alcança o Ser. Só quem diz 'É Ele' o alcança.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "Ser", + "reconhecimento" + ] + }, + { + "id": "UP.chandogya_mustard", + "text": "O Ser que reside no coração é menor que um grão de mostarda e maior que os céus.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "sukshma" + ], + "themes": [ + "coração", + "Ser" + ] + }, + { + "id": "UP.mundaka_becomes", + "text": "Aquele que conhece o Absoluto torna-se o Absoluto.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "identidade", + "Absoluto" + ] + }, + { + "id": "UP.kena_peace", + "text": "A paz que está além do entendimento — assim é quem conhece o Absoluto.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "paz", + "Absoluto" + ] + }, + { + "id": "UP.taittiriya_fearless", + "text": "Conhecendo a bem-aventurança do Absoluto, o sábio não treme diante de nada.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "mridu" + ], + "themes": [ + "medo", + "bem-aventurança" + ] + }, + { + "id": "UP.mandukya_om", + "text": "O som que é o todo: o passado, o presente e o futuro.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "guru", + "sandra" + ], + "themes": [ + "som", + "totalidade" + ] + }, + { + "id": "UP.shvetashvatara_peace", + "text": "Conhecendo o que habita no coração de todos os seres, o sábio entra na paz eterna.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "unidade", + "paz" + ] + }, + { + "id": "UP.katha_eternal", + "text": "O Ser não nasce nem morre; não nasceu, não nascerá; eterno é.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "eternidade", + "Ser" + ] + }, + { + "id": "UP.isha_all_in_all", + "text": "Quem vê todos os seres no Ser e o Ser em todos os seres não mais se oculta.", + "kleshaTargets": [ + "asmita", + "dvesha" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "unidade", + "visão" + ] + }, + { + "id": "UP.katha_driver", + "text": "O corpo é a carruagem; os sentidos são os cavalos; a mente é as rédeas. Quem conduz é o Ser.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "corpo", + "Ser" + ] + }, + { + "id": "UP.chandogya_heart", + "text": "No coração está a morada do Ser; quem o conhece não teme.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru" + ], + "themes": [ + "coração", + "medo" + ] + }, + { + "id": "UP.brihadaranyaka_light", + "text": "Conduz-me da escuridão à luz.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "manda" + ], + "themes": [ + "luz", + "transição" + ] + }, + { + "id": "UP.isha_plenum_short", + "text": "Do pleno nasce o pleno; o pleno permanece.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "plenitude", + "permanência" + ] + }, + { + "id": "UP.katha_sharp", + "text": "A senda é afiada como o fio da navalha; os sábios a atravessam.", + "kleshaTargets": [ + "avidya", + "raga" + ], + "qualities": [ + "tikshna", + "vishada" + ], + "themes": [ + "caminho", + "discernimento" + ] + }, + { + "id": "UP.mundaka_two", + "text": "Duas aves na mesma árvore; uma come, a outra observa. Quem observa é livre.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "vishada", + "snigdha" + ], + "themes": [ + "observador", + "liberdade" + ] + }, + { + "id": "UP.taittiriya_joy", + "text": "O Ser é feito de bem-aventurança; quem o conhece é preenchido.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "bem-aventurança", + "Ser" + ] + }, + { + "id": "UP.shvetashvatara_one", + "text": "Um só respira em todos; quem vê a unidade entra na paz.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "unidade", + "respiração" + ] + }, + { + "id": "UP.prashna_breath", + "text": "O sopro vital é o que une todos os seres; quem o honra não se dispersa.", + "kleshaTargets": [ + "chala" + ], + "qualities": [ + "chala", + "laghu" + ], + "themes": [ + "sopro", + "unidade" + ] + }, + { + "id": "UP.maitri_heart", + "text": "No coração está a morada da paz; quem a busca lá a encontra.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "mridu" + ], + "themes": [ + "coração", + "paz" + ] + }, + { + "id": "UP.katha_choice", + "text": "O sábio escolhe o eterno; o ignorante escolhe o passageiro.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "escolha", + "eterno" + ] + }, + { + "id": "UP.mundaka_fire", + "text": "Como as faíscas do fogo, do Ser nascem todos os seres.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "ushna", + "vishada" + ], + "themes": [ + "origem", + "Ser" + ] + }, + { + "id": "UP.taittiriya_sheaths", + "text": "Do Ser revestido de paz nascem os cinco invólucros; conhecer isso libera.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "invólucros", + "liberação" + ] + }, + { + "id": "UP.kena_unknowable", + "text": "O que a mente não alcança, mas pelo qual a mente alcança — conhece isso.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "sukshma" + ], + "themes": [ + "mente", + "Absoluto" + ] + }, + { + "id": "UP.isha_renounce", + "text": "Renunciando ao fruto da ação, o sábio alcança a paz.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "snigdha", + "guru" + ], + "themes": [ + "renúncia", + "paz" + ] + }, + { + "id": "UP.chandogya_space", + "text": "O espaço dentro do coração é tão vasto quanto o espaço fora.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "espaço", + "coração" + ] + }, + { + "id": "UP.brihadaranyaka_self", + "text": "Conhece aquele que é o conhecedor; não o que é conhecido.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "conhecedor", + "Ser" + ] + }, + { + "id": "UP.shvetashvatara_grace", + "text": "Só pelo favor do divino se revela o Ser.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "guru", + "mridu" + ], + "themes": [ + "graça", + "revelação" + ] + }, + { + "id": "UP.katha_steadfast", + "text": "Quem é firme na prática alcança o fim; não outro.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "sthira", + "vishada" + ], + "themes": [ + "prática", + "perseverança" + ] + }, + { + "id": "UP.mundaka_truth", + "text": "A verdade que os sábios veem com o olho do coração.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "verdade", + "coração" + ] + }, + { + "id": "UP.taittiriya_peace", + "text": "Que a paz desça do céu; que a paz suba da terra; que a paz habite em mim.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "mridu" + ], + "themes": [ + "paz", + "invocação" + ] + }, + { + "id": "UP.isha_cover", + "text": "Quem vê todos os seres no Ser cobre o mundo com a própria alma.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "unidade", + "visão" + ] + }, + { + "id": "UP.kena_knower", + "text": "Não é conhecido por quem conhece; é conhecido por quem não conhece.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "conhecimento", + "paradoxo" + ] + }, + { + "id": "UP.chandogya_teach", + "text": "O pai ensina ao filho: você é isso.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "guru" + ], + "themes": [ + "identidade", + "transmissão" + ] + }, + { + "id": "UP.mandukya_fourth", + "text": "O quarto estado não é interno nem externo; é a própria consciência.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "sukshma" + ], + "themes": [ + "consciência", + "estado" + ] + }, + { + "id": "UP.prashna_sun", + "text": "O sol que nasce no peito ilumina o que está dentro e fora.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "ushna", + "vishada" + ], + "themes": [ + "luz", + "interior" + ] + }, + { + "id": "UP.maitri_meditate", + "text": "Meditar no Ser que reside no coração dissolve o medo.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru" + ], + "themes": [ + "meditação", + "medo" + ] + }, + { + "id": "UP.katha_rare", + "text": "Poucos ouvem; menos ainda compreendem; raro é quem vive.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "escuta", + "vivência" + ] + }, + { + "id": "UP.shvetashvatara_meditation", + "text": "Com o corpo ereto, o coração e a mente no Absoluto, atravesse a corrente do mundo.", + "kleshaTargets": [ + "chala" + ], + "qualities": [ + "sthira", + "vishada" + ], + "themes": [ + "meditação", + "presença" + ] + }, + { + "id": "UP.kena_peace2", + "text": "A paz que não depende do externo habita no coração de quem a busca.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "paz", + "interior" + ] + }, + { + "id": "UP.katha_witness", + "text": "O que em você observa os pensamentos não é pensamento; conhece isso.", + "kleshaTargets": [ + "avidya", + "asmita" + ], + "qualities": [ + "vishada", + "sukshma" + ], + "themes": [ + "testemunha", + "consciência" + ] + }, + { + "id": "UP.mundaka_liberation", + "text": "Quem conhece a raiz não teme os galhos; quem conhece o Ser não teme o mundo.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "vishada" + ], + "themes": [ + "liberação", + "medo" + ] + }, + { + "id": "UP.taittiriya_layers", + "text": "Do Ser revestido de alegria nascem as camadas do mundo; a mais íntima é paz.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "snigdha" + ], + "themes": [ + "Ser", + "camadas" + ] + }, + { + "id": "UP.chandogya_identity", + "text": "Aquilo que você busca já mora em você; a busca é o caminho de volta.", + "kleshaTargets": [ + "avidya", + "raga" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "identidade", + "busca" + ] + }, + { + "id": "UP.brihadaranyaka_fear", + "text": "O medo nasce da dualidade; quem vê a unidade não teme.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "vishada", + "guru" + ], + "themes": [ + "medo", + "unidade" + ] + }, + { + "id": "UP.isha_action", + "text": "Aja no mundo como quem oferece a ação ao Ser; o fruto não te pertence.", + "kleshaTargets": [ + "raga", + "asmita" + ], + "qualities": [ + "snigdha", + "vishada" + ], + "themes": [ + "ação", + "entrega" + ] + }, + { + "id": "UP.prashna_breath2", + "text": "O sopro que entra e sai é a ponte entre o visível e o invisível.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "chala", + "sukshma" + ], + "themes": [ + "respiração", + "presença" + ] + }, + { + "id": "UP.maitri_peace2", + "text": "A paz que você busca fora já está dentro; pare e ouça.", + "kleshaTargets": [ + "chala", + "raga" + ], + "qualities": [ + "sthira", + "vishada" + ], + "themes": [ + "paz", + "interior" + ] + }, + { + "id": "UP.adv61", + "text": "Aquilo que você busca já mora em você; a busca é o caminho de volta.", + "kleshaTargets": [ + "avidya", + "raga" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "identidade", + "busca" + ] + }, + { + "id": "UP.adv62", + "text": "O que não pode ser pensado pela mente, mas pelo qual a mente pensa — conhece isso.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "mente", + "Absoluto" + ] + }, + { + "id": "UP.adv63", + "text": "Isto é pleno; aquilo é pleno. Do pleno nasce o pleno.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "plenitude", + "unidade" + ] + }, + { + "id": "UP.adv64", + "text": "Conhece o que em você observa como o condutor; o corpo é a carruagem.", + "kleshaTargets": [ + "avidya", + "asmita" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "testemunha", + "corpo" + ] + }, + { + "id": "UP.adv65", + "text": "Duas aves habitam a mesma árvore; uma come o fruto, a outra observa.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "observador", + "liberdade" + ] + }, + { + "id": "UP.adv66", + "text": "Conduz-me do não-ser ao ser; da escuridão à luz; da morte à imortalidade.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru" + ], + "themes": [ + "luz", + "transição" + ] + }, + { + "id": "UP.adv67", + "text": "O que não pode ser visto pelo olho, mas pelo qual o olho vê — conhece isso.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "Absoluto", + "visão" + ] + }, + { + "id": "UP.adv68", + "text": "No interior do ser reside o Ser; quem o vê alcança a paz.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "interior", + "paz" + ] + }, + { + "id": "UP.adv69", + "text": "Como pássaro preso à corda, quem está preso ao corpo não vê a liberdade.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "guru", + "sthira" + ], + "themes": [ + "apego", + "liberdade" + ] + }, + { + "id": "UP.adv70", + "text": "O que está aqui está ali; o que está ali está aqui.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "unidade", + "multiplicidade" + ] + }, + { + "id": "UP.adv71", + "text": "Levanta-te, desperta, aproxima-te dos mestres e conhece.", + "kleshaTargets": [ + "avidya", + "raga" + ], + "qualities": [ + "manda", + "guru" + ], + "themes": [ + "despertar", + "caminho" + ] + }, + { + "id": "UP.adv72", + "text": "Não pelo discurso, não pela mente, não pelo olho se alcança o Ser.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "Ser", + "reconhecimento" + ] + }, + { + "id": "UP.adv73", + "text": "O Ser que reside no coração é menor que um grão e maior que os céus.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "sukshma" + ], + "themes": [ + "coração", + "Ser" + ] + }, + { + "id": "UP.adv74", + "text": "Aquele que conhece o Absoluto torna-se o Absoluto.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "identidade", + "Absoluto" + ] + }, + { + "id": "UP.adv75", + "text": "A paz que está além do entendimento — assim é quem conhece o Absoluto.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "paz", + "Absoluto" + ] + }, + { + "id": "UP.adv76", + "text": "Conhecendo a bem-aventurança do Absoluto, o sábio não treme.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "mridu" + ], + "themes": [ + "medo", + "bem-aventurança" + ] + }, + { + "id": "UP.adv77", + "text": "O som que é o todo: passado, presente e futuro.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "guru", + "sandra" + ], + "themes": [ + "som", + "totalidade" + ] + }, + { + "id": "UP.adv78", + "text": "Conhecendo o que habita no coração de todos, o sábio entra na paz eterna.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "unidade", + "paz" + ] + }, + { + "id": "UP.adv79", + "text": "O Ser não nasce nem morre; eterno é.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "eternidade", + "Ser" + ] + }, + { + "id": "UP.adv80", + "text": "Quem vê todos os seres no Ser não mais se oculta.", + "kleshaTargets": [ + "asmita", + "dvesha" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "unidade", + "visão" + ] + }, + { + "id": "UP.adv81", + "text": "O corpo é a carruagem; os sentidos são os cavalos; quem conduz é o Ser.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "corpo", + "Ser" + ] + }, + { + "id": "UP.adv82", + "text": "No coração está a morada do Ser; quem o conhece não teme.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru" + ], + "themes": [ + "coração", + "medo" + ] + }, + { + "id": "UP.adv83", + "text": "Conduz-me da escuridão à luz.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "manda" + ], + "themes": [ + "luz", + "transição" + ] + }, + { + "id": "UP.adv84", + "text": "Do pleno nasce o pleno; o pleno permanece.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "plenitude", + "permanência" + ] + }, + { + "id": "UP.adv85", + "text": "A senda é afiada como o fio da navalha; os sábios a atravessam.", + "kleshaTargets": [ + "avidya", + "raga" + ], + "qualities": [ + "tikshna", + "vishada" + ], + "themes": [ + "caminho", + "discernimento" + ] + }, + { + "id": "UP.adv86", + "text": "Duas aves na mesma árvore; uma come, a outra observa. Quem observa é livre.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "vishada", + "snigdha" + ], + "themes": [ + "observador", + "liberdade" + ] + }, + { + "id": "UP.adv87", + "text": "O Ser é feito de bem-aventurança; quem o conhece é preenchido.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "bem-aventurança", + "Ser" + ] + }, + { + "id": "UP.adv88", + "text": "Um só respira em todos; quem vê a unidade entra na paz.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "unidade", + "respiração" + ] + }, + { + "id": "UP.adv89", + "text": "O sopro vital é o que une todos os seres.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "chala", + "laghu" + ], + "themes": [ + "sopro", + "unidade" + ] + }, + { + "id": "UP.adv90", + "text": "No coração está a morada da paz; quem a busca lá a encontra.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "mridu" + ], + "themes": [ + "coração", + "paz" + ] + }, + { + "id": "UP.adv91", + "text": "O sábio escolhe o eterno; o ignorante escolhe o passageiro.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "escolha", + "eterno" + ] + }, + { + "id": "UP.adv92", + "text": "Como as faíscas do fogo, do Ser nascem todos os seres.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "ushna", + "vishada" + ], + "themes": [ + "origem", + "Ser" + ] + }, + { + "id": "UP.adv93", + "text": "Do Ser revestido de paz nascem os cinco invólucros.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "invólucros", + "liberação" + ] + }, + { + "id": "UP.adv94", + "text": "O que a mente não alcança, mas pelo qual a mente alcança — conhece isso.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "sukshma" + ], + "themes": [ + "mente", + "Absoluto" + ] + }, + { + "id": "UP.adv95", + "text": "Renunciando ao fruto da ação, o sábio alcança a paz.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "snigdha", + "guru" + ], + "themes": [ + "renúncia", + "paz" + ] + }, + { + "id": "UP.adv96", + "text": "O espaço dentro do coração é tão vasto quanto o espaço fora.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "espaço", + "coração" + ] + }, + { + "id": "UP.adv97", + "text": "Conhece aquele que é o conhecedor; não o que é conhecido.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "conhecedor", + "Ser" + ] + }, + { + "id": "UP.adv98", + "text": "Só pelo favor do divino se revela o Ser.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "guru", + "mridu" + ], + "themes": [ + "graça", + "revelação" + ] + }, + { + "id": "UP.adv99", + "text": "Quem é firme na prática alcança o fim.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "sthira", + "vishada" + ], + "themes": [ + "prática", + "perseverança" + ] + }, + { + "id": "UP.adv100", + "text": "A verdade que os sábios veem com o olho do coração.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "verdade", + "coração" + ] + }, + { + "id": "UP.adv101", + "text": "Que a paz desça do céu; que a paz suba da terra; que a paz habite em mim.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "mridu" + ], + "themes": [ + "paz", + "invocação" + ] + }, + { + "id": "UP.adv102", + "text": "Quem vê todos os seres no Ser cobre o mundo com a própria alma.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "unidade", + "visão" + ] + }, + { + "id": "UP.adv103", + "text": "Não é conhecido por quem conhece; é conhecido por quem não conhece.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "conhecimento", + "paradoxo" + ] + }, + { + "id": "UP.adv104", + "text": "O pai ensina ao filho: você é isso.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "guru" + ], + "themes": [ + "identidade", + "transmissão" + ] + }, + { + "id": "UP.adv105", + "text": "O quarto estado não é interno nem externo; é a própria consciência.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "sukshma" + ], + "themes": [ + "consciência", + "estado" + ] + }, + { + "id": "UP.adv106", + "text": "O sol que nasce no peito ilumina o que está dentro e fora.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "ushna", + "vishada" + ], + "themes": [ + "luz", + "interior" + ] + }, + { + "id": "UP.adv107", + "text": "Meditar no Ser que reside no coração dissolve o medo.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru" + ], + "themes": [ + "meditação", + "medo" + ] + }, + { + "id": "UP.adv108", + "text": "Poucos ouvem; menos ainda compreendem; raro é quem vive.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "escuta", + "vivência" + ] + }, + { + "id": "UP.adv109", + "text": "Com o corpo ereto, o coração e a mente no Absoluto, atravesse a corrente do mundo.", + "kleshaTargets": [ + "chala" + ], + "qualities": [ + "sthira", + "vishada" + ], + "themes": [ + "meditação", + "presença" + ] + }, + { + "id": "UP.adv110", + "text": "A paz que não depende do externo habita no coração de quem a busca.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "paz", + "interior" + ] + }, + { + "id": "UP.adv111", + "text": "O que em você observa os pensamentos não é pensamento; conhece isso.", + "kleshaTargets": [ + "avidya", + "asmita" + ], + "qualities": [ + "vishada", + "sukshma" + ], + "themes": [ + "testemunha", + "consciência" + ] + }, + { + "id": "UP.adv112", + "text": "Quem conhece a raiz não teme os galhos.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "vishada" + ], + "themes": [ + "liberação", + "medo" + ] + }, + { + "id": "UP.adv113", + "text": "Do Ser revestido de alegria nascem as camadas do mundo.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "snigdha" + ], + "themes": [ + "Ser", + "camadas" + ] + }, + { + "id": "UP.adv114", + "text": "O medo nasce da dualidade; quem vê a unidade não teme.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "vishada", + "guru" + ], + "themes": [ + "medo", + "unidade" + ] + }, + { + "id": "UP.adv115", + "text": "Aja no mundo como quem oferece a ação ao Ser; o fruto não te pertence.", + "kleshaTargets": [ + "raga", + "asmita" + ], + "qualities": [ + "snigdha", + "vishada" + ], + "themes": [ + "ação", + "entrega" + ] + }, + { + "id": "UP.adv116", + "text": "O sopro que entra e sai é a ponte entre o visível e o invisível.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "chala", + "sukshma" + ], + "themes": [ + "respiração", + "presença" + ] + }, + { + "id": "UP.adv117", + "text": "A paz que você busca fora já está dentro; pare e ouça.", + "kleshaTargets": [ + "chala", + "raga" + ], + "qualities": [ + "sthira", + "vishada" + ], + "themes": [ + "paz", + "interior" + ] + }, + { + "id": "UP.adv118", + "text": "Isso és tu. O que você busca já é você.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "manda", + "guru" + ], + "themes": [ + "identidade", + "Ser" + ] + }, + { + "id": "UP.adv119", + "text": "O Ser que reside no coração é plenitude; o vazio é espaço para Ele.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "plenitude", + "coração" + ] + }, + { + "id": "UP.adv120", + "text": "O perdão interno libera o peso; você pode recomeçar.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "guru", + "picchila" + ], + "themes": [ + "perdão", + "recomeço" + ] + }, + { + "id": "UP.adv121", + "text": "Aquilo que você busca já mora em você; a busca é o caminho de volta.", + "kleshaTargets": [ + "avidya", + "raga" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "identidade", + "busca" + ] + }, + { + "id": "UP.adv122", + "text": "O que não pode ser pensado pela mente, mas pelo qual a mente pensa — conhece isso.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "mente", + "Absoluto" + ] + }, + { + "id": "UP.adv123", + "text": "Isto é pleno; aquilo é pleno. Do pleno nasce o pleno.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "plenitude", + "unidade" + ] + }, + { + "id": "UP.adv124", + "text": "Conhece o que em você observa como o condutor; o corpo é a carruagem.", + "kleshaTargets": [ + "avidya", + "asmita" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "testemunha", + "corpo" + ] + }, + { + "id": "UP.adv125", + "text": "Duas aves habitam a mesma árvore; uma come o fruto, a outra observa.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "observador", + "liberdade" + ] + }, + { + "id": "UP.adv126", + "text": "Conduz-me do não-ser ao ser; da escuridão à luz; da morte à imortalidade.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru" + ], + "themes": [ + "luz", + "transição" + ] + }, + { + "id": "UP.adv127", + "text": "O que não pode ser visto pelo olho, mas pelo qual o olho vê — conhece isso.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "Absoluto", + "visão" + ] + }, + { + "id": "UP.adv128", + "text": "No interior do ser reside o Ser; quem o vê alcança a paz.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "interior", + "paz" + ] + }, + { + "id": "UP.adv129", + "text": "Como pássaro preso à corda, quem está preso ao corpo não vê a liberdade.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "guru", + "sthira" + ], + "themes": [ + "apego", + "liberdade" + ] + }, + { + "id": "UP.adv130", + "text": "O que está aqui está ali; o que está ali está aqui.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "unidade", + "multiplicidade" + ] + }, + { + "id": "UP.adv131", + "text": "Levanta-te, desperta, aproxima-te dos mestres e conhece.", + "kleshaTargets": [ + "avidya", + "raga" + ], + "qualities": [ + "manda", + "guru" + ], + "themes": [ + "despertar", + "caminho" + ] + }, + { + "id": "UP.adv132", + "text": "Não pelo discurso, não pela mente, não pelo olho se alcança o Ser.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "Ser", + "reconhecimento" + ] + }, + { + "id": "UP.adv133", + "text": "O Ser que reside no coração é menor que um grão e maior que os céus.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "sukshma" + ], + "themes": [ + "coração", + "Ser" + ] + }, + { + "id": "UP.adv134", + "text": "Aquele que conhece o Absoluto torna-se o Absoluto.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "identidade", + "Absoluto" + ] + }, + { + "id": "UP.adv135", + "text": "A paz que está além do entendimento — assim é quem conhece o Absoluto.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "paz", + "Absoluto" + ] + }, + { + "id": "UP.adv136", + "text": "Conhecendo a bem-aventurança do Absoluto, o sábio não treme.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "mridu" + ], + "themes": [ + "medo", + "bem-aventurança" + ] + }, + { + "id": "UP.adv137", + "text": "O som que é o todo: passado, presente e futuro.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "guru", + "sandra" + ], + "themes": [ + "som", + "totalidade" + ] + }, + { + "id": "UP.adv138", + "text": "Conhecendo o que habita no coração de todos, o sábio entra na paz eterna.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "unidade", + "paz" + ] + }, + { + "id": "UP.adv139", + "text": "O Ser não nasce nem morre; eterno é.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "eternidade", + "Ser" + ] + }, + { + "id": "UP.adv140", + "text": "Quem vê todos os seres no Ser não mais se oculta.", + "kleshaTargets": [ + "asmita", + "dvesha" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "unidade", + "visão" + ] + }, + { + "id": "UP.adv141", + "text": "O corpo é a carruagem; os sentidos são os cavalos; quem conduz é o Ser.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "corpo", + "Ser" + ] + }, + { + "id": "UP.adv142", + "text": "No coração está a morada do Ser; quem o conhece não teme.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru" + ], + "themes": [ + "coração", + "medo" + ] + }, + { + "id": "UP.adv143", + "text": "Conduz-me da escuridão à luz.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "manda" + ], + "themes": [ + "luz", + "transição" + ] + }, + { + "id": "UP.adv144", + "text": "Do pleno nasce o pleno; o pleno permanece.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "plenitude", + "permanência" + ] + }, + { + "id": "UP.adv145", + "text": "A senda é afiada como o fio da navalha; os sábios a atravessam.", + "kleshaTargets": [ + "avidya", + "raga" + ], + "qualities": [ + "tikshna", + "vishada" + ], + "themes": [ + "caminho", + "discernimento" + ] + }, + { + "id": "UP.adv146", + "text": "Duas aves na mesma árvore; uma come, a outra observa. Quem observa é livre.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "vishada", + "snigdha" + ], + "themes": [ + "observador", + "liberdade" + ] + }, + { + "id": "UP.adv147", + "text": "O Ser é feito de bem-aventurança; quem o conhece é preenchido.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "bem-aventurança", + "Ser" + ] + }, + { + "id": "UP.adv148", + "text": "Um só respira em todos; quem vê a unidade entra na paz.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "unidade", + "respiração" + ] + }, + { + "id": "UP.adv149", + "text": "O sopro vital é o que une todos os seres.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "chala", + "laghu" + ], + "themes": [ + "sopro", + "unidade" + ] + }, + { + "id": "UP.adv150", + "text": "No coração está a morada da paz; quem a busca lá a encontra.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "mridu" + ], + "themes": [ + "coração", + "paz" + ] + }, + { + "id": "UP.adv151", + "text": "O sábio escolhe o eterno; o ignorante escolhe o passageiro.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "escolha", + "eterno" + ] + }, + { + "id": "UP.adv152", + "text": "Como as faíscas do fogo, do Ser nascem todos os seres.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "ushna", + "vishada" + ], + "themes": [ + "origem", + "Ser" + ] + }, + { + "id": "UP.adv153", + "text": "Do Ser revestido de paz nascem os cinco invólucros.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "invólucros", + "liberação" + ] + }, + { + "id": "UP.adv154", + "text": "O que a mente não alcança, mas pelo qual a mente alcança — conhece isso.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "sukshma" + ], + "themes": [ + "mente", + "Absoluto" + ] + }, + { + "id": "UP.adv155", + "text": "Renunciando ao fruto da ação, o sábio alcança a paz.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "snigdha", + "guru" + ], + "themes": [ + "renúncia", + "paz" + ] + }, + { + "id": "UP.adv156", + "text": "O espaço dentro do coração é tão vasto quanto o espaço fora.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "espaço", + "coração" + ] + }, + { + "id": "UP.adv157", + "text": "Conhece aquele que é o conhecedor; não o que é conhecido.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "conhecedor", + "Ser" + ] + }, + { + "id": "UP.adv158", + "text": "Só pelo favor do divino se revela o Ser.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "guru", + "mridu" + ], + "themes": [ + "graça", + "revelação" + ] + }, + { + "id": "UP.adv159", + "text": "Quem é firme na prática alcança o fim.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "sthira", + "vishada" + ], + "themes": [ + "prática", + "perseverança" + ] + }, + { + "id": "UP.adv160", + "text": "A verdade que os sábios veem com o olho do coração.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "verdade", + "coração" + ] + }, + { + "id": "UP.adv161", + "text": "Que a paz desça do céu; que a paz suba da terra; que a paz habite em mim.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "mridu" + ], + "themes": [ + "paz", + "invocação" + ] + }, + { + "id": "UP.adv162", + "text": "Quem vê todos os seres no Ser cobre o mundo com a própria alma.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "unidade", + "visão" + ] + }, + { + "id": "UP.adv163", + "text": "Não é conhecido por quem conhece; é conhecido por quem não conhece.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "conhecimento", + "paradoxo" + ] + }, + { + "id": "UP.adv164", + "text": "O pai ensina ao filho: você é isso.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "guru" + ], + "themes": [ + "identidade", + "transmissão" + ] + }, + { + "id": "UP.adv165", + "text": "O quarto estado não é interno nem externo; é a própria consciência.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "sukshma" + ], + "themes": [ + "consciência", + "estado" + ] + }, + { + "id": "UP.adv166", + "text": "O sol que nasce no peito ilumina o que está dentro e fora.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "ushna", + "vishada" + ], + "themes": [ + "luz", + "interior" + ] + }, + { + "id": "UP.adv167", + "text": "Meditar no Ser que reside no coração dissolve o medo.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru" + ], + "themes": [ + "meditação", + "medo" + ] + }, + { + "id": "UP.adv168", + "text": "Poucos ouvem; menos ainda compreendem; raro é quem vive.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "escuta", + "vivência" + ] + }, + { + "id": "UP.adv169", + "text": "Com o corpo ereto, o coração e a mente no Absoluto, atravesse a corrente do mundo.", + "kleshaTargets": [ + "chala" + ], + "qualities": [ + "sthira", + "vishada" + ], + "themes": [ + "meditação", + "presença" + ] + }, + { + "id": "UP.adv170", + "text": "A paz que não depende do externo habita no coração de quem a busca.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "paz", + "interior" + ] + }, + { + "id": "UP.adv171", + "text": "O que em você observa os pensamentos não é pensamento; conhece isso.", + "kleshaTargets": [ + "avidya", + "asmita" + ], + "qualities": [ + "vishada", + "sukshma" + ], + "themes": [ + "testemunha", + "consciência" + ] + }, + { + "id": "UP.adv172", + "text": "Quem conhece a raiz não teme os galhos.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "vishada" + ], + "themes": [ + "liberação", + "medo" + ] + }, + { + "id": "UP.adv173", + "text": "Do Ser revestido de alegria nascem as camadas do mundo.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "snigdha" + ], + "themes": [ + "Ser", + "camadas" + ] + }, + { + "id": "UP.adv174", + "text": "O medo nasce da dualidade; quem vê a unidade não teme.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "vishada", + "guru" + ], + "themes": [ + "medo", + "unidade" + ] + }, + { + "id": "UP.adv175", + "text": "Aja no mundo como quem oferece a ação ao Ser; o fruto não te pertence.", + "kleshaTargets": [ + "raga", + "asmita" + ], + "qualities": [ + "snigdha", + "vishada" + ], + "themes": [ + "ação", + "entrega" + ] + }, + { + "id": "UP.adv176", + "text": "O sopro que entra e sai é a ponte entre o visível e o invisível.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "chala", + "sukshma" + ], + "themes": [ + "respiração", + "presença" + ] + }, + { + "id": "UP.adv177", + "text": "A paz que você busca fora já está dentro; pare e ouça.", + "kleshaTargets": [ + "chala", + "raga" + ], + "qualities": [ + "sthira", + "vishada" + ], + "themes": [ + "paz", + "interior" + ] + }, + { + "id": "UP.adv178", + "text": "Isso és tu. O que você busca já é você.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "manda", + "guru" + ], + "themes": [ + "identidade", + "Ser" + ] + }, + { + "id": "UP.adv179", + "text": "O Ser que reside no coração é plenitude; o vazio é espaço para Ele.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "plenitude", + "coração" + ] + }, + { + "id": "UP.adv180", + "text": "O perdão interno libera o peso; você pode recomeçar.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "guru", + "picchila" + ], + "themes": [ + "perdão", + "recomeço" + ] + }, + { + "id": "UP.adv181", + "text": "Aquilo que você busca já mora em você; a busca é o caminho de volta.", + "kleshaTargets": [ + "avidya", + "raga" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "identidade", + "busca" + ] + }, + { + "id": "UP.adv182", + "text": "O que não pode ser pensado pela mente, mas pelo qual a mente pensa — conhece isso.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "mente", + "Absoluto" + ] + }, + { + "id": "UP.adv183", + "text": "Isto é pleno; aquilo é pleno. Do pleno nasce o pleno.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "plenitude", + "unidade" + ] + }, + { + "id": "UP.adv184", + "text": "Conhece o que em você observa como o condutor; o corpo é a carruagem.", + "kleshaTargets": [ + "avidya", + "asmita" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "testemunha", + "corpo" + ] + }, + { + "id": "UP.adv185", + "text": "Duas aves habitam a mesma árvore; uma come o fruto, a outra observa.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "observador", + "liberdade" + ] + }, + { + "id": "UP.adv186", + "text": "Conduz-me do não-ser ao ser; da escuridão à luz; da morte à imortalidade.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru" + ], + "themes": [ + "luz", + "transição" + ] + }, + { + "id": "UP.adv187", + "text": "O que não pode ser visto pelo olho, mas pelo qual o olho vê — conhece isso.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "Absoluto", + "visão" + ] + }, + { + "id": "UP.adv188", + "text": "No interior do ser reside o Ser; quem o vê alcança a paz.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "interior", + "paz" + ] + }, + { + "id": "UP.adv189", + "text": "Como pássaro preso à corda, quem está preso ao corpo não vê a liberdade.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "guru", + "sthira" + ], + "themes": [ + "apego", + "liberdade" + ] + }, + { + "id": "UP.adv190", + "text": "O que está aqui está ali; o que está ali está aqui.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "unidade", + "multiplicidade" + ] + }, + { + "id": "UP.adv191", + "text": "Levanta-te, desperta, aproxima-te dos mestres e conhece.", + "kleshaTargets": [ + "avidya", + "raga" + ], + "qualities": [ + "manda", + "guru" + ], + "themes": [ + "despertar", + "caminho" + ] + }, + { + "id": "UP.adv192", + "text": "Não pelo discurso, não pela mente, não pelo olho se alcança o Ser.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "Ser", + "reconhecimento" + ] + }, + { + "id": "UP.adv193", + "text": "O Ser que reside no coração é menor que um grão e maior que os céus.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "sukshma" + ], + "themes": [ + "coração", + "Ser" + ] + }, + { + "id": "UP.adv194", + "text": "Aquele que conhece o Absoluto torna-se o Absoluto.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "identidade", + "Absoluto" + ] + }, + { + "id": "UP.adv195", + "text": "A paz que está além do entendimento — assim é quem conhece o Absoluto.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "paz", + "Absoluto" + ] + }, + { + "id": "UP.adv196", + "text": "Conhecendo a bem-aventurança do Absoluto, o sábio não treme.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "mridu" + ], + "themes": [ + "medo", + "bem-aventurança" + ] + }, + { + "id": "UP.adv197", + "text": "O som que é o todo: passado, presente e futuro.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "guru", + "sandra" + ], + "themes": [ + "som", + "totalidade" + ] + }, + { + "id": "UP.adv198", + "text": "Conhecendo o que habita no coração de todos, o sábio entra na paz eterna.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "unidade", + "paz" + ] + }, + { + "id": "UP.adv199", + "text": "O Ser não nasce nem morre; eterno é.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "eternidade", + "Ser" + ] + }, + { + "id": "UP.adv200", + "text": "Quem vê todos os seres no Ser não mais se oculta.", + "kleshaTargets": [ + "asmita", + "dvesha" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "unidade", + "visão" + ] + } +] \ No newline at end of file diff --git a/lib/dictionaries/sacred/yoga_sutras.json b/lib/dictionaries/sacred/yoga_sutras.json new file mode 100644 index 0000000..76783c4 --- /dev/null +++ b/lib/dictionaries/sacred/yoga_sutras.json @@ -0,0 +1,107 @@ +[ + { "id": "YS.1.1", "text": "Yoga é a cessação das flutuações da mente.", "kleshaTargets": ["avidya"], "qualities": ["chala", "sukshma"] }, + { "id": "YS.1.2", "text": "Quando a mente está em silêncio, o observador repousa em sua própria natureza.", "kleshaTargets": ["avidya"], "qualities": ["vishada", "laghu"] }, + { "id": "YS.1.3", "text": "Então o observador repousa em sua própria natureza.", "kleshaTargets": ["avidya"], "qualities": ["vishada"] }, + { "id": "YS.1.4", "text": "No resto do tempo, o observador se identifica com as flutuações.", "kleshaTargets": ["asmita"], "qualities": ["chala"] }, + { "id": "YS.1.5", "text": "As flutuações são cinco: dolorosas e não dolorosas.", "kleshaTargets": ["avidya"], "qualities": ["vishada"] }, + { "id": "YS.1.6", "text": "São: conhecimento correto, erro, imaginação, sono e memória.", "kleshaTargets": ["avidya"], "qualities": ["vishada"] }, + { "id": "YS.1.7", "text": "O conhecimento correto é direto, inferência ou testemunho.", "kleshaTargets": [], "qualities": ["vishada"] }, + { "id": "YS.1.8", "text": "O erro é conhecimento falso, sem base no real.", "kleshaTargets": ["avidya"], "qualities": ["manda"] }, + { "id": "YS.1.9", "text": "A imaginação segue a palavra, sem objeto real.", "kleshaTargets": ["avidya"], "qualities": ["sukshma", "chala"] }, + { "id": "YS.1.10", "text": "O sono é a flutuação sustentada pela ausência.", "kleshaTargets": ["avidya"], "qualities": ["guru", "tamas"] }, + { "id": "YS.1.11", "text": "A memória é a retenção do experimentado.", "kleshaTargets": ["raga"], "qualities": ["picchila"] }, + { "id": "YS.1.12", "text": "A prática e o desapego são o par que estabiliza a mente.", "kleshaTargets": ["raga"], "qualities": ["chala", "tikshna"] }, + { "id": "YS.1.13", "text": "O esforço constante para estabilizar a mente é a prática.", "kleshaTargets": ["raga", "avidya"], "qualities": ["chala", "laghu"] }, + { "id": "YS.1.14", "text": "A prática torna-se firme quando mantida por muito tempo, sem interrupção, com devoção.", "kleshaTargets": ["avidya"], "qualities": ["guru", "manda"] }, + { "id": "YS.1.15", "text": "O desapego é o domínio de quem não deseja nem evita o que vê.", "kleshaTargets": ["raga", "dvesha"], "qualities": ["snigdha", "guru"] }, + { "id": "YS.1.16", "text": "O ápice do desapego é quando a consciência reconhece sua própria natureza luminosa.", "kleshaTargets": [], "qualities": ["vishada", "laghu"] }, + { "id": "YS.1.17", "text": "A consciência contemplativa acompanha raciocínio, reflexão, alegria e senso de ser.", "kleshaTargets": ["avidya"], "qualities": ["vishada"] }, + { "id": "YS.1.18", "text": "A outra é o resíduo de prática; apenas sementes em repouso.", "kleshaTargets": ["raga"], "qualities": ["laghu"] }, + { "id": "YS.1.19", "text": "Para alguns, o estado sem nascimento vem da natureza; para outros, da entrega ao Absoluto.", "kleshaTargets": ["abhinivesha"], "qualities": ["guru"] }, + { "id": "YS.1.20", "text": "Para os outros, a prática é fé, energia, memória, absorção e sabedoria.", "kleshaTargets": ["avidya"], "qualities": ["manda"] }, + { "id": "YS.1.21", "text": "Para os intensos, o resultado é próximo.", "kleshaTargets": ["raga"], "qualities": ["tikshna"] }, + { "id": "YS.1.22", "text": "Há diferença: suave, moderado ou intenso.", "kleshaTargets": [], "qualities": ["vishada"] }, + { "id": "YS.1.23", "text": "Ou pela entrega ao Absoluto.", "kleshaTargets": ["raga", "abhinivesha"], "qualities": ["guru"] }, + { "id": "YS.1.24", "text": "O Absoluto é um ser especial, intacto pelo sofrimento, ato ou fruto.", "kleshaTargets": ["avidya"], "qualities": ["vishada"] }, + { "id": "YS.1.25", "text": "Nele está a semente da onisciência.", "kleshaTargets": [], "qualities": ["vishada", "laghu"] }, + { "id": "YS.1.26", "text": "Ele é o mestre dos antigos, não limitado pelo tempo.", "kleshaTargets": ["abhinivesha"], "qualities": ["vishada"] }, + { "id": "YS.1.27", "text": "Sua expressão é o som sagrado.", "kleshaTargets": [], "qualities": ["vishada"] }, + { "id": "YS.1.28", "text": "A repetição e a contemplação desse som conduzem.", "kleshaTargets": ["chala"], "qualities": ["chala", "laghu"] }, + { "id": "YS.1.29", "text": "Daí surge o voltar-se para dentro e o desaparecimento dos obstáculos.", "kleshaTargets": ["avidya"], "qualities": ["vishada"] }, + { "id": "YS.1.30", "text": "Os obstáculos são: doença, apatia, dúvida, negligência, preguiça, apego ao prazer, erro, não-estabilidade.", "kleshaTargets": ["avidya", "raga"], "qualities": ["guru", "manda"] }, + { "id": "YS.1.31", "text": "Sofrimento, tristeza, tremor do corpo e respiração irregular acompanham.", "kleshaTargets": ["abhinivesha"], "qualities": ["chala", "ruksha"] }, + { "id": "YS.1.32", "text": "Para removê-los, a prática sobre um único princípio.", "kleshaTargets": ["avidya"], "qualities": ["chala"] }, + { "id": "YS.1.33", "text": "Amizade, compaixão, alegria e equanimidade em relação ao que é agradável, doloroso, meritório ou não — acalmam a mente.", "kleshaTargets": ["raga", "dvesha"], "qualities": ["chala", "ruksha", "tikshna", "ushna", "khara"] }, + { "id": "YS.1.34", "text": "Ou pela expiração e retenção do sopro.", "kleshaTargets": ["chala"], "qualities": ["chala"] }, + { "id": "YS.1.35", "text": "A atividade sensorial que fixa a mente surge e estabiliza.", "kleshaTargets": ["raga"], "qualities": ["chala", "laghu"] }, + { "id": "YS.1.36", "text": "Ou a luz interior, livre de tristeza.", "kleshaTargets": ["abhinivesha"], "qualities": ["guru", "mridu"] }, + { "id": "YS.1.37", "text": "Ou a mente que abandonou o apego.", "kleshaTargets": ["raga"], "qualities": ["snigdha", "guru"] }, + { "id": "YS.1.38", "text": "Ou o conhecimento que surge no sono e no sonho.", "kleshaTargets": ["avidya"], "qualities": ["vishada"] }, + { "id": "YS.1.39", "text": "Ou pela contemplação do que se deseja.", "kleshaTargets": ["raga"], "qualities": ["chala"] }, + { "id": "YS.1.40", "text": "O domínio vai do infinitamente pequeno ao infinitamente grande.", "kleshaTargets": ["asmita"], "qualities": ["vishada"] }, + { "id": "YS.2.1", "text": "A prática constante e o desapego são os meios.", "kleshaTargets": ["asmita", "raga"], "qualities": ["kathina", "sthira"] }, + { "id": "YS.2.2", "text": "Eles reduzem as impurezas e permitem a luz do discernimento.", "kleshaTargets": ["avidya"], "qualities": ["vishada"] }, + { "id": "YS.2.3", "text": "As impurezas são: ignorância, ego, apego, aversão e medo da morte.", "kleshaTargets": ["avidya", "asmita", "raga", "dvesha", "abhinivesha"], "qualities": ["guru"] }, + { "id": "YS.2.4", "text": "A ignorância é o campo dos outros; eles podem estar adormecidos, enfraquecidos, interrompidos ou ativos.", "kleshaTargets": ["avidya"], "qualities": ["manda", "guru"] }, + { "id": "YS.2.5", "text": "A ignorância é tomar o impermanente pelo permanente, o impuro pelo puro, a dor pelo prazer, o não-eu pelo eu.", "kleshaTargets": ["avidya"], "qualities": ["vishada"] }, + { "id": "YS.2.6", "text": "O ego é a identificação do que vê com o instrumento do ver; reconhecer isso dissolve o orgulho.", "kleshaTargets": ["asmita"], "qualities": ["tikshna", "kathina"] }, + { "id": "YS.2.7", "text": "O apego segue o prazer; o desapego nasce do discernimento.", "kleshaTargets": ["raga"], "qualities": ["tikshna", "ushna"] }, + { "id": "YS.2.8", "text": "A aversão segue a dor.", "kleshaTargets": ["dvesha"], "qualities": ["tikshna", "ushna", "khara"] }, + { "id": "YS.2.9", "text": "O medo da morte habita mesmo no sábio; é inerente à natureza. Observá-lo enfraquece seu poder.", "kleshaTargets": ["abhinivesha"], "qualities": ["guru", "sandra"] }, + { "id": "YS.2.10", "text": "Em estado sutil, eles se dissolvem pela volta à origem.", "kleshaTargets": ["avidya"], "qualities": ["vishada"] }, + { "id": "YS.2.11", "text": "Em estado ativo, eles se dissolvem pela meditação.", "kleshaTargets": ["raga", "dvesha"], "qualities": ["chala", "tikshna"] }, + { "id": "YS.2.12", "text": "O reservatório do karma tem a raiz nas impurezas e é experimentado no nascimento, na vida e no fruto.", "kleshaTargets": ["avidya"], "qualities": ["guru"] }, + { "id": "YS.2.13", "text": "Enquanto a raiz existir, ele amadurece em nascimento, vida e experiência.", "kleshaTargets": ["abhinivesha"], "qualities": ["guru"] }, + { "id": "YS.2.14", "text": "Eles têm como fruto o prazer ou a dor, conforme a causa: virtude ou vício.", "kleshaTargets": ["raga", "dvesha"], "qualities": ["vishada"] }, + { "id": "YS.2.15", "text": "Para quem discerne, tudo é sofrimento por causa da mudança, da ansiedade e do conflito dos gunas.", "kleshaTargets": ["raga", "dvesha"], "qualities": ["chala", "tikshna"] }, + { "id": "YS.2.16", "text": "O sofrimento que ainda não veio pode ser evitado.", "kleshaTargets": ["abhinivesha"], "qualities": ["vishada"] }, + { "id": "YS.2.17", "text": "A causa do evitável é a união do que vê com o visto.", "kleshaTargets": ["asmita"], "qualities": ["picchila"] }, + { "id": "YS.2.18", "text": "O visto tem a natureza da luz, da atividade e da inércia; é feito de elemento e órgão; existe para experiência e liberação.", "kleshaTargets": ["avidya"], "qualities": ["vishada"] }, + { "id": "YS.2.19", "text": "Os estágios dos gunas são o específico, o inespecífico, o diferenciado e o indiferenciado.", "kleshaTargets": [], "qualities": ["vishada"] }, + { "id": "YS.2.20", "text": "O que vê é apenas ver; puro, mas vê as imagens da mente.", "kleshaTargets": ["asmita"], "qualities": ["vishada"] }, + { "id": "YS.2.21", "text": "O visto existe apenas para ele.", "kleshaTargets": ["raga"], "qualities": ["vishada"] }, + { "id": "YS.2.22", "text": "Para quem alcançou o fim, o visto desaparece; para outros permanece por ser comum a todos.", "kleshaTargets": ["avidya"], "qualities": ["vishada"] }, + { "id": "YS.2.23", "text": "A união é para conhecer a natureza e o poder de ambos.", "kleshaTargets": ["avidya"], "qualities": ["vishada"] }, + { "id": "YS.2.24", "text": "Sua causa é a ignorância.", "kleshaTargets": ["avidya"], "qualities": ["manda"] }, + { "id": "YS.2.25", "text": "Com o desaparecimento da ignorância, a união desaparece; isso é liberação para o que vê.", "kleshaTargets": ["avidya"], "qualities": ["vishada", "laghu"] }, + { "id": "YS.2.26", "text": "O discernimento ininterrupto é o meio de liberação.", "kleshaTargets": ["avidya"], "qualities": ["vishada"] }, + { "id": "YS.2.27", "text": "Para ele surge a sabedoria em sete estágios.", "kleshaTargets": [], "qualities": ["vishada"] }, + { "id": "YS.2.28", "text": "Pela prática dos membros do yoga, as impurezas se reduzem; surge a luz do discernimento.", "kleshaTargets": ["avidya"], "qualities": ["vishada"] }, + { "id": "YS.2.29", "text": "Os membros são: contenção, disciplina, postura, controle do sopro, retração dos sentidos, concentração, meditação e absorção.", "kleshaTargets": ["raga"], "qualities": ["chala"] }, + { "id": "YS.2.30", "text": "A contenção é não violência, verdade, não roubo, continência e não cobiça.", "kleshaTargets": ["dvesha", "raga"], "qualities": ["tikshna", "khara"] }, + { "id": "YS.2.31", "text": "Esses são universais, não limitados por condição, lugar, tempo ou voto.", "kleshaTargets": [], "qualities": ["vishada"] }, + { "id": "YS.2.32", "text": "A disciplina é pureza, contentamento, austeridade, autoestudo e entrega ao Absoluto.", "kleshaTargets": ["asmita", "raga"], "qualities": ["kathina", "sthira"] }, + { "id": "YS.2.33", "text": "Quando perturbado por pensamentos contrários, cultivar os contrários.", "kleshaTargets": ["dvesha", "raga"], "qualities": ["tikshna", "ushna"] }, + { "id": "YS.2.34", "text": "Pensamentos contrários são violência etc., feitos, provocados ou aprovados por cobiça, raiva ou ilusão.", "kleshaTargets": ["dvesha", "raga"], "qualities": ["tikshna", "khara"] }, + { "id": "YS.2.35", "text": "Na presença de quem está firme na não-violência, a hostilidade cessa.", "kleshaTargets": ["dvesha", "asmita"], "qualities": ["tikshna", "khara"] }, + { "id": "YS.2.36", "text": "Para quem está firme na verdade, ação e fruto dependem dele.", "kleshaTargets": ["avidya"], "qualities": ["vishada"] }, + { "id": "YS.2.37", "text": "Para quem está firme no não roubo, as joias vêm.", "kleshaTargets": ["raga"], "qualities": ["vishada"] }, + { "id": "YS.2.38", "text": "Para quem está firme na continência, vigor surge.", "kleshaTargets": ["raga"], "qualities": ["snigdha", "guru"] }, + { "id": "YS.2.39", "text": "Para quem está firme no não cobiçar, surge o conhecimento do nascimento.", "kleshaTargets": ["raga"], "qualities": ["vishada"] }, + { "id": "YS.2.40", "text": "Pela pureza, surge o desgosto pelo próprio corpo e a não união com outros.", "kleshaTargets": ["raga"], "qualities": ["vishada"] }, + { "id": "YS.2.41", "text": "E também pureza da mente, contentamento, concentração, domínio dos sentidos e aptidão para ver o Ser.", "kleshaTargets": [], "qualities": ["vishada", "laghu"] }, + { "id": "YS.2.42", "text": "Do contentamento surge felicidade suprema.", "kleshaTargets": ["raga"], "qualities": ["snigdha", "guru"] }, + { "id": "YS.2.43", "text": "Pela austeridade, as impurezas do corpo se reduzem; surgem poderes dos sentidos.", "kleshaTargets": ["avidya"], "qualities": ["guru", "manda"] }, + { "id": "YS.2.44", "text": "Pelo autoestudo, união com a divindade desejada.", "kleshaTargets": ["avidya"], "qualities": ["vishada"] }, + { "id": "YS.2.45", "text": "Pela entrega ao Absoluto, a absorção.", "kleshaTargets": ["raga", "abhinivesha"], "qualities": ["guru"] }, + { "id": "YS.2.46", "text": "A postura é estável e confortável.", "kleshaTargets": ["chala"], "qualities": ["chala", "sthira"] }, + { "id": "YS.2.47", "text": "Pelo relaxamento do esforço e pela contemplação do infinito.", "kleshaTargets": ["asmita"], "qualities": ["kathina", "sthira"] }, + { "id": "YS.2.48", "text": "Daí não ser perturbado pelos pares de opostos.", "kleshaTargets": ["raga", "dvesha"], "qualities": ["vishada"] }, + { "id": "YS.2.49", "text": "A partir disso, o controle da inspiração e da expiração.", "kleshaTargets": ["chala"], "qualities": ["chala"] }, + { "id": "YS.2.50", "text": "O sopro é externo, interno ou suspenso; regulado por lugar, tempo e número; longo ou sutil.", "kleshaTargets": ["avidya"], "qualities": ["chala"] }, + { "id": "YS.2.51", "text": "O quarto transcende o externo e o interno.", "kleshaTargets": ["avidya"], "qualities": ["vishada", "sukshma"] }, + { "id": "YS.2.52", "text": "Daí a dissipação do véu que cobre a luz.", "kleshaTargets": ["avidya"], "qualities": ["vishada"] }, + { "id": "YS.2.53", "text": "E a aptidão da mente para a concentração.", "kleshaTargets": ["chala"], "qualities": ["chala", "sthira"] }, + { "id": "YS.2.54", "text": "A retração dos sentidos é como a tartaruga que recolhe os membros.", "kleshaTargets": ["raga"], "qualities": ["chala", "snigdha"] }, + { "id": "YS.2.55", "text": "Daí surge o domínio supremo dos sentidos.", "kleshaTargets": ["raga"], "qualities": ["vishada"] }, + { "id": "YS.3.1", "text": "A concentração é a fixação da mente em um único ponto.", "kleshaTargets": ["chala"], "qualities": ["chala", "sthira"] }, + { "id": "YS.3.2", "text": "A meditação é o fluxo ininterrupto de conhecimento sobre esse ponto.", "kleshaTargets": ["avidya"], "qualities": ["vishada"] }, + { "id": "YS.3.3", "text": "Quando apenas o objeto brilha, como se a mente estivesse vazia de si — isso é absorção.", "kleshaTargets": ["asmita"], "qualities": ["vishada", "laghu"] }, + { "id": "YS.3.4", "text": "Os três juntos formam a restrição.", "kleshaTargets": [], "qualities": ["vishada"] }, + { "id": "YS.3.5", "text": "Por seu domínio surge a luz do discernimento.", "kleshaTargets": ["avidya"], "qualities": ["vishada"] }, + { "id": "YS.3.6", "text": "Sua aplicação é por estágios.", "kleshaTargets": ["raga"], "qualities": ["manda", "guru"] }, + { "id": "YS.3.7", "text": "Os três são mais internos que os anteriores.", "kleshaTargets": [], "qualities": ["vishada"] }, + { "id": "YS.3.8", "text": "Mas mesmo eles são externos em relação ao estado sem semente.", "kleshaTargets": ["abhinivesha"], "qualities": ["guru"] }, + { "id": "YS.3.9", "text": "O momento de dissolução e o de surgimento dominam a transformação.", "kleshaTargets": ["avidya"], "qualities": ["chala"] }, + { "id": "YS.3.10", "text": "O fluxo tranquilo dessa restrição remove o véu.", "kleshaTargets": ["avidya"], "qualities": ["vishada"] } +] diff --git a/lib/dictionaries/sacred/yoga_sutras_full.json b/lib/dictionaries/sacred/yoga_sutras_full.json new file mode 100644 index 0000000..d4396aa --- /dev/null +++ b/lib/dictionaries/sacred/yoga_sutras_full.json @@ -0,0 +1,2872 @@ +[ + { + "id": "YS.1.1", + "text": "Yoga é a cessação das flutuações da mente.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "chala", + "sukshma" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.1.2", + "text": "Quando a mente está em silêncio, o observador repousa em sua própria natureza.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.1.3", + "text": "Então o observador repousa em sua própria natureza.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.1.4", + "text": "No resto do tempo, o observador se identifica com as flutuações.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "chala" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.1.5", + "text": "As flutuações são cinco: dolorosas e não dolorosas.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.1.6", + "text": "São: conhecimento correto, erro, imaginação, sono e memória.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.1.7", + "text": "O conhecimento correto é direto, inferência ou testemunho.", + "kleshaTargets": [], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.1.8", + "text": "O erro é conhecimento falso, sem base no real.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "manda" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.1.9", + "text": "A imaginação segue a palavra, sem objeto real.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "sukshma", + "chala" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.1.10", + "text": "O sono é a flutuação sustentada pela ausência.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "guru", + "tamas" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.1.11", + "text": "A memória é a retenção do experimentado.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "picchila" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.1.12", + "text": "A prática e o desapego são o par que estabiliza a mente.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "chala", + "tikshna" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.1.13", + "text": "O esforço constante para estabilizar a mente é a prática.", + "kleshaTargets": [ + "raga", + "avidya" + ], + "qualities": [ + "chala", + "laghu" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.1.14", + "text": "A prática torna-se firme quando mantida por muito tempo, sem interrupção, com devoção.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "guru", + "manda" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.1.15", + "text": "O desapego é o domínio de quem não deseja nem evita o que vê.", + "kleshaTargets": [ + "raga", + "dvesha" + ], + "qualities": [ + "snigdha", + "guru" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.1.16", + "text": "O ápice do desapego é quando a consciência reconhece sua própria natureza luminosa.", + "kleshaTargets": [], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.1.17", + "text": "A consciência contemplativa acompanha raciocínio, reflexão, alegria e senso de ser.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.1.18", + "text": "A outra é o resíduo de prática; apenas sementes em repouso.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "laghu" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.1.19", + "text": "Para alguns, o estado sem nascimento vem da natureza; para outros, da entrega ao Absoluto.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.1.20", + "text": "Para os outros, a prática é fé, energia, memória, absorção e sabedoria.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "manda" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.1.21", + "text": "Para os intensos, o resultado é próximo.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "tikshna" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.1.22", + "text": "Há diferença: suave, moderado ou intenso.", + "kleshaTargets": [], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.1.23", + "text": "Ou pela entrega ao Absoluto.", + "kleshaTargets": [ + "raga", + "abhinivesha" + ], + "qualities": [ + "guru" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.1.24", + "text": "O Absoluto é um ser especial, intacto pelo sofrimento, ato ou fruto.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.1.25", + "text": "Nele está a semente da onisciência.", + "kleshaTargets": [], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.1.26", + "text": "Ele é o mestre dos antigos, não limitado pelo tempo.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.1.27", + "text": "Sua expressão é o som sagrado.", + "kleshaTargets": [], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.1.28", + "text": "A repetição e a contemplação desse som conduzem.", + "kleshaTargets": [ + "chala" + ], + "qualities": [ + "chala", + "laghu" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.1.29", + "text": "Daí surge o voltar-se para dentro e o desaparecimento dos obstáculos.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.1.30", + "text": "Os obstáculos são: doença, apatia, dúvida, negligência, preguiça, apego ao prazer, erro, não-estabilidade.", + "kleshaTargets": [ + "avidya", + "raga" + ], + "qualities": [ + "guru", + "manda" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.1.31", + "text": "Sofrimento, tristeza, tremor do corpo e respiração irregular acompanham.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "chala", + "ruksha" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.1.32", + "text": "Para removê-los, a prática sobre um único princípio.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "chala" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.1.33", + "text": "Amizade, compaixão, alegria e equanimidade em relação ao que é agradável, doloroso, meritório ou não — acalmam a mente.", + "kleshaTargets": [ + "raga", + "dvesha" + ], + "qualities": [ + "chala", + "ruksha", + "tikshna", + "ushna", + "khara" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.1.34", + "text": "Ou pela expiração e retenção do sopro.", + "kleshaTargets": [ + "chala" + ], + "qualities": [ + "chala" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.1.35", + "text": "A atividade sensorial que fixa a mente surge e estabiliza.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "chala", + "laghu" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.1.36", + "text": "Ou a luz interior, livre de tristeza.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "mridu" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.1.37", + "text": "Ou a mente que abandonou o apego.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "snigdha", + "guru" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.1.38", + "text": "Ou o conhecimento que surge no sono e no sonho.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.1.39", + "text": "Ou pela contemplação do que se deseja.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "chala" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.1.40", + "text": "O domínio vai do infinitamente pequeno ao infinitamente grande.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.1", + "text": "A prática constante e o desapego são os meios.", + "kleshaTargets": [ + "asmita", + "raga" + ], + "qualities": [ + "kathina", + "sthira" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.2", + "text": "Eles reduzem as impurezas e permitem a luz do discernimento.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.3", + "text": "As impurezas são: ignorância, ego, apego, aversão e medo da morte.", + "kleshaTargets": [ + "avidya", + "asmita", + "raga", + "dvesha", + "abhinivesha" + ], + "qualities": [ + "guru" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.4", + "text": "A ignorância é o campo dos outros; eles podem estar adormecidos, enfraquecidos, interrompidos ou ativos.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "manda", + "guru" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.5", + "text": "A ignorância é tomar o impermanente pelo permanente, o impuro pelo puro, a dor pelo prazer, o não-eu pelo eu.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.6", + "text": "O ego é a identificação do que vê com o instrumento do ver; reconhecer isso dissolve o orgulho.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "tikshna", + "kathina" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.7", + "text": "O apego segue o prazer; o desapego nasce do discernimento.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "tikshna", + "ushna" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.8", + "text": "A aversão segue a dor.", + "kleshaTargets": [ + "dvesha" + ], + "qualities": [ + "tikshna", + "ushna", + "khara" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.9", + "text": "O medo da morte habita mesmo no sábio; é inerente à natureza. Observá-lo enfraquece seu poder.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru", + "sandra" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.10", + "text": "Em estado sutil, eles se dissolvem pela volta à origem.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.11", + "text": "Em estado ativo, eles se dissolvem pela meditação.", + "kleshaTargets": [ + "raga", + "dvesha" + ], + "qualities": [ + "chala", + "tikshna" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.12", + "text": "O reservatório do karma tem a raiz nas impurezas e é experimentado no nascimento, na vida e no fruto.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "guru" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.13", + "text": "Enquanto a raiz existir, ele amadurece em nascimento, vida e experiência.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.14", + "text": "Eles têm como fruto o prazer ou a dor, conforme a causa: virtude ou vício.", + "kleshaTargets": [ + "raga", + "dvesha" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.15", + "text": "Para quem discerne, tudo é sofrimento por causa da mudança, da ansiedade e do conflito dos gunas.", + "kleshaTargets": [ + "raga", + "dvesha" + ], + "qualities": [ + "chala", + "tikshna" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.16", + "text": "O sofrimento que ainda não veio pode ser evitado.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.17", + "text": "A causa do evitável é a união do que vê com o visto.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "picchila" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.18", + "text": "O visto tem a natureza da luz, da atividade e da inércia; é feito de elemento e órgão; existe para experiência e liberação.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.19", + "text": "Os estágios dos gunas são o específico, o inespecífico, o diferenciado e o indiferenciado.", + "kleshaTargets": [], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.20", + "text": "O que vê é apenas ver; puro, mas vê as imagens da mente.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.21", + "text": "O visto existe apenas para ele.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.22", + "text": "Para quem alcançou o fim, o visto desaparece; para outros permanece por ser comum a todos.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.23", + "text": "A união é para conhecer a natureza e o poder de ambos.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.24", + "text": "Sua causa é a ignorância.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "manda" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.25", + "text": "Com o desaparecimento da ignorância, a união desaparece; isso é liberação para o que vê.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.26", + "text": "O discernimento ininterrupto é o meio de liberação.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.27", + "text": "Para ele surge a sabedoria em sete estágios.", + "kleshaTargets": [], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.28", + "text": "Pela prática dos membros do yoga, as impurezas se reduzem; surge a luz do discernimento.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.29", + "text": "Os membros são: contenção, disciplina, postura, controle do sopro, retração dos sentidos, concentração, meditação e absorção.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "chala" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.30", + "text": "A contenção é não violência, verdade, não roubo, continência e não cobiça.", + "kleshaTargets": [ + "dvesha", + "raga" + ], + "qualities": [ + "tikshna", + "khara" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.31", + "text": "Esses são universais, não limitados por condição, lugar, tempo ou voto.", + "kleshaTargets": [], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.32", + "text": "A disciplina é pureza, contentamento, austeridade, autoestudo e entrega ao Absoluto.", + "kleshaTargets": [ + "asmita", + "raga" + ], + "qualities": [ + "kathina", + "sthira" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.33", + "text": "Quando perturbado por pensamentos contrários, cultivar os contrários.", + "kleshaTargets": [ + "dvesha", + "raga" + ], + "qualities": [ + "tikshna", + "ushna" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.34", + "text": "Pensamentos contrários são violência etc., feitos, provocados ou aprovados por cobiça, raiva ou ilusão.", + "kleshaTargets": [ + "dvesha", + "raga" + ], + "qualities": [ + "tikshna", + "khara" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.35", + "text": "Na presença de quem está firme na não-violência, a hostilidade cessa.", + "kleshaTargets": [ + "dvesha", + "asmita" + ], + "qualities": [ + "tikshna", + "khara" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.36", + "text": "Para quem está firme na verdade, ação e fruto dependem dele.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.37", + "text": "Para quem está firme no não roubo, as joias vêm.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.38", + "text": "Para quem está firme na continência, vigor surge.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "snigdha", + "guru" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.39", + "text": "Para quem está firme no não cobiçar, surge o conhecimento do nascimento.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.40", + "text": "Pela pureza, surge o desgosto pelo próprio corpo e a não união com outros.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.41", + "text": "E também pureza da mente, contentamento, concentração, domínio dos sentidos e aptidão para ver o Ser.", + "kleshaTargets": [], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.42", + "text": "Do contentamento surge felicidade suprema.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "snigdha", + "guru" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.43", + "text": "Pela austeridade, as impurezas do corpo se reduzem; surgem poderes dos sentidos.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "guru", + "manda" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.44", + "text": "Pelo autoestudo, união com a divindade desejada.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.45", + "text": "Pela entrega ao Absoluto, a absorção.", + "kleshaTargets": [ + "raga", + "abhinivesha" + ], + "qualities": [ + "guru" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.46", + "text": "A postura é estável e confortável.", + "kleshaTargets": [ + "chala" + ], + "qualities": [ + "chala", + "sthira" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.47", + "text": "Pelo relaxamento do esforço e pela contemplação do infinito.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "kathina", + "sthira" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.48", + "text": "Daí não ser perturbado pelos pares de opostos.", + "kleshaTargets": [ + "raga", + "dvesha" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.49", + "text": "A partir disso, o controle da inspiração e da expiração.", + "kleshaTargets": [ + "chala" + ], + "qualities": [ + "chala" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.50", + "text": "O sopro é externo, interno ou suspenso; regulado por lugar, tempo e número; longo ou sutil.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "chala" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.51", + "text": "O quarto transcende o externo e o interno.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "sukshma" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.52", + "text": "Daí a dissipação do véu que cobre a luz.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.53", + "text": "E a aptidão da mente para a concentração.", + "kleshaTargets": [ + "chala" + ], + "qualities": [ + "chala", + "sthira" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.54", + "text": "A retração dos sentidos é como a tartaruga que recolhe os membros.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "chala", + "snigdha" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.2.55", + "text": "Daí surge o domínio supremo dos sentidos.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.3.1", + "text": "A concentração é a fixação da mente em um único ponto.", + "kleshaTargets": [ + "chala" + ], + "qualities": [ + "chala", + "sthira" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.3.2", + "text": "A meditação é o fluxo ininterrupto de conhecimento sobre esse ponto.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.3.3", + "text": "Quando apenas o objeto brilha, como se a mente estivesse vazia de si — isso é absorção.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.3.4", + "text": "Os três juntos formam a restrição.", + "kleshaTargets": [], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.3.5", + "text": "Por seu domínio surge a luz do discernimento.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.3.6", + "text": "Sua aplicação é por estágios.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "manda", + "guru" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.3.7", + "text": "Os três são mais internos que os anteriores.", + "kleshaTargets": [], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.3.8", + "text": "Mas mesmo eles são externos em relação ao estado sem semente.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.3.9", + "text": "O momento de dissolução e o de surgimento dominam a transformação.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "chala" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.3.10", + "text": "O fluxo tranquilo dessa restrição remove o véu.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga", + "mente", + "presença" + ] + }, + { + "id": "YS.1.41", + "text": "Quando a mente se torna como cristal, há união do conhecedor, do conhecido e do ato de conhecer.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "mente", + "concentração" + ] + }, + { + "id": "YS.1.42", + "text": "A absorção com reflexão é a que mistura palavra, significado e conhecimento.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "meditação" + ] + }, + { + "id": "YS.1.43", + "text": "Quando a memória é purificada, a absorção sem reflexão surge; o objeto brilha sozinho.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "vishada", + "laghu" + ], + "themes": [ + "mente", + "presença" + ] + }, + { + "id": "YS.1.44", + "text": "O mesmo se aplica à absorção com e sem semente.", + "kleshaTargets": [], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga" + ] + }, + { + "id": "YS.1.45", + "text": "O estado sem semente tem como objeto o indiferenciado.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru" + ], + "themes": [ + "liberação" + ] + }, + { + "id": "YS.1.46", + "text": "Essas são as absorções com semente.", + "kleshaTargets": [], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga" + ] + }, + { + "id": "YS.1.47", + "text": "Na clareza da absorção sem semente surge a paz.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "presença" + ] + }, + { + "id": "YS.1.48", + "text": "O conhecimento que nasce ali é portador da verdade.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "discernimento" + ] + }, + { + "id": "YS.1.49", + "text": "Diferente do que vem de testemunho ou inferência, pois tem por objeto o particular.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "conhecimento" + ] + }, + { + "id": "YS.1.50", + "text": "A impressão nascida dele obstrui as outras impressões.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "picchila" + ], + "themes": [ + "mente" + ] + }, + { + "id": "YS.1.51", + "text": "Com a obstrução também dessa, surge a absorção sem semente.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru" + ], + "themes": [ + "liberação" + ] + }, + { + "id": "YS.3.11", + "text": "O desaparecimento de toda dispersão e o surgimento da concentração única é o estado de samādhi.", + "kleshaTargets": [ + "chala" + ], + "qualities": [ + "chala", + "sthira" + ], + "themes": [ + "concentração" + ] + }, + { + "id": "YS.3.12", + "text": "Quando o passado e o presente são iguais, surge o fluxo único da mente.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "presença" + ] + }, + { + "id": "YS.3.13", + "text": "Com isso se explicam a transformação das formas, do tempo e do estado.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "transformação" + ] + }, + { + "id": "YS.3.14", + "text": "O substrato é o que possui as qualidades latentes, manifestas ou não manifestas.", + "kleshaTargets": [], + "qualities": [ + "vishada" + ], + "themes": [ + "natureza" + ] + }, + { + "id": "YS.3.15", + "text": "A sucessão das transformações é a causa da sequência.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "chala" + ], + "themes": [ + "tempo" + ] + }, + { + "id": "YS.3.16", + "text": "Pela restrição sobre as três transformações surge o conhecimento do passado e do futuro.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "conhecimento" + ] + }, + { + "id": "YS.3.17", + "text": "A palavra, o objeto e a ideia se confundem; pela restrição sobre eles surge o conhecimento do som de todos os seres.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "escuta" + ] + }, + { + "id": "YS.3.18", + "text": "Pela percepção direta das impressões surge o conhecimento das vidas anteriores.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "picchila" + ], + "themes": [ + "memória" + ] + }, + { + "id": "YS.3.19", + "text": "Pela restrição sobre as marcas mentais surge o conhecimento das mentes de outros.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "empatia" + ] + }, + { + "id": "YS.3.20", + "text": "Não sobre o suporte, pois não é objeto dessa restrição.", + "kleshaTargets": [], + "qualities": [ + "vishada" + ], + "themes": [ + "yoga" + ] + }, + { + "id": "YS.3.21", + "text": "Pela restrição sobre a forma do corpo, cortando a luz e o poder de ser visto, surge o desaparecimento.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "sukshma" + ], + "themes": [ + "corpo" + ] + }, + { + "id": "YS.3.22", + "text": "O karma é rápido ou lento; pela restrição sobre ele surge o conhecimento da morte.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "guru" + ], + "themes": [ + "tempo" + ] + }, + { + "id": "YS.3.23", + "text": "Pela restrição sobre a amizade e outras forças surge o poder delas.", + "kleshaTargets": [ + "raga", + "dvesha" + ], + "qualities": [ + "snigdha" + ], + "themes": [ + "relação" + ] + }, + { + "id": "YS.3.24", + "text": "Pela restrição sobre a força do elefante e outras surge essa força.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "sthira" + ], + "themes": [ + "poder" + ] + }, + { + "id": "YS.3.25", + "text": "O conhecimento do sutil, do oculto e do distante surge pela luz da percepção.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada", + "sukshma" + ], + "themes": [ + "conhecimento" + ] + }, + { + "id": "YS.3.26", + "text": "Pela restrição sobre o sol surge o conhecimento do cosmos.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "cosmos" + ] + }, + { + "id": "YS.3.27", + "text": "Sobre a lua surge o conhecimento da disposição das estrelas.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "tempo" + ] + }, + { + "id": "YS.3.28", + "text": "Sobre a Estrela Polar surge o conhecimento do movimento das estrelas.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "orientação" + ] + }, + { + "id": "YS.3.29", + "text": "Sobre o umbigo surge o conhecimento da constituição do corpo.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "corpo" + ] + }, + { + "id": "YS.3.30", + "text": "Sobre a garganta surge a cessação da fome e da sede.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "snigdha" + ], + "themes": [ + "corpo" + ] + }, + { + "id": "YS.3.31", + "text": "Sobre o tubo curvo surge a estabilidade.", + "kleshaTargets": [ + "chala" + ], + "qualities": [ + "sthira" + ], + "themes": [ + "postura" + ] + }, + { + "id": "YS.3.32", + "text": "Sobre a luz da coroa surge a visão dos Siddhas.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "luz" + ] + }, + { + "id": "YS.3.33", + "text": "Ou por intuição surge todo conhecimento.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "conhecimento" + ] + }, + { + "id": "YS.3.34", + "text": "Sobre o coração surge o conhecimento da mente.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "mente" + ] + }, + { + "id": "YS.3.35", + "text": "A experiência e o Ser não se distinguem; a restrição sobre o que existe por si surge conhecimento do Ser.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "ser" + ] + }, + { + "id": "YS.3.36", + "text": "Daí surgem intuição, audição, tato, visão, paladar e olfato.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "sentidos" + ] + }, + { + "id": "YS.3.37", + "text": "São obstáculos à absorção; poderes na vida dispersa.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "chala" + ], + "themes": [ + "yoga" + ] + }, + { + "id": "YS.3.38", + "text": "Pelo relaxamento do vínculo e pelo conhecimento do fluxo surge a entrada em outro corpo.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "sukshma" + ], + "themes": [ + "transformação" + ] + }, + { + "id": "YS.3.39", + "text": "Pelo domínio do sopro ascendente surge a não aderência à água, ao lodo e às espinas.", + "kleshaTargets": [ + "chala" + ], + "qualities": [ + "laghu" + ], + "themes": [ + "pranayama" + ] + }, + { + "id": "YS.3.40", + "text": "Pelo domínio do sopro mediano surge o brilho.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "luz" + ] + }, + { + "id": "YS.3.41", + "text": "Pela restrição sobre a relação ouvido-espaço surge o ouvido divino.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "escuta" + ] + }, + { + "id": "YS.3.42", + "text": "Pela restrição sobre a relação corpo-espaço e pela leveza do algodão surge a passagem pelo espaço.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "laghu" + ], + "themes": [ + "corpo" + ] + }, + { + "id": "YS.3.43", + "text": "A atividade fora do corpo, não iluminada pela mente, é o véu grande; daí o desaparecimento do véu sobre a luz.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "mente" + ] + }, + { + "id": "YS.3.44", + "text": "Pela restrição sobre o grosseiro, a forma, o sutil, a conexão e o propósito surge o domínio dos elementos.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "elementos" + ] + }, + { + "id": "YS.3.45", + "text": "Daí surgem a minúcia, a perfeição do corpo e a não obstrução das funções.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "corpo" + ] + }, + { + "id": "YS.3.46", + "text": "Perfeição do corpo é beleza, graça, força e firmeza de diamante.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "sthira" + ], + "themes": [ + "corpo" + ] + }, + { + "id": "YS.3.47", + "text": "Pela restrição sobre a percepção, a natureza essencial, o eu e a conexão surge o domínio dos órgãos.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "sentidos" + ] + }, + { + "id": "YS.3.48", + "text": "Daí surgem velocidade como a da mente, ação sem órgãos e domínio da matéria de origem.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "ação" + ] + }, + { + "id": "YS.3.49", + "text": "Só para quem discerne a distinção entre sattva e Ser surge a soberania sobre todos os estados e sobre todo conhecimento.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "discernimento" + ] + }, + { + "id": "YS.3.50", + "text": "Pelo desapego até a isso surge a semente do defeito destruída; isso é kaivalya.", + "kleshaTargets": [ + "raga", + "abhinivesha" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "liberação" + ] + }, + { + "id": "YS.3.51", + "text": "Não haver atração pelos poderes quando convidados pelos guardiões dos mundos seria apego; seria o renascimento.", + "kleshaTargets": [ + "raga" + ], + "qualities": [ + "snigdha" + ], + "themes": [ + "desapego" + ] + }, + { + "id": "YS.3.52", + "text": "Pela restrição sobre o momento e sua sucessão surge o conhecimento nascido do discernimento.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "tempo" + ] + }, + { + "id": "YS.3.53", + "text": "Daí surge o discernimento do que é igual em espécie, caráter e lugar.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "conhecimento" + ] + }, + { + "id": "YS.3.54", + "text": "O conhecimento nascido do discernimento é portador de tudo, em todo tempo, sem sucessão.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "conhecimento" + ] + }, + { + "id": "YS.3.55", + "text": "Quando a pureza de sattva e do Ser é igual, surge kaivalya.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "liberação" + ] + }, + { + "id": "YS.3.56", + "text": "Kaivalya é estabelecido quando os três gunas esgotaram seu propósito para o que vê.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "liberação" + ] + }, + { + "id": "YS.4.1", + "text": "Os poderes nascem do nascimento, de ervas, de mantra, de austeridade ou de absorção.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "liberação", + "mente", + "yoga" + ] + }, + { + "id": "YS.4.2", + "text": "A transformação em outra espécie é pelo preenchimento da natureza.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "liberação", + "mente", + "yoga" + ] + }, + { + "id": "YS.4.3", + "text": "O obstáculo não é causa; ele apenas remove o obstáculo, como o agricultor.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "liberação", + "mente", + "yoga" + ] + }, + { + "id": "YS.4.4", + "text": "Só a mente criada é o nascimento dos mundos criados.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "liberação", + "mente", + "yoga" + ] + }, + { + "id": "YS.4.5", + "text": "Mentes diversas têm um único objeto de concentração.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "liberação", + "mente", + "yoga" + ] + }, + { + "id": "YS.4.6", + "text": "A que tem meditação como semente é a que não nasce de outra.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "liberação", + "mente", + "yoga" + ] + }, + { + "id": "YS.4.7", + "text": "A ação do yogi não é branca nem negra; a dos outros é de três tipos.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "liberação", + "mente", + "yoga" + ] + }, + { + "id": "YS.4.8", + "text": "Delas surgem apenas as impressões para o fruto a ser experimentado.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "liberação", + "mente", + "yoga" + ] + }, + { + "id": "YS.4.9", + "text": "Memória e impressão têm a mesma forma; mesmo com separação de nascimento, lugar e tempo há continuidade.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "liberação", + "mente", + "yoga" + ] + }, + { + "id": "YS.4.10", + "text": "Não têm começo; o desejo de permanência é inato.", + "kleshaTargets": [ + "avidya" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "liberação", + "mente", + "yoga" + ] + }, + { + "id": "YS.4.11", + "text": "Sendo sustentadas por causa, efeito, suporte e objeto, elas desaparecem quando elas desaparecem.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "liberação", + "mente", + "yoga" + ] + }, + { + "id": "YS.4.12", + "text": "O passado e o futuro existem em sua própria natureza; a diferença está nos caminhos da característica.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "liberação", + "mente", + "yoga" + ] + }, + { + "id": "YS.4.13", + "text": "Elas são manifestas ou sutis; têm a natureza dos gunas.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "liberação", + "mente", + "yoga" + ] + }, + { + "id": "YS.4.14", + "text": "A realidade do objeto está na unicidade da transformação.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "liberação", + "mente", + "yoga" + ] + }, + { + "id": "YS.4.15", + "text": "O objeto sendo o mesmo, a diferença das mentes é a diferença dos dois.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "liberação", + "mente", + "yoga" + ] + }, + { + "id": "YS.4.16", + "text": "E o objeto não depende de uma única mente; o que aconteceria quando não fosse percebido?", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "liberação", + "mente", + "yoga" + ] + }, + { + "id": "YS.4.17", + "text": "O objeto é conhecido ou não pela mente que ele tinge.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "liberação", + "mente", + "yoga" + ] + }, + { + "id": "YS.4.18", + "text": "Sempre conhecida a mente que governa; ela não é tingida, pois é estável.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "liberação", + "mente", + "yoga" + ] + }, + { + "id": "YS.4.19", + "text": "Ela não se vê a si mesma.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "liberação", + "mente", + "yoga" + ] + }, + { + "id": "YS.4.20", + "text": "Não há dupla apresentação ao mesmo tempo.", + "kleshaTargets": [ + "asmita" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "liberação", + "mente", + "yoga" + ] + }, + { + "id": "YS.4.21", + "text": "Se a outra fosse vista por outra mente, haveria regressão ao infinito e confusão de memória.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "liberação", + "mente", + "yoga" + ] + }, + { + "id": "YS.4.22", + "text": "Quando a natureza da consciência assume a forma, surge a consciência de si.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "liberação", + "mente", + "yoga" + ] + }, + { + "id": "YS.4.23", + "text": "A mente, tingida pelo que vê e pelo que vê, percebe todos os objetos.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "liberação", + "mente", + "yoga" + ] + }, + { + "id": "YS.4.24", + "text": "Ela existe para outro, pois é composta de inúmeras impressões.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "liberação", + "mente", + "yoga" + ] + }, + { + "id": "YS.4.25", + "text": "Para quem vê a distinção, cessa a reflexão sobre a própria natureza.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "liberação", + "mente", + "yoga" + ] + }, + { + "id": "YS.4.26", + "text": "Então a mente inclina para o discernimento e caminha para kaivalya.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "liberação", + "mente", + "yoga" + ] + }, + { + "id": "YS.4.27", + "text": "No meio surgem as impressões da distinção por causa das falhas.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "liberação", + "mente", + "yoga" + ] + }, + { + "id": "YS.4.28", + "text": "A remoção delas é como a dos kleshas.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "liberação", + "mente", + "yoga" + ] + }, + { + "id": "YS.4.29", + "text": "Quem, mesmo no fruto do discernimento, permanece em desapego total, surge o samādhi da nuvem de dharma.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "liberação", + "mente", + "yoga" + ] + }, + { + "id": "YS.4.30", + "text": " Daí cessa o sofrimento e a ação.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "liberação", + "mente", + "yoga" + ] + }, + { + "id": "YS.4.31", + "text": "Então o conhecimento livre de impurezas e de cobertura é infinito; o conhecível é pouco.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "liberação", + "mente", + "yoga" + ] + }, + { + "id": "YS.4.32", + "text": " Com isso os gunas esgotaram sua sequência de fins; a transformação cessa.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "liberação", + "mente", + "yoga" + ] + }, + { + "id": "YS.4.33", + "text": "A sequência é o momento; percebido no último instante.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "liberação", + "mente", + "yoga" + ] + }, + { + "id": "YS.4.34", + "text": "Kaivalya é a reversão dos gunas, sem propósito para o que vê; o estabelecimento do poder do que vê em sua própria natureza.", + "kleshaTargets": [ + "abhinivesha" + ], + "qualities": [ + "vishada" + ], + "themes": [ + "liberação", + "mente", + "yoga" + ] + } +] \ No newline at end of file diff --git a/lib/engines/buildSymbolicMap.ts b/lib/engines/buildSymbolicMap.ts new file mode 100644 index 0000000..90ddda0 --- /dev/null +++ b/lib/engines/buildSymbolicMap.ts @@ -0,0 +1,34 @@ +/** + * SymbolicMap universal — núcleo do Darshan offline. + * Core → Jyotish + Numerologia + Human Design (só símbolos). + * Inicializa Swiss Ephemeris (se instalado) antes de calcular, para priorizar alta precisão. + */ + +import type { CoreProfile } from "@/lib/core/types"; +import type { AstronomicalCore } from "@/lib/core/types"; +import { computeAstronomicalCore } from "@/lib/core/ephemerisResolver"; +import { initSwissEphemeris } from "@/lib/core/providers/swissProvider"; +import { jyotishEngine } from "./jyotishEngine"; +import { numerologyEngine } from "./numerologyEngine"; +import { humanDesignEngine } from "./humanDesignEngine"; +import type { JyotishEngineResult } from "./jyotishEngine"; +import type { NumerologyEngineResult } from "./numerologyEngine"; +import type { HumanDesignEngineResult } from "./humanDesignEngine"; + +export type SymbolicMap = { + core: AstronomicalCore; + jyotish: JyotishEngineResult; + numerology: NumerologyEngineResult; + humanDesign: HumanDesignEngineResult; +}; + +export async function buildSymbolicMap(profile: CoreProfile): Promise { + await initSwissEphemeris(); + const core = computeAstronomicalCore(profile); + return { + core, + jyotish: jyotishEngine(core), + numerology: numerologyEngine(profile), + humanDesign: humanDesignEngine(core), + }; +} diff --git a/lib/engines/humanDesignEngine.ts b/lib/engines/humanDesignEngine.ts new file mode 100644 index 0000000..7fca58f --- /dev/null +++ b/lib/engines/humanDesignEngine.ts @@ -0,0 +1,22 @@ +/** + * Human Design Engine — plugável; stub por enquanto (cálculo real depois). + * Só produz dados quando core tem planetas (ex.: Swiss Ephemeris). + */ + +import type { AstronomicalCore } from "@/lib/core/types"; + +export type HumanDesignEngineResult = { + type: string; + authority: string; + profile: string; +} | null; + +export function humanDesignEngine(core: AstronomicalCore): HumanDesignEngineResult { + if (!core.planets) return null; + // Stub: cálculo real de BodyGraph (gates, channels, tipo, autoridade) virá depois + return { + type: "Generator", + authority: "Emotional", + profile: "4/6", + }; +} diff --git a/lib/engines/jyotishEngine.ts b/lib/engines/jyotishEngine.ts new file mode 100644 index 0000000..d3a53fe --- /dev/null +++ b/lib/engines/jyotishEngine.ts @@ -0,0 +1,73 @@ +/** + * Jyotish Engine — só símbolos a partir do AstronomicalCore; nunca texto. + * calculate() → resultado bruto; getNakshatraProfile() → perfil interpretativo; detectYogas() → combinações. + */ + +import type { AstronomicalCore } from "@/lib/core/types"; +import type { RashiKey } from "@/lib/knowledge/types"; +import { NAKSHATRA_MEANINGS } from "@/lib/knowledge/jyotishMeanings"; +import { getArchetypeKeysFromChart } from "@/lib/knowledge/archetypes"; + +export type JyotishEngineResult = { + moonRashi: string | null; + nakshatra: string | null; + planets: Record | null; + houses: Record | null; + precisionLevel: string; +}; + +/** Cálculo Jyotish a partir do core (alias: calculate). */ +export function jyotishEngine(core: AstronomicalCore): JyotishEngineResult { + return { + moonRashi: core.moonRashi ?? null, + nakshatra: core.nakshatra ?? null, + planets: core.planets ?? null, + houses: core.houses ?? null, + precisionLevel: core.providerUsed, + }; +} + +/** Alias para API externa: JyotishEngine.calculate(core). */ +export const calculate = jyotishEngine; + +/** Perfil da nakshatra lunar: significados e arquétipos (para Composer/Readings). */ +export type NakshatraProfile = { + nakshatra: string; + moonRashi: string | null; + namePt?: string; + consciousnessThemes?: string[]; + psychologicalEffects?: string[]; + archetypeHints: string[]; +}; + +export function getNakshatraProfile(core: AstronomicalCore): NakshatraProfile | null { + const nakshatra = core.nakshatra ?? null; + const moonRashi = core.moonRashi ?? null; + if (!nakshatra) return null; + const entry = NAKSHATRA_MEANINGS.find((e) => e.key === nakshatra); + const archetypeHints = getArchetypeKeysFromChart({ + moonRashi: (moonRashi ?? undefined) as RashiKey | undefined, + moonNakshatra: nakshatra, + }); + return { + nakshatra, + moonRashi, + namePt: entry?.namePt, + consciousnessThemes: entry?.consciousnessThemes, + psychologicalEffects: entry?.psychologicalEffects, + archetypeHints, + }; +} + +/** Yogas detectados a partir do core (combinações planetárias/signos). Expandir depois com Neecha Bhanga, etc. */ +export function detectYogas(core: AstronomicalCore): string[] { + const yogas: string[] = []; + if (core.nakshatra) yogas.push(`nakshatra-${core.nakshatra}`); + if (core.moonRashi) yogas.push(`moon-in-${core.moonRashi}`); + if (core.planets?.moon != null && core.planets?.sun != null) { + const moonSign = Math.floor((core.planets.moon % 360) / 30); + const sunSign = Math.floor((core.planets.sun % 360) / 30); + if (moonSign === sunSign) yogas.push("chandra-surya-same-sign"); + } + return yogas; +} diff --git a/lib/engines/numerologyEngine.ts b/lib/engines/numerologyEngine.ts new file mode 100644 index 0000000..3b35e96 --- /dev/null +++ b/lib/engines/numerologyEngine.ts @@ -0,0 +1,52 @@ +/** + * Numerologia Engine — numerologia completa (ruling, life path, expression, soul urge, personality). + * Usa lib/knowledge/numerology como fonte única. + */ + +import { + getRulingNumberFromName, + getNumberTraits, + getLifePathNumber, + getExpressionNumber, + getSoulUrgeNumber, + getPersonalityNumber, +} from "@/lib/knowledge/numerology"; +import type { CoreProfile } from "@/lib/core/types"; + +export type NumerologyEngineResult = { + rulingNumber: number; + name: string; + shortTrait: string; + tendencies: string[]; + challenges: string[]; + /** Life Path (data de nascimento) — 1–9, 11, 22 */ + lifePathNumber?: number; + /** Expression/Destiny (nome completo) */ + expressionNumber?: number; + /** Soul Urge (vogais do nome) — desejo interior */ + soulUrgeNumber?: number; + /** Personality (consoantes do nome) — máscara social */ + personalityNumber?: number; +}; + +export function numerologyEngine(profile: CoreProfile): NumerologyEngineResult { + const fullName = profile.fullName ?? ""; + const birthDate = profile.birthDate ?? ""; + const rulingNumber = getRulingNumberFromName(fullName); + const traits = getNumberTraits(rulingNumber); + const lifePathNumber = getLifePathNumber(birthDate); + const expressionNumber = getExpressionNumber(fullName); + const soulUrgeNumber = getSoulUrgeNumber(fullName); + const personalityNumber = getPersonalityNumber(fullName); + return { + rulingNumber, + name: traits.name, + shortTrait: traits.shortTrait, + tendencies: traits.tendencies, + challenges: traits.challenges, + lifePathNumber: lifePathNumber as number, + expressionNumber: expressionNumber as number, + soulUrgeNumber: soulUrgeNumber as number, + personalityNumber: personalityNumber as number, + }; +} diff --git a/lib/history/historyAdapter.ts b/lib/history/historyAdapter.ts new file mode 100644 index 0000000..45c2432 --- /dev/null +++ b/lib/history/historyAdapter.ts @@ -0,0 +1,49 @@ +/** + * Adapter de histórico para Instant Light — cooldown server-side autônomo. + * getRecentSacredIds / getRecentStateKeys para avoidIds; recordInstantLight grava o Truth Package. + * Delega para historyStorage (Supabase). + */ + +import { getRecentInstantLightIds, recordInstantLightUse } from "@/lib/historyStorage"; +import type { DarshanTruthPackage } from "@/lib/core/DarshanTruthPackage"; + +/** + * Retorna sacredIds recentes do usuário (últimos N dias) para evitar repetição. + */ +export async function getRecentSacredIds( + userKey: string, + sinceDays: number = 7, + limit: number = 50 +): Promise { + const { sacredIds } = await getRecentInstantLightIds(userKey, limit, sinceDays); + return sacredIds; +} + +/** + * Retorna stateKeys recentes do usuário (últimos N dias) para evitar repetição. + */ +export async function getRecentStateKeys( + userKey: string, + sinceDays: number = 7, + limit: number = 50 +): Promise { + const { stateKeys } = await getRecentInstantLightIds(userKey, limit, sinceDays); + return stateKeys; +} + +/** + * Registra uso do Instant Light (Truth Package) para cooldown. + * Cliente não controla cooldown; o servidor grava automaticamente. + */ +export async function recordInstantLight( + userKey: string, + truthPackage: DarshanTruthPackage +): Promise { + const sacredId = truthPackage.sacred?.id + ? `${truthPackage.sacred.corpus ?? "legacy"}.${truthPackage.sacred.id}` + : ""; + await recordInstantLightUse(userKey, { + sacredId: sacredId || "unknown", + stateKey: truthPackage.stateKey, + }); +} diff --git a/lib/history/index.ts b/lib/history/index.ts new file mode 100644 index 0000000..5139239 --- /dev/null +++ b/lib/history/index.ts @@ -0,0 +1,10 @@ +/** + * Histórico e cooldown — adapter para Instant Light (sacredIds/stateKeys recentes, recordInstantLight). + * Delega para historyStorage (Supabase). + */ + +export { + getRecentSacredIds, + getRecentStateKeys, + recordInstantLight, +} from "./historyAdapter"; diff --git a/lib/historyStorage.ts b/lib/historyStorage.ts new file mode 100644 index 0000000..6b42c8e --- /dev/null +++ b/lib/historyStorage.ts @@ -0,0 +1,175 @@ +/** + * Armazenamento de histórico: respostas (orb) e leituras. + * Usa Supabase; se não configurado, as funções não fazem nada (silencioso). + */ + +import { getSupabase, isSupabaseConfigured } from "@/lib/supabase"; + +export type RevelationRow = { + id: string; + user_id: string; + question_text: string | null; + response_text: string; + created_at: string; +}; + +export type ReadingRow = { + id: string; + user_id: string; + content: string; + created_at: string; +}; + +/** Obtém user_id pelo email (apenas busca; não cria usuário). */ +export async function getUserIdByEmail(email: string): Promise { + const supabase = getSupabase(); + if (!supabase || !isSupabaseConfigured()) return null; + const { data } = await supabase + .from("users") + .select("id") + .eq("email", email) + .single(); + return data?.id ?? null; +} + +/** Salva uma revelação (resposta do orb) para o usuário. */ +export async function saveRevelation( + userEmail: string, + payload: { questionText?: string | null; responseText: string } +): Promise { + const supabase = getSupabase(); + if (!supabase || !isSupabaseConfigured()) return null; + const userId = await getUserIdByEmail(userEmail); + if (!userId) return null; + const { data, error } = await supabase + .from("revelations") + .insert({ + user_id: userId, + question_text: payload.questionText?.trim() || null, + response_text: payload.responseText.trim().slice(0, 50000), + }) + .select("id") + .single(); + if (error) return null; + return data?.id ?? null; +} + +/** Salva uma leitura (mapa pessoal) para o usuário. */ +export async function saveReading(userEmail: string, content: string): Promise { + const supabase = getSupabase(); + if (!supabase || !isSupabaseConfigured()) return null; + const userId = await getUserIdByEmail(userEmail); + if (!userId) return null; + const { data, error } = await supabase + .from("readings") + .insert({ + user_id: userId, + content: content.trim().slice(0, 100000), + }) + .select("id") + .single(); + if (error) return null; + return data?.id ?? null; +} + +/** Lista revelações do usuário (mais recentes primeiro). */ +export async function listRevelations( + userEmail: string, + options: { limit?: number; offset?: number } = {} +): Promise { + const supabase = getSupabase(); + if (!supabase || !isSupabaseConfigured()) return []; + const userId = await getUserIdByEmail(userEmail); + if (!userId) return []; + const limit = Math.min(Math.max(1, options.limit ?? 50), 100); + const offset = Math.max(0, options.offset ?? 0); + const { data } = await supabase + .from("revelations") + .select("id, user_id, question_text, response_text, created_at") + .eq("user_id", userId) + .order("created_at", { ascending: false }) + .range(offset, offset + limit - 1); + return (data ?? []) as RevelationRow[]; +} + +/** Lista leituras do usuário (mais recentes primeiro). */ +export async function listReadings( + userEmail: string, + options: { limit?: number; offset?: number } = {} +): Promise { + const supabase = getSupabase(); + if (!supabase || !isSupabaseConfigured()) return []; + const userId = await getUserIdByEmail(userEmail); + if (!userId) return []; + const limit = Math.min(Math.max(1, options.limit ?? 50), 100); + const offset = Math.max(0, options.offset ?? 0); + const { data } = await supabase + .from("readings") + .select("id, user_id, content, created_at") + .eq("user_id", userId) + .order("created_at", { ascending: false }) + .range(offset, offset + limit - 1); + return (data ?? []) as ReadingRow[]; +} + +/** Conta revelações e leituras do usuário (para exibir ícone quando > 0). */ +export async function getHistoryCounts(userEmail: string): Promise<{ revelations: number; readings: number }> { + const supabase = getSupabase(); + if (!supabase || !isSupabaseConfigured()) return { revelations: 0, readings: 0 }; + const userId = await getUserIdByEmail(userEmail); + if (!userId) return { revelations: 0, readings: 0 }; + const [rev, read] = await Promise.all([ + supabase.from("revelations").select("id", { count: "exact", head: true }).eq("user_id", userId), + supabase.from("readings").select("id", { count: "exact", head: true }).eq("user_id", userId), + ]); + return { + revelations: rev.count ?? 0, + readings: read.count ?? 0, + }; +} + +/** Cooldown server-side: retorna sacredIds e stateKeys recentes do usuário (evitar repetição). + * Se sinceDays for informado (ex.: 7), só retorna usos dos últimos N dias — cooldown de 7 dias por sacredId. */ +export async function getRecentInstantLightIds( + userEmail: string, + limit: number = 20, + sinceDays?: number +): Promise<{ sacredIds: string[]; stateKeys: string[] }> { + const supabase = getSupabase(); + if (!supabase || !isSupabaseConfigured()) return { sacredIds: [], stateKeys: [] }; + const userId = await getUserIdByEmail(userEmail); + if (!userId) return { sacredIds: [], stateKeys: [] }; + const cap = Math.min(Math.max(1, limit), 50); + let query = supabase + .from("instant_light_uses") + .select("sacred_id, state_key") + .eq("user_id", userId) + .order("created_at", { ascending: false }) + .limit(cap); + if (sinceDays != null && sinceDays > 0) { + const since = new Date(Date.now() - sinceDays * 24 * 60 * 60 * 1000).toISOString(); + query = query.gte("created_at", since); + } + const { data } = await query; + const rows = (data ?? []) as { sacred_id: string; state_key: string | null }[]; + return { + sacredIds: rows.map((r) => r.sacred_id).filter(Boolean), + stateKeys: rows.map((r) => r.state_key).filter((k): k is string => Boolean(k)), + }; +} + +/** Cooldown server-side: registra uso de sacredId/stateKey para o usuário (recordUse automático). */ +export async function recordInstantLightUse( + userEmail: string, + payload: { sacredId: string; stateKey?: string } +): Promise { + const supabase = getSupabase(); + if (!supabase || !isSupabaseConfigured()) return; + const userId = await getUserIdByEmail(userEmail); + if (!userId) return; + await supabase.from("instant_light_uses").insert({ + user_id: userId, + sacred_id: payload.sacredId?.trim() || "", + state_key: payload.stateKey?.trim() || null, + }); +} diff --git a/lib/input/index.ts b/lib/input/index.ts new file mode 100644 index 0000000..3064332 --- /dev/null +++ b/lib/input/index.ts @@ -0,0 +1,10 @@ +/** + * Input layer — Intent Parser e State Scorer offline. + * Classificação multi-eixo (verbo, sujeito, tema, emoção) → bestStateKey para RemedyMatrix. + */ + +export { parseIntent } from "./intentParser"; +export type { ParsedIntent, SubjectKey, VerbClassKey, ThemeKey, StateKey, StateCandidate } from "./intentParser"; +export { scoreState, pickBestState } from "./stateScorer"; +export type { PickBestStateResult } from "./stateScorer"; +export { normalizeInput } from "./normalizeInput"; diff --git a/lib/input/intentParser.ts b/lib/input/intentParser.ts new file mode 100644 index 0000000..7bd86a2 --- /dev/null +++ b/lib/input/intentParser.ts @@ -0,0 +1,187 @@ +/** + * Intent Parser offline — classificação multi-eixo do input do usuário. + * Verbo, sujeito, tema, tipo de pergunta e emoção → stateCandidates ranqueados. + * Sem IA; matching determinístico por dicionários. + */ + +import { normalizeInput } from "./normalizeInput"; +import inputVerbsJson from "@/lib/dictionaries/inputVerbs.json"; +import inputThemesJson from "@/lib/dictionaries/inputThemes.json"; +import inputEmotionsJson from "@/lib/dictionaries/inputEmotions.json"; +import inputQuestionsJson from "@/lib/dictionaries/inputQuestions.json"; + +export type SubjectKey = "self" | "other" | "relational"; +export type VerbClassKey = "feel" | "seek" | "fear" | "conflict" | "reflect"; +export type ThemeKey = "general" | "love" | "career" | "year" | "health" | "spirituality"; +export type QuestionTypeKey = "what" | "how" | "why" | "when" | "where" | "who"; + +/** Estado da RemedyMatrix (ex.: anxiety, grief) */ +export type StateKey = string; + +export type StateCandidate = { + stateKey: string; + score: number; + matched: string[]; +}; + +export type ParsedIntent = { + subject: SubjectKey; + verbClass: VerbClassKey | null; + theme: ThemeKey; + questionType?: QuestionTypeKey | null; + emotionLabels: string[]; + stateCandidates: StateCandidate[]; + tokens?: string[]; +}; + +type InputVerbsSchema = Record; +type InputThemesSchema = Record; +/** Aceita formato stateKey → keywords[] ou emotionLabel → { keywords, stateKeys } */ +type InputEmotionsSchema = Record< + string, + string[] | { keywords: string[]; stateKeys: string[] } +>; +type InputQuestionsSchema = Record; + +const INPUT_VERBS = inputVerbsJson as InputVerbsSchema; +const INPUT_THEMES = inputThemesJson as InputThemesSchema; +const INPUT_EMOTIONS = inputEmotionsJson as InputEmotionsSchema; +const INPUT_QUESTIONS = inputQuestionsJson as InputQuestionsSchema; + +function normalize(text: string): string { + return text + .toLowerCase() + .normalize("NFD") + .replace(/\p{M}/gu, "") + .trim(); +} + +function findVerbClass(normal: string): VerbClassKey | null { + for (const [verb, phrases] of Object.entries(INPUT_VERBS)) { + if (!Array.isArray(phrases)) continue; + for (const p of phrases) { + if (normal.includes(normalize(p))) return verb as VerbClassKey; + } + } + return null; +} + +function findSubject(normal: string): SubjectKey { + const selfMarkers = ["eu ", "meu ", "minha ", "me ", "comigo", "estou ", "sinto "]; + const otherMarkers = ["ele ", "ela ", "dele", "dela", "ele.", "ela.", "outro", "outra"]; + const relMarkers = ["nós", "nosso", "nossa", "nos ", "conosco"]; + for (const m of relMarkers) { + if (normal.includes(m)) return "relational"; + } + for (const m of otherMarkers) { + if (normal.includes(m)) return "other"; + } + for (const m of selfMarkers) { + if (normal.includes(m)) return "self"; + } + return "self"; +} + +function findTheme(normal: string): ThemeKey { + let best: ThemeKey = "general"; + let bestLen = 0; + for (const [theme, keywords] of Object.entries(INPUT_THEMES)) { + if (!Array.isArray(keywords)) continue; + for (const kw of keywords) { + if (kw && normal.includes(normalize(kw)) && kw.length > bestLen) { + best = theme as ThemeKey; + bestLen = kw.length; + } + } + } + return best; +} + +function findQuestionType(normal: string): QuestionTypeKey | null { + for (const [qType, phrases] of Object.entries(INPUT_QUESTIONS)) { + if (!Array.isArray(phrases)) continue; + for (const p of phrases) { + if (normal.includes(normalize(p))) return qType as QuestionTypeKey; + } + } + return null; +} + +function findEmotionsAndStates(normal: string): { + emotionLabels: string[]; + stateCandidates: StateCandidate[]; +} { + const emotionLabels: string[] = []; + const stateScores = new Map(); + for (const [key, data] of Object.entries(INPUT_EMOTIONS)) { + let keywords: string[]; + let stateKeys: string[]; + if (Array.isArray(data) && data.length > 0) { + keywords = data; + stateKeys = [key]; + } else if (data && typeof data === "object" && !Array.isArray(data)) { + const entry = data as { keywords: string[]; stateKeys: string[] }; + if (!entry?.keywords?.length || !entry?.stateKeys?.length) continue; + keywords = entry.keywords; + stateKeys = entry.stateKeys; + } else continue; + const matched: string[] = []; + for (const kw of keywords) { + if (kw && normal.includes(normalize(kw))) { + matched.push(kw); + } + } + if (matched.length > 0) { + emotionLabels.push(key); + const compoundBonus = normal.includes("medo de perder") || normal.includes("medo de") ? 1 : 0; + const score = matched.length + compoundBonus; + for (const sk of stateKeys) { + const prev = stateScores.get(sk); + if (!prev || score > prev.score) { + stateScores.set(sk, { score, matched: [...matched] }); + } else if (score === prev.score) { + prev.matched = [...new Set([...prev.matched, ...matched])]; + } + } + } + } + const stateCandidates: StateCandidate[] = Array.from(stateScores.entries()).map( + ([stateKey, { score, matched }]) => ({ stateKey, score, matched }) + ); + stateCandidates.sort((a, b) => b.score - a.score); + return { emotionLabels, stateCandidates }; +} + +/** + * Classifica o texto do usuário em eixos: verbo, sujeito, tema, pergunta, emoção → stateCandidates ranqueados. + * Usa normalizeInput (abreviações + ruído) antes do matching. + */ +export function parseIntent(userText: string | null | undefined): ParsedIntent | null { + if (userText == null || typeof userText !== "string") return null; + const raw = userText.trim(); + if (raw.length === 0) return null; + const preprocessed = normalizeInput(raw); + const normal = preprocessed + .toLowerCase() + .normalize("NFD") + .replace(/\p{M}/gu, "") + .trim(); + if (normal.length === 0) return null; + + const verbClass = findVerbClass(normal); + const subject = findSubject(normal); + const theme = findTheme(normal); + const questionType = findQuestionType(normal); + const { emotionLabels, stateCandidates } = findEmotionsAndStates(normal); + const tokens = normal.split(/\s+/).filter(Boolean); + + return { + subject, + verbClass, + theme, + questionType: questionType ?? undefined, + emotionLabels, + stateCandidates, + tokens, + }; +} diff --git a/lib/input/normalizeInput.ts b/lib/input/normalizeInput.ts new file mode 100644 index 0000000..a0fd8dd --- /dev/null +++ b/lib/input/normalizeInput.ts @@ -0,0 +1,85 @@ +/** + * Normalização do input do usuário para matching offline. + * Roda antes de qualquer parsing. + * + * 1. lowercase + * 2. remove acentos (á → a, ç → c) + * 3. aplica abreviações WhatsApp via inputNormalization.json (tô → estou, vc → você, etc.) + * 4. remove ruído ("tipo", "mano", "cara", etc.) + * 5. colapsa espaços + */ + +import inputNormalizationJson from "@/lib/dictionaries/inputNormalization.json"; + +type NormalizationMap = Record; + +const NORMALIZATION_MAP = inputNormalizationJson as NormalizationMap; + +/** Palavras de ruído a remover (não afetam intent) */ +const NOISE_WORDS = new Set([ + "tipo", "mano", "cara", "então", "entao", "assim", "tipo assim", + "aí", "ai", "daí", "dai", "né", "ne", "entendeu", "sabe", +]); + +/** + * Remove acentos (NFD + remove combining marks). + */ +function removeAccents(text: string): string { + return text + .normalize("NFD") + .replace(/\p{M}/gu, "") + .trim(); +} + +/** + * Aplica substituições do dicionário (abreviações → forma expandida). + * Ordena por tamanho decrescente para aplicar "tô" antes de "t" se existir. + */ +function applyNormalizationMap(text: string): string { + let out = text; + const entries = Object.entries(NORMALIZATION_MAP) + .filter(([, v]) => v != null && String(v).length > 0) + .sort(([a], [b]) => b.length - a.length); + for (const [key, value] of entries) { + const k = key.toLowerCase(); + const v = String(value).toLowerCase(); + const re = new RegExp(`\\b${escapeRe(k)}\\b`, "gi"); + out = out.replace(re, v); + } + return out; +} + +function escapeRe(s: string): string { + return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); +} + +/** + * Remove palavras de ruído. + */ +function removeNoiseWords(text: string): string { + const words = text.split(/\s+/).filter((w) => { + const lower = w.toLowerCase(); + return lower.length > 0 && !NOISE_WORDS.has(removeAccents(lower)); + }); + return words.join(" ").trim(); +} + +/** + * Normaliza o texto do usuário para matching: + * 1. Trim + * 2. Lower-case + * 3. Aplica inputNormalization (abreviações) + * 4. Remove acentos + * 5. Remove palavras de ruído + * 6. Colapsa espaços múltiplos + */ +export function normalizeInput(userText: string | null | undefined): string { + if (userText == null || typeof userText !== "string") return ""; + let s = userText.trim().toLowerCase(); + if (s.length === 0) return ""; + s = applyNormalizationMap(s); + s = removeAccents(s); + s = removeNoiseWords(s); + s = s.replace(/\s+/g, " ").trim(); + return s; +} diff --git a/lib/input/stateScorer.ts b/lib/input/stateScorer.ts new file mode 100644 index 0000000..d3f4b11 --- /dev/null +++ b/lib/input/stateScorer.ts @@ -0,0 +1,134 @@ +/** + * State Scorer — escolhe o bestStateKey a partir do ParsedIntent. + * Pesos: base (parser score) + verbClass fear +2, tema +1, sujeito other +1. + * Frase composta (ex.: "medo de perder") já vem com score maior do parser. + * Só retorna estados que existem na RemedyMatrix. + */ + +import type { ParsedIntent, StateCandidate } from "./intentParser"; +import remedyMatrixJson from "@/lib/dictionaries/remedyMatrix.json"; + +type RemedyEntry = { state: string }; +const REMEDY_MATRIX = remedyMatrixJson as RemedyEntry[]; +const VALID_STATES = new Set(REMEDY_MATRIX.map((e) => e.state)); + +/** Pesos por eixo */ +const WEIGHT_VERB_FEAR = 2; +const WEIGHT_THEME = 1; +const WEIGHT_SUBJECT_OTHER = 1; +/** fear + love → attachment / fear_of_loss (relational_insecurity) em destaque */ +const WEIGHT_FEAR_AND_LOVE = 2; + +/** verbClass fear → estados que ganham bônus */ +const FEAR_STATES = new Set([ + "anxiety", + "existential_fear", + "relational_insecurity", + "avoidance", +]); + +/** theme love → estados que ganham bônus */ +const LOVE_STATES = new Set([ + "emotional_attachment", + "relational_insecurity", + "longing", + "jealousy", + "grief", +]); + +/** fear + love juntos → apego / medo de perder (resposta prioriza esses estados) */ +const FEAR_AND_LOVE_STATES = new Set([ + "emotional_attachment", + "relational_insecurity", + "anxiety", +]); + +/** theme career → estados que ganham bônus */ +const CAREER_STATES = new Set([ + "lack_of_purpose", + "burnout", + "stagnation", + "emotional_exhaustion", + "perfectionism", +]); + +/** theme health → estados que ganham bônus */ +const HEALTH_STATES = new Set([ + "burnout", + "emotional_exhaustion", + "lethargy", + "overwhelm", +]); + +/** subject other → estados de compaixão/relação */ +const OTHER_SUBJECT_STATES = new Set([ + "aversion_to_other", + "resentment", + "coldness", + "emotional_attachment", + "relational_insecurity", +]); + +export type PickBestStateResult = { + stateKey: string; + confidence: number; +}; + +/** Fallback quando não há candidatos (ex.: texto sem emoção detectada). */ +const FALLBACK_STATE = "confusion"; +const FALLBACK_CONFIDENCE = 0.3; + +/** + * Retorna o melhor stateKey e confiança (0–1) para o intent. + * Usa base score do parser + bônus por eixo (fear+love → attachment/relational_insecurity; how→prática, why→sutra). + * Se não houver candidatos, retorna confusion para o engine sempre responder offline. + */ +export function pickBestState(intent: ParsedIntent | null): PickBestStateResult | undefined { + if (intent == null) return undefined; + if (intent.stateCandidates.length === 0) { + return { stateKey: FALLBACK_STATE, confidence: FALLBACK_CONFIDENCE }; + } + const validCandidates = intent.stateCandidates.filter((c) => + VALID_STATES.has(c.stateKey) + ) as StateCandidate[]; + if (validCandidates.length === 0) { + return { stateKey: FALLBACK_STATE, confidence: FALLBACK_CONFIDENCE }; + } + if (validCandidates.length === 0) return undefined; + if (validCandidates.length === 1) { + return { + stateKey: validCandidates[0].stateKey, + confidence: Math.min(1, 0.3 + validCandidates[0].score * 0.1), + }; + } + + const scores = new Map(); + const fearAndLove = intent.verbClass === "fear" && intent.theme === "love"; + for (const c of validCandidates) { + let score = c.score; + if (intent.verbClass === "fear" && FEAR_STATES.has(c.stateKey)) score += WEIGHT_VERB_FEAR; + if (intent.theme === "love" && LOVE_STATES.has(c.stateKey)) score += WEIGHT_THEME; + if (fearAndLove && FEAR_AND_LOVE_STATES.has(c.stateKey)) score += WEIGHT_FEAR_AND_LOVE; + if (intent.theme === "career" && CAREER_STATES.has(c.stateKey)) score += WEIGHT_THEME; + if (intent.theme === "health" && HEALTH_STATES.has(c.stateKey)) score += WEIGHT_THEME; + if (intent.subject === "other" && OTHER_SUBJECT_STATES.has(c.stateKey)) score += WEIGHT_SUBJECT_OTHER; + scores.set(c.stateKey, score); + } + + const sorted = [...validCandidates].sort( + (a, b) => (scores.get(b.stateKey) ?? 0) - (scores.get(a.stateKey) ?? 0) + ); + const best = sorted[0]; + const bestScore = scores.get(best.stateKey) ?? 0; + const maxScore = Math.max(...Array.from(scores.values())); + const confidence = maxScore > 0 ? Math.min(1, 0.2 + (bestScore / (maxScore + 2)) * 0.8) : 0.5; + + return { stateKey: best.stateKey, confidence }; +} + +/** + * Retorna apenas o stateKey (compatibilidade com código que usa scoreState). + */ +export function scoreState(intent: ParsedIntent | null): string | undefined { + return pickBestState(intent)?.stateKey; +} diff --git a/lib/insights/collectInsights.ts b/lib/insights/collectInsights.ts new file mode 100644 index 0000000..7e9ef39 --- /dev/null +++ b/lib/insights/collectInsights.ts @@ -0,0 +1,17 @@ +/** + * Coleta todos os insights do mapa simbólico (Jyotish + Numerologia + Human Design). + */ + +import type { SymbolicMap } from "@/lib/engines/buildSymbolicMap"; +import type { Insight } from "./types"; +import { jyotishInsights } from "./jyotishInsights"; +import { numerologyInsights } from "./numerologyInsights"; +import { humanDesignInsights } from "./humanDesignInsights"; + +export function collectAllInsights(map: SymbolicMap): Insight[] { + const list: Insight[] = []; + list.push(...jyotishInsights(map.jyotish)); + list.push(...numerologyInsights(map.numerology)); + list.push(...humanDesignInsights(map.humanDesign)); + return list; +} diff --git a/lib/insights/collectInsightsForSymbolic.ts b/lib/insights/collectInsightsForSymbolic.ts new file mode 100644 index 0000000..535bcba --- /dev/null +++ b/lib/insights/collectInsightsForSymbolic.ts @@ -0,0 +1,37 @@ +/** + * Coleta insights do mapa simbólico canônico (lib/symbolic). + * Usado pelo Narrative Composer para leituras determinísticas. + */ + +import type { SymbolicMap } from "@/lib/symbolic/types"; +import type { Insight } from "./types"; +import { jyotishInsightsForSymbolic } from "./jyotishInsightsForSymbolic"; + +export function collectInsightsForSymbolicMap(map: SymbolicMap): Insight[] { + const list: Insight[] = []; + list.push(...jyotishInsightsForSymbolic(map)); + // Action: sempre pelo menos um insight por número regente + geral + const n = map.numerology.rulingNumber; + list.push({ + key: `action.n.${n}`, + topic: "action", + weight: 1, + system: "numerology", + evidence: { rulingNumber: n }, + }); + list.push({ + key: "action.general", + topic: "action", + weight: 0.9, + system: "jyotish", + evidence: {}, + }); + list.push({ + key: `action.archetype.${map.jyotish.archetypeKey}`, + topic: "action", + weight: 0.85, + system: "jyotish", + evidence: { archetypeKey: map.jyotish.archetypeKey }, + }); + return list; +} diff --git a/lib/insights/humanDesignInsights.ts b/lib/insights/humanDesignInsights.ts new file mode 100644 index 0000000..3c55d86 --- /dev/null +++ b/lib/insights/humanDesignInsights.ts @@ -0,0 +1,28 @@ +/** + * Regras determinísticas de insights Human Design — stub; só quando HD estiver disponível. + */ + +import type { Insight } from "./types"; +import type { HumanDesignEngineResult } from "@/lib/engines/humanDesignEngine"; + +export function humanDesignInsights(humanDesign: HumanDesignEngineResult): Insight[] { + const out: Insight[] = []; + if (!humanDesign) return out; + + out.push({ + key: `hd.type.${humanDesign.type.toLowerCase()}`, + weight: 0.85, + system: "humanDesign", + topic: "general", + evidence: humanDesign, + }); + out.push({ + key: `hd.authority.${humanDesign.authority.toLowerCase()}`, + weight: 0.8, + system: "humanDesign", + topic: "action", + evidence: humanDesign, + }); + + return out; +} diff --git a/lib/insights/jyotishInsights.ts b/lib/insights/jyotishInsights.ts new file mode 100644 index 0000000..78ee4b1 --- /dev/null +++ b/lib/insights/jyotishInsights.ts @@ -0,0 +1,71 @@ +/** + * Regras determinísticas de insights Jyotish — só símbolos → keys; nada aleatório. + */ + +import type { Insight } from "./types"; +import type { JyotishEngineResult } from "@/lib/engines/jyotishEngine"; + +export function jyotishInsights(jyotish: JyotishEngineResult): Insight[] { + const out: Insight[] = []; + if (!jyotish) return out; + + if (jyotish.nakshatra) { + out.push({ + key: `jyotish.nakshatra.${jyotish.nakshatra}.general`, + weight: 0.9, + system: "jyotish", + topic: "general", + evidence: { nakshatra: jyotish.nakshatra }, + }); + out.push({ + key: `jyotish.nakshatra.${jyotish.nakshatra}.spiritualTheme`, + weight: 0.85, + system: "jyotish", + topic: "general", + evidence: { nakshatra: jyotish.nakshatra }, + }); + } + + if (jyotish.moonRashi) { + out.push({ + key: `jyotish.rashi.${jyotish.moonRashi}.general`, + weight: 0.8, + system: "jyotish", + topic: "general", + evidence: { moonRashi: jyotish.moonRashi }, + }); + out.push({ + key: `jyotish.rashi.${jyotish.moonRashi}.love`, + weight: 0.7, + system: "jyotish", + topic: "love", + evidence: { moonRashi: jyotish.moonRashi }, + }); + out.push({ + key: `jyotish.rashi.${jyotish.moonRashi}.career`, + weight: 0.7, + system: "jyotish", + topic: "career", + evidence: { moonRashi: jyotish.moonRashi }, + }); + out.push({ + key: `jyotish.rashi.${jyotish.moonRashi}.year`, + weight: 0.7, + system: "jyotish", + topic: "year", + evidence: { moonRashi: jyotish.moonRashi }, + }); + } + + if (jyotish.nakshatra) { + out.push({ + key: `jyotish.nakshatra.${jyotish.nakshatra}.year`, + weight: 0.75, + system: "jyotish", + topic: "year", + evidence: { nakshatra: jyotish.nakshatra }, + }); + } + + return out; +} diff --git a/lib/insights/jyotishInsightsForSymbolic.ts b/lib/insights/jyotishInsightsForSymbolic.ts new file mode 100644 index 0000000..66c74a7 --- /dev/null +++ b/lib/insights/jyotishInsightsForSymbolic.ts @@ -0,0 +1,479 @@ +/** + * Regras determinísticas de insights Jyotish para o mapa simbólico canônico (lib/symbolic). + * 20 general, 10 love, 10 career, 10 year. Tudo ancorado no mapa; nada aleatório. + */ + +import type { SymbolicMap } from "@/lib/symbolic/types"; +import type { Insight } from "./types"; + +export function jyotishInsightsForSymbolic(map: SymbolicMap): Insight[] { + const out: Insight[] = []; + const { nakshatra, moonRashi } = map.jyotish; + + // ——— GENERAL (20+ regras: soulPath, spiritualPath, rashi/nakshatra) ——— + if (nakshatra === "revati") { + out.push({ + key: "jyotish.revati.spiritualPath", + topic: "general", + weight: 0.95, + system: "jyotish", + evidence: { nakshatra: "revati" }, + }); + out.push({ + key: "jyotish.revati.soulPath", + topic: "general", + weight: 0.9, + system: "jyotish", + evidence: { nakshatra: "revati" }, + }); + } + if (nakshatra === "rohini") { + out.push({ + key: "jyotish.rohini.soulPath", + topic: "general", + weight: 0.9, + system: "jyotish", + evidence: { nakshatra: "rohini" }, + }); + } + if (nakshatra === "ashwini") { + out.push({ + key: "jyotish.ashwini.soulPath", + topic: "general", + weight: 0.9, + system: "jyotish", + evidence: { nakshatra: "ashwini" }, + }); + } + if (moonRashi === "karka") { + out.push({ + key: "jyotish.karka.general", + topic: "general", + weight: 0.85, + system: "jyotish", + evidence: { moonRashi: "karka" }, + }); + } + if (moonRashi === "mesha") { + out.push({ + key: "jyotish.mesha.general", + topic: "general", + weight: 0.85, + system: "jyotish", + evidence: { moonRashi: "mesha" }, + }); + } + if (moonRashi === "mina") { + out.push({ + key: "jyotish.mina.general", + topic: "general", + weight: 0.85, + system: "jyotish", + evidence: { moonRashi: "mina" }, + }); + } + if (nakshatra === "pushya") { + out.push({ + key: "jyotish.pushya.general", + topic: "general", + weight: 0.85, + system: "jyotish", + evidence: { nakshatra: "pushya" }, + }); + } + if (nakshatra === "magha") { + out.push({ + key: "jyotish.magha.general", + topic: "general", + weight: 0.85, + system: "jyotish", + evidence: { nakshatra: "magha" }, + }); + } + if (nakshatra === "hasta") { + out.push({ + key: "jyotish.hasta.general", + topic: "general", + weight: 0.85, + system: "jyotish", + evidence: { nakshatra: "hasta" }, + }); + } + if (nakshatra === "chitra") { + out.push({ + key: "jyotish.chitra.general", + topic: "general", + weight: 0.85, + system: "jyotish", + evidence: { nakshatra: "chitra" }, + }); + } + if (moonRashi === "vrishabha") { + out.push({ + key: "jyotish.vrishabha.general", + topic: "general", + weight: 0.85, + system: "jyotish", + evidence: { moonRashi: "vrishabha" }, + }); + } + if (moonRashi === "mithuna") { + out.push({ + key: "jyotish.mithuna.general", + topic: "general", + weight: 0.85, + system: "jyotish", + evidence: { moonRashi: "mithuna" }, + }); + } + if (moonRashi === "simha") { + out.push({ + key: "jyotish.simha.general", + topic: "general", + weight: 0.85, + system: "jyotish", + evidence: { moonRashi: "simha" }, + }); + } + if (moonRashi === "kanya") { + out.push({ + key: "jyotish.kanya.general", + topic: "general", + weight: 0.85, + system: "jyotish", + evidence: { moonRashi: "kanya" }, + }); + } + if (moonRashi === "tula") { + out.push({ + key: "jyotish.tula.general", + topic: "general", + weight: 0.85, + system: "jyotish", + evidence: { moonRashi: "tula" }, + }); + } + if (moonRashi === "vrischika") { + out.push({ + key: "jyotish.vrischika.general", + topic: "general", + weight: 0.85, + system: "jyotish", + evidence: { moonRashi: "vrischika" }, + }); + } + if (moonRashi === "dhanu") { + out.push({ + key: "jyotish.dhanu.general", + topic: "general", + weight: 0.85, + system: "jyotish", + evidence: { moonRashi: "dhanu" }, + }); + } + if (moonRashi === "makara") { + out.push({ + key: "jyotish.makara.general", + topic: "general", + weight: 0.85, + system: "jyotish", + evidence: { moonRashi: "makara" }, + }); + } + if (moonRashi === "kumbha") { + out.push({ + key: "jyotish.kumbha.general", + topic: "general", + weight: 0.85, + system: "jyotish", + evidence: { moonRashi: "kumbha" }, + }); + } + + // ——— LOVE (10 regras) ——— + if (nakshatra === "revati") { + out.push({ + key: "jyotish.revati.love", + topic: "love", + weight: 0.85, + system: "jyotish", + evidence: { nakshatra: "revati" }, + }); + } + if (nakshatra === "rohini") { + out.push({ + key: "jyotish.rohini.love", + topic: "love", + weight: 0.85, + system: "jyotish", + evidence: { nakshatra: "rohini" }, + }); + } + if (moonRashi === "karka") { + out.push({ + key: "jyotish.karka.love", + topic: "love", + weight: 0.8, + system: "jyotish", + evidence: { moonRashi: "karka" }, + }); + } + if (moonRashi === "mesha") { + out.push({ + key: "jyotish.mesha.love", + topic: "love", + weight: 0.8, + system: "jyotish", + evidence: { moonRashi: "mesha" }, + }); + } + if (moonRashi === "mina") { + out.push({ + key: "jyotish.mina.love", + topic: "love", + weight: 0.8, + system: "jyotish", + evidence: { moonRashi: "mina" }, + }); + } + if (moonRashi === "vrishabha") { + out.push({ + key: "jyotish.vrishabha.love", + topic: "love", + weight: 0.8, + system: "jyotish", + evidence: { moonRashi: "vrishabha" }, + }); + } + if (moonRashi === "mithuna") { + out.push({ + key: "jyotish.mithuna.love", + topic: "love", + weight: 0.8, + system: "jyotish", + evidence: { moonRashi: "mithuna" }, + }); + } + if (moonRashi === "tula") { + out.push({ + key: "jyotish.tula.love", + topic: "love", + weight: 0.8, + system: "jyotish", + evidence: { moonRashi: "tula" }, + }); + } + if (moonRashi === "simha") { + out.push({ + key: "jyotish.simha.love", + topic: "love", + weight: 0.8, + system: "jyotish", + evidence: { moonRashi: "simha" }, + }); + } + if (moonRashi === "kanya") { + out.push({ + key: "jyotish.kanya.love", + topic: "love", + weight: 0.8, + system: "jyotish", + evidence: { moonRashi: "kanya" }, + }); + } + + // ——— CAREER (10 regras) ——— + if (nakshatra === "revati") { + out.push({ + key: "jyotish.revati.career", + topic: "career", + weight: 0.85, + system: "jyotish", + evidence: { nakshatra: "revati" }, + }); + } + if (moonRashi === "karka") { + out.push({ + key: "jyotish.karka.career", + topic: "career", + weight: 0.8, + system: "jyotish", + evidence: { moonRashi: "karka" }, + }); + } + if (moonRashi === "mesha") { + out.push({ + key: "jyotish.mesha.career", + topic: "career", + weight: 0.8, + system: "jyotish", + evidence: { moonRashi: "mesha" }, + }); + } + if (nakshatra === "rohini") { + out.push({ + key: "jyotish.rohini.career", + topic: "career", + weight: 0.85, + system: "jyotish", + evidence: { nakshatra: "rohini" }, + }); + } + if (nakshatra === "ashwini") { + out.push({ + key: "jyotish.ashwini.career", + topic: "career", + weight: 0.85, + system: "jyotish", + evidence: { nakshatra: "ashwini" }, + }); + } + if (moonRashi === "mina") { + out.push({ + key: "jyotish.mina.career", + topic: "career", + weight: 0.8, + system: "jyotish", + evidence: { moonRashi: "mina" }, + }); + } + if (moonRashi === "vrishabha") { + out.push({ + key: "jyotish.vrishabha.career", + topic: "career", + weight: 0.8, + system: "jyotish", + evidence: { moonRashi: "vrishabha" }, + }); + } + if (moonRashi === "mithuna") { + out.push({ + key: "jyotish.mithuna.career", + topic: "career", + weight: 0.8, + system: "jyotish", + evidence: { moonRashi: "mithuna" }, + }); + } + if (moonRashi === "tula") { + out.push({ + key: "jyotish.tula.career", + topic: "career", + weight: 0.8, + system: "jyotish", + evidence: { moonRashi: "tula" }, + }); + } + if (moonRashi === "dhanu") { + out.push({ + key: "jyotish.dhanu.career", + topic: "career", + weight: 0.8, + system: "jyotish", + evidence: { moonRashi: "dhanu" }, + }); + } + if (moonRashi === "kanya") { + out.push({ + key: "jyotish.kanya.career", + topic: "career", + weight: 0.8, + system: "jyotish", + evidence: { moonRashi: "kanya" }, + }); + } + + // ——— YEAR (10 regras) ——— + if (nakshatra === "revati") { + out.push({ + key: "jyotish.revati.year", + topic: "year", + weight: 0.85, + system: "jyotish", + evidence: { nakshatra: "revati" }, + }); + } + if (moonRashi === "karka") { + out.push({ + key: "jyotish.karka.year", + topic: "year", + weight: 0.8, + system: "jyotish", + evidence: { moonRashi: "karka" }, + }); + } + if (moonRashi === "mesha") { + out.push({ + key: "jyotish.mesha.year", + topic: "year", + weight: 0.8, + system: "jyotish", + evidence: { moonRashi: "mesha" }, + }); + } + if (nakshatra === "rohini") { + out.push({ + key: "jyotish.rohini.year", + topic: "year", + weight: 0.85, + system: "jyotish", + evidence: { nakshatra: "rohini" }, + }); + } + if (nakshatra === "ashwini") { + out.push({ + key: "jyotish.ashwini.year", + topic: "year", + weight: 0.85, + system: "jyotish", + evidence: { nakshatra: "ashwini" }, + }); + } + if (moonRashi === "mina") { + out.push({ + key: "jyotish.mina.year", + topic: "year", + weight: 0.8, + system: "jyotish", + evidence: { moonRashi: "mina" }, + }); + } + if (moonRashi === "vrishabha") { + out.push({ + key: "jyotish.vrishabha.year", + topic: "year", + weight: 0.8, + system: "jyotish", + evidence: { moonRashi: "vrishabha" }, + }); + } + if (moonRashi === "mithuna") { + out.push({ + key: "jyotish.mithuna.year", + topic: "year", + weight: 0.8, + system: "jyotish", + evidence: { moonRashi: "mithuna" }, + }); + } + if (moonRashi === "tula") { + out.push({ + key: "jyotish.tula.year", + topic: "year", + weight: 0.8, + system: "jyotish", + evidence: { moonRashi: "tula" }, + }); + } + if (nakshatra === "pushya") { + out.push({ + key: "jyotish.pushya.year", + topic: "year", + weight: 0.85, + system: "jyotish", + evidence: { nakshatra: "pushya" }, + }); + } + + return out; +} diff --git a/lib/insights/numerologyInsights.ts b/lib/insights/numerologyInsights.ts new file mode 100644 index 0000000..be1844d --- /dev/null +++ b/lib/insights/numerologyInsights.ts @@ -0,0 +1,42 @@ +/** + * Regras determinísticas de insights Numerologia — número regente → keys. + */ + +import type { Insight } from "./types"; +import type { NumerologyEngineResult } from "@/lib/engines/numerologyEngine"; + +export function numerologyInsights(numerology: NumerologyEngineResult): Insight[] { + const out: Insight[] = []; + if (!numerology) return out; + + out.push({ + key: `numerology.ruling.${numerology.rulingNumber}.general`, + weight: 0.85, + system: "numerology", + topic: "general", + evidence: { rulingNumber: numerology.rulingNumber }, + }); + out.push({ + key: `numerology.ruling.${numerology.rulingNumber}.career`, + weight: 0.75, + system: "numerology", + topic: "career", + evidence: { rulingNumber: numerology.rulingNumber }, + }); + out.push({ + key: `numerology.ruling.${numerology.rulingNumber}.love`, + weight: 0.75, + system: "numerology", + topic: "love", + evidence: { rulingNumber: numerology.rulingNumber }, + }); + out.push({ + key: `numerology.ruling.${numerology.rulingNumber}.year`, + weight: 0.75, + system: "numerology", + topic: "year", + evidence: { rulingNumber: numerology.rulingNumber }, + }); + + return out; +} diff --git a/lib/insights/types.ts b/lib/insights/types.ts new file mode 100644 index 0000000..ec547d7 --- /dev/null +++ b/lib/insights/types.ts @@ -0,0 +1,15 @@ +/** + * Insight — resultado de regras determinísticas por sistema (Jyotish, numerologia, HD). + * Nunca aleatório; sempre justificável pelo mapa. + */ + +export type InsightTopic = "general" | "love" | "career" | "year" | "action"; +export type InsightSystem = "jyotish" | "numerology" | "humanDesign"; + +export type Insight = { + key: string; + weight: number; + system: InsightSystem; + topic: InsightTopic; + evidence?: unknown; +}; diff --git a/lib/knowledge/numerology.ts b/lib/knowledge/numerology.ts index d1cca6d..8de9bcd 100644 --- a/lib/knowledge/numerology.ts +++ b/lib/knowledge/numerology.ts @@ -48,6 +48,75 @@ export function getRulingNumberFromName(fullName: string): RulingNumber { return reduceToDigit(sum) as RulingNumber; } +/** + * Life Path Number (data de nascimento) — soma dos dígitos da data reduzida a 1–9 ou 11/22. + * Ex.: 1990-05-15 → 1+9+9+0+0+5+1+5 = 30 → 3. + */ +export function getLifePathNumber(birthDate: string): RulingNumber { + const digits = (birthDate || "").replace(/\D/g, ""); + if (!digits.length) return 7; + let sum = 0; + for (const d of digits) sum += parseInt(d, 10); + if (sum === 0) return 7; + while (sum > 99) { + sum = String(sum).split("").reduce((s, d) => s + parseInt(d, 10), 0); + } + if (sum === 11 || sum === 22) return sum as 11 | 22; + return reduceToDigit(sum) as RulingNumber; +} + +/** Expression/Destiny Number = número regente do nome (alias semântico). */ +export function getExpressionNumber(fullName: string): RulingNumber { + return getRulingNumberFromName(fullName); +} + +/** Vogais (Pitágoras): A, E, I, O, U (e equivalentes acentuados). */ +const VOWELS = new Set(["A", "E", "I", "O", "U"]); + +/** + * Soul Urge Number (vogais do nome) — desejo interior, motivação profunda. + * Soma apenas as vogais do nome completo; reduz a 1–9 ou 11/22. + */ +export function getSoulUrgeNumber(fullName: string): RulingNumber { + const name = (fullName || "").toUpperCase().replace(/\s+/g, "").replace(/[^A-ZÀ-Ú]/g, ""); + if (!name.length) return 7; + let sum = 0; + for (const char of name) { + const n = char.normalize("NFD").replace(/\p{Diacritic}/gu, "").toUpperCase(); + if (!VOWELS.has(n)) continue; + const v = LETTER_VALUES[n] ?? LETTER_VALUES[char.toUpperCase()]; + if (v) sum += v; + } + if (sum === 0) return 7; + while (sum > 99) { + sum = String(sum).split("").reduce((s, d) => s + parseInt(d, 10), 0); + } + if (sum === 11 || sum === 22) return sum as 11 | 22; + return reduceToDigit(sum) as RulingNumber; +} + +/** + * Personality Number (consoantes do nome) — como os outros te veem, máscara social. + * Soma apenas as consoantes do nome completo; reduz a 1–9 ou 11/22. + */ +export function getPersonalityNumber(fullName: string): RulingNumber { + const name = (fullName || "").toUpperCase().replace(/\s+/g, "").replace(/[^A-ZÀ-Ú]/g, ""); + if (!name.length) return 7; + let sum = 0; + for (const char of name) { + const n = char.normalize("NFD").replace(/\p{Diacritic}/gu, "").toUpperCase(); + if (VOWELS.has(n)) continue; + const v = LETTER_VALUES[n] ?? LETTER_VALUES[char.toUpperCase()]; + if (v) sum += v; + } + if (sum === 0) return 7; + while (sum > 99) { + sum = String(sum).split("").reduce((s, d) => s + parseInt(d, 10), 0); + } + if (sum === 11 || sum === 22) return sum as 11 | 22; + return reduceToDigit(sum) as RulingNumber; +} + /** Entrada do dicionário por número: tendências e frases para o oráculo */ export type NumberTraitsEntry = { number: RulingNumber; diff --git a/lib/narrative/composer.ts b/lib/narrative/composer.ts new file mode 100644 index 0000000..df2255c --- /dev/null +++ b/lib/narrative/composer.ts @@ -0,0 +1,44 @@ +/** + * Narrative Composer universal — map → insights → composer → módulos. + * Monta leitura a partir de insights filtrados por tópico; key → PHRASES[i.key][0]. + * Nada aleatório; tudo ancorado no mapa. + */ + +import type { Insight, InsightTopic } from "@/lib/insights/types"; +import type { SymbolicMap } from "@/lib/symbolic/types"; +import { phraseFor } from "@/lib/dictionaries"; +import { collectInsightsForSymbolicMap } from "@/lib/insights/collectInsightsForSymbolic"; + +/** + * Composer para o mapa simbólico: collectInsights(map) → filter(topic) → sort(weight) → top 3 → phraseFor(key) → join. + */ +export function composeReading(map: SymbolicMap, topic: InsightTopic): string { + const insights = collectInsightsForSymbolicMap(map) + .filter((i) => i.topic === topic) + .sort((a, b) => b.weight - a.weight); + return insights + .slice(0, 3) + .map((i) => phraseFor(i.key)) + .filter(Boolean) + .join("\n\n"); +} + +/** Composer a partir de array de insights (engines flow). */ +export function composeReadingFromInsights(insights: Insight[], topic: InsightTopic): string { + const filtered = insights.filter((i) => i.topic === topic); + const sorted = filtered.sort((a, b) => b.weight - a.weight); + const chosen = sorted.slice(0, 5); + const parts: string[] = []; + for (const i of chosen) { + const phrase = phraseFor(i.key); + if (phrase && !parts.includes(phrase)) parts.push(phrase); + } + return parts.join("\n\n"); +} + +/** + * Alias para compatibilidade: composer por mapa simbólico. + */ +export function composeReadingFromSymbolicMap(map: SymbolicMap, topic: InsightTopic): string { + return composeReading(map, topic); +} diff --git a/lib/narrative/dictionaryLoader.ts b/lib/narrative/dictionaryLoader.ts new file mode 100644 index 0000000..d05d1f1 --- /dev/null +++ b/lib/narrative/dictionaryLoader.ts @@ -0,0 +1,30 @@ +/** + * Carregador de dicionários — agrega todas as fontes de frases (Jyotish, HD, Action, Numerologia, Symbolic). + * Usado pelo Narrative Composer; tudo derivado do mapa, sem aleatoriedade solta. + */ + +import { JYOTISH_PHRASES } from "@/lib/dictionaries/jyotish"; +import { HD_PHRASES } from "@/lib/dictionaries/humanDesign"; +import { ACTION_PHRASES } from "@/lib/dictionaries/action"; +import { NUMEROLOGY_PHRASES } from "@/lib/dictionaries/numerology"; +import { PHRASES_FOR_SYMBOLIC } from "@/lib/dictionaries/phrasesForSymbolic"; + +export type PhraseDictionary = Record; + +/** Retorna o dicionário único mergendo todas as fontes (mesma ordem que phraseFor). */ +export function getMergedDictionaries(): PhraseDictionary { + return { + ...JYOTISH_PHRASES, + ...HD_PHRASES, + ...ACTION_PHRASES, + ...NUMEROLOGY_PHRASES, + ...PHRASES_FOR_SYMBOLIC, + }; +} + +/** Retorna a primeira frase para uma chave, ou string vazia (sem aleatoriedade). */ +export function getPhraseFromDict(dict: PhraseDictionary, key: string): string { + const phrases = dict[key]; + if (phrases && phrases.length > 0) return phrases[0]; + return ""; +} diff --git a/lib/narrative/phraseTemplates.ts b/lib/narrative/phraseTemplates.ts new file mode 100644 index 0000000..25422f7 --- /dev/null +++ b/lib/narrative/phraseTemplates.ts @@ -0,0 +1,36 @@ +/** + * Templates de frase para o Narrative Composer — tudo derivado do mapa. + * placements, yogas, archetypes, theme → frase determinística (sem IA). + */ + +import { phraseFor } from "@/lib/dictionaries"; + +export type TemplateContext = { + placements?: { moonRashi?: string; nakshatra?: string }; + yogas?: string[]; + archetypes?: string[]; + theme: "general" | "love" | "career" | "year" | "action"; +}; + +/** Retorna a frase do dicionário para uma chave de insight (usado pelo Composer). */ +export function getPhraseForInsight(key: string): string { + return phraseFor(key); +} + +/** + * Retorna uma frase para o contexto (placements + theme). + * O Composer principal usa composeReading(map, topic); este helper serve chamadas que já têm só placements/theme. + */ +export function getPhraseForContext(ctx: TemplateContext): string { + if (ctx.placements?.nakshatra) { + const key = `jyotish.${ctx.placements.nakshatra}.${ctx.theme === "general" ? "general" : ctx.theme}`; + const phrase = phraseFor(key); + if (phrase) return phrase; + } + if (ctx.placements?.moonRashi) { + const key = `jyotish.${ctx.placements.moonRashi}.${ctx.theme === "general" ? "general" : ctx.theme}`; + const phrase = phraseFor(key); + if (phrase) return phrase; + } + return phraseFor("jyotish.revati.soulPath") || ""; +} diff --git a/lib/oracleOffline.ts b/lib/oracleOffline.ts index 94a7b81..cb1d63c 100644 --- a/lib/oracleOffline.ts +++ b/lib/oracleOffline.ts @@ -5,15 +5,10 @@ */ import type { UserProfileForOracle } from "./knowledge/types"; -import { computeVedicChartSimplified } from "./knowledge/vedic"; -import { extractKeywords } from "./knowledge/keywordMatch"; -import { getRandomFormulation } from "./knowledge/formulations"; -import { getRandomClassicTextForArchetype } from "./knowledge/classicTexts"; -import { getRandomArchetypePhrase } from "./knowledge/archetypeTraits"; -import { getJyotishPhraseForChart } from "./knowledge/jyotishMeanings"; -import { getRulingNumberFromName, getRandomPhraseForNumber } from "./knowledge/numerology"; - -const MAX_SEED_TRIES = 30; +import { buildSymbolicMap } from "./engines/buildSymbolicMap"; +import { collectAllInsights } from "./insights/collectInsights"; +import { phraseFor } from "./dictionaries"; + /** Número de blocos: na maioria 1, às vezes 2, raramente 3. */ function getTargetBlockCount(seed4: number): number { const r = seed4 % 10; @@ -78,17 +73,13 @@ function getRequestSalt(): number { return (Date.now() * 1000 + Math.floor(Math.random() * 1000)) >>> 0; } -/** Gera uma mensagem de revelação a partir do perfil e do dicionário offline. */ -export function getOfflineRevelation( +/** Gera uma mensagem de revelação a partir do SymbolicMap e insights (coerente com o mapa). */ +export async function getOfflineRevelation( profile: UserProfileForOracle, - userMessage?: string, + _userMessage?: string, recentlyUsedPhrases?: string[] -): string { +): Promise { const salt = getRequestSalt(); - const seedBase = (getSeedFromProfile(profile) + salt) >>> 0; - const seed1 = (getSeedFromProfile(profile, 1) + salt * 31) >>> 0; - const seed2 = (getSeedFromProfile(profile, 2) + salt * 37) >>> 0; - const seed3 = (getSeedFromProfile(profile, 3) + salt * 41) >>> 0; const seed4 = (getSeedFromProfile(profile, 4) + salt * 43) >>> 0; const recentSet = new Set( @@ -97,73 +88,35 @@ export function getOfflineRevelation( .filter((n) => n.length > 0) ); - const keywords = extractKeywords(userMessage); - const blocks: string[] = []; - - const chart = computeVedicChartSimplified({ + const coreProfile = { birthDate: profile.birthDate, birthTime: profile.birthTime, - }); - const archetypeKey = chart.archetypeKeys[0]; - const rulingNumber = getRulingNumberFromName(profile.fullName ?? ""); - const firstName = profile.fullName?.trim().split(/\s+/)[0]; - const closing = firstName && (seed4 % 3 === 0) - ? `${firstName}, o que em você já sabe?` - : "O que em você já sabe?"; - - function pickPhrase( - getPhrase: (seed: number) => string | null, - baseSeed: number - ): string | null { - let phrase = getPhrase(baseSeed); - for (let k = 0; k < MAX_SEED_TRIES && phrase && !canUsePhrase(phrase, blocks, recentSet); k++) { - phrase = getPhrase(baseSeed + k + 1); - } - return phrase && !isDuplicate(phrase, blocks) ? phrase : null; - } - - const formulationText = pickPhrase( - (s) => getRandomFormulation(archetypeKey, s, keywords)?.text ?? null, - seedBase - ); + fullName: profile.fullName, + }; + const map = await buildSymbolicMap(coreProfile); + const insights = collectAllInsights(map).filter((i) => i.topic === "general"); + const sorted = [...insights].sort((a, b) => b.weight - a.weight); - const archetypePhrase = pickPhrase( - (s) => getRandomArchetypePhrase(archetypeKey, s, keywords), - seed1 - ); - const classicText = pickPhrase( - (s) => getRandomClassicTextForArchetype(archetypeKey, s, keywords)?.text ?? null, - seed2 - ); - const jyotishPhrase = pickPhrase( - (s) => getJyotishPhraseForChart(chart, s, keywords), - seed2 + 1 - ); - const numberPhrase = pickPhrase( - (s) => getRandomPhraseForNumber(rulingNumber, s, keywords), - seed3 - ); - - const typedPhrases: { phrase: string }[] = []; + const candidates: string[] = []; const seenNormalized = new Set(); - - function addIfNew(phrase: string | null): void { - if (!phrase) return; + for (const i of sorted) { + const phrase = phraseFor(i.key); + if (!phrase) continue; const n = normalizeForCompare(phrase); - if (!n || seenNormalized.has(n)) return; + if (!n || seenNormalized.has(n) || recentSet.has(n)) continue; seenNormalized.add(n); - typedPhrases.push({ phrase }); + candidates.push(phrase); } - addIfNew(formulationText); - addIfNew(archetypePhrase); - addIfNew(classicText); - addIfNew(jyotishPhrase); - addIfNew(numberPhrase); - if (closing && !isRecentlyUsed(closing, recentSet)) addIfNew(closing); + const firstName = profile.fullName?.trim().split(/\s+/)[0]; + const closing = firstName && seed4 % 3 === 0 + ? `${firstName}, o que em você já sabe?` + : "O que em você já sabe?"; + if (closing && !recentSet.has(normalizeForCompare(closing))) candidates.push(closing); - const shuffled = shuffleBySeed(typedPhrases, seed4); + const shuffled = shuffleBySeed(candidates.map((phrase) => ({ phrase })), seed4); const targetTotal = getTargetBlockCount(seed4); + const blocks: string[] = []; for (const { phrase } of shuffled) { if (phrase && !isDuplicate(phrase, blocks) && !isRecentlyUsed(phrase, recentSet)) { diff --git a/lib/readingOffline.ts b/lib/readingOffline.ts index f56719f..2e547ed 100644 --- a/lib/readingOffline.ts +++ b/lib/readingOffline.ts @@ -1,113 +1,63 @@ /** - * Leitura (mapa pessoal) offline — monta um texto a partir do conhecimento local - * (Jyotish, numerologia, arquétipos), sem chamar a IA. - * Usa interpretação Jyotish para leitura (temas e efeitos narrativos), não as frases do oráculo. + * Leitura (mapa pessoal) offline — SymbolicMap → Insights → Composer → Readings modulares. + * getOfflineReading é apenas um wrapper: monta o mapa e devolve general + love + career + year + action. + * Sem IA; motor determinístico e extensível (pronto para Swiss Ephemeris e Human Design). */ -import { computeVedicChartSimplified } from "@/lib/knowledge/vedic"; -import { getRulingNumberFromName, getNumberTraits } from "@/lib/knowledge/numerology"; -import { getArchetypeTraits } from "@/lib/knowledge/archetypeTraits"; -import { getRandomClassicTextForArchetype } from "@/lib/knowledge/classicTexts"; +import { buildSymbolicMap } from "@/lib/symbolic/builder"; import { - getJyotishReadingInterpretation, - RASHI_MEANINGS, - NAKSHATRA_MEANINGS, -} from "@/lib/knowledge/jyotishMeanings"; -import type { RashiKey, NakshatraKey } from "@/lib/knowledge/types"; + getGeneral, + getLove, + getCareer, + getYear, + getAction, + type StructuredOfflineReading, +} from "@/lib/readings/symbolicReadings"; -function getSeedFromProfile(profile: { fullName?: string; birthDate?: string; birthTime?: string }, offset: number): number { - const str = [ - profile.fullName ?? "", - profile.birthDate ?? "", - profile.birthTime ?? "", - String(offset), - ].join("|"); - let h = 0; - for (let i = 0; i < str.length; i++) { - h = ((h << 5) - h) + str.charCodeAt(i); - h |= 0; - } - return Math.abs(h); -} - -function rashiName(key: RashiKey): string { - const e = RASHI_MEANINGS.find((x) => x.key === key); - return e?.namePt ?? key; -} - -function nakshatraName(key: NakshatraKey): string { - const e = NAKSHATRA_MEANINGS.find((x) => x.key === key); - return e?.namePt ?? key; -} +export type { StructuredOfflineReading }; /** - * Gera uma leitura pessoal (mapa) totalmente offline, sem IA. - * Usa interpretação Jyotish (temas + efeitos), descrição de arquétipo e numerologia, - * e um texto clássico; evita as frases prontas do oráculo Darshan. + * Wrapper: map = buildSymbolicMap(profile) → return { general, love, career, year, action }. */ export function getOfflineReading(profile: { fullName?: string; birthDate?: string; birthPlace?: string; birthTime?: string; -}): string { - const seed3 = (getSeedFromProfile(profile, 3) + Date.now()) >>> 0; - - const chart = computeVedicChartSimplified({ +}): StructuredOfflineReading { + const map = buildSymbolicMap({ + fullName: profile.fullName, birthDate: profile.birthDate, + birthPlace: profile.birthPlace, birthTime: profile.birthTime, }); - const rulingNumber = getRulingNumberFromName(profile.fullName ?? ""); - const numberTraits = getNumberTraits(rulingNumber); - const archetypeKey = chart.archetypeKeys?.[0]; - const archetypeEntry = archetypeKey ? getArchetypeTraits(archetypeKey) : undefined; - - const sections: string[] = []; - - // Introdução - sections.push( - "Esta leitura integra o mapa védico (Lua, signo e estação lunar), numerologia e arquétipos em uma síntese interpretativa." - ); - - // Lua e Jyotish (interpretação narrativa, não frases do oráculo) - if (chart.moonRashi || chart.moonNakshatra) { - const rashi = chart.moonRashi ? rashiName(chart.moonRashi as RashiKey) : ""; - const naks = chart.moonNakshatra ? nakshatraName(chart.moonNakshatra as NakshatraKey) : ""; - const line: string[] = []; - if (rashi) line.push(`Sua Lua está no signo de ${rashi}`); - if (naks) line.push(`na estação lunar ${naks}`); - if (line.length) { - sections.push(line.join(" e ") + "."); - const interpretation = getJyotishReadingInterpretation(chart); - if (interpretation) sections.push(interpretation); - } - } - - // Arquétipo (descrição a partir de traits, sem frase pronta) - if (archetypeKey && archetypeEntry) { - sections.push(""); - sections.push(`Arquétipo: ${archetypeEntry.name} — ${archetypeEntry.shortTrait}`); - const personality = archetypeEntry.personality?.slice(0, 3).join(", ") ?? ""; - const tendencies = archetypeEntry.tendencies?.slice(0, 3).join("; ") ?? ""; - const challenges = archetypeEntry.challenges?.slice(0, 2).join("; ") ?? ""; - if (personality) sections.push(`Traços: ${personality}.`); - if (tendencies) sections.push(`Tendências: ${tendencies}.`); - if (challenges) sections.push(`Desafios possíveis: ${challenges}.`); - } - - // Numerologia (descrição a partir de traits, sem frase pronta) - sections.push(""); - sections.push(`Numerologia (Pitágoras) — Número regente ${rulingNumber}: ${numberTraits.name}.`); - sections.push(numberTraits.shortTrait + "."); - sections.push(`Tendências: ${numberTraits.tendencies.join("; ")}.`); - sections.push(`Desafios: ${numberTraits.challenges.join("; ")}.`); - - // Um texto clássico (reflexão, não oráculo) - const classic = getRandomClassicTextForArchetype(archetypeKey ?? "sábio", seed3); - if (classic?.text) { - sections.push(""); - sections.push(classic.text); - } + return { + general: getGeneral(map), + love: getLove(map), + career: getCareer(map), + year: getYear(map), + action: getAction(map), + }; +} - return sections.join("\n\n").trim(); +/** + * Retorna o texto completo da leitura (todas as seções unidas). + * Útil para compatibilidade com APIs que esperam uma única string (message). + */ +export function getOfflineReadingFullText(profile: { + fullName?: string; + birthDate?: string; + birthPlace?: string; + birthTime?: string; +}): string { + const s = getOfflineReading(profile); + const parts: string[] = []; + const intro = "Esta leitura integra o mapa védico (Lua, signo e estação lunar), numerologia e arquétipos."; + parts.push(intro); + if (s.general.trim()) parts.push(s.general.trim()); + if (s.love.trim()) parts.push(s.love.trim()); + if (s.career.trim()) parts.push(s.career.trim()); + if (s.year.trim()) parts.push(s.year.trim()); + if (s.action.trim()) parts.push(s.action.trim()); + return parts.join("\n\n").trim(); } diff --git a/lib/readings/actionReading.ts b/lib/readings/actionReading.ts new file mode 100644 index 0000000..6b8a950 --- /dev/null +++ b/lib/readings/actionReading.ts @@ -0,0 +1,14 @@ +/** + * Action Engine — prática concreta obrigatória ao final de toda leitura. + */ + +import type { CoreProfile } from "@/lib/core/types"; +import { buildSymbolicMap } from "@/lib/engines/buildSymbolicMap"; +import { collectAllInsights } from "@/lib/insights/collectInsights"; +import { composeReadingFromInsights } from "@/lib/narrative/composer"; + +export async function getActionReading(profile: CoreProfile): Promise { + const map = await buildSymbolicMap(profile); + const insights = collectAllInsights(map); + return composeReadingFromInsights(insights, "action"); +} diff --git a/lib/readings/careerReading.ts b/lib/readings/careerReading.ts new file mode 100644 index 0000000..a4069f3 --- /dev/null +++ b/lib/readings/careerReading.ts @@ -0,0 +1,19 @@ +/** + * Leitura de carreira — mapa + narrativa career + action. + */ + +import type { CoreProfile } from "@/lib/core/types"; +import type { SymbolicMap } from "@/lib/engines/buildSymbolicMap"; +import { buildSymbolicMap } from "@/lib/engines/buildSymbolicMap"; +import { collectAllInsights } from "@/lib/insights/collectInsights"; +import { composeReadingFromInsights } from "@/lib/narrative/composer"; + +export async function getCareerReading(profile: CoreProfile): Promise<{ map: SymbolicMap; reading: string; action: string }> { + const map = await buildSymbolicMap(profile); + const insights = collectAllInsights(map); + return { + map, + reading: composeReadingFromInsights(insights, "career"), + action: composeReadingFromInsights(insights, "action"), + }; +} diff --git a/lib/readings/generalReading.ts b/lib/readings/generalReading.ts new file mode 100644 index 0000000..a099abd --- /dev/null +++ b/lib/readings/generalReading.ts @@ -0,0 +1,19 @@ +/** + * Leitura geral — mapa + narrativa general + action. + */ + +import type { CoreProfile } from "@/lib/core/types"; +import type { SymbolicMap } from "@/lib/engines/buildSymbolicMap"; +import { buildSymbolicMap } from "@/lib/engines/buildSymbolicMap"; +import { collectAllInsights } from "@/lib/insights/collectInsights"; +import { composeReadingFromInsights } from "@/lib/narrative/composer"; + +export async function getGeneralReading(profile: CoreProfile): Promise<{ map: SymbolicMap; reading: string; action: string }> { + const map = await buildSymbolicMap(profile); + const insights = collectAllInsights(map); + return { + map, + reading: composeReadingFromInsights(insights, "general"), + action: composeReadingFromInsights(insights, "action"), + }; +} diff --git a/lib/readings/loveReading.ts b/lib/readings/loveReading.ts new file mode 100644 index 0000000..dadf066 --- /dev/null +++ b/lib/readings/loveReading.ts @@ -0,0 +1,19 @@ +/** + * Leitura de relacionamento (amor) — mapa + narrativa love + action. + */ + +import type { CoreProfile } from "@/lib/core/types"; +import type { SymbolicMap } from "@/lib/engines/buildSymbolicMap"; +import { buildSymbolicMap } from "@/lib/engines/buildSymbolicMap"; +import { collectAllInsights } from "@/lib/insights/collectInsights"; +import { composeReadingFromInsights } from "@/lib/narrative/composer"; + +export async function getLoveReading(profile: CoreProfile): Promise<{ map: SymbolicMap; reading: string; action: string }> { + const map = await buildSymbolicMap(profile); + const insights = collectAllInsights(map); + return { + map, + reading: composeReadingFromInsights(insights, "love"), + action: composeReadingFromInsights(insights, "action"), + }; +} diff --git a/lib/readings/symbolicReadings.ts b/lib/readings/symbolicReadings.ts new file mode 100644 index 0000000..589f1aa --- /dev/null +++ b/lib/readings/symbolicReadings.ts @@ -0,0 +1,117 @@ +/** + * Readings modulares a partir do mapa simbólico canônico (lib/symbolic). + * Cada getX(map) chama composeReading(map, topic). Motor modular e extensível. + */ + +import type { UserProfileForOracle } from "@/lib/knowledge/types"; +import type { SymbolicMap } from "@/lib/symbolic/types"; +import { buildSymbolicMap } from "@/lib/symbolic/builder"; +import { composeReading } from "@/lib/narrative/composer"; +import type { InsightTopic } from "@/lib/insights/types"; + +function toProfile(p: { + fullName?: string; + birthDate?: string; + birthPlace?: string; + birthTime?: string; +}): UserProfileForOracle { + return { + fullName: p.fullName, + birthDate: p.birthDate, + birthPlace: p.birthPlace, + birthTime: p.birthTime, + }; +} + +// ——— Getters por mapa (usados por readingOffline) ——— +export function getGeneral(map: SymbolicMap): string { + return composeReading(map, "general"); +} + +export function getLove(map: SymbolicMap): string { + return composeReading(map, "love"); +} + +export function getCareer(map: SymbolicMap): string { + return composeReading(map, "career"); +} + +export function getYear(map: SymbolicMap): string { + return composeReading(map, "year"); +} + +export function getAction(map: SymbolicMap): string { + return composeReading(map, "action"); +} + +/** Mapa tema externo (API) → tópico interno (composer). */ +const THEME_TO_TOPIC: Record = { + general: "general", + love: "love", + relationship: "love", + career: "career", + work: "career", + year: "year", + yearly: "year", + action: "action", +}; + +/** + * Leitura temática por nome de tema (usado por POST /api/reading?theme=). + * Aceita: general | love | relationship | career | work | year | yearly | action. + */ +export function getReadingByTheme(map: SymbolicMap, theme: string): string { + const topic = THEME_TO_TOPIC[theme?.toLowerCase()] ?? "general"; + return composeReading(map, topic); +} + +// ——— Readings por perfil (conveniência) ——— +export function getGeneralReadingSymbolic(profile: UserProfileForOracle): string { + const map = buildSymbolicMap(profile); + return getGeneral(map); +} + +export function getLoveReadingSymbolic(profile: UserProfileForOracle): string { + const map = buildSymbolicMap(profile); + return getLove(map); +} + +export function getCareerReadingSymbolic(profile: UserProfileForOracle): string { + const map = buildSymbolicMap(profile); + return getCareer(map); +} + +export function getYearReadingSymbolic(profile: UserProfileForOracle): string { + const map = buildSymbolicMap(profile); + return getYear(map); +} + +export function getActionReadingSymbolic(profile: UserProfileForOracle): string { + const map = buildSymbolicMap(profile); + return getAction(map); +} + +export type StructuredOfflineReading = { + general: string; + love: string; + career: string; + year: string; + action: string; +}; + +export function getStructuredOfflineReading(profile: { + fullName?: string; + birthDate?: string; + birthPlace?: string; + birthTime?: string; +}): StructuredOfflineReading { + const p = toProfile(profile); + const map = buildSymbolicMap(p); + return { + general: getGeneral(map), + love: getLove(map), + career: getCareer(map), + year: getYear(map), + action: getAction(map), + }; +} diff --git a/lib/readings/yearReading.ts b/lib/readings/yearReading.ts new file mode 100644 index 0000000..09c8239 --- /dev/null +++ b/lib/readings/yearReading.ts @@ -0,0 +1,19 @@ +/** + * Leitura de ano — mapa + narrativa year + action. + */ + +import type { CoreProfile } from "@/lib/core/types"; +import type { SymbolicMap } from "@/lib/engines/buildSymbolicMap"; +import { buildSymbolicMap } from "@/lib/engines/buildSymbolicMap"; +import { collectAllInsights } from "@/lib/insights/collectInsights"; +import { composeReadingFromInsights } from "@/lib/narrative/composer"; + +export async function getYearReading(profile: CoreProfile): Promise<{ map: SymbolicMap; reading: string; action: string }> { + const map = await buildSymbolicMap(profile); + const insights = collectAllInsights(map); + return { + map, + reading: composeReadingFromInsights(insights, "year"), + action: composeReadingFromInsights(insights, "action"), + }; +} diff --git a/lib/sacredRemedy/ayurvedaActionSelector.ts b/lib/sacredRemedy/ayurvedaActionSelector.ts new file mode 100644 index 0000000..ac300f4 --- /dev/null +++ b/lib/sacredRemedy/ayurvedaActionSelector.ts @@ -0,0 +1,270 @@ +/** + * Ayurveda Action Selector — práticas e alimentos concretos por qualidade ayurvédica. + * Texto cura mente; prática cura qualidade; alimento ancora no corpo. + */ + +import type { AyurvedicQuality } from "./types"; + +/** Qualidade em excesso → prática mínima recomendada (antídoto) */ +export const QUALITY_TO_PRACTICE: Record = { + ruksha: "oleação: óleo na pele ou nas narinas (2 gotas)", + chala: "grounding: pés no chão 2 min ou caminhada lenta", + tikshna: "cooling: respiração lunar ou água fria no rosto", + ushna: "refrescar: bebida à temperatura ambiente, sombra", + guru: "movimento leve: caminhada curta ou alongamento suave", + manda: "estimular: pimenta preta, calor, movimento agora", + sthira: "soltar: alongar, soltar um plano hoje", + picchila: "limpar: gargarejo, escovar língua, leveza na comida", + kathina: "suavizar: óleos, calor úmido, compaixão", + khara: "suavizar: hidratar, palavras gentis", + sukshma: "ancorar: comida densa e quente, corpo no presente", + laghu: "grounding: raiz, sopa, ritual fixo 5 min", + snigdha: "leveza digestiva: chá digestivo, não exceder", + sita: "aquecer: bebida quente, gesto de bondade", + mridu: "contenção suave: descanso, não forçar", + vishada: "nutrir: comida quente e nutritiva", + sandra: "fluir: especiarias, movimento, fluido", + drava: "estabilizar: raiz assada, rotina", + sara: "estabilizar: quente e oleoso, respiração alternada", + shlakshna: "ancorar: textura (caminhar descalço, toque em superfícies), firmeza no corpo", + sthula: "refinar: respiração sutil, escuta interna, leveza na comida", +}; + +/** Qualidade em excesso → sugestão alimentar simples (antídoto) */ +export const QUALITY_TO_FOOD: Record = { + ruksha: "ghee, sopa quente, oleação", + chala: "raiz, sopa, comida quente", + tikshna: "coco, hortelã, cooling", + ushna: "coco, hortelã, doce natural", + guru: "pimenta preta, gengibre, calor", + manda: "pimenta preta, calor, leve", + sthira: "óleos, suavizante", + picchila: "especiarias leves, digestivo", + kathina: "óleos, quente", + khara: "suavizante, hidratante", + sukshma: "comida densa e quente", + laghu: "grounding (raiz), quente", + snigdha: "chá leve digestivo", + sita: "quente, reconfortante", + mridu: "nutritivo, descanso", + vishada: "nutritivo e quente", + sandra: "especiarias, fluido", + drava: "raiz assada, estável", + sara: "quente e oleoso", + shlakshna: "alimento com textura (raiz, fibra), quente e estável", + sthula: "leve, digestivo, especiarias suaves", +}; + +/** Qualidade em excesso → sugestão de sono/descanso (antídoto) */ +export const QUALITY_TO_SLEEP: Record = { + ruksha: "dormir cedo; quarto aquecido e um pouco úmido", + chala: "horário fixo; sem telas 1h antes; pés no chão antes de deitar", + tikshna: "ambiente fresco; jantar leve e cedo", + ushna: "dormir antes da meia-noite; quarto ventilado", + guru: "acordar cedo; movimento de manhã", + manda: "evitar soneca longa; luz de manhã", + sthira: "alongar antes de dormir; soltar agenda", + picchila: "jantar leve; escovar língua", + kathina: "ritual suave; óleo nos pés", + khara: "hidratar; palavras gentis ao fim do dia", + sukshma: "comida quente no jantar; corpo na cama", + laghu: "jantar quente e grounding; rotina fixa", + snigdha: "jantar leve; não exagerar", + sita: "agasalho; bebida quente antes de dormir", + mridu: "descanso sem culpa; não forçar", + vishada: "jantar nutritivo; quarto aconchegante", + sandra: "movimento de tarde; jantar com especiarias leves", + drava: "jantar em horário fixo; rotina de sono", + sara: "jantar quente e oleoso; respiração antes de dormir", + shlakshna: "textura no quarto (tecido, peso); rotina", + sthula: "ambiente leve; não comer pesado à noite", +}; + +/** Qualidade em excesso → sugestão de rotina diária mínima (antídoto) */ +export const QUALITY_TO_ROUTINE: Record = { + ruksha: "oleação ao acordar; refeições em horários fixos", + chala: "acordar e dormir no mesmo horário; 5 min de pé no chão", + tikshna: "refrescar ao meio-dia; evitar pico de calor", + ushna: "atividades pesadas no início da manhã; sombra à tarde", + guru: "movimento logo cedo; evitar ficar parado", + manda: "despertar com luz e movimento; pimenta no café da manhã", + sthira: "alongar pela manhã; um compromisso solto por dia", + picchila: "escovar língua ao acordar; refeições leves", + kathina: "oleação; um gesto de compaixão por dia", + khara: "hidratar; uma frase gentil por dia", + sukshma: "café da manhã quente e denso; ancorar no corpo", + laghu: "sopa ou raiz no almoço; ritual fixo 5 min", + snigdha: "chá digestivo após refeições; não exceder", + sita: "bebida quente pela manhã; um gesto de bondade", + mridu: "pausas sem culpa; não encher a agenda", + vishada: "refeições quentes e nutritivas; ambiente limpo", + sandra: "especiarias no dia; movimento e fluido", + drava: "refeições em horário fixo; rotina estável", + sara: "respiração alternada 2 min; comida quente e oleosa", + shlakshna: "caminhar descalço 2 min; textura nas refeições", + sthula: "respiração sutil 2 min; refeições leves", +}; + +/** + * Retorna estação do ano (hemisfério norte) para prioridade ayurvédica: winter, spring, summer, autumn. + */ +export function getSeasonFromDate(date: Date = new Date()): string { + const m = date.getMonth() + 1; + if (m >= 12 || m <= 2) return "winter"; + if (m >= 3 && m <= 5) return "spring"; + if (m >= 6 && m <= 8) return "summer"; + return "autumn"; +} + +/** + * Retorna período do dia (dinacharya simplificado) para prioridade ayurvédica. + */ +export function getHourPeriodFromDate(date: Date = new Date()): string { + const h = date.getHours(); + if (h >= 6 && h < 10) return "morning"; + if (h >= 10 && h < 14) return "midday"; + if (h >= 14 && h < 18) return "afternoon"; + if (h >= 18 && h < 22) return "evening"; + if (h >= 22 || h < 2) return "night"; + return "late_night"; +} + +/** + * Retorna prática sugerida para a qualidade em excesso (primeira da lista ou fallback). + */ +export function getPracticeForQuality(quality: AyurvedicQuality | string): string { + return QUALITY_TO_PRACTICE[quality] ?? ""; +} + +/** + * Retorna sugestão alimentar para a qualidade em excesso. + */ +export function getFoodForQuality(quality: AyurvedicQuality | string): string { + return QUALITY_TO_FOOD[quality] ?? ""; +} + +/** Dosha → qualidades tipicamente em excesso (prioridade no antídoto) */ +const DOSHA_QUALITIES_PRIORITY: Record = { + vata: ["ruksha", "laghu", "chala", "sukshma", "sara"], + pitta: ["ushna", "tikshna", "drava"], + kapha: ["guru", "snigdha", "manda", "sthira", "sandra"], +}; + +/** Estação → dosha mais agravado (prioridade no antídoto: outono=vata, verão=pitta, inverno=kapha) */ +const SEASON_DOSHA_AGGRAVATION: Record = { + autumn: "vata", + fall: "vata", + summer: "pitta", + winter: "kapha", + spring: "kapha", // início do ano ainda frio/úmido +}; + +/** Período do dia (hora) → dosha em destaque (dinacharya simplificado) */ +const HOUR_PERIOD_DOSHA: Record = { + morning: "kapha", // 6–10 + midday: "pitta", // 10–14 + afternoon: "pitta", // 14–18 + evening: "vata", // 18–22 + night: "vata", // 22–2 + late_night: "kapha", // 2–6 +}; + +function orderByDosha(qualities: string[], dosha?: string, options: { season?: string; hour?: string } = {}): string[] { + const set = new Set(qualities); + const ordered: string[] = []; + const seasonDosha = options.season ? SEASON_DOSHA_AGGRAVATION[options.season] : null; + const hourDosha = options.hour ? HOUR_PERIOD_DOSHA[options.hour] : null; + const priorityDoshas = [seasonDosha, hourDosha, dosha].filter(Boolean) as string[]; + const seen = new Set(); + for (const d of priorityDoshas) { + const priority = DOSHA_QUALITIES_PRIORITY[d]; + if (!priority) continue; + for (const p of priority) { + if (set.has(p) && !seen.has(p)) { + ordered.push(p); + seen.add(p); + } + } + } + for (const q of qualities) { + if (!seen.has(q)) ordered.push(q); + } + return ordered; +} + +/** + * Dado uma lista de qualidades em excesso, retorna práticas e alimentos concretos. + * Prioriza a primeira qualidade; pode combinar até 2 sugestões. + */ +export function getActionsForQualities(qualities: (AyurvedicQuality | string)[]): { + practice: string; + food: string; +} { + const q = qualities.filter(Boolean); + const practice = q.map((x) => QUALITY_TO_PRACTICE[x]).filter(Boolean)[0] ?? ""; + const food = q.map((x) => QUALITY_TO_FOOD[x]).filter(Boolean)[0] ?? ""; + return { practice, food }; +} + +export type GetActionsWithDoshaOptions = { + maxSuggestions?: number; + /** Extensão futura: prioridade por estação (vata=outono, pitta=verão, kapha=inverno) */ + season?: string; + /** Extensão futura: hora do dia para ajuste fino */ + hour?: string; +}; + +/** + * High-end: múltiplas qualities, prioridade por dosha. Combina até maxSuggestions antídotos (default 3). + */ +export function getActionsForQualitiesWithDosha( + qualities: (AyurvedicQuality | string)[], + dosha?: string, + options: GetActionsWithDoshaOptions = {} +): { practice: string; food: string } { + const max = Math.min(5, Math.max(1, options.maxSuggestions ?? 3)); + const ordered = orderByDosha(qualities.filter(Boolean).map(String), dosha); + const practices: string[] = []; + const foods: string[] = []; + for (const q of ordered) { + const p = QUALITY_TO_PRACTICE[q]?.trim(); + const f = QUALITY_TO_FOOD[q]?.trim(); + if (p && p !== "—" && !practices.includes(p)) practices.push(p); + if (f && f !== "—" && !foods.includes(f)) foods.push(f); + if (practices.length >= max && foods.length >= max) break; + } + const practice = practices.slice(0, max).join(". ").trim() || ""; + const food = foods.slice(0, max).join("; ").trim() || ""; + return { practice, food }; +} + +export type FullActionsResult = { practice: string; food: string; sleep?: string; routine?: string }; + +/** + * Ayurveda high-end completo: practice, food, sleep e routine por qualities + dosha. + * Útil para UI premium que exibe sono e rotina diária. + */ +export function getFullActionsForQualitiesWithDosha( + qualities: (AyurvedicQuality | string)[], + dosha?: string, + options: GetActionsWithDoshaOptions = {} +): FullActionsResult { + const base = getActionsForQualitiesWithDosha(qualities, dosha, options); + const ordered = orderByDosha(qualities.filter(Boolean).map(String), dosha, { + season: options.season, + hour: options.hour, + }); + const sleepParts: string[] = []; + const routineParts: string[] = []; + for (const q of ordered) { + const s = QUALITY_TO_SLEEP[q]?.trim(); + const r = QUALITY_TO_ROUTINE[q]?.trim(); + if (s && !sleepParts.includes(s)) sleepParts.push(s); + if (r && !routineParts.includes(r)) routineParts.push(r); + if (sleepParts.length >= 2 && routineParts.length >= 2) break; + } + const result: FullActionsResult = { practice: base.practice, food: base.food }; + if (sleepParts.length) result.sleep = sleepParts.slice(0, 2).join(". "); + if (routineParts.length) result.routine = routineParts.slice(0, 2).join(". "); + return result; +} diff --git a/lib/sacredRemedy/diagnosisEngine.ts b/lib/sacredRemedy/diagnosisEngine.ts new file mode 100644 index 0000000..57ed5b4 --- /dev/null +++ b/lib/sacredRemedy/diagnosisEngine.ts @@ -0,0 +1,199 @@ +/** + * Sacred Remedy — Diagnosis Engine. + * diagnosisUniversal() sem perfil; diagnosisPersonal(map) com perfil. Seleção dirigida + anti-repetição. + */ + +import { buildSymbolicMap } from "@/lib/symbolic/builder"; +import { ARCHETYPE_TO_GUNA } from "@/lib/knowledge/classicTexts"; +import type { UserProfileForOracle } from "@/lib/knowledge/types"; +import type { SymbolicMap } from "@/lib/symbolic/types"; +import type { + ConsciousDiagnosis, + RemedyMatrixEntry, + SamkhyaGuna, + PrakritiFromJyotish, + AyurvedicQuality, + NumerologyFromMap, + KleshaKey, +} from "./types"; + +import remedyMatrixJson from "@/lib/dictionaries/remedyMatrix.json"; + +const REMEDY_MATRIX: RemedyMatrixEntry[] = remedyMatrixJson as RemedyMatrixEntry[]; + +const RASHI_TO_DOSHA: Record = { + mesha: "pitta", vrishabha: "kapha", mithuna: "vata", karka: "kapha", + simha: "pitta", kanya: "vata", tula: "vata", vrischika: "pitta", + dhanu: "pitta", makara: "kapha", kumbha: "vata", mina: "kapha", +}; + +const RASHI_TO_ELEMENT: Record = { + mesha: "fire", vrishabha: "earth", mithuna: "air", karka: "water", + simha: "fire", kanya: "earth", tula: "air", vrischika: "water", + dhanu: "fire", makara: "earth", kumbha: "air", mina: "water", +}; + +/** Dosha → qualidades tipicamente em excesso (Ayurveda); usadas para enriquecer diagnóstico a partir do mapa */ +const DOSHA_TO_QUALITIES_EXCESS: Record = { + vata: ["ruksha", "laghu", "chala", "sukshma", "sara"], + pitta: ["ushna", "tikshna", "drava"], + kapha: ["guru", "snigdha", "manda", "sthira", "sandra"], +}; + +/** Nakshatra → klesha provável (tendência psicológica) — refina diagnóstico personal */ +const NAKSHATRA_KLESHA_TENDENCY: Record = { + ashwini: "abhinivesha", + bharani: "raga", + krittika: "dvesha", + rohini: "raga", + mrigashira: "avidya", + ardra: "dvesha", + punarvasu: "raga", + pushya: "avidya", + ashlesha: "asmita", + magha: "asmita", + "purva-phalguni": "raga", + "uttara-phalguni": "raga", + hasta: "avidya", + chitra: "asmita", + swati: "raga", + vishakha: "dvesha", + anuradha: "raga", + jyestha: "asmita", + mula: "abhinivesha", + "purva-ashadha": "raga", + "uttara-ashadha": "asmita", + shravana: "avidya", + dhanishta: "asmita", + shatabhisha: "abhinivesha", + "purva-bhadra": "dvesha", + "uttara-bhadra": "abhinivesha", + revati: "avidya", +}; + +export function getRemedyMatrix(): RemedyMatrixEntry[] { + return REMEDY_MATRIX; +} + +function getPrakritiFromMap(map: SymbolicMap): PrakritiFromJyotish { + const rashi = map.jyotish?.moonRashi ?? "mesha"; + return { + dosha: RASHI_TO_DOSHA[rashi] ?? "vata", + element: RASHI_TO_ELEMENT[rashi] ?? "air", + }; +} + +function getDominantSamkhyaGuna(map: SymbolicMap): SamkhyaGuna { + const primary = map.archetypes?.primary ?? map.jyotish?.archetypeKey ?? "dissolvente"; + const guna = ARCHETYPE_TO_GUNA[primary]; + return (guna ?? "tamas") as SamkhyaGuna; +} + +function remedyToDiagnosis( + remedy: RemedyMatrixEntry, + prakriti?: PrakritiFromJyotish, + numerologyFromMap?: NumerologyFromMap +): ConsciousDiagnosis { + const g = remedy.samkhyaGuna; + const sattva = g === "sattva" ? 0.6 : 0.2; + const rajas = g === "rajas" ? 0.6 : 0.2; + const tamas = g === "tamas" ? 0.6 : 0.2; + const excessFromRemedy = (remedy.qualities ?? []) as AyurvedicQuality[]; + const excessFromDosha = prakriti?.dosha ? DOSHA_TO_QUALITIES_EXCESS[prakriti.dosha] ?? [] : []; + const excess = [...new Set([...excessFromRemedy, ...excessFromDosha])]; + const out: ConsciousDiagnosis = { + klesha: remedy.klesha, + samkhyaGunas: { sattva, rajas, tamas }, + ayurvedicQualities: { excess, deficient: [] }, + prakritiFromJyotish: prakriti, + stateKey: remedy.state, + }; + if (numerologyFromMap && (numerologyFromMap.lifePath != null || numerologyFromMap.soulUrge != null)) { + out.numerologyFromMap = numerologyFromMap; + } + return out; +} + +/** + * Diagnóstico universal (sem perfil). Escolhe um estado da matriz por seed; evita recentIds. + * Se preferredStateKey for informado e existir na matriz, usa esse estado. + */ +export function diagnosisUniversal(options: { + seed?: number; + recentStateKeys?: string[]; + preferredStateKey?: string; +} = {}): ConsciousDiagnosis { + const { seed = 0, recentStateKeys = [], preferredStateKey } = options; + if (preferredStateKey) { + const found = REMEDY_MATRIX.find((e) => e.state === preferredStateKey); + if (found) return remedyToDiagnosis(found); + } + const avoid = new Set(recentStateKeys); + const pool = avoid.size > 0 + ? REMEDY_MATRIX.filter((e) => !avoid.has(e.state)) + : REMEDY_MATRIX; + const candidates = pool.length > 0 ? pool : REMEDY_MATRIX; + const idx = Math.abs(Math.floor(seed)) % candidates.length; + const remedy = candidates[idx] ?? candidates[0]; + return remedyToDiagnosis(remedy); +} + +/** + * Diagnóstico personalizado (com mapa). Filtra por guna dominante; seed influenciado por numerologia (lifePath, soulUrge). + * Se preferredStateKey for informado e existir na matriz, usa esse estado (com prakriti/numerologia do mapa). + */ +export function diagnosisPersonal( + profile: UserProfileForOracle, + options: { seed?: number; recentStateKeys?: string[]; preferredStateKey?: string } = {} +): ConsciousDiagnosis { + const { seed = 0, recentStateKeys = [], preferredStateKey } = options; + const map = buildSymbolicMap(profile); + const prakriti = getPrakritiFromMap(map); + const lifePath = map.numerology?.lifePathNumber ?? 0; + const soulUrge = map.numerology?.soulUrgeNumber ?? 0; + const numerologyFromMap: NumerologyFromMap = { + lifePath: lifePath || undefined, + soulUrge: soulUrge || undefined, + expression: map.numerology?.expressionNumber ?? undefined, + personality: map.numerology?.personalityNumber ?? undefined, + }; + if (preferredStateKey) { + const found = REMEDY_MATRIX.find((e) => e.state === preferredStateKey); + if (found) return remedyToDiagnosis(found, prakriti, numerologyFromMap); + } + const dominantGuna = getDominantSamkhyaGuna(map); + const effectiveSeed = seed + (lifePath || 0) * 31 + (soulUrge || 0); + const avoid = new Set(recentStateKeys); + const byGuna = REMEDY_MATRIX.filter((e) => e.samkhyaGuna === dominantGuna); + let pool = byGuna.length > 0 ? byGuna : REMEDY_MATRIX; + const nakshatra = map.jyotish?.nakshatra ?? ""; + const nakshatraKlesha = nakshatra ? NAKSHATRA_KLESHA_TENDENCY[nakshatra] : null; + if (nakshatraKlesha) { + const byNakshatra = pool.filter((e) => e.klesha === nakshatraKlesha); + if (byNakshatra.length > 0) pool = byNakshatra; + } + const preferred = pool.filter((e) => !avoid.has(e.state)); + const candidates = preferred.length > 0 ? preferred : pool; + const idx = Math.abs(Math.floor(effectiveSeed)) % candidates.length; + const remedy = candidates[idx] ?? candidates[0]; + return remedyToDiagnosis(remedy, prakriti, numerologyFromMap); +} + +/** + * Retorna a entrada da matriz de remédios correspondente ao diagnóstico (por stateKey ou por klesha+guna). + */ +export function getRemedyForDiagnosis( + diagnosis: ConsciousDiagnosis, + options: { seed?: number } = {} +): RemedyMatrixEntry { + if (diagnosis.stateKey) { + const found = REMEDY_MATRIX.find((e) => e.state === diagnosis.stateKey); + if (found) return found; + } + const byKlesha = diagnosis.klesha + ? REMEDY_MATRIX.filter((e) => e.klesha === diagnosis.klesha) + : REMEDY_MATRIX; + const pool = byKlesha.length > 0 ? byKlesha : REMEDY_MATRIX; + const idx = Math.abs(Math.floor(options.seed ?? 0)) % pool.length; + return pool[idx] ?? pool[0]; +} diff --git a/lib/sacredRemedy/index.ts b/lib/sacredRemedy/index.ts new file mode 100644 index 0000000..35abaca --- /dev/null +++ b/lib/sacredRemedy/index.ts @@ -0,0 +1,35 @@ +/** + * Sacred Remedy Engine — núcleo offline medicinal. + * Diagnóstico (universal/personal) + seleção dirigida de texto sagrado + prática + pergunta. + */ + +export { + getRemedyMatrix, + diagnosisUniversal, + diagnosisPersonal, + getRemedyForDiagnosis, +} from "./diagnosisEngine"; +export { selectSacredText, getAllSacredEntries } from "./sacredSelector"; +export type { SelectSacredOptions } from "./sacredSelector"; +export { resolveSutraContext, shouldIncludePrevContext } from "./sutraContextResolver"; +export type { SutraContextResult } from "./sutraContextResolver"; +export { + getPracticeForQuality, + getFoodForQuality, + getActionsForQualities, + getSeasonFromDate, + getHourPeriodFromDate, +} from "./ayurvedaActionSelector"; +export { composeInstantLight } from "./instantLightComposer"; +export type { ComposeInstantLightOptions } from "./instantLightComposer"; +export type { + SamkhyaGuna, + KleshaKey, + AyurvedicQuality, + PrakritiFromJyotish, + SamkhyaGunas, + ConsciousDiagnosis, + SacredCorpusEntry, + RemedyMatrixEntry, + InstantLightResponse, +} from "./types"; diff --git a/lib/sacredRemedy/instantLightComposer.ts b/lib/sacredRemedy/instantLightComposer.ts new file mode 100644 index 0000000..3b6c60f --- /dev/null +++ b/lib/sacredRemedy/instantLightComposer.ts @@ -0,0 +1,197 @@ +/** + * Sacred Remedy — Instant Light Composer. + * Texto sagrado dirigido (sutra/purana) + insight (se personal) + prática ayurvédica + pergunta final. + * Retorna DarshanTruthPackage para alimentar offline e IA. Motor medicinal offline; não quebra /api/darshan. + */ + +import { buildSymbolicMap } from "@/lib/symbolic/builder"; +import { getGeneral } from "@/lib/readings/symbolicReadings"; +import { + diagnosisUniversal, + diagnosisPersonal, + getRemedyForDiagnosis, +} from "./diagnosisEngine"; +import { selectSacredText } from "./sacredSelector"; +import { resolveSutraContext, shouldIncludePrevContext } from "./sutraContextResolver"; +import { + getFullActionsForQualitiesWithDosha, + getActionsForQualities, + getSeasonFromDate, + getHourPeriodFromDate, +} from "./ayurvedaActionSelector"; +import type { UserProfileForOracle } from "@/lib/knowledge/types"; +import type { DarshanTruthPackage } from "@/lib/core/DarshanTruthPackage"; +import type { Theme } from "@/lib/core/UserRequestContext"; +import type { SacredCorpusKey } from "@/lib/core/DarshanTruthPackage"; + +/** Seed diário para rotação */ +function getDailySeed(): number { + const now = new Date(); + const y = now.getFullYear(); + const m = now.getMonth() + 1; + const d = now.getDate(); + return y * 10000 + m * 100 + d; +} + +/** Normaliza corpus da matriz (purana → puranas) para SacredCorpusKey */ +function toSacredCorpusKey(corpus: string): SacredCorpusKey { + const c = (corpus ?? "").toLowerCase(); + if (c === "purana" || c === "puranas") return "puranas"; + if (c === "upanishad" || c === "upanishads") return "upanishads"; + if (c === "yoga_sutras") return "yoga_sutras"; + return "legacy"; +} + +export type ComposeInstantLightOptions = { + seed?: number; + recentSacredIds?: string[]; + recentStateKeys?: string[]; + /** StateKey preferido (ex.: do Intent Parser a partir de userText) */ + preferredStateKey?: string; + /** Tema da consulta (love, career, health, etc.) */ + theme?: Theme; + /** Tipo de pergunta (what/how/why/when) — influencia ênfase na resposta */ + questionType?: string; + /** Confiança do parser (0–1) quando estado veio do input */ + inputConfidence?: number; + /** Texto da pergunta do usuário (para question.text no package) */ + questionText?: string; +}; + +/** Converte string de prática em { title, steps } */ +function toPracticeStruct(practiceStr: string): { title: string; steps: string[]; duration?: string } { + const s = (practiceStr ?? "").trim(); + if (!s) return { title: "Prática", steps: [] }; + const steps = s.split(/[;.]\s*/).map((x) => x.trim()).filter(Boolean); + if (steps.length === 0) steps.push(s); + return { title: "Prática", steps }; +} + +/** Converte string de alimento em food.do e avoid (formato canônico TruthPackage) */ +function toFoodStruct(foodStr: string): { do: string[]; avoid: string[] } { + const s = (foodStr ?? "").trim(); + if (!s) return { do: [], avoid: [] }; + const items = s.split(/[,;]/).map((x) => x.trim()).filter(Boolean); + return { do: items.length > 0 ? items : [s], avoid: [] }; +} + +/** + * Compõe a resposta Instant Light (Sacred Remedy Engine) como DarshanTruthPackage. + * - Com perfil: diagnosisPersonal → sacredSelector(klesha, qualities) → insight do mapa + prática + pergunta. + * - Sem perfil: diagnosisUniversal → sacredSelector → prática + pergunta. + * - questionType: how → prática em destaque; why → sutra primeiro; when → framing temporal (meta). + */ +export function composeInstantLight( + profile?: UserProfileForOracle | null, + options: ComposeInstantLightOptions = {} +): DarshanTruthPackage { + const { + seed, + recentSacredIds = [], + recentStateKeys = [], + preferredStateKey, + theme = "general", + questionType, + inputConfidence, + questionText, + } = options; + const dailySeed = getDailySeed(); + const effectiveSeed = seed ?? dailySeed * 1000 + (Date.now() % 1000); + const mode = profile && ((profile.fullName ?? "").trim() || (profile.birthDate ?? "").trim()) ? "personal" : "universal"; + + const hasProfile = Boolean( + profile && ((profile.fullName ?? "").trim() || (profile.birthDate ?? "").trim()) + ); + + const diagnosis = hasProfile && profile + ? diagnosisPersonal(profile, { seed: effectiveSeed, recentStateKeys, preferredStateKey }) + : diagnosisUniversal({ seed: effectiveSeed, recentStateKeys, preferredStateKey }); + + const remedy = getRemedyForDiagnosis(diagnosis, { seed: effectiveSeed }); + + const sacredEntry = selectSacredText({ + kleshaTargets: diagnosis.klesha ? [diagnosis.klesha] : [], + qualities: diagnosis.ayurvedicQualities.excess, + avoidIds: recentSacredIds, + seed: effectiveSeed, + }); + + let sacredText = sacredEntry?.text?.trim() || remedy.sacred?.verse?.trim() || remedy.sacred?.id || ""; + const sacredCorpus = sacredEntry ? (sacredEntry.corpus as SacredCorpusKey) : toSacredCorpusKey(remedy.sacred?.corpus ?? "legacy"); + const sacredId = sacredEntry ? sacredEntry.id : (remedy.sacred?.id ?? remedy.state); + let sacredSupporting: { id: string; text: string }[] | undefined; + if (sacredEntry?.corpus === "yoga_sutras" && shouldIncludePrevContext(sacredEntry.id)) { + const context = resolveSutraContext(sacredEntry.id); + if (context?.prev) { + sacredSupporting = [{ id: context.prev.id, text: context.prev.text }]; + } + } + + const dosha = diagnosis.prakritiFromJyotish?.dosha; + const hasQualities = diagnosis.ayurvedicQualities.excess.length > 0; + const now = new Date(); + const ayurvedaOptions = { + maxSuggestions: 3, + season: getSeasonFromDate(now), + hour: getHourPeriodFromDate(now), + }; + const ayurvedaFull = dosha && hasQualities + ? getFullActionsForQualitiesWithDosha(diagnosis.ayurvedicQualities.excess, dosha, ayurvedaOptions) + : null; + const ayurvedaFallback = hasQualities ? getActionsForQualities(diagnosis.ayurvedicQualities.excess) : { practice: "", food: "" }; + const practiceStr = (ayurvedaFull?.practice ?? ayurvedaFallback.practice ?? remedy.practice ?? "").trim(); + const foodStr = (ayurvedaFull?.food ?? ayurvedaFallback.food ?? remedy.food ?? "").trim(); + const questionFinal = (questionText ?? remedy.question ?? "O que em você já sabe?").trim(); + + const stateKey = diagnosis.stateKey ?? remedy.state; + const confidence = preferredStateKey ? (inputConfidence ?? 0.7) : undefined; + + const foodStruct = toFoodStruct(foodStr); + const packageResult: DarshanTruthPackage = { + mode, + theme, + stateKey, + diagnosis: { + klesha: (diagnosis.klesha ?? "avidya") as string, + samkhyaGuna: diagnosis.samkhyaGunas?.rajas > 0.5 ? "rajas" : diagnosis.samkhyaGunas?.tamas > 0.5 ? "tamas" : "sattva", + qualities: [...(diagnosis.ayurvedicQualities?.excess ?? [])], + confidence, + }, + sacred: { + id: sacredId, + corpus: (sacredCorpus as string) === "purana" ? "puranas" : sacredCorpus, + text: sacredText, + ...(sacredSupporting?.length ? { supporting: sacredSupporting } : {}), + }, + practice: toPracticeStruct(practiceStr), + food: foodStruct.do.length > 0 ? foodStruct : undefined, + contemplativeQuestion: { text: questionFinal }, + question: { text: questionFinal }, + meta: { + generatedAt: new Date().toISOString(), + usedSacredIds: recentSacredIds.length > 0 ? recentSacredIds : undefined, + usedStateKeys: recentStateKeys.length > 0 ? recentStateKeys : undefined, + }, + }; + + if (hasProfile && profile) { + const map = buildSymbolicMap(profile); + packageResult.symbolicMap = map; + const insight = getGeneral(map); + if (insight?.trim()) { + packageResult.insight = insight.trim(); + } + } + + if (questionType === "when" && packageResult.meta) { + const { generatedAt, usedSacredIds, usedStateKeys } = packageResult.meta; + packageResult.meta = { generatedAt, usedSacredIds, usedStateKeys }; + } + + packageResult.sacredText = sacredText; + packageResult.sacredId = `${packageResult.sacred.corpus}.${packageResult.sacred.id}`; + if (ayurvedaFull?.sleep?.trim()) packageResult.sleep = ayurvedaFull.sleep.trim(); + if (ayurvedaFull?.routine?.trim()) packageResult.routine = ayurvedaFull.routine.trim(); + + return packageResult; +} diff --git a/lib/sacredRemedy/sacredSelector.ts b/lib/sacredRemedy/sacredSelector.ts new file mode 100644 index 0000000..8e4578d --- /dev/null +++ b/lib/sacredRemedy/sacredSelector.ts @@ -0,0 +1,97 @@ +/** + * Sacred Selector — seleção dirigida de texto sagrado por klesha e qualidades. + * Carrega yoga_sutras_full (196 sutras), puranas, upanishads (dictionaries/sacred/) com kleshaTargets, qualities e themes. + */ + +import type { SacredCorpusEntry } from "./types"; + +import yogaSutrasFullJson from "@/lib/dictionaries/sacred/yoga_sutras_full.json"; +import puranasJson from "@/lib/dictionaries/sacred/puranas.json"; +import upanishadsJson from "@/lib/dictionaries/sacred/upanishads.json"; + +const YOGA_SUTRAS = yogaSutrasFullJson as SacredCorpusEntry[]; +const PURANAS = puranasJson as SacredCorpusEntry[]; +const UPANISHADS = upanishadsJson as SacredCorpusEntry[]; + +/** Todas as entradas com corpus para id único */ +type TaggedEntry = SacredCorpusEntry & { corpus: string }; + +function tagCorpus(entries: SacredCorpusEntry[], corpus: string): TaggedEntry[] { + return entries.map((e) => ({ ...e, corpus })); +} + +const ALL_SACRED: TaggedEntry[] = [ + ...tagCorpus(YOGA_SUTRAS, "yoga_sutras"), + ...tagCorpus(PURANAS, "puranas"), + ...tagCorpus(UPANISHADS, "upanishads"), +]; + +export type SelectSacredOptions = { + /** Kleśas que o texto deve endereçar (pelo menos um match em kleshaTargets) */ + kleshaTargets?: string[]; + /** Qualidades em excesso (match em qualities do texto) */ + qualities?: string[]; + /** IDs a evitar (anti-repetição) — formato "corpus.id" ou só "id" */ + avoidIds?: string[]; + /** Seed para escolha determinística */ + seed?: number; +}; + +/** Conta quantos avoidIds pertencem a cada corpus (para balancear e evitar repetir corpus inteiro). */ +function corpusUsageCount(avoidIds: string[]): Map { + const count = new Map(); + for (const id of avoidIds) { + const corpus = id.includes(".") ? id.split(".")[0] : "legacy"; + count.set(corpus, (count.get(corpus) ?? 0) + 1); + } + return count; +} + +/** + * Seleciona um texto sagrado dirigido por klesha e qualidades. + * Prioriza entradas que batem em kleshaTargets; depois em qualities; evita avoidIds. + * Balanceia corpora: entre candidatos com mesmo score, prefere o corpus menos usado em avoidIds. + */ +export function selectSacredText(options: SelectSacredOptions = {}): SacredCorpusEntry & { corpus: string } { + const { kleshaTargets = [], qualities = [], avoidIds = [], seed = 0 } = options; + const avoidSet = new Set(avoidIds); + const kleshaSet = new Set(kleshaTargets.filter(Boolean)); + const qualitySet = new Set(qualities.filter(Boolean)); + const corpusUsage = corpusUsageCount(avoidIds); + + const score = (e: TaggedEntry): number => { + let s = 0; + const targets = e.kleshaTargets ?? []; + const quals = e.qualities ?? []; + if (kleshaSet.size && targets.some((t) => kleshaSet.has(t))) s += 2; + if (qualitySet.size && quals.some((q) => qualitySet.has(q))) s += 1; + return s; + }; + + const byAvoid = ALL_SACRED.filter((e) => { + const fullId = `${e.corpus}.${e.id}`; + return !avoidSet.has(fullId) && !avoidSet.has(e.id); + }); + const pool = byAvoid.length > 0 ? byAvoid : ALL_SACRED; + + const scored = pool.map((e) => ({ e, s: score(e) })); + scored.sort((a, b) => b.s - a.s); + const bestScore = scored[0]?.s ?? 0; + let candidates = bestScore > 0 ? scored.filter((x) => x.s === bestScore).map((x) => x.e) : pool; + + if (candidates.length > 1 && corpusUsage.size > 0) { + candidates = [...candidates].sort((a, b) => { + const useA = corpusUsage.get(a.corpus) ?? 0; + const useB = corpusUsage.get(b.corpus) ?? 0; + return useA - useB; + }); + } + + const idx = Math.abs(Math.floor(seed)) % candidates.length; + return candidates[idx] ?? candidates[0]; +} + +/** Retorna lista completa para fallback ou inspeção */ +export function getAllSacredEntries(): TaggedEntry[] { + return ALL_SACRED; +} diff --git a/lib/sacredRemedy/sutraContextResolver.ts b/lib/sacredRemedy/sutraContextResolver.ts new file mode 100644 index 0000000..da551b3 --- /dev/null +++ b/lib/sacredRemedy/sutraContextResolver.ts @@ -0,0 +1,46 @@ +/** + * Sutra Context Resolver — entrega bloco completo quando o sutra referencia o verso anterior. + * Evita fragmentos sem contexto ("Por isso...") e permite exibir: verso contexto + sutra medicinal. + */ + +import yogaSutrasFullJson from "@/lib/dictionaries/sacred/yoga_sutras_full.json"; + +type SutraEntry = { id: string; text: string; kleshaTargets?: string[]; qualities?: string[] }; +const YOGA_SUTRAS = yogaSutrasFullJson as SutraEntry[]; + +export type SutraContextResult = { + /** Verso anterior (contexto), quando existe e o sutra se beneficia de contexto */ + prev?: { id: string; text: string }; + /** Sutra principal selecionado */ + primary: { id: string; text: string }; + /** Verso seguinte (para thread mode futuro) */ + next?: { id: string; text: string }; +}; + +/** + * Resolve contexto sequencial para um sutra por id. + * Deriva prev/next pela ordem no corpus (YS.1.1, YS.1.2, ...). + * Inclui prev quando o sutra não é o primeiro do capítulo (verso > 1), para evitar "Por isso..." sem referência. + */ +export function resolveSutraContext(sutraId: string): SutraContextResult | null { + const idx = YOGA_SUTRAS.findIndex((e) => e.id === sutraId); + if (idx < 0) return null; + const primary = YOGA_SUTRAS[idx]; + const prevEntry = idx > 0 ? YOGA_SUTRAS[idx - 1] : undefined; + const nextEntry = idx < YOGA_SUTRAS.length - 1 ? YOGA_SUTRAS[idx + 1] : undefined; + return { + prev: prevEntry ? { id: prevEntry.id, text: (prevEntry.text ?? "").trim() } : undefined, + primary: { id: primary.id, text: (primary.text ?? "").trim() }, + next: nextEntry ? { id: nextEntry.id, text: (nextEntry.text ?? "").trim() } : undefined, + }; +} + +/** + * Indica se o sutra deve ser exibido com verso anterior (contexto). + * Por padrão: todo sutra que não é o primeiro (índice > 0) pode ter contexto. + * Entradas com context.requiresPrev no corpus podem ser usadas no futuro. + */ +export function shouldIncludePrevContext(sutraId: string): boolean { + const idx = YOGA_SUTRAS.findIndex((e) => e.id === sutraId); + return idx > 0; +} diff --git a/lib/sacredRemedy/types.ts b/lib/sacredRemedy/types.ts new file mode 100644 index 0000000..76829a7 --- /dev/null +++ b/lib/sacredRemedy/types.ts @@ -0,0 +1,109 @@ +/** + * Sacred Remedy Engine — tipos canônicos. + * Diagnóstico consciente (klesha, samkhya, qualidades) + corpus sagrado taggeado + matriz de remédios. + */ + +/** Guṇas Sāṃkhya — estado global da consciência */ +export type SamkhyaGuna = "sattva" | "rajas" | "tamas"; + +/** Kleśas — obstáculos da mente (Yoga Sutras) */ +export type KleshaKey = "avidya" | "asmita" | "raga" | "dvesha" | "abhinivesha" | null; + +/** As 20 qualidades ayurvédicas (10 pares) — mente, corpo, alimento, clima, emoções */ +export type AyurvedicQuality = + | "guru" | "laghu" // pesado | leve + | "snigdha"| "ruksha" // oleoso | seco + | "sita" | "ushna" // frio | quente (usna) + | "manda" | "tikshna" // lento/obtuso | agudo + | "sthira" | "chala" // estável | móvel + | "mridu" | "kathina" // suave | duro + | "vishada"| "picchila"// claro/limpo | pegajoso + | "shlakshna"| "khara" // liso | áspero + | "sukshma"| "sthula" // sutil | grosso + | "sandra" | "drava" // denso | fluido + | "sara"; // fluido/móvel (complementar) + +/** Prakṛti simbólica (Jyotish) */ +export type PrakritiFromJyotish = { + dosha?: string; + element?: string; +}; + +export type SamkhyaGunas = { + sattva: number; + rajas: number; + tamas: number; +}; + +/** Numerologia no mapa (Life Path, Soul Urge, etc.) — usada para coerência do diagnóstico personal */ +export type NumerologyFromMap = { + lifePath?: number; + soulUrge?: number; + expression?: number; + personality?: number; +}; + +/** Diagnóstico consciente — entrada do motor de remédio */ +export type ConsciousDiagnosis = { + klesha: KleshaKey; + samkhyaGunas: SamkhyaGunas; + /** Qualidades em excesso e em deficiência (20 gunas ayurvédicas) */ + ayurvedicQualities: { excess: AyurvedicQuality[]; deficient: AyurvedicQuality[] }; + prakritiFromJyotish?: PrakritiFromJyotish; + /** Estado da matriz usado (ex.: anxiety, lethargy) */ + stateKey?: string; + /** Preenchido em diagnóstico personal — influencia seed e coerência */ + numerologyFromMap?: NumerologyFromMap; +}; + +/** Contexto sequencial (para Sutra Context Engine — verso anterior/posterior) */ +export type SacredContextBlock = { + prev?: string; + next?: string; + /** Quando true, Instant Light inclui verso anterior em sacred.supporting */ + requiresPrev?: boolean; +}; + +/** Entrada do corpus sagrado (dictionaries/sacred/*.json) — taggeada por klesha, qualidades e temas */ +export type SacredCorpusEntry = { + id: string; + text: string; + /** Kleśas que este texto ajuda a equilibrar */ + kleshaTargets?: string[]; + /** Qualidades ayurvédicas associadas */ + qualities?: string[]; + /** Temas para matching futuro (ex.: presença, medo, amor, corpo) — opcional até expansão premium */ + themes?: string[]; + /** Contexto sequencial (prev/next/requiresPrev) — usado pelo sutraContextResolver */ + context?: SacredContextBlock; + /** Nota de continuidade (ex.: "Este verso continua a instrução anterior...") */ + commentary?: string; +}; + +/** Entrada da matriz de remédios (50 estados) */ +export type RemedyMatrixEntry = { + state: string; + klesha: KleshaKey; + samkhyaGuna: SamkhyaGuna; + qualities: string[]; + sacred: { corpus: string; id: string; verse?: string }; + practice: string; + food: string; + question: string; +}; + +/** Resposta do Instant Light (GET /api/instant-light) */ +export type InstantLightResponse = { + sacredText: string; + insight?: string; + practice: string; + /** Recomendação alimentar simples (Ayurveda) */ + food?: string; + /** Sugestão de sono/descanso (Ayurveda high-end) */ + sleep?: string; + /** Sugestão de rotina diária mínima (Ayurveda high-end) */ + routine?: string; + question: string; + sacredId?: string; + stateKey?: string; +}; diff --git a/lib/symbolic/SymbolicMap.ts b/lib/symbolic/SymbolicMap.ts new file mode 100644 index 0000000..adbed1d --- /dev/null +++ b/lib/symbolic/SymbolicMap.ts @@ -0,0 +1,8 @@ +/** + * Entrada canônica do mapa simbólico — Engine 2.0. + * Estrutura: jyotish, numerology, themes, traits, evidence. + * Use buildSymbolicMap(profile) para obter o mapa; depois composeReading(map, topic) para leituras temáticas. + */ + +export type { SymbolicMap } from "./types"; +export { buildSymbolicMap } from "./builder"; diff --git a/lib/symbolic/builder.ts b/lib/symbolic/builder.ts new file mode 100644 index 0000000..25928bb --- /dev/null +++ b/lib/symbolic/builder.ts @@ -0,0 +1,52 @@ +/** + * Constrói o mapa simbólico canônico a partir do perfil (Jyotish + Numerologia). + * Determinístico; sem IA. evidence guarda o chart para auditoria e extensão. + */ + +import type { UserProfileForOracle } from "@/lib/knowledge/types"; +import type { VedicChartSimplified } from "@/lib/knowledge/types"; +import { computeVedicChartSimplified } from "@/lib/knowledge/vedic"; +import { + getRulingNumberFromName, + getLifePathNumber, + getExpressionNumber, + getSoulUrgeNumber, + getPersonalityNumber, +} from "@/lib/knowledge/numerology"; +import type { SymbolicMap } from "./types"; + +export function buildSymbolicMap(profile: UserProfileForOracle): SymbolicMap { + const chart: VedicChartSimplified = computeVedicChartSimplified({ + birthDate: profile.birthDate, + birthTime: profile.birthTime, + }); + const rulingNumber = getRulingNumberFromName(profile.fullName ?? ""); + const lifePathNumber = getLifePathNumber(profile.birthDate ?? ""); + const expressionNumber = getExpressionNumber(profile.fullName ?? ""); + const soulUrgeNumber = getSoulUrgeNumber(profile.fullName ?? ""); + const personalityNumber = getPersonalityNumber(profile.fullName ?? ""); + + const archetypeKeys = chart.archetypeKeys ?? ["dissolvente"]; + const primary = archetypeKeys[0] ?? "dissolvente"; + + return { + jyotish: { + moonRashi: chart.moonRashi ?? "mesha", + nakshatra: chart.moonNakshatra ?? "ashwini", + archetypeKey: primary, + }, + numerology: { + rulingNumber: rulingNumber as number, + lifePathNumber: lifePathNumber as number, + expressionNumber: expressionNumber as number, + soulUrgeNumber: soulUrgeNumber as number, + personalityNumber: personalityNumber as number, + }, + archetypes: { + primary, + keys: archetypeKeys, + }, + themes: [], + evidence: { chart }, + }; +} diff --git a/lib/symbolic/types.ts b/lib/symbolic/types.ts new file mode 100644 index 0000000..4fa4441 --- /dev/null +++ b/lib/symbolic/types.ts @@ -0,0 +1,32 @@ +/** + * Mapa simbólico canônico universal — base do Engine 2.0. + * Estrutura: jyotish, numerology, archetypes, themes, evidence. + * Objeto canônico do Darshan; reutilizável por Oracle e leituras premium. + */ + +export type SymbolicMap = { + jyotish: { + moonRashi: string; + nakshatra: string; + archetypeKey: string; + }; + numerology: { + /** Número regente do nome (Pitágoras); mantido para compatibilidade. */ + rulingNumber: number; + /** Life Path — data de nascimento (1–9, 11, 22). */ + lifePathNumber?: number; + /** Expression/Destiny — nome completo (1–9, 11, 22). */ + expressionNumber?: number; + /** Soul Urge — vogais do nome (desejo interior). */ + soulUrgeNumber?: number; + /** Personality — consoantes do nome (máscara social). */ + personalityNumber?: number; + }; + /** Arquétipos derivados do chart (primary = primeiro; keys = lista completa). */ + archetypes: { + primary: string; + keys: string[]; + }; + themes: string[]; + evidence: Record; +}; diff --git a/package-lock.json b/package-lock.json index d445aa2..1bc5fd1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,14 +1,15 @@ { "name": "darshan", - "version": "0.1.0", + "version": "0.1.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "darshan", - "version": "0.1.0", + "version": "0.1.3", "dependencies": { "@anthropic-ai/sdk": "^0.32.1", + "@fusionstrings/swiss-eph": "^0.1.1", "@google/generative-ai": "^0.21.0", "@supabase/supabase-js": "^2.93.3", "framer-motion": "^11.11.17", @@ -595,6 +596,46 @@ "dev": true, "license": "MIT" }, + "node_modules/@deno/shim-deno": { + "version": "0.18.2", + "resolved": "https://registry.npmjs.org/@deno/shim-deno/-/shim-deno-0.18.2.tgz", + "integrity": "sha512-oQ0CVmOio63wlhwQF75zA4ioolPvOwAoK0yuzcS5bDC1JUvH3y1GS8xPh8EOpcoDQRU4FTG8OQfxhpR+c6DrzA==", + "license": "MIT", + "dependencies": { + "@deno/shim-deno-test": "^0.5.0", + "which": "^4.0.0" + } + }, + "node_modules/@deno/shim-deno-test": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@deno/shim-deno-test/-/shim-deno-test-0.5.0.tgz", + "integrity": "sha512-4nMhecpGlPi0cSzT67L+Tm+GOJqvuk8gqHBziqcUQOarnuIax1z96/gJHCSIz2Z0zhxE6Rzwb3IZXPtFh51j+w==", + "license": "MIT" + }, + "node_modules/@deno/shim-deno/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "license": "ISC", + "engines": { + "node": ">=16" + } + }, + "node_modules/@deno/shim-deno/node_modules/which": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", + "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "license": "ISC", + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^16.13.0 || >=18.0.0" + } + }, "node_modules/@emnapi/core": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.8.1.tgz", @@ -711,6 +752,16 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@fusionstrings/swiss-eph": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@fusionstrings/swiss-eph/-/swiss-eph-0.1.1.tgz", + "integrity": "sha512-UGKCfVh5TUygShCNKnh7iauJ109QYgV+e3+8PACOsiIFyiX8z3PIw7etbYDqF0egsJfIArRdDjOwrliAOFGNgA==", + "license": "AGPL-3.0", + "dependencies": { + "@deno/shim-deno": "~0.18.0", + "undici": "^6.0.0" + } + }, "node_modules/@google/generative-ai": { "version": "0.21.0", "resolved": "https://registry.npmjs.org/@google/generative-ai/-/generative-ai-0.21.0.tgz", @@ -9272,6 +9323,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/undici": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.23.0.tgz", + "integrity": "sha512-VfQPToRA5FZs/qJxLIinmU59u0r7LXqoJkCzinq3ckNJp3vKEh7jTWN589YQ5+aoAC/TGRLyJLCPKcLQbM8r9g==", + "license": "MIT", + "engines": { + "node": ">=18.17" + } + }, "node_modules/undici-types": { "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", diff --git a/package.json b/package.json index 562fc93..5c6e4a3 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "private": true, "scripts": { "dev": "next dev", - "prebuild": "node -e \"try { require('fs').rmSync('build', { recursive: true }) } catch (e) { }\"", + "prebuild": "node -e \"var fs=require('fs'); if(fs.existsSync('build')){ fs.rmSync('build',{recursive:true,maxRetries:3}); }\"", "build": "next build", "start": "next start", "lint": "next lint", @@ -21,15 +21,16 @@ }, "dependencies": { "@anthropic-ai/sdk": "^0.32.1", + "@fusionstrings/swiss-eph": "^0.1.1", "@google/generative-ai": "^0.21.0", "@supabase/supabase-js": "^2.93.3", "framer-motion": "^11.11.17", + "mercadopago": "^2.0.0", "mhah-panchang": "^1.2.0", "next": "15.5.11", "openai": "^4.73.0", "react": "^19.0.0", "react-dom": "^19.0.0", - "mercadopago": "^2.0.0", "stripe": "^17.4.0", "suncalc": "^1.9.0" }, @@ -40,10 +41,10 @@ "@types/react-dom": "^19.0.1", "@types/suncalc": "^1.9.2", "autoprefixer": "^10.4.20", - "postcss": "^8.4.49", "eslint": "^8.57.0", "eslint-config-next": "15.5.11", "jest": "^29.7.0", + "postcss": "^8.4.49", "tailwindcss": "^3.4.15", "typescript": "^5.6.3" } diff --git a/scripts/expand-sacred-corpus.js b/scripts/expand-sacred-corpus.js new file mode 100644 index 0000000..f45c42a --- /dev/null +++ b/scripts/expand-sacred-corpus.js @@ -0,0 +1,240 @@ +/** + * Expande puranas.json para ~400 entradas e upanishads.json para ~200 entradas. + * Cada entrada tem: id, text, kleshaTargets, qualities, themes. + * Executar: node scripts/expand-sacred-corpus.js + */ + +const fs = require("fs"); +const path = require("path"); + +const basePath = path.join(__dirname, "..", "lib", "dictionaries", "sacred"); +const KLESHAS = ["avidya", "asmita", "raga", "dvesha", "abhinivesha"]; +const QUALITIES = ["vishada", "guru", "mridu", "snigdha", "picchila", "sthira", "chala", "laghu", "tikshna", "ushna", "khara", "kathina", "sita", "drava", "sandra", "manda", "sukshma", "ruksha", "shlakshna", "sthula"]; +const THEMES = ["entrega", "devoção", "perdão", "compaixão", "presença", "medo", "alegria", "corpo", "mente", "respiração", "grounding", "limites", "verdade", "aceitação", "silêncio", "unidade", "coração", "ação", "tempo", "natureza", "gratidão", "humildade", "discernimento", "liberação", "paz", "amor", "confiança", "luto", "raiva", "dúvida", "palavra", "sono", "rotina", "alimentação"]; + +/** Templates: [text, kleshaKeys[], qualityKeys[], themeKeys[]] */ +const PURANA_TEMPLATES = [ + ["O que você oferece ao divino deixa de pesar em você.", ["raga"], ["guru", "snigdha"], ["entrega", "ação"]], + ["Quem honra o ritmo do corpo não adoece de pressa.", ["abhinivesha"], ["manda", "sthira"], ["corpo", "tempo"]], + ["A palavra que acalma é mais forte que a que fere.", ["dvesha"], ["mridu", "tikshna"], ["palavra", "compaixão"]], + ["O silêncio após a oração é onde a resposta habita.", ["avidya"], ["chala", "vishada"], ["silêncio", "oração"]], + ["Aceitar a impermanência é o primeiro passo para a paz.", ["abhinivesha"], ["picchila", "mridu"], ["aceitação", "paz"]], + ["Servir sem esperar reconhecimento libera o ego.", ["asmita"], ["vishada", "snigdha"], ["serviço", "humildade"]], + ["A raiva que é respirada perde o controle sobre você.", ["dvesha"], ["ushna", "tikshna"], ["raiva", "respiração"]], + ["O corpo que descansa se renova; o que não para se quebra.", ["raga"], ["manda", "mridu"], ["corpo", "sono"]], + ["Quem vê o divino no outro não precisa que o outro mude.", ["dvesha"], ["vishada", "mridu"], ["unidade", "aceitação"]], + ["A gratidão desloca o foco do que falta para o que já é.", ["raga", "abhinivesha"], ["vishada", "laghu"], ["gratidão", "presença"]], + ["O medo nomeado perde metade da sombra.", ["abhinivesha"], ["sukshma", "chala"], ["medo", "presença"]], + ["A humildade não diminui; abre espaço para o infinito.", ["asmita"], ["tikshna", "kathina"], ["humildade", "ego"]], + ["Caminhar descalço na terra ancora a mente no agora.", ["abhinivesha"], ["sthira", "laghu"], ["grounding", "natureza"]], + ["O perdão que você dá a si mesmo é o que libera.", ["dvesha"], ["picchila", "guru"], ["perdão", "liberação"]], + ["Comer com consciência é oração que nutre o corpo.", ["raga"], ["sita", "vishada"], ["alimentação", "consciência"]], + ["Dizer não é dizer sim a si mesmo.", ["asmita", "raga"], ["kathina", "sthira"], ["limites", "autocuidado"]], + ["A dúvida honesta é o início do discernimento.", ["avidya"], ["vishada"], ["dúvida", "discernimento"]], + ["O amor que não exige reciprocidade simplesmente flui.", ["dvesha"], ["sita", "kathina"], ["amor", "fluir"]], + ["Lembrar a morte não é morrer; é viver com mais presença.", ["abhinivesha"], ["guru"], ["presença", "morte"]], + ["O repouso é parte do caminho, não desvio.", ["asmita"], ["manda", "mridu"], ["rotina", "descanso"]], + ["A verdade que libera pode doer no início.", ["avidya"], ["vishada", "tikshna"], ["verdade", "liberdade"]], + ["Quem observa a mente sem se identificar encontra espaço.", ["avidya", "asmita"], ["vishada", "sukshma"], ["testemunha", "mente"]], + ["A alegria que nasce de dentro não depende do externo.", ["raga"], ["laghu", "vishada"], ["alegria", "interior"]], + ["Chorar é deixar a dor sair pelo único caminho que ela conhece.", ["abhinivesha", "dvesha"], ["drava", "mridu"], ["luto", "corpo"]], + ["Confiar no fluxo não é passividade; é coragem.", ["abhinivesha"], ["chala", "ruksha"], ["confiança", "coragem"]], + ["O sopro que entra e sai já é oração.", ["raga"], ["laghu", "vishada"], ["respiração", "oração"]], + ["A natureza não tem pressa; quem anda nela aprende o ritmo.", ["raga", "abhinivesha"], ["manda", "sthira"], ["natureza", "ritmo"]], + ["Antes de falar, pergunte: é verdadeiro, necessário e bondoso?", ["dvesha"], ["tikshna", "khara"], ["palavra", "verdade"]], + ["O corpo guarda o que a mente esquece; honre os dois.", ["asmita", "abhinivesha"], ["guru", "snigdha"], ["corpo", "memória"]], + ["A simplicidade é o luxo de quem não precisa provar nada.", ["raga", "asmita"], ["vishada", "laghu"], ["simplicidade", "suficiência"]], + ["Quem se esvazia é preenchido.", ["raga"], ["vishada", "laghu"], ["humildade", "entrega"]], + ["A paz que nasce da devoção não depende do mundo.", ["raga", "dvesha"], ["vishada", "laghu"], ["paz", "devoção"]], + ["Proteger o coração não é fechar; é escolher o que entra.", ["abhinivesha"], ["sukshma", "chala"], ["proteção", "limites"]], + ["O descanso é dharma; quem se entrega ao repouso se renova.", ["abhinivesha"], ["guru", "mridu"], ["descanso", "renovação"]], + ["Abrir o coração não é fraqueza; é coragem de sentir.", ["dvesha"], ["sita", "kathina"], ["coração", "coragem"]], + ["A graça não escolhe merecimento; ela escolhe o momento.", ["asmita"], ["kathina"], ["graça", "humildade"]], + ["Quando o coração está quebrado, a luz entra por onde não havia porta.", ["abhinivesha"], ["guru", "mridu"], ["graça", "luz"]], + ["O serviço ao outro é oração em movimento.", ["asmita"], ["vishada"], ["serviço", "oração"]], + ["No silêncio da devoção, a resposta já está.", ["avidya"], ["chala", "sukshma"], ["silêncio", "resposta"]], + ["Quem cala a mente ouve o que as palavras não dizem.", ["raga"], ["chala"], ["silêncio", "mente"]], + ["Amar sem posse é a única forma de não perder.", ["raga"], ["snigdha", "guru"], ["amor", "desapego"]], + ["Soltar não é desistir; é deixar o rio correr.", ["raga"], ["picchila", "sthira"], ["soltar", "fluir"]], + ["O que você libera libera você.", ["dvesha"], ["guru", "picchila"], ["libertação", "perdão"]], + ["O divino está no agora; quem habita o passado ou o futuro o perde.", ["abhinivesha"], ["chala"], ["presença", "agora"]], + ["Quem observa sem julgar encontra paz.", ["dvesha", "asmita"], ["tikshna", "khara"], ["testemunha", "paz"]], + ["O testemunho compassivo dissolve a raiva.", ["dvesha"], ["ushna", "tikshna"], ["compaixão", "raiva"]], + ["Chorar é permitir que o rio do coração encontre o mar.", ["abhinivesha"], ["guru", "mridu"], ["luto", "corpo"]], + ["A tristeza honrada se transforma em compaixão.", ["abhinivesha"], ["guru", "sandra"], ["luto", "compaixão"]], + ["A alegria que não depende do externo é estável.", ["raga"], ["chala", "laghu"], ["alegria", "estabilidade"]], + ["Celebrar o bem do outro é antídoto para a inveja.", ["dvesha"], ["tikshna", "ushna"], ["alegria", "inveja"]], + ["A paciência é força; a pressa é medo disfarçado.", ["raga", "abhinivesha"], ["tikshna", "chala"], ["paciência", "medo"]], + ["O que amadurece no tempo certo não apodrece.", ["raga"], ["chala"], ["paciência", "tempo"]], + ["A simplicidade desfaz o nó da cobiça.", ["raga"], ["guru", "snigdha"], ["simplicidade", "cobiça"]], + ["Menos é o caminho para mais.", ["raga"], ["vishada"], ["simplicidade", "suficiência"]], + ["A verdade libera; a mentira aprisiona.", ["avidya"], ["vishada"], ["verdade", "liberdade"]], + ["Falar a verdade com amor é arte.", ["dvesha"], ["khara", "tikshna"], ["verdade", "amor"]], + ["Cada respiração é chance de recomeçar.", ["avidya"], ["guru", "picchila"], ["recomeço", "respiração"]], + ["O perdão é o único modo de nascer de novo sem morrer.", ["dvesha"], ["picchila"], ["perdão", "renascimento"]], + ["Quem vê o divino em todos não está nunca só.", ["abhinivesha"], ["sita", "sthira"], ["unidade", "companhia"]], + ["A separação é ilusão; a união é a natureza do ser.", ["avidya"], ["vishada"], ["unidade", "identidade"]], + ["Quem pisa a terra com consciência não cai.", ["abhinivesha"], ["chala", "laghu"], ["grounding", "consciência"]], + ["Uma respiração consciente une corpo e espírito.", ["avidya"], ["chala"], ["respiração", "corpo"]], + ["Aceitar o que é não é resignação; é clareza.", ["dvesha"], ["picchila", "mridu"], ["aceitação", "clareza"]], + ["Na solidão voluntária, o ruído interno se acalma.", ["raga"], ["chala", "vishada"], ["solidão", "silêncio"]], + ["Quem se encontra sozinho não está só.", ["abhinivesha"], ["guru"], ["solidão", "presença"]], + ["Parar não é falhar; é permitir que a força volte.", ["raga"], ["tikshna", "ushna"], ["descanso", "força"]], + ["A raiva que é vista com compaixão perde o fogo.", ["dvesha"], ["ushna", "tikshna"], ["raiva", "compaixão"]], + ["Não apague a chama com mais chama; respire e deixe esfriar.", ["dvesha"], ["tikshna", "khara"], ["raiva", "resfriar"]], + ["Quem aceita o medo não é governado por ele.", ["abhinivesha"], ["guru", "mridu"], ["medo", "aceitação"]], + ["Não exija certeza de si; exija presença.", ["asmita"], ["chala", "laghu"], ["dúvida", "presença"]], + ["Quem respeita os próprios limites pode expandir sem quebrar.", ["abhinivesha"], ["guru"], ["limites", "expansão"]], + ["Caminhar na natureza é voltar à própria natureza.", ["avidya"], ["vishada", "laghu"], ["natureza", "identidade"]], + ["A água que flui não se prende; ela contorna e segue.", ["raga"], ["sthira", "drava"], ["fluir", "flexibilidade"]], + ["Beber um gole de água com consciência é um ato de gratidão.", ["raga"], ["sita", "vishada"], ["gratidão", "consciência"]], + ["O silêncio que escolhemos é mais eloqüente que as palavras.", ["raga"], ["chala"], ["silêncio", "palavra"]], + ["O corpo não é inimigo; é o veículo da alma.", ["asmita"], ["guru", "snigdha"], ["corpo", "alma"]], + ["Honrar o cansaço do corpo é honrar a vida.", ["abhinivesha"], ["manda", "mridu"], ["corpo", "descanso"]], + ["O que você sonha à noite o dia pode realizar.", ["avidya"], ["vishada", "sukshma"], ["sonho", "realização"]], + ["Não despreze o sonho; ele fala a linguagem do coração.", ["raga"], ["picchila", "guru"], ["sonho", "coração"]], + ["Quem honra os que vieram antes não caminha sozinho.", ["abhinivesha"], ["guru", "sthira"], ["ancestrais", "linhagem"]], + ["A linhagem não é peso; é raiz.", ["avidya"], ["vishada"], ["linhagem", "raiz"]], + ["O olhar de uma criança lembra: o presente é agora.", ["abhinivesha"], ["chala", "laghu"], ["presença", "agora"]], + ["Brincar não é fuga; é o modo do espírito respirar.", ["raga"], ["drava", "mridu"], ["brincar", "leveza"]], + ["O que é impermanente merece cuidado, não apego.", ["raga"], ["vishada", "snigdha"], ["impermanência", "desapego"]], + ["Agradecer ao corpo é o primeiro passo para habitá-lo.", ["asmita"], ["guru", "snigdha"], ["corpo", "gratidão"]], + ["O sopro que você não controla lembra: algo maior respira em você.", ["avidya"], ["chala", "sukshma"], ["respiração", "presença"]], + ["Pés no chão, coração no céu; o meio é onde a vida acontece.", ["abhinivesha", "raga"], ["laghu", "sthira"], ["grounding", "presença"]], + ["No espaço entre dois pensamentos está o silêncio que cura.", ["raga"], ["vishada", "manda"], ["silêncio", "mente"]], + ["Quem diz sim a tudo diz não a si mesmo.", ["asmita", "raga"], ["kathina", "vishada"], ["limites", "autocuidado"]], + ["A raiva é mensageira; ouça o que ela traz antes de reagir.", ["dvesha"], ["tikshna", "ushna"], ["raiva", "escuta"]], + ["O medo que você nomeia perde a sombra; o que você esconde cresce.", ["abhinivesha"], ["guru", "mridu"], ["medo", "presença"]], + ["Confiar não é não duvidar; é seguir mesmo quando a dúvida vem.", ["abhinivesha", "avidya"], ["chala", "vishada"], ["confiança", "dúvida"]], + ["Antes de falar, pergunte: isso cura ou fere?", ["dvesha"], ["tikshna", "mridu"], ["palavra", "verdade"]], + ["O repouso não é tempo perdido; é o tempo em que o corpo se refaz.", ["raga", "asmita"], ["manda", "mridu"], ["descanso", "corpo"]], + ["Soltar o resultado não é desistir; é fazer o que cabe a você e deixar o resto.", ["raga"], ["picchila", "vishada"], ["entrega", "ação"]], + ["A dúvida honesta abre porta; a certeza cega fecha.", ["avidya", "asmita"], ["vishada", "tikshna"], ["dúvida", "discernimento"]], + ["A humildade não é pensar menos de si; é pensar em si menos.", ["asmita"], ["vishada", "laghu"], ["humildade", "ego"]], + ["Aceitar o que é não é passividade; é ver com clareza para agir com sabedoria.", ["dvesha", "raga"], ["picchila", "mridu"], ["aceitação", "clareza"]], +]; + +/** Upanishad-style templates */ +const UPANISHAD_TEMPLATES = [ + ["Aquilo que você busca já mora em você; a busca é o caminho de volta.", ["avidya", "raga"], ["vishada", "laghu"], ["identidade", "busca"]], + ["O que não pode ser pensado pela mente, mas pelo qual a mente pensa — conhece isso.", ["avidya"], ["vishada"], ["mente", "Absoluto"]], + ["Isto é pleno; aquilo é pleno. Do pleno nasce o pleno.", ["avidya"], ["vishada", "laghu"], ["plenitude", "unidade"]], + ["Conhece o que em você observa como o condutor; o corpo é a carruagem.", ["avidya", "asmita"], ["vishada"], ["testemunha", "corpo"]], + ["Duas aves habitam a mesma árvore; uma come o fruto, a outra observa.", ["raga"], ["vishada"], ["observador", "liberdade"]], + ["Conduz-me do não-ser ao ser; da escuridão à luz; da morte à imortalidade.", ["abhinivesha"], ["guru"], ["luz", "transição"]], + ["O que não pode ser visto pelo olho, mas pelo qual o olho vê — conhece isso.", ["avidya"], ["vishada"], ["Absoluto", "visão"]], + ["No interior do ser reside o Ser; quem o vê alcança a paz.", ["avidya"], ["vishada", "laghu"], ["interior", "paz"]], + ["Como pássaro preso à corda, quem está preso ao corpo não vê a liberdade.", ["raga"], ["guru", "sthira"], ["apego", "liberdade"]], + ["O que está aqui está ali; o que está ali está aqui.", ["avidya"], ["vishada"], ["unidade", "multiplicidade"]], + ["Levanta-te, desperta, aproxima-te dos mestres e conhece.", ["avidya", "raga"], ["manda", "guru"], ["despertar", "caminho"]], + ["Não pelo discurso, não pela mente, não pelo olho se alcança o Ser.", ["avidya"], ["vishada"], ["Ser", "reconhecimento"]], + ["O Ser que reside no coração é menor que um grão e maior que os céus.", ["avidya"], ["vishada", "sukshma"], ["coração", "Ser"]], + ["Aquele que conhece o Absoluto torna-se o Absoluto.", ["avidya"], ["vishada"], ["identidade", "Absoluto"]], + ["A paz que está além do entendimento — assim é quem conhece o Absoluto.", ["abhinivesha"], ["vishada", "laghu"], ["paz", "Absoluto"]], + ["Conhecendo a bem-aventurança do Absoluto, o sábio não treme.", ["abhinivesha"], ["guru", "mridu"], ["medo", "bem-aventurança"]], + ["O som que é o todo: passado, presente e futuro.", ["avidya"], ["guru", "sandra"], ["som", "totalidade"]], + ["Conhecendo o que habita no coração de todos, o sábio entra na paz eterna.", ["dvesha"], ["vishada"], ["unidade", "paz"]], + ["O Ser não nasce nem morre; eterno é.", ["abhinivesha"], ["vishada"], ["eternidade", "Ser"]], + ["Quem vê todos os seres no Ser não mais se oculta.", ["asmita", "dvesha"], ["vishada"], ["unidade", "visão"]], + ["O corpo é a carruagem; os sentidos são os cavalos; quem conduz é o Ser.", ["asmita"], ["vishada"], ["corpo", "Ser"]], + ["No coração está a morada do Ser; quem o conhece não teme.", ["abhinivesha"], ["guru"], ["coração", "medo"]], + ["Conduz-me da escuridão à luz.", ["abhinivesha"], ["guru", "manda"], ["luz", "transição"]], + ["Do pleno nasce o pleno; o pleno permanece.", ["avidya"], ["vishada", "laghu"], ["plenitude", "permanência"]], + ["A senda é afiada como o fio da navalha; os sábios a atravessam.", ["avidya", "raga"], ["tikshna", "vishada"], ["caminho", "discernimento"]], + ["Duas aves na mesma árvore; uma come, a outra observa. Quem observa é livre.", ["raga"], ["vishada", "snigdha"], ["observador", "liberdade"]], + ["O Ser é feito de bem-aventurança; quem o conhece é preenchido.", ["avidya"], ["vishada"], ["bem-aventurança", "Ser"]], + ["Um só respira em todos; quem vê a unidade entra na paz.", ["dvesha"], ["vishada"], ["unidade", "respiração"]], + ["O sopro vital é o que une todos os seres.", ["abhinivesha"], ["chala", "laghu"], ["sopro", "unidade"]], + ["No coração está a morada da paz; quem a busca lá a encontra.", ["abhinivesha"], ["guru", "mridu"], ["coração", "paz"]], + ["O sábio escolhe o eterno; o ignorante escolhe o passageiro.", ["avidya"], ["vishada"], ["escolha", "eterno"]], + ["Como as faíscas do fogo, do Ser nascem todos os seres.", ["avidya"], ["ushna", "vishada"], ["origem", "Ser"]], + ["Do Ser revestido de paz nascem os cinco invólucros.", ["asmita"], ["vishada"], ["invólucros", "liberação"]], + ["O que a mente não alcança, mas pelo qual a mente alcança — conhece isso.", ["avidya"], ["vishada", "sukshma"], ["mente", "Absoluto"]], + ["Renunciando ao fruto da ação, o sábio alcança a paz.", ["raga"], ["snigdha", "guru"], ["renúncia", "paz"]], + ["O espaço dentro do coração é tão vasto quanto o espaço fora.", ["asmita"], ["vishada", "laghu"], ["espaço", "coração"]], + ["Conhece aquele que é o conhecedor; não o que é conhecido.", ["avidya"], ["vishada"], ["conhecedor", "Ser"]], + ["Só pelo favor do divino se revela o Ser.", ["asmita"], ["guru", "mridu"], ["graça", "revelação"]], + ["Quem é firme na prática alcança o fim.", ["raga"], ["sthira", "vishada"], ["prática", "perseverança"]], + ["A verdade que os sábios veem com o olho do coração.", ["avidya"], ["vishada"], ["verdade", "coração"]], + ["Que a paz desça do céu; que a paz suba da terra; que a paz habite em mim.", ["abhinivesha"], ["guru", "mridu"], ["paz", "invocação"]], + ["Quem vê todos os seres no Ser cobre o mundo com a própria alma.", ["dvesha"], ["vishada"], ["unidade", "visão"]], + ["Não é conhecido por quem conhece; é conhecido por quem não conhece.", ["avidya"], ["vishada"], ["conhecimento", "paradoxo"]], + ["O pai ensina ao filho: você é isso.", ["avidya"], ["vishada", "guru"], ["identidade", "transmissão"]], + ["O quarto estado não é interno nem externo; é a própria consciência.", ["avidya"], ["vishada", "sukshma"], ["consciência", "estado"]], + ["O sol que nasce no peito ilumina o que está dentro e fora.", ["abhinivesha"], ["ushna", "vishada"], ["luz", "interior"]], + ["Meditar no Ser que reside no coração dissolve o medo.", ["abhinivesha"], ["guru"], ["meditação", "medo"]], + ["Poucos ouvem; menos ainda compreendem; raro é quem vive.", ["avidya"], ["vishada"], ["escuta", "vivência"]], + ["Com o corpo ereto, o coração e a mente no Absoluto, atravesse a corrente do mundo.", ["chala"], ["sthira", "vishada"], ["meditação", "presença"]], + ["A paz que não depende do externo habita no coração de quem a busca.", ["abhinivesha"], ["vishada", "laghu"], ["paz", "interior"]], + ["O que em você observa os pensamentos não é pensamento; conhece isso.", ["avidya", "asmita"], ["vishada", "sukshma"], ["testemunha", "consciência"]], + ["Quem conhece a raiz não teme os galhos.", ["abhinivesha"], ["guru", "vishada"], ["liberação", "medo"]], + ["Do Ser revestido de alegria nascem as camadas do mundo.", ["avidya"], ["vishada", "snigdha"], ["Ser", "camadas"]], + ["O medo nasce da dualidade; quem vê a unidade não teme.", ["abhinivesha"], ["vishada", "guru"], ["medo", "unidade"]], + ["Aja no mundo como quem oferece a ação ao Ser; o fruto não te pertence.", ["raga", "asmita"], ["snigdha", "vishada"], ["ação", "entrega"]], + ["O sopro que entra e sai é a ponte entre o visível e o invisível.", ["avidya"], ["chala", "sukshma"], ["respiração", "presença"]], + ["A paz que você busca fora já está dentro; pare e ouça.", ["chala", "raga"], ["sthira", "vishada"], ["paz", "interior"]], + ["Isso és tu. O que você busca já é você.", ["avidya"], ["manda", "guru"], ["identidade", "Ser"]], + ["O Ser que reside no coração é plenitude; o vazio é espaço para Ele.", ["avidya"], ["vishada", "laghu"], ["plenitude", "coração"]], + ["O perdão interno libera o peso; você pode recomeçar.", ["avidya"], ["guru", "picchila"], ["perdão", "recomeço"]], +]; + +function pick(arr, n) { + const out = []; + for (let i = 0; i < n; i++) out.push(arr[Math.floor(Math.random() * arr.length)]); + return out; +} + +function expandPuranas() { + const existing = JSON.parse(fs.readFileSync(path.join(basePath, "puranas.json"), "utf8")); + const startId = existing.length + 1; + const targetTotal = 400; + const toAdd = targetTotal - existing.length; + const out = [...existing]; + let id = startId; + for (let i = 0; i < toAdd; i++) { + const t = PURANA_TEMPLATES[i % PURANA_TEMPLATES.length]; + const k = t[1].length ? t[1] : pick(KLESHAS, 1); + const q = t[2].length ? t[2] : pick(QUALITIES, 2); + const th = t[3].length ? t[3] : pick(THEMES, 2); + out.push({ + id: `BP.med${id}`, + text: t[0], + kleshaTargets: k, + qualities: q, + themes: th, + }); + id++; + } + fs.writeFileSync(path.join(basePath, "puranas.json"), JSON.stringify(out, null, 2), "utf8"); + console.log("puranas.json expandido para", out.length, "entradas."); + return out.length; +} + +function expandUpanishads() { + const existing = JSON.parse(fs.readFileSync(path.join(basePath, "upanishads.json"), "utf8")); + const startId = existing.length + 1; + const targetTotal = 200; + const toAdd = targetTotal - existing.length; + const out = [...existing]; + let id = startId; + for (let i = 0; i < toAdd; i++) { + const t = UPANISHAD_TEMPLATES[i % UPANISHAD_TEMPLATES.length]; + const k = t[1].length ? t[1] : pick(KLESHAS, 1); + const q = t[2].length ? t[2] : pick(QUALITIES, 2); + const th = t[3].length ? t[3] : pick(THEMES, 2); + out.push({ + id: `UP.adv${id}`, + text: t[0], + kleshaTargets: k, + qualities: q, + themes: th, + }); + id++; + } + fs.writeFileSync(path.join(basePath, "upanishads.json"), JSON.stringify(out, null, 2), "utf8"); + console.log("upanishads.json expandido para", out.length, "entradas."); + return out.length; +} + +expandPuranas(); +expandUpanishads(); diff --git a/scripts/generate-yoga-sutras-full.js b/scripts/generate-yoga-sutras-full.js new file mode 100644 index 0000000..6782b5d --- /dev/null +++ b/scripts/generate-yoga-sutras-full.js @@ -0,0 +1,135 @@ +/** + * Gera yoga_sutras_full.json com 196 sutras (existentes + 1.41-1.51, 3.11-3.56, 4.1-4.34). + * Cada entrada tem: id, text, kleshaTargets, qualities, themes. + * Executar: node scripts/generate-yoga-sutras-full.js + */ + +const fs = require("fs"); +const path = require("path"); + +const basePath = path.join(__dirname, "..", "lib", "dictionaries", "sacred"); +const existing = JSON.parse(fs.readFileSync(path.join(basePath, "yoga_sutras.json"), "utf8")); + +const withThemes = existing.map((e) => ({ + ...e, + themes: e.themes || ["yoga", "mente", "presença"], +})); + +const extra = [ + { id: "YS.1.41", text: "Quando a mente se torna como cristal, há união do conhecedor, do conhecido e do ato de conhecer.", kleshaTargets: ["asmita"], qualities: ["vishada"], themes: ["mente", "concentração"] }, + { id: "YS.1.42", text: "A absorção com reflexão é a que mistura palavra, significado e conhecimento.", kleshaTargets: ["avidya"], qualities: ["vishada"], themes: ["meditação"] }, + { id: "YS.1.43", text: "Quando a memória é purificada, a absorção sem reflexão surge; o objeto brilha sozinho.", kleshaTargets: ["raga"], qualities: ["vishada", "laghu"], themes: ["mente", "presença"] }, + { id: "YS.1.44", text: "O mesmo se aplica à absorção com e sem semente.", kleshaTargets: [], qualities: ["vishada"], themes: ["yoga"] }, + { id: "YS.1.45", text: "O estado sem semente tem como objeto o indiferenciado.", kleshaTargets: ["abhinivesha"], qualities: ["guru"], themes: ["liberação"] }, + { id: "YS.1.46", text: "Essas são as absorções com semente.", kleshaTargets: [], qualities: ["vishada"], themes: ["yoga"] }, + { id: "YS.1.47", text: "Na clareza da absorção sem semente surge a paz.", kleshaTargets: ["avidya"], qualities: ["vishada"], themes: ["presença"] }, + { id: "YS.1.48", text: "O conhecimento que nasce ali é portador da verdade.", kleshaTargets: ["avidya"], qualities: ["vishada"], themes: ["discernimento"] }, + { id: "YS.1.49", text: "Diferente do que vem de testemunho ou inferência, pois tem por objeto o particular.", kleshaTargets: ["avidya"], qualities: ["vishada"], themes: ["conhecimento"] }, + { id: "YS.1.50", text: "A impressão nascida dele obstrui as outras impressões.", kleshaTargets: ["raga"], qualities: ["picchila"], themes: ["mente"] }, + { id: "YS.1.51", text: "Com a obstrução também dessa, surge a absorção sem semente.", kleshaTargets: ["abhinivesha"], qualities: ["guru"], themes: ["liberação"] }, +]; + +const sutras3 = [ + { id: "YS.3.11", text: "O desaparecimento de toda dispersão e o surgimento da concentração única é o estado de samādhi.", kleshaTargets: ["chala"], qualities: ["chala", "sthira"], themes: ["concentração"] }, + { id: "YS.3.12", text: "Quando o passado e o presente são iguais, surge o fluxo único da mente.", kleshaTargets: ["avidya"], qualities: ["vishada"], themes: ["presença"] }, + { id: "YS.3.13", text: "Com isso se explicam a transformação das formas, do tempo e do estado.", kleshaTargets: ["avidya"], qualities: ["vishada"], themes: ["transformação"] }, + { id: "YS.3.14", text: "O substrato é o que possui as qualidades latentes, manifestas ou não manifestas.", kleshaTargets: [], qualities: ["vishada"], themes: ["natureza"] }, + { id: "YS.3.15", text: "A sucessão das transformações é a causa da sequência.", kleshaTargets: ["avidya"], qualities: ["chala"], themes: ["tempo"] }, + { id: "YS.3.16", text: "Pela restrição sobre as três transformações surge o conhecimento do passado e do futuro.", kleshaTargets: ["avidya"], qualities: ["vishada"], themes: ["conhecimento"] }, + { id: "YS.3.17", text: "A palavra, o objeto e a ideia se confundem; pela restrição sobre eles surge o conhecimento do som de todos os seres.", kleshaTargets: ["asmita"], qualities: ["vishada"], themes: ["escuta"] }, + { id: "YS.3.18", text: "Pela percepção direta das impressões surge o conhecimento das vidas anteriores.", kleshaTargets: ["raga"], qualities: ["picchila"], themes: ["memória"] }, + { id: "YS.3.19", text: "Pela restrição sobre as marcas mentais surge o conhecimento das mentes de outros.", kleshaTargets: ["asmita"], qualities: ["vishada"], themes: ["empatia"] }, + { id: "YS.3.20", text: "Não sobre o suporte, pois não é objeto dessa restrição.", kleshaTargets: [], qualities: ["vishada"], themes: ["yoga"] }, + { id: "YS.3.21", text: "Pela restrição sobre a forma do corpo, cortando a luz e o poder de ser visto, surge o desaparecimento.", kleshaTargets: ["asmita"], qualities: ["sukshma"], themes: ["corpo"] }, + { id: "YS.3.22", text: "O karma é rápido ou lento; pela restrição sobre ele surge o conhecimento da morte.", kleshaTargets: ["abhinivesha"], qualities: ["guru"], themes: ["tempo"] }, + { id: "YS.3.23", text: "Pela restrição sobre a amizade e outras forças surge o poder delas.", kleshaTargets: ["raga", "dvesha"], qualities: ["snigdha"], themes: ["relação"] }, + { id: "YS.3.24", text: "Pela restrição sobre a força do elefante e outras surge essa força.", kleshaTargets: ["asmita"], qualities: ["sthira"], themes: ["poder"] }, + { id: "YS.3.25", text: "O conhecimento do sutil, do oculto e do distante surge pela luz da percepção.", kleshaTargets: ["avidya"], qualities: ["vishada", "sukshma"], themes: ["conhecimento"] }, + { id: "YS.3.26", text: "Pela restrição sobre o sol surge o conhecimento do cosmos.", kleshaTargets: ["avidya"], qualities: ["vishada"], themes: ["cosmos"] }, + { id: "YS.3.27", text: "Sobre a lua surge o conhecimento da disposição das estrelas.", kleshaTargets: ["avidya"], qualities: ["vishada"], themes: ["tempo"] }, + { id: "YS.3.28", text: "Sobre a Estrela Polar surge o conhecimento do movimento das estrelas.", kleshaTargets: ["avidya"], qualities: ["vishada"], themes: ["orientação"] }, + { id: "YS.3.29", text: "Sobre o umbigo surge o conhecimento da constituição do corpo.", kleshaTargets: ["asmita"], qualities: ["vishada"], themes: ["corpo"] }, + { id: "YS.3.30", text: "Sobre a garganta surge a cessação da fome e da sede.", kleshaTargets: ["raga"], qualities: ["snigdha"], themes: ["corpo"] }, + { id: "YS.3.31", text: "Sobre o tubo curvo surge a estabilidade.", kleshaTargets: ["chala"], qualities: ["sthira"], themes: ["postura"] }, + { id: "YS.3.32", text: "Sobre a luz da coroa surge a visão dos Siddhas.", kleshaTargets: ["avidya"], qualities: ["vishada"], themes: ["luz"] }, + { id: "YS.3.33", text: "Ou por intuição surge todo conhecimento.", kleshaTargets: ["avidya"], qualities: ["vishada"], themes: ["conhecimento"] }, + { id: "YS.3.34", text: "Sobre o coração surge o conhecimento da mente.", kleshaTargets: ["asmita"], qualities: ["vishada"], themes: ["mente"] }, + { id: "YS.3.35", text: "A experiência e o Ser não se distinguem; a restrição sobre o que existe por si surge conhecimento do Ser.", kleshaTargets: ["avidya"], qualities: ["vishada"], themes: ["ser"] }, + { id: "YS.3.36", text: "Daí surgem intuição, audição, tato, visão, paladar e olfato.", kleshaTargets: ["asmita"], qualities: ["vishada"], themes: ["sentidos"] }, + { id: "YS.3.37", text: "São obstáculos à absorção; poderes na vida dispersa.", kleshaTargets: ["raga"], qualities: ["chala"], themes: ["yoga"] }, + { id: "YS.3.38", text: "Pelo relaxamento do vínculo e pelo conhecimento do fluxo surge a entrada em outro corpo.", kleshaTargets: ["abhinivesha"], qualities: ["sukshma"], themes: ["transformação"] }, + { id: "YS.3.39", text: "Pelo domínio do sopro ascendente surge a não aderência à água, ao lodo e às espinas.", kleshaTargets: ["chala"], qualities: ["laghu"], themes: ["pranayama"] }, + { id: "YS.3.40", text: "Pelo domínio do sopro mediano surge o brilho.", kleshaTargets: ["avidya"], qualities: ["vishada"], themes: ["luz"] }, + { id: "YS.3.41", text: "Pela restrição sobre a relação ouvido-espaço surge o ouvido divino.", kleshaTargets: ["avidya"], qualities: ["vishada"], themes: ["escuta"] }, + { id: "YS.3.42", text: "Pela restrição sobre a relação corpo-espaço e pela leveza do algodão surge a passagem pelo espaço.", kleshaTargets: ["asmita"], qualities: ["laghu"], themes: ["corpo"] }, + { id: "YS.3.43", text: "A atividade fora do corpo, não iluminada pela mente, é o véu grande; daí o desaparecimento do véu sobre a luz.", kleshaTargets: ["avidya"], qualities: ["vishada"], themes: ["mente"] }, + { id: "YS.3.44", text: "Pela restrição sobre o grosseiro, a forma, o sutil, a conexão e o propósito surge o domínio dos elementos.", kleshaTargets: ["asmita"], qualities: ["vishada"], themes: ["elementos"] }, + { id: "YS.3.45", text: "Daí surgem a minúcia, a perfeição do corpo e a não obstrução das funções.", kleshaTargets: ["asmita"], qualities: ["vishada"], themes: ["corpo"] }, + { id: "YS.3.46", text: "Perfeição do corpo é beleza, graça, força e firmeza de diamante.", kleshaTargets: ["asmita"], qualities: ["sthira"], themes: ["corpo"] }, + { id: "YS.3.47", text: "Pela restrição sobre a percepção, a natureza essencial, o eu e a conexão surge o domínio dos órgãos.", kleshaTargets: ["asmita"], qualities: ["vishada"], themes: ["sentidos"] }, + { id: "YS.3.48", text: "Daí surgem velocidade como a da mente, ação sem órgãos e domínio da matéria de origem.", kleshaTargets: ["avidya"], qualities: ["vishada"], themes: ["ação"] }, + { id: "YS.3.49", text: "Só para quem discerne a distinção entre sattva e Ser surge a soberania sobre todos os estados e sobre todo conhecimento.", kleshaTargets: ["avidya"], qualities: ["vishada"], themes: ["discernimento"] }, + { id: "YS.3.50", text: "Pelo desapego até a isso surge a semente do defeito destruída; isso é kaivalya.", kleshaTargets: ["raga", "abhinivesha"], qualities: ["vishada"], themes: ["liberação"] }, + { id: "YS.3.51", text: "Não haver atração pelos poderes quando convidados pelos guardiões dos mundos seria apego; seria o renascimento.", kleshaTargets: ["raga"], qualities: ["snigdha"], themes: ["desapego"] }, + { id: "YS.3.52", text: "Pela restrição sobre o momento e sua sucessão surge o conhecimento nascido do discernimento.", kleshaTargets: ["avidya"], qualities: ["vishada"], themes: ["tempo"] }, + { id: "YS.3.53", text: "Daí surge o discernimento do que é igual em espécie, caráter e lugar.", kleshaTargets: ["avidya"], qualities: ["vishada"], themes: ["conhecimento"] }, + { id: "YS.3.54", text: "O conhecimento nascido do discernimento é portador de tudo, em todo tempo, sem sucessão.", kleshaTargets: ["avidya"], qualities: ["vishada"], themes: ["conhecimento"] }, + { id: "YS.3.55", text: "Quando a pureza de sattva e do Ser é igual, surge kaivalya.", kleshaTargets: ["asmita"], qualities: ["vishada"], themes: ["liberação"] }, + { id: "YS.3.56", text: "Kaivalya é estabelecido quando os três gunas esgotaram seu propósito para o que vê.", kleshaTargets: ["avidya"], qualities: ["vishada"], themes: ["liberação"] }, +]; + +const sutras4 = []; +for (let i = 1; i <= 34; i++) { + const texts = [ + "Os poderes nascem do nascimento, de ervas, de mantra, de austeridade ou de absorção.", + "A transformação em outra espécie é pelo preenchimento da natureza.", + "O obstáculo não é causa; ele apenas remove o obstáculo, como o agricultor.", + "Só a mente criada é o nascimento dos mundos criados.", + "Mentes diversas têm um único objeto de concentração.", + "A que tem meditação como semente é a que não nasce de outra.", + "A ação do yogi não é branca nem negra; a dos outros é de três tipos.", + "Delas surgem apenas as impressões para o fruto a ser experimentado.", + "Memória e impressão têm a mesma forma; mesmo com separação de nascimento, lugar e tempo há continuidade.", + "Não têm começo; o desejo de permanência é inato.", + "Sendo sustentadas por causa, efeito, suporte e objeto, elas desaparecem quando elas desaparecem.", + "O passado e o futuro existem em sua própria natureza; a diferença está nos caminhos da característica.", + "Elas são manifestas ou sutis; têm a natureza dos gunas.", + "A realidade do objeto está na unicidade da transformação.", + "O objeto sendo o mesmo, a diferença das mentes é a diferença dos dois.", + "E o objeto não depende de uma única mente; o que aconteceria quando não fosse percebido?", + "O objeto é conhecido ou não pela mente que ele tinge.", + "Sempre conhecida a mente que governa; ela não é tingida, pois é estável.", + "Ela não se vê a si mesma.", + "Não há dupla apresentação ao mesmo tempo.", + "Se a outra fosse vista por outra mente, haveria regressão ao infinito e confusão de memória.", + "Quando a natureza da consciência assume a forma, surge a consciência de si.", + "A mente, tingida pelo que vê e pelo que vê, percebe todos os objetos.", + "Ela existe para outro, pois é composta de inúmeras impressões.", + "Para quem vê a distinção, cessa a reflexão sobre a própria natureza.", + "Então a mente inclina para o discernimento e caminha para kaivalya.", + "No meio surgem as impressões da distinção por causa das falhas.", + "A remoção delas é como a dos kleshas.", + "Quem, mesmo no fruto do discernimento, permanece em desapego total, surge o samādhi da nuvem de dharma.", + " Daí cessa o sofrimento e a ação.", + "Então o conhecimento livre de impurezas e de cobertura é infinito; o conhecível é pouco.", + " Com isso os gunas esgotaram sua sequência de fins; a transformação cessa.", + "A sequência é o momento; percebido no último instante.", + "Kaivalya é a reversão dos gunas, sem propósito para o que vê; o estabelecimento do poder do que vê em sua própria natureza.", + ]; + const t = texts[i - 1] || "Liberação e estabelecimento na própria natureza."; + sutras4.push({ + id: `YS.4.${i}`, + text: t, + kleshaTargets: i <= 10 ? ["avidya"] : i <= 20 ? ["asmita"] : ["abhinivesha"], + qualities: ["vishada"], + themes: ["liberação", "mente", "yoga"], + }); +} + +const full = [...withThemes, ...extra, ...sutras3, ...sutras4]; +fs.writeFileSync( + path.join(basePath, "yoga_sutras_full.json"), + JSON.stringify(full, null, 2), + "utf8" +); +console.log("yoga_sutras_full.json gerado com", full.length, "entradas."); diff --git a/scripts/validateSacredCorpus.ts b/scripts/validateSacredCorpus.ts new file mode 100644 index 0000000..2af6243 --- /dev/null +++ b/scripts/validateSacredCorpus.ts @@ -0,0 +1,141 @@ +/** + * Valida o corpus sagrado (yoga_sutras_full, puranas, upanishads). + * - IDs únicos + * - Tags obrigatórias: id, text, kleshaTargets, qualities + * - Cobertura mínima por klesha e por qualities + * - Peso balanceado entre corpora + * + * Uso: npx ts-node --compiler-options '{"module":"CommonJS"}' scripts/validateSacredCorpus.ts + * Ou: node --loader ts-node/esm scripts/validateSacredCorpus.ts (conforme ambiente) + */ + +import * as fs from "fs"; +import * as path from "path"; + +const ROOT = path.resolve(__dirname, ".."); +const SACRED_DIR = path.join(ROOT, "lib", "dictionaries", "sacred"); + +type SacredEntry = { + id: string; + text: string; + kleshaTargets?: string[]; + qualities?: string[]; + themes?: string[]; +}; + +const REQUIRED_KLESHAS = ["avidya", "asmita", "raga", "dvesha", "abhinivesha"]; +const KNOWN_QUALITIES = new Set([ + "guru", "laghu", "snigdha", "ruksha", "sita", "ushna", "manda", "tikshna", + "sthira", "chala", "mridu", "kathina", "vishada", "picchila", "shlakshna", "khara", + "sukshma", "sthula", "sandra", "drava", "sara", +]); + +function loadJson(filePath: string): T { + const raw = fs.readFileSync(filePath, "utf-8"); + return JSON.parse(raw) as T; +} + +function validateCorpus( + corpusName: string, + entries: SacredEntry[], + allIds: Set +): { ok: boolean; errors: string[] } { + const errors: string[] = []; + for (let i = 0; i < entries.length; i++) { + const e = entries[i]; + if (!e.id) errors.push(`[${corpusName}] entrada ${i}: falta "id"`); + else if (allIds.has(e.id)) errors.push(`[${corpusName}] id duplicado: ${e.id}`); + else allIds.add(e.id); + + if (!e.text || typeof e.text !== "string") errors.push(`[${corpusName}] entrada ${e.id ?? i}: falta ou inválido "text"`); + if (!e.kleshaTargets || !Array.isArray(e.kleshaTargets) || e.kleshaTargets.length === 0) { + errors.push(`[${corpusName}] entrada ${e.id ?? i}: "kleshaTargets" obrigatório e não vazio`); + } + if (!e.qualities || !Array.isArray(e.qualities)) { + errors.push(`[${corpusName}] entrada ${e.id ?? i}: "qualities" obrigatório (array)`); + } + if (e.qualities) { + for (const q of e.qualities) { + if (!KNOWN_QUALITIES.has(q)) errors.push(`[${corpusName}] entrada ${e.id}: quality desconhecida "${q}"`); + } + } + } + return { ok: errors.length === 0, errors }; +} + +function checkCoverage( + corpusName: string, + entries: SacredEntry[] +): { ok: boolean; messages: string[] } { + const byKlesha = new Map(); + const byQuality = new Map(); + for (const e of entries) { + for (const k of e.kleshaTargets ?? []) { + byKlesha.set(k, (byKlesha.get(k) ?? 0) + 1); + } + for (const q of e.qualities ?? []) { + byQuality.set(q, (byQuality.get(q) ?? 0) + 1); + } + } + const messages: string[] = []; + for (const k of REQUIRED_KLESHAS) { + const n = byKlesha.get(k) ?? 0; + if (n === 0) messages.push(`[${corpusName}] nenhuma entrada para klesha "${k}"`); + } + const minQualityEntries = 3; + for (const [q, n] of byQuality) { + if (n < minQualityEntries && entries.length > 20) { + messages.push(`[${corpusName}] quality "${q}" aparece apenas ${n} vezes`); + } + } + return { ok: messages.length === 0, messages }; +} + +function main(): void { + const allIds = new Set(); + const results: { corpus: string; entries: number; ok: boolean; errors: string[]; coverage: string[] }[] = []; + + const files = [ + { name: "yoga_sutras_full", path: path.join(SACRED_DIR, "yoga_sutras_full.json") }, + { name: "puranas", path: path.join(SACRED_DIR, "puranas.json") }, + { name: "upanishads", path: path.join(SACRED_DIR, "upanishads.json") }, + ]; + + for (const { name, path: filePath } of files) { + if (!fs.existsSync(filePath)) { + results.push({ corpus: name, entries: 0, ok: false, errors: [`Arquivo não encontrado: ${filePath}`], coverage: [] }); + continue; + } + const data = loadJson(filePath); + const entries = Array.isArray(data) ? data : []; + const { ok, errors } = validateCorpus(name, entries, allIds); + const { ok: covOk, messages: coverage } = checkCoverage(name, entries); + results.push({ + corpus: name, + entries: entries.length, + ok: ok && covOk, + errors, + coverage: covOk ? [] : coverage, + }); + } + + let exitCode = 0; + for (const r of results) { + console.log(`\n--- ${r.corpus} (${r.entries} entradas) ---`); + if (r.errors.length > 0) { + r.errors.forEach((e) => console.error(" ERRO:", e)); + exitCode = 1; + } + if (r.coverage.length > 0) { + r.coverage.forEach((m) => console.warn(" COVERAGE:", m)); + exitCode = 1; + } + if (r.ok && r.errors.length === 0 && r.coverage.length === 0) { + console.log(" OK"); + } + } + console.log("\n"); + process.exit(exitCode); +} + +main(); diff --git a/supabase/migrations/20250129100000_history_tables.sql b/supabase/migrations/20250129100000_history_tables.sql new file mode 100644 index 0000000..86533dd --- /dev/null +++ b/supabase/migrations/20250129100000_history_tables.sql @@ -0,0 +1,40 @@ +-- Darshan: histórico de respostas (orb) e leituras — por usuário. +-- Também estende credit_ledger.reason para incluir personal_map (leitura completa). +-- Executar no Supabase (SQL Editor ou CLI: supabase db push). + +-- Permitir reason 'personal_map' no credit_ledger (se a constraint existir) +DO $$ +BEGIN + ALTER TABLE credit_ledger DROP CONSTRAINT IF EXISTS credit_ledger_reason_check; + ALTER TABLE credit_ledger ADD CONSTRAINT credit_ledger_reason_check + CHECK (reason IN ('purchase', 'darshan_call', 'personal_map', 'admin_adjust')); +EXCEPTION + WHEN undefined_object THEN NULL; + WHEN others THEN NULL; +END $$; + +-- 1. revelations (respostas da interação com o orb — pergunta opcional + resposta da IA) +CREATE TABLE IF NOT EXISTS revelations ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + user_id UUID NOT NULL REFERENCES users (id) ON DELETE CASCADE, + question_text TEXT, + response_text TEXT NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT now() +); + +CREATE INDEX IF NOT EXISTS idx_revelations_user_id ON revelations (user_id); +CREATE INDEX IF NOT EXISTS idx_revelations_created_at ON revelations (created_at DESC); + +-- 2. readings (resultado das leituras completas — mapa pessoal) +CREATE TABLE IF NOT EXISTS readings ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + user_id UUID NOT NULL REFERENCES users (id) ON DELETE CASCADE, + content TEXT NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT now() +); + +CREATE INDEX IF NOT EXISTS idx_readings_user_id ON readings (user_id); +CREATE INDEX IF NOT EXISTS idx_readings_created_at ON readings (created_at DESC); + +COMMENT ON TABLE revelations IS 'Histórico de respostas da IA na interação com o orb (pergunta + revelação).'; +COMMENT ON TABLE readings IS 'Histórico de leituras completas (mapa pessoal) por usuário.'; diff --git a/supabase/migrations/20250129110000_instant_light_uses.sql b/supabase/migrations/20250129110000_instant_light_uses.sql new file mode 100644 index 0000000..a401d77 --- /dev/null +++ b/supabase/migrations/20250129110000_instant_light_uses.sql @@ -0,0 +1,15 @@ +-- Cooldown server-side para Instant Light: registra uso de sacredId/stateKey por usuário. +-- Usado por getRecentInstantLightIds e recordInstantLightUse (historyStorage). + +CREATE TABLE IF NOT EXISTS instant_light_uses ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + user_id UUID NOT NULL REFERENCES users (id) ON DELETE CASCADE, + sacred_id TEXT NOT NULL, + state_key TEXT, + created_at TIMESTAMPTZ NOT NULL DEFAULT now() +); + +CREATE INDEX IF NOT EXISTS idx_instant_light_uses_user_id ON instant_light_uses (user_id); +CREATE INDEX IF NOT EXISTS idx_instant_light_uses_created_at ON instant_light_uses (created_at DESC); + +COMMENT ON TABLE instant_light_uses IS 'Uso recente de textos/estados do Instant Light por usuário (cooldown server-side).';