-
Notifications
You must be signed in to change notification settings - Fork 0
Claude/symbolic moment person selection cu zt y #457
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -485,7 +485,7 @@ | |||||||
| return 'Voice failed this turn.'; | ||||||||
| } | ||||||||
|
|
||||||||
| export default function App() { | ||||||||
|
Check failure on line 488 in vessel/src/app/page.tsx
|
||||||||
| const router = useRouter(); | ||||||||
| const { tier } = useTier(); | ||||||||
| const [user, setUser] = useState<User | null>(null); | ||||||||
|
|
@@ -579,11 +579,19 @@ | |||||||
| const [pendingSoloMirrorResolver, setPendingSoloMirrorResolver] = useState<{ | ||||||||
| desc: string; | ||||||||
| } | null>(null); | ||||||||
| const [pendingSymbolicMomentResolver, setPendingSymbolicMomentResolver] = useState<{ | ||||||||
| desc: string; | ||||||||
| } | null>(null); | ||||||||
| useEffect(() => { | ||||||||
| if (!pendingSoloMirrorResolver) return; | ||||||||
| if (observerStagedProfiles.length > 0) return; | ||||||||
| setPendingSoloMirrorResolver(null); | ||||||||
| }, [observerStagedProfiles.length, pendingSoloMirrorResolver]); | ||||||||
| useEffect(() => { | ||||||||
| if (!pendingSymbolicMomentResolver) return; | ||||||||
| if (observerStagedProfiles.length > 0) return; | ||||||||
| setPendingSymbolicMomentResolver(null); | ||||||||
| }, [observerStagedProfiles.length, pendingSymbolicMomentResolver]); | ||||||||
| useEffect(() => { | ||||||||
| if (observerStagedProfiles.length > 0) return; | ||||||||
| if (!primaryOnlyScope) return; | ||||||||
|
|
@@ -1789,6 +1797,7 @@ | |||||||
| setPrimaryOnlyScope(false); | ||||||||
| setStagedContexts([]); | ||||||||
| setPendingSoloMirrorResolver(null); | ||||||||
| setPendingSymbolicMomentResolver(null); | ||||||||
| advancedClockSuggestionShownForSessionRef.current = null; | ||||||||
| setAdvancedClocksOpen(false); | ||||||||
| setLastDebugInfo(null); | ||||||||
|
|
@@ -1841,6 +1850,7 @@ | |||||||
| ); | ||||||||
| setPendingSemanticDepth('plain'); | ||||||||
| setPendingSoloMirrorResolver(null); | ||||||||
| setPendingSymbolicMomentResolver(null); | ||||||||
| setIsFlightRecorderOpen(false); | ||||||||
| setReadLaneArmed(snapshot.structuredReadingOptIn === true && snapshot.promptMode !== 'CHAT'); | ||||||||
| }); | ||||||||
|
|
@@ -2557,6 +2567,7 @@ | |||||||
|
|
||||||||
| const handleHeaderModeSelect = useCallback((mode: 'CHAT' | 'SOLO_MIRROR' | 'FIELD_REPORT') => { | ||||||||
| setPendingSoloMirrorResolver(null); | ||||||||
| setPendingSymbolicMomentResolver(null); | ||||||||
| if (mode === 'CHAT') { | ||||||||
| setStructuredReadingOptIn(false); | ||||||||
| setActiveMode('CHAT'); | ||||||||
|
|
@@ -2570,13 +2581,16 @@ | |||||||
| appendClientRuntimeEvent('HEADER_MODE_SELECTED', { mode, structured: !structuredReadLocked }); | ||||||||
| }, [appendClientRuntimeEvent, structuredReadLocked]); | ||||||||
|
|
||||||||
| const handleGuidedEntry = useCallback((label: string, desc: string) => { | ||||||||
|
Check failure on line 2584 in vessel/src/app/page.tsx
|
||||||||
| const intent = resolveGuidedEntryIntent(label); | ||||||||
| const safeDesc = typeof desc === 'string' && desc.trim().length > 0 ? desc : label; | ||||||||
| const intentRequiresArchitect = guidedEntryRequiresArchitect(intent); | ||||||||
| if (intent !== 'CHECK_BONES' && pendingSoloMirrorResolver) { | ||||||||
| setPendingSoloMirrorResolver(null); | ||||||||
| } | ||||||||
| if (intent !== 'SYMBOLIC_MOMENT' && pendingSymbolicMomentResolver) { | ||||||||
| setPendingSymbolicMomentResolver(null); | ||||||||
| } | ||||||||
|
|
||||||||
| if (structuredReadLocked && intentRequiresArchitect) { | ||||||||
| const requestedMode = resolveGuidedEntryTargetMode(intent); | ||||||||
|
|
@@ -2693,18 +2707,13 @@ | |||||||
| return; | ||||||||
| } | ||||||||
| if (intent === 'SYMBOLIC_MOMENT') { | ||||||||
| const structuredFieldReport = true; | ||||||||
| setRelationshipMappingActive(false); | ||||||||
| enterReadMode('FIELD_REPORT', structuredFieldReport); | ||||||||
| if (!requestReadArm('guided_entry_symbolic_moments')) { | ||||||||
| const symbolicDesc = safeDesc || 'Read my symbolic moment(s).'; | ||||||||
| if (observerStagedProfiles.length > 0 && !soloScopedProfile) { | ||||||||
| setPendingSymbolicMomentResolver({ desc: symbolicDesc }); | ||||||||
| return; | ||||||||
| } | ||||||||
| armCorridorLoadingMode(safeDesc || 'Read my symbolic moment(s).'); | ||||||||
| maybePrimeAlignmentCorridor('guided_entry', { targetMode: 'FIELD_REPORT' }); | ||||||||
| queueGuidedSend(safeDesc || 'Read my symbolic moment(s).', { | ||||||||
| targetModeOverride: 'FIELD_REPORT', | ||||||||
| structuredReadingOptInOverride: structuredFieldReport, | ||||||||
| }); | ||||||||
| runSymbolicMomentLane(symbolicDesc, { source: 'guided_entry_symbolic_moments' }); | ||||||||
| return; | ||||||||
| } | ||||||||
| if (intent === 'SET_LOCATION') { | ||||||||
|
|
@@ -2759,7 +2768,7 @@ | |||||||
| structuredReadingOptInOverride: true, | ||||||||
| }); | ||||||||
| // eslint-disable-next-line react-hooks/exhaustive-deps | ||||||||
| }, [activeMode, activeProfile, appendClientRuntimeEvent, appendConsoleNotice, appendStructuredUpgradeGateNotice, armCorridorLoadingMode, clearCorridorPrimeTimers, observerStagedProfiles, observerStagedProfiles.length, pendingSoloMirrorResolver, primeAlignmentCorridor, quickScopeCounterpart?.name, requestReadArm, soloScopedProfile, stagedContexts.length, structuredReadLocked, structuredReadingOptIn]); | ||||||||
| }, [activeMode, activeProfile, appendClientRuntimeEvent, appendConsoleNotice, appendStructuredUpgradeGateNotice, armCorridorLoadingMode, clearCorridorPrimeTimers, observerStagedProfiles, observerStagedProfiles.length, pendingSoloMirrorResolver, pendingSymbolicMomentResolver, primeAlignmentCorridor, quickScopeCounterpart?.name, requestReadArm, soloScopedProfile, stagedContexts.length, structuredReadLocked, structuredReadingOptIn]); | ||||||||
|
|
||||||||
| const sendScopedMessage = useCallback(( | ||||||||
| text: string, | ||||||||
|
|
@@ -2973,9 +2982,60 @@ | |||||||
| targetModeOverride: 'SOLO_MIRROR', | ||||||||
| structuredReadingOptInOverride: structuredSoloMirror, | ||||||||
| }).catch(() => { }); | ||||||||
|
|
||||||||
| }, [armCorridorLoadingMode, primeAlignmentCorridor, requestReadArm, sendMessage, sendScopedMessage, structuredReadLocked]); | ||||||||
|
|
||||||||
| const runSymbolicMomentLane = useCallback(( | ||||||||
| desc: string, | ||||||||
| options?: { | ||||||||
| forcePrimaryScope?: boolean; | ||||||||
| stagedOnlyScope?: boolean; | ||||||||
| profileOverride?: VaultProfile | null; | ||||||||
| source?: string; | ||||||||
| }, | ||||||||
| ) => { | ||||||||
| const structuredFieldReport = true; | ||||||||
| setRelationshipMappingActive(false); | ||||||||
| chatInputRef.current?.setText?.(''); | ||||||||
| const safeDesc = typeof desc === 'string' && desc.trim().length > 0 ? desc : 'Read my symbolic moment(s).'; | ||||||||
| setStructuredReadingOptIn(structuredFieldReport); | ||||||||
| setActiveMode('FIELD_REPORT'); | ||||||||
| if (!requestReadArm(options?.source || 'guided_entry_symbolic_moments')) { | ||||||||
| return; | ||||||||
| } | ||||||||
| armCorridorLoadingMode(safeDesc); | ||||||||
| maybePrimeAlignmentCorridor('guided_entry', { targetMode: 'FIELD_REPORT' }); | ||||||||
| if (options?.profileOverride) { | ||||||||
| void sendMessage(safeDesc, { | ||||||||
| profileOverride: options.profileOverride, | ||||||||
| stagedContextsOverride: [], | ||||||||
| targetModeOverride: 'FIELD_REPORT', | ||||||||
| structuredReadingOptInOverride: structuredFieldReport, | ||||||||
| }).catch(() => { }); | ||||||||
| return; | ||||||||
| } | ||||||||
| if (options?.forcePrimaryScope) { | ||||||||
| void sendMessage(safeDesc, { | ||||||||
| stagedContextsOverride: [], | ||||||||
| targetModeOverride: 'FIELD_REPORT', | ||||||||
| structuredReadingOptInOverride: structuredFieldReport, | ||||||||
| }).catch(() => { }); | ||||||||
| return; | ||||||||
| } | ||||||||
| if (options?.stagedOnlyScope) { | ||||||||
| void sendMessage(safeDesc, { | ||||||||
| stagedContextsOverride: observerStagedProfiles.map((p) => ({ profile: p, role: 'OBSERVER' as const })), | ||||||||
| targetModeOverride: 'FIELD_REPORT', | ||||||||
| structuredReadingOptInOverride: structuredFieldReport, | ||||||||
| }).catch(() => { }); | ||||||||
| return; | ||||||||
| } | ||||||||
| void sendScopedMessage(safeDesc, { | ||||||||
|
Check failure on line 3033 in vessel/src/app/page.tsx
|
||||||||
| targetModeOverride: 'FIELD_REPORT', | ||||||||
| structuredReadingOptInOverride: structuredFieldReport, | ||||||||
| }).catch(() => { }); | ||||||||
| }, [armCorridorLoadingMode, observerStagedProfiles, primeAlignmentCorridor, requestReadArm, sendMessage, sendScopedMessage]); | ||||||||
|
|
||||||||
| const handleCounterpartSoloMirror = useCallback((profile: VaultProfile, source: string) => { | ||||||||
| appendClientRuntimeEvent('COUNTERPART_QUICK_ACTION_SELECTED', { | ||||||||
| action: 'solo_mirror', | ||||||||
|
|
@@ -4047,6 +4107,114 @@ | |||||||
| </div> | ||||||||
| )} | ||||||||
|
|
||||||||
| {pendingSymbolicMomentResolver && observerStagedProfiles.length > 0 && ( | ||||||||
| <div className="mb-2 rounded-xl border border-amber-500/30 bg-amber-950/20 p-3"> | ||||||||
| <p className="text-[10px] font-mono uppercase tracking-[0.15em] text-amber-200"> | ||||||||
| Symbolic Moment Target | ||||||||
| </p> | ||||||||
| <p className="mt-1 text-xs text-slate-200 leading-relaxed"> | ||||||||
| {observerStagedProfiles.length === 1 | ||||||||
| ? `${observerStagedProfiles[0].name} is staged. Choose who or what to read in this moment.` | ||||||||
| : `${observerStagedProfiles.length} profiles staged. Choose the focus or read them together.`} | ||||||||
| </p> | ||||||||
| <div className="mt-2 flex flex-wrap items-center gap-2"> | ||||||||
| <button | ||||||||
| type="button" | ||||||||
| onClick={() => { | ||||||||
| setPendingSymbolicMomentResolver(null); | ||||||||
| setSoloFocusProfileId(null); | ||||||||
| runSymbolicMomentLane( | ||||||||
| pendingSymbolicMomentResolver.desc, | ||||||||
| { forcePrimaryScope: true, source: 'guided_entry_symbolic_moments_primary' }, | ||||||||
| ); | ||||||||
| }} | ||||||||
| className="px-3 py-1.5 rounded-md border border-emerald-400/40 bg-emerald-500/20 text-emerald-100 text-[10px] font-mono uppercase tracking-wider hover:bg-emerald-500/30 transition-colors" | ||||||||
| > | ||||||||
| Read For Me {activeProfile?.name ? `(${activeProfile.name})` : ''} | ||||||||
| </button> | ||||||||
| {observerStagedProfiles.map((profile) => ( | ||||||||
| <button | ||||||||
| key={`symbolic-moment-target-${profile.id}`} | ||||||||
| type="button" | ||||||||
| onClick={() => { | ||||||||
| setPendingSymbolicMomentResolver(null); | ||||||||
| setSoloFocusProfileId(profile.id); | ||||||||
| appendConsoleNotice( | ||||||||
| `Solo focus is now set to ${profile.name}. Upcoming turns will read ${profile.name}'s chart unless you tap Restore Me.`, | ||||||||
| ); | ||||||||
| runSymbolicMomentLane( | ||||||||
| pendingSymbolicMomentResolver.desc, | ||||||||
| { profileOverride: profile, source: `guided_entry_symbolic_moments_${profile.id}` }, | ||||||||
| ); | ||||||||
| }} | ||||||||
| className="px-3 py-1.5 rounded-md border border-cyan-400/40 bg-cyan-500/20 text-cyan-100 text-[10px] font-mono uppercase tracking-wider hover:bg-cyan-500/30 transition-colors" | ||||||||
| > | ||||||||
| Symbolic Moment: {profile.name} | ||||||||
| </button> | ||||||||
| ))} | ||||||||
| {observerStagedProfiles.length > 1 && ( | ||||||||
| <button | ||||||||
| type="button" | ||||||||
| onClick={() => { | ||||||||
| setPendingSymbolicMomentResolver(null); | ||||||||
| setSoloFocusProfileId(null); | ||||||||
| runSymbolicMomentLane( | ||||||||
| pendingSymbolicMomentResolver.desc, | ||||||||
| { stagedOnlyScope: true, source: 'guided_entry_symbolic_moments_all_staged' }, | ||||||||
| ); | ||||||||
| }} | ||||||||
| className="px-3 py-1.5 rounded-md border border-indigo-400/40 bg-indigo-500/20 text-indigo-100 text-[10px] font-mono uppercase tracking-wider hover:bg-indigo-500/30 transition-colors" | ||||||||
| title={`Read symbolic moment for: ${observerStagedProfiles.map((p) => p.name).join(', ')}`} | ||||||||
| > | ||||||||
| Read All Staged ({observerStagedProfiles.length}) | ||||||||
| </button> | ||||||||
| )} | ||||||||
| {observerStagedProfiles.length > 0 && ( | ||||||||
| <button | ||||||||
| type="button" | ||||||||
| onClick={() => { | ||||||||
| setPendingSymbolicMomentResolver(null); | ||||||||
| setSoloFocusProfileId(null); | ||||||||
|
||||||||
| setSoloFocusProfileId(null); | |
| setSoloFocusProfileId(null); | |
| setPrimaryOnlyScope(false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
runSymbolicMomentLaneusesmaybePrimeAlignmentCorridor(...), but theuseCallbackdeps don’t includemaybePrimeAlignmentCorridor(and includeprimeAlignmentCorridor, which isn’t referenced). This risks a stale closure ifmaybePrimeAlignmentCorridorchanges. IncludemaybePrimeAlignmentCorridorin the deps array and drop unused deps.