1616#include <stdio.h>
1717#include <time.h>
1818
19- // Simple placeholder hash function (not cryptographic, just consistent)
2019void fossil_jellyfish_hash (const char * input , const char * output , uint8_t * hash_out ) {
21- // Enhanced: Use a simple FNV-1a-like mixing over input and output
2220 const uint32_t FNV_PRIME = 0x01000193 ;
2321 uint32_t hash = 0x811c9dc5 ;
2422 size_t in_len = strlen (input );
2523 size_t out_len = strlen (output );
2624
25+ // Mix in lengths
26+ hash ^= in_len ;
27+ hash *= FNV_PRIME ;
28+ hash ^= out_len ;
29+ hash *= FNV_PRIME ;
30+
2731 // Mix input
2832 for (size_t i = 0 ; i < in_len ; ++ i ) {
2933 hash ^= (uint8_t )input [i ];
3034 hash *= FNV_PRIME ;
35+ hash ^= (hash >> 5 );
3136 }
37+
3238 // Mix output
3339 for (size_t i = 0 ; i < out_len ; ++ i ) {
3440 hash ^= (uint8_t )output [i ];
3541 hash *= FNV_PRIME ;
42+ hash ^= (hash >> 5 );
3643 }
3744
38- // Spread hash into hash_out buffer
45+ // Final mix
46+ hash ^= (hash << 7 );
47+ hash ^= (hash >> 3 );
48+
49+ // Spread into output
50+ uint32_t h = hash ;
3951 for (size_t i = 0 ; i < FOSSIL_JELLYFISH_HASH_SIZE ; ++ i ) {
40- hash ^= (hash >> 13 );
41- hash *= FNV_PRIME ;
42- hash_out [i ] = (uint8_t )((hash >> (8 * (i % 4 ))) & 0xFF );
52+ h ^= (h >> 13 );
53+ h *= FNV_PRIME ;
54+ h ^= (h << 11 );
55+ hash_out [i ] = (uint8_t )((h >> (8 * (i % 4 ))) & 0xFF );
4356 }
4457}
4558
@@ -123,13 +136,30 @@ int fossil_jellyfish_load(fossil_jellyfish_chain *chain, const char *filepath) {
123136 return 1 ;
124137}
125138
126- // Simple Levenshtein-like distance (cost is # of mismatched chars)
127139static int fossil_jellyfish_similarity (const char * a , const char * b ) {
128- int score = 0 ;
129- for (int i = 0 ; a [i ] && b [i ]; ++ i ) {
130- if (a [i ] != b [i ]) score ++ ;
140+ int cost = 0 ;
141+ size_t i = 0 , j = 0 ;
142+
143+ while (a [i ] && b [j ]) {
144+ char ac = a [i ];
145+ char bc = b [j ];
146+
147+ // case-insensitive match
148+ if (ac >= 'A' && ac <= 'Z' ) ac += 32 ;
149+ if (bc >= 'A' && bc <= 'Z' ) bc += 32 ;
150+
151+ if (ac != bc ) {
152+ cost ++ ;
153+ }
154+ i ++ ;
155+ j ++ ;
131156 }
132- return score ;
157+
158+ // Penalty for remaining characters
159+ while (a [i ++ ]) cost ++ ;
160+ while (b [j ++ ]) cost ++ ;
161+
162+ return cost ;
133163}
134164
135165const char * fossil_jellyfish_reason_fuzzy (fossil_jellyfish_chain * chain , const char * input ) {
@@ -140,31 +170,56 @@ const char* fossil_jellyfish_reason_fuzzy(fossil_jellyfish_chain *chain, const c
140170 if (!chain -> memory [i ].valid ) continue ;
141171
142172 int score = fossil_jellyfish_similarity (input , chain -> memory [i ].input );
173+ if (score == 0 ) return chain -> memory [i ].output ; // Exact match
143174 if (score < best_score ) {
144175 best_score = score ;
145176 best_output = chain -> memory [i ].output ;
146177 }
147178 }
148179
180+ // impose a fuzzy threshold
181+ if (best_score > (int )(strlen (input ) / 2 )) {
182+ return "Unknown" ;
183+ }
184+
149185 return best_output ;
150186}
151187
152188void fossil_jellyfish_decay_confidence (fossil_jellyfish_chain * chain , float decay_rate ) {
189+ const float MIN_CONFIDENCE = 0.05f ;
190+
153191 for (size_t i = 0 ; i < chain -> count ; ++ i ) {
154192 if (!chain -> memory [i ].valid ) continue ;
155193
156- chain -> memory [i ].confidence -= decay_rate ;
157- if (chain -> memory [i ].confidence < 0.05f ) {
158- chain -> memory [i ].valid = 0 ; // mark for cleanup
194+ // Apply exponential decay
195+ chain -> memory [i ].confidence *= (1.0f - decay_rate );
196+
197+ // Clamp to zero
198+ if (chain -> memory [i ].confidence < 0.0f ) {
199+ chain -> memory [i ].confidence = 0.0f ;
200+ }
201+
202+ // Invalidate if confidence too low
203+ if (chain -> memory [i ].confidence < MIN_CONFIDENCE ) {
204+ chain -> memory [i ].valid = 0 ;
159205 }
160206 }
161207}
162208
163209const char * fossil_jellyfish_reason_chain (fossil_jellyfish_chain * chain , const char * input , int depth ) {
164- if (depth <= 0 ) return input ;
210+ const char * current = input ;
211+ const char * last_valid = input ;
212+
213+ for (int i = 0 ; i < depth ; ++ i ) {
214+ const char * next = fossil_jellyfish_reason_fuzzy (chain , current );
165215
166- const char * first = fossil_jellyfish_reason_fuzzy (chain , input );
167- if (strcmp (first , "Unknown" ) == 0 ) return first ;
216+ if (strcmp (next , "Unknown" ) == 0 || strcmp (next , current ) == 0 ) {
217+ break ;
218+ }
219+
220+ last_valid = next ;
221+ current = next ;
222+ }
168223
169- return fossil_jellyfish_reason_chain ( chain , first , depth - 1 ) ;
224+ return last_valid ;
170225}
0 commit comments