feat: regime system — Find Matching + By Regime view

- Pattern Lab: "Find Matching" button per pattern uses GPT-4o-mini to classify against library (merge_as_instance / counter_scenario / new_pattern); shows match badge + confidence + suggested #regime_tag; conditional action buttons (Merge / Save counter / Save new)
- save_pattern_from_run handles action='instance' (appends to historical_instances + updates stats), action='counter' (new pattern with counter_of link, tags parent regime_tag), action='new' (unchanged + regime_tag support)
- useApi.ts: extended useSaveLabPattern type + new useFindMatchingPattern mutation + MatchResult export type
- DB migrations: regime_tag + counter_of columns on custom_patterns
- PatternExplorer: new "By Regime" view groups saved patterns by regime_tag; RegimeCard shows historical instances, hit rate, counter-of link (orange); untagged group at bottom

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
OpenSquared
2026-06-22 20:52:11 +02:00
parent 198341b0c2
commit a435c11246
5 changed files with 438 additions and 47 deletions

View File

@@ -996,6 +996,8 @@ export const useSaveLabPattern = () => {
mutationFn: (body: {
run_id: string; pattern_index: number; name?: string;
category?: string; signal_direction?: string; asset_class?: string;
action?: 'new' | 'instance' | 'counter';
target_id?: string; regime_tag?: string; event_name?: string;
}) => api.post('/pattern-lab/save-pattern', body).then(r => r.data),
onSuccess: () => {
qc.invalidateQueries({ queryKey: ['all-patterns'] })
@@ -1004,6 +1006,21 @@ export const useSaveLabPattern = () => {
})
}
export type MatchResult = {
recommendation: 'merge_as_instance' | 'counter_scenario' | 'new_pattern'
match_id?: string
match_name?: string
confidence: number
reasoning: string
suggested_regime_tag?: string
}
export const useFindMatchingPattern = () =>
useMutation({
mutationFn: (body: { run_id: string; pattern_index: number }): Promise<MatchResult> =>
api.post('/pattern-lab/find-matching', body).then(r => r.data),
})
export const useDeleteLabRun = () => {
const qc = useQueryClient()
return useMutation({