From f8ad9cf631efec5e471b4562086a9923e3eb60e5 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Wed, 5 Nov 2025 19:39:43 +0000 Subject: [PATCH] Fix: Correctly trigger initial report reading This commit fixes a logical flaw where the Poetic Brain would misinterpret the user's first input after a report was loaded. Previously, a command like "Continue" was treated as a conversational reply, leading to an incorrect "osr_detected" response. The fix introduces a check to specifically identify when the user is providing a trigger phrase (e.g., "Continue," "Okay," "Start") immediately after the "report ready" announcement. When this context is detected, the system now correctly initiates the full, detailed report reading as intended. This restores the expected user flow and prevents the erroneous conversational analysis from firing in this specific scenario. --- app/api/chat/route.ts | 206 ++++++++++++++++++++++-------------------- 1 file changed, 109 insertions(+), 97 deletions(-) diff --git a/app/api/chat/route.ts b/app/api/chat/route.ts index f58a4697..e5fad885 100644 --- a/app/api/chat/route.ts +++ b/app/api/chat/route.ts @@ -87,7 +87,7 @@ function checkForClearAffirmation(text: string): boolean { // Check if user is requesting to start/continue the reading (not OSR) function checkForReadingStartRequest(text: string): boolean { - const lower = text.toLowerCase(); + const lower = text.toLowerCase().trim(); const startReadingPhrases = [ 'give me the reading', 'start the reading', @@ -107,9 +107,13 @@ function checkForReadingStartRequest(text: string): boolean { 'let\'s start', 'please continue', 'go ahead', - 'proceed' + 'proceed', + 'continue', + 'okay', + 'yes', + 'read it' ]; - + return startReadingPhrases.some(phrase => lower.includes(phrase)); } @@ -345,41 +349,49 @@ Give a short, plain-language summary of the current planetary weather in two par return new Response(responseBody, { headers: { 'Content-Type': 'text/plain; charset=utf-8' }}); } - // Check for natural follow-up flow based on user response type - // - // DESIGN NOTE: Skip OSR checks on first turn UNLESS explicit OSR phrases used - // Rationale: First turn after "Session Started" is typically a command, not a resonance response. - // However, we still detect explicit OSR phrases like "doesn't resonate" for edge cases. - // - // The OSR check is duplicated here (before classifyUserResponse) intentionally: - // - Early exit for first-turn commands (performance optimization) - // - Preserves classification logic independence in classifyUserResponse() - // - Makes the first-turn special case explicit and easy to understand - const skipOSRCheck = isFirstTurn && !checkForOSRIndicators(text); - const responseType = skipOSRCheck - ? 'CLEAR_WB' - : classifyUserResponse(text); - - // Mock session context (in production, this would be persisted) - const mockSessionContext: SessionContext = { - wbHits: [], - abeHits: [], - osrMisses: [], - actorWeighting: 0, - roleWeighting: 0, - driftIndex: 0, - sessionActive: true - }; - - // Generate natural follow-up based on response type - if (responseType === 'CLEAR_WB') { - const followUp = naturalFollowUpFlow.generateFollowUp({ - type: 'AFFIRM', - content: text, - originalMirror: text - }, mockSessionContext); - - analysisPrompt = `The user clearly confirmed resonance: "${text}" + const lastRavenMessage = messages.filter((m: any) => m.role === 'raven').pop(); + const isAfterReportReady = lastRavenMessage?.html?.includes('is ready for interpretation'); + const isTriggerForReading = checkForReadingStartRequest(text); + + if (isAfterReportReady && isTriggerForReading) { + analysisPrompt = `CONTEXT: The following chart data has been provided. Use it to generate a complete, conversational mirror reflection following the Five-Step Delivery Framework. +INSTRUCTIONS: Begin with warm recognition of the person's stance/pattern. Use the chart geometry as context, but write in natural, conversational paragraphs. Follow the FIELD→MAP→VOICE protocol. No technical openings, no data summaries—just the warm, direct mirror.`; + } else { + // Check for natural follow-up flow based on user response type + // + // DESIGN NOTE: Skip OSR checks on first turn UNLESS explicit OSR phrases used + // Rationale: First turn after "Session Started" is typically a command, not a resonance response. + // However, we still detect explicit OSR phrases like "doesn't resonate" for edge cases. + // + // The OSR check is duplicated here (before classifyUserResponse) intentionally: + // - Early exit for first-turn commands (performance optimization) + // - Preserves classification logic independence in classifyUserResponse() + // - Makes the first-turn special case explicit and easy to understand + const skipOSRCheck = isFirstTurn && !checkForOSRIndicators(text); + const responseType = skipOSRCheck + ? 'CLEAR_WB' + : classifyUserResponse(text); + + // Mock session context (in production, this would be persisted) + const mockSessionContext: SessionContext = { + wbHits: [], + abeHits: [], + osrMisses: [], + actorWeighting: 0, + roleWeighting: 0, + driftIndex: 0, + sessionActive: true + }; + + // Generate natural follow-up based on response type + if (responseType === 'CLEAR_WB') { + const followUp = naturalFollowUpFlow.generateFollowUp({ + type: 'AFFIRM', + content: text, + originalMirror: text + }, mockSessionContext); + + analysisPrompt = `The user clearly confirmed resonance: "${text}" **AUTO-CLASSIFICATION: WB (Within Boundary)** Log this as confirmed resonance. Do NOT ask for additional validation. @@ -399,9 +411,9 @@ Your response should: 4. Skip any additional truth gates User's clear affirmation: ${text}`; - - } else if (responseType === 'PARTIAL_ABE') { - analysisPrompt = `The user gave partial confirmation: "${text}" + + } else if (responseType === 'PARTIAL_ABE') { + analysisPrompt = `The user gave partial confirmation: "${text}" **CLASSIFICATION: ABE (At Boundary Edge)** This needs clarification, not full repair. Ask for refinement: @@ -409,50 +421,49 @@ This needs clarification, not full repair. Ask for refinement: "I'm logging this as ABE—partially resonant but needs fine-tuning. What part lands, and what feels off?" User's partial response: ${text}`; - - } else if (responseType === 'OSR') { - const followUp = naturalFollowUpFlow.generateFollowUp({ - type: 'OSR', - content: text, - originalMirror: text - }, mockSessionContext); - - analysisPrompt = `The user indicated that something didn't resonate. Generate a response that includes this natural OSR probe: "${followUp.question}" + + } else if (responseType === 'OSR') { + const followUp = naturalFollowUpFlow.generateFollowUp({ + type: 'OSR', + content: text, + originalMirror: text + }, mockSessionContext); + + analysisPrompt = `The user indicated that something didn't resonate. Generate a response that includes this natural OSR probe: "${followUp.question}" User's OSR response: ${text} Your response should acknowledge their feedback and offer the choice-based clarification probe to convert the miss into diagnostic data. Keep it skippable and non-forcing.`; - - } else if (text.toLowerCase().includes('poetic card') || text.toLowerCase().includes('generate card')) { - analysisPrompt = `The user is requesting a poetic card based on their session. Generate a visual card display showing: + + } else if (text.toLowerCase().includes('poetic card') || text.toLowerCase().includes('generate card')) { + analysisPrompt = `The user is requesting a poetic card based on their session. Generate a visual card display showing: - Resonance Pattern summary - Score indicators (WB/ABE/OSR) - Actor/Role composite guess - Any drift flags Do NOT generate a new poem. This is a summary card of what has already resonated.`; - - } else if (text.toLowerCase().includes('done') || text.toLowerCase().includes('finished') || text.toLowerCase().includes('session complete')) { - const closure = naturalFollowUpFlow.generateSessionClosure(); - analysisPrompt = `The user is indicating they want to end this reading session. Generate a response that includes: "${closure.resetPrompt}" + + } else if (text.toLowerCase().includes('done') || text.toLowerCase().includes('finished') || text.toLowerCase().includes('session complete')) { + const closure = naturalFollowUpFlow.generateSessionClosure(); + analysisPrompt = `The user is indicating they want to end this reading session. Generate a response that includes: "${closure.resetPrompt}" This will reset the scorecard but not make you forget who you're talking to. Offer these options: ${closure.continuationOptions.join(', ')}`; - } else { - const lastRavenMessage = messages.filter((m: any) => m.role === 'raven').pop(); - const isResponseToProbe = lastRavenMessage && - (lastRavenMessage.html.includes('Does any of this feel familiar') || - lastRavenMessage.html.includes('Does this fit your experience') || - lastRavenMessage.html.includes('feel accurate') || - lastRavenMessage.html.includes('resonate')); - - if (isResponseToProbe) { - if (isMetaSignalAboutRepetition(text)) { - const reversed = [...messages].filter((m:any)=> m.role==='user').reverse(); - const previousUser = reversed[1]; - const prevText = previousUser?.content || previousUser?.html || ''; - const prevType = prevText ? classifyUserResponse(prevText) : 'UNCLEAR'; - - if (prevType === 'CLEAR_WB') { - analysisPrompt = `The user expressed irritation at being asked again (meta-signal), not new content: "${text}". + } else { + const isResponseToProbe = lastRavenMessage && + (lastRavenMessage.html.includes('Does any of this feel familiar') || + lastRavenMessage.html.includes('Does this fit your experience') || + lastRavenMessage.html.includes('feel accurate') || + lastRavenMessage.html.includes('resonate')); + + if (isResponseToProbe) { + if (isMetaSignalAboutRepetition(text)) { + const reversed = [...messages].filter((m: any) => m.role === 'user').reverse(); + const previousUser = reversed[1]; + const prevText = previousUser?.content || previousUser?.html || ''; + const prevType = prevText ? classifyUserResponse(prevText) : 'UNCLEAR'; + + if (prevType === 'CLEAR_WB') { + analysisPrompt = `The user expressed irritation at being asked again (meta-signal), not new content: "${text}". Preserve the prior classification: WB (Within Boundary). Do NOT re-open validation. @@ -465,30 +476,30 @@ Rules: 1) No additional "does this feel true?" gates 2) No motive analysis or personality inference 3) Mirror only structural pressure and pivot to somatic/behavioral deepening`; - } else if (prevType === 'PARTIAL_ABE') { - analysisPrompt = `The user commented on repetition (meta-signal), not new content: "${text}". + } else if (prevType === 'PARTIAL_ABE') { + analysisPrompt = `The user commented on repetition (meta-signal), not new content: "${text}". Preserve prior classification: ABE (At Boundary Edge). Do NOT re-open the main validation gate. Respond with: Acknowledge the irritation + offer one focused refinement question about what part lands vs. what doesn't, using their words where possible. Rules: no new metaphors, no psychoanalysis, keep it brief and user-led.`; - } else if (prevType === 'OSR') { - analysisPrompt = `The user commented on repetition (meta-signal): "${text}". + } else if (prevType === 'OSR') { + analysisPrompt = `The user commented on repetition (meta-signal): "${text}". Preserve prior classification: OSR (Outside Symbolic Range). Do NOT analyze the meta-comment. Offer a minimal repair that uses their prior correction, then validate the repair only if they choose to engage. Keep it skippable and brief; acknowledge the repetition irritation.`; - } else { - analysisPrompt = `Treat this as a meta-signal about repetition: "${text}". + } else { + analysisPrompt = `Treat this as a meta-signal about repetition: "${text}". Do not analyze it. Briefly acknowledge the irritation and ask one gentle, concrete deepening question about the previously discussed pressure (without re-validating).`; - } - } else { - const probeResponseType = classifyUserResponse(text); - - if (probeResponseType === 'CLEAR_WB') { - analysisPrompt = `The user clearly confirmed resonance to your probe: "${text}" + } + } else { + const probeResponseType = classifyUserResponse(text); + + if (probeResponseType === 'CLEAR_WB') { + analysisPrompt = `The user clearly confirmed resonance to your probe: "${text}" **AUTO-CLASSIFICATION: WB (Within Boundary)** This is confirmed resonance. Log it immediately without additional validation. @@ -505,9 +516,9 @@ This is confirmed resonance. Log it immediately without additional validation. **DO NOT** ask "Does this feel true?" or any additional validation. The user already confirmed it. User's clear confirmation: "${text}"`; - - } else if (probeResponseType === 'PARTIAL_ABE') { - analysisPrompt = `The user gave partial confirmation to your probe: "${text}" + + } else if (probeResponseType === 'PARTIAL_ABE') { + analysisPrompt = `The user gave partial confirmation to your probe: "${text}" **CLASSIFICATION: ABE (At Boundary Edge)** This needs refinement, not full repair. @@ -518,9 +529,9 @@ This needs refinement, not full repair. 3. Refine the image based on their feedback User's partial response: "${text}"`; - - } else if (probeResponseType === 'OSR') { - analysisPrompt = `The user redirected/contradicted your probe: "${text}" + + } else if (probeResponseType === 'OSR') { + analysisPrompt = `The user redirected/contradicted your probe: "${text}" **CLASSIFICATION: OSR (Outside Symbolic Range)** This requires a repair branch with validation. @@ -532,9 +543,9 @@ This requires a repair branch with validation. 4. Validate REPAIR only: "Does this repair feel true?" [Yes] [Partly] [No] User's OSR response: "${text}"`; - - } else { - analysisPrompt = `The user gave an unclear response to your probe: "${text}" + + } else { + analysisPrompt = `The user gave an unclear response to your probe: "${text}" **CLASSIFICATION: UNCLEAR** This needs gentle clarification to determine WB/ABE/OSR. @@ -543,9 +554,9 @@ This needs gentle clarification to determine WB/ABE/OSR. Ask for clarification: "I want to make sure I'm tracking you—does the image I offered feel familiar, or does it miss the mark?" User's unclear response: "${text}"`; + } } - } - } else { + } else { analysisPrompt = `This appears to be a request for astrological insight or general conversation that could benefit from symbolic reflection. **MANDATORY: Deliver COMPLETE Core Flow structure in your response:** @@ -564,6 +575,7 @@ SESSION FLAG: FIRST_TURN = ${isFirstTurn ? 'TRUE' : 'FALSE'} "Does any of this feel familiar?" User's input: "${text}"`; + } } }