@jefuriiij/synthra 0.14.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +813 -774
- package/dist/cli/index.js +84 -10
- package/dist/cli/index.js.map +1 -1
- package/dist/dashboard/index.js +2 -2
- package/dist/dashboard/index.js.map +1 -1
- package/dist/server/index.js +82 -8
- package/dist/server/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,774 +1,813 @@
|
|
|
1
|
-
# Synthra changelog
|
|
2
|
-
|
|
3
|
-
Notable changes per version. This file ships inside the npm tarball — `syn .`
|
|
4
|
-
reads it after an auto-update to show you what changed.
|
|
5
|
-
|
|
6
|
-
For older versions, see [GitHub Releases](https://github.com/jefuriiij/synthra/releases).
|
|
7
|
-
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
## [0.
|
|
11
|
-
|
|
12
|
-
### Added
|
|
13
|
-
|
|
14
|
-
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
###
|
|
214
|
-
|
|
215
|
-
- **
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
the
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
- **
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
the
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
---
|
|
357
|
-
|
|
358
|
-
## [0.
|
|
359
|
-
|
|
360
|
-
###
|
|
361
|
-
|
|
362
|
-
- **
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
`
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
- **
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
-
|
|
462
|
-
`
|
|
463
|
-
|
|
464
|
-
`
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
###
|
|
518
|
-
|
|
519
|
-
- **
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
- **
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
- **
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
1
|
+
# Synthra changelog
|
|
2
|
+
|
|
3
|
+
Notable changes per version. This file ships inside the npm tarball — `syn .`
|
|
4
|
+
reads it after an auto-update to show you what changed.
|
|
5
|
+
|
|
6
|
+
For older versions, see [GitHub Releases](https://github.com/jefuriiij/synthra/releases).
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## [0.15.0] — 2026-07-02
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **Your remembered context now talks back.** Synthra's second brain was
|
|
15
|
+
write-only — decisions and gotchas went in via `context_remember` and never
|
|
16
|
+
resurfaced. Now they appear exactly where they're relevant:
|
|
17
|
+
- `graph_read` of a file (or a symbol in it) shows a `📌 Remembered for this
|
|
18
|
+
file` block with the entries linked to that file.
|
|
19
|
+
- `graph_continue` packs include `Remembered:` lines for entries matching the
|
|
20
|
+
query.
|
|
21
|
+
- **Memories know when they might be wrong.** Entries linked to files are now
|
|
22
|
+
*anchored* to those files' content hashes at capture time. When the code
|
|
23
|
+
changes afterwards (tracked live by auto-reindex), every surfacing of that
|
|
24
|
+
entry — graph_read, graph_continue, context_recall — carries
|
|
25
|
+
`⚠ possibly stale — <file> changed since stored`. Old entries without anchors
|
|
26
|
+
keep working and are never flagged; the shared context-store format is
|
|
27
|
+
unchanged (additive optional field).
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## [0.14.1] — 2026-07-02
|
|
32
|
+
|
|
33
|
+
### Added
|
|
34
|
+
|
|
35
|
+
- **Dashboard: copy button beside every Arsenal card name.** One click copies the
|
|
36
|
+
skill/agent/MCP name to your clipboard (with a ✓ flash) — handy for invoking a
|
|
37
|
+
skill or referencing an agent — without toggling the card open.
|
|
38
|
+
|
|
39
|
+
### Fixed
|
|
40
|
+
|
|
41
|
+
- **Dashboard: expanding an Arsenal card no longer stretches its neighbors.**
|
|
42
|
+
Opening a skill/agent card made the cards beside it in the same grid row grow
|
|
43
|
+
to matching height — looking expanded while their text stayed clamped until
|
|
44
|
+
clicked. Cards now align to the top of their row, so only the clicked card
|
|
45
|
+
grows and neighbors keep their compact size.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## [0.14.0] — 2026-07-02
|
|
50
|
+
|
|
51
|
+
### Added
|
|
52
|
+
|
|
53
|
+
- **`syn remove [path]` — cleanly uninstall Synthra from a project.** Ran `syn .`
|
|
54
|
+
in the wrong folder, or just want Synthra out of a repo? `syn remove` reverses
|
|
55
|
+
the bootstrap: deletes `.synthra-graph/` and `.synthra/`, strips the policy
|
|
56
|
+
block from `CLAUDE.md`, Synthra's entries from `.gitignore`, its hooks from
|
|
57
|
+
`.claude/` — **your own content in those files survives**; a file is deleted
|
|
58
|
+
only when nothing else remains. Also deregisters the MCP entry (with a direct
|
|
59
|
+
`.mcp.json` fallback when the `claude` CLI isn't available) and removes the
|
|
60
|
+
project from the dashboard registry. Shows a summary and asks `[y/N]` first;
|
|
61
|
+
pass `--yes` to skip (required when not running in a terminal).
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## [0.13.1] — 2026-06-24
|
|
66
|
+
|
|
67
|
+
### Fixed
|
|
68
|
+
|
|
69
|
+
- **Minified/bundle files are no longer indexed.** Committed vendored plugin JS
|
|
70
|
+
(`*.min.js`, `*.bundle.js`, `*.min.css`, …) has no readable symbols, so indexing
|
|
71
|
+
it only polluted retrieval and caused **useless Moat blocks** on markup-heavy
|
|
72
|
+
projects — a Grep for CSS classes like `nav|menu|toggle` would spuriously match a
|
|
73
|
+
symbol *inside* the minified library and get blocked, only for `graph_continue` to
|
|
74
|
+
then find nothing. The scanner now skips these files (cleaner retrieval, smaller
|
|
75
|
+
graph, no behavior change for real source).
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## [0.13.0] — 2026-06-24
|
|
80
|
+
|
|
81
|
+
### Added
|
|
82
|
+
|
|
83
|
+
- **The resume digest now lists the symbols that changed since your last session.**
|
|
84
|
+
The SessionStart "Since you were last here" primer showed *files* touched; it now
|
|
85
|
+
leads its supporting context with the actual **symbols/signatures** that changed —
|
|
86
|
+
e.g. `src/auth.ts::login (function) — function login(creds: Creds): Promise<...>`.
|
|
87
|
+
Computed from a git diff against the previous session's HEAD (committed **and**
|
|
88
|
+
uncommitted changes), overlapped with the current graph. Best-effort: silently
|
|
89
|
+
omitted in non-git projects.
|
|
90
|
+
- **`call_path(from, to)` — trace control flow.** Returns the shortest chain of
|
|
91
|
+
calls from one symbol to another (`handler → service → repo`), so you can see how
|
|
92
|
+
one symbol reaches another. The forward complement to `blast_radius` (callers).
|
|
93
|
+
Each of `from`/`to` is a `file::symbol` target or a bare symbol name when unique.
|
|
94
|
+
|
|
95
|
+
Both reuse the existing call graph + git — no graph schema change, no new dependencies.
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## [0.12.0] — 2026-06-24
|
|
100
|
+
|
|
101
|
+
### Added
|
|
102
|
+
|
|
103
|
+
- **`find_symbol(name)` — reuse before you re-implement.** Before writing a new
|
|
104
|
+
helper, ask Synthra whether one already exists: `find_symbol` returns every
|
|
105
|
+
exact-name definition (with signatures + ready `graph_read` targets), or — if
|
|
106
|
+
there's no exact match — similarly-named symbols to reuse or extend. "No symbol
|
|
107
|
+
matching … — safe to create" is the green light that it's genuinely new. The
|
|
108
|
+
injected policy now nudges the agent to check first.
|
|
109
|
+
- **`duplicate_symbols` — consolidation candidates.** Lists symbol names defined
|
|
110
|
+
in more than one file (functions/classes/types; methods excluded, since shared
|
|
111
|
+
method names are normal). Advisory — duplicates can be intentional; it never
|
|
112
|
+
says "delete."
|
|
113
|
+
|
|
114
|
+
Both are built on the symbol index (exact name lookup) — no false-positive risk,
|
|
115
|
+
no new dependencies.
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## [0.11.0] — 2026-06-24
|
|
120
|
+
|
|
121
|
+
### Added
|
|
122
|
+
|
|
123
|
+
- **`graph_read` now shows which tests cover a symbol.** A symbol read appends a
|
|
124
|
+
`Tests (file-level): …` line listing the test files linked to the symbol's file
|
|
125
|
+
(via the graph's `tests` edges) — so after an edit you run the *right* test
|
|
126
|
+
instead of guessing or running the whole suite. Ordinary source files with no
|
|
127
|
+
linked test get a one-line "none linked" nudge.
|
|
128
|
+
- **`blast_radius` is now symbol-aware.** A `file::symbol` target returns the
|
|
129
|
+
exact caller **symbols** that transitively call it (`name → file:line`), plus a
|
|
130
|
+
line naming the test files that guard the impact — the precise view you want
|
|
131
|
+
before a rename. A bare file target keeps the existing file-level dependent
|
|
132
|
+
list. (The `graph_read` "Used by (N)" footer remains the cheap always-on
|
|
133
|
+
direct-caller summary; this is the complete, transitive, on-demand one.)
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## [0.10.0] — 2026-06-20
|
|
138
|
+
|
|
139
|
+
### Added
|
|
140
|
+
|
|
141
|
+
- **Terminal-bypass visibility (observe-only).** The Moat blocks `Grep`/`Glob`,
|
|
142
|
+
but the agent can still explore the codebase through the shell — `rg foo src/`,
|
|
143
|
+
`cat src/x.ts`, `find …` — and every such call is a read the graph could have
|
|
144
|
+
served in ~50 tokens. Synthra now watches `Bash` too: it classifies these
|
|
145
|
+
exploration commands and records each one — with whether the graph could have
|
|
146
|
+
answered it — to `bash_log.jsonl`, surfaced on the dashboard's Moat card as
|
|
147
|
+
"N terminal hunts · M the graph could answer." It is **observe-only — it never
|
|
148
|
+
blocks a Bash command** — so you can measure the leak before deciding whether
|
|
149
|
+
to close it. Conservative by design (it ignores `npm`/`git`/builds, stdin
|
|
150
|
+
filters like `… | grep`, and any command with a redirect). Disable with
|
|
151
|
+
`SYN_NO_BASH_OBSERVE`.
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## [0.9.0] — 2026-06-20
|
|
156
|
+
|
|
157
|
+
### Added
|
|
158
|
+
|
|
159
|
+
- **The graph auto-reindexes edited files mid-session — it never goes stale.**
|
|
160
|
+
Previously the in-memory graph was a snapshot from the last `syn .`: edit a
|
|
161
|
+
file and `graph_read` / `blast_radius` / the dependency footer would keep
|
|
162
|
+
serving the *old* signature, body, and line ranges until the next manual scan.
|
|
163
|
+
Now the running server watches for source changes and, ~1s after edits settle,
|
|
164
|
+
re-runs the incremental scan and hot-swaps the graph in place — so reads always
|
|
165
|
+
reflect what's on disk. The rescan is incremental (only the changed file hits
|
|
166
|
+
tree-sitter; everything else reuses the content-hash parse cache) and debounced
|
|
167
|
+
so a burst of saves coalesces into one rebuild. Tune with
|
|
168
|
+
`SYN_REINDEX_DEBOUNCE_MS` (default `1000`); disable with `SYN_NO_AUTOREINDEX`.
|
|
169
|
+
|
|
170
|
+
### Fixed
|
|
171
|
+
|
|
172
|
+
- **In-session rescans (auto-reindex and branch-switch) no longer rewrite your
|
|
173
|
+
`CLAUDE.md` / `.gitignore`.** A rescan now skips the bootstrap step — it only
|
|
174
|
+
rebuilds the graph. This also closes a feedback loop the new auto-reindex would
|
|
175
|
+
otherwise hit (rewriting the watched `CLAUDE.md` on every rescan would retrigger
|
|
176
|
+
the watcher endlessly).
|
|
177
|
+
- **`CLAUDE.md` no longer accumulates a blank line on every `syn .`.** The policy
|
|
178
|
+
block patcher is now idempotent — re-running with nothing to change is a true
|
|
179
|
+
no-op instead of appending an empty line above the managed block each time.
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## [0.8.1] — 2026-06-16
|
|
184
|
+
|
|
185
|
+
### Changed
|
|
186
|
+
|
|
187
|
+
- **Dashboard polish.** The Overview is now a tidy bento — equal-height cards,
|
|
188
|
+
with the Savings and Total-spend cards sized to their content and a tall Moat
|
|
189
|
+
spanning the right that scrolls internally. The Arsenal view groups skills,
|
|
190
|
+
agents, and MCP servers into labeled sections by source ("In this project",
|
|
191
|
+
"Personal · this machine", and one per plugin) so a big toolkit is easy to
|
|
192
|
+
scan. Base text bumped to 14px for readability. UI-only; data unchanged.
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## [0.8.0] — 2026-06-15
|
|
197
|
+
|
|
198
|
+
### Changed
|
|
199
|
+
|
|
200
|
+
- **The dashboard is rebuilt on Svelte + shadcn-svelte with a real sidebar.** A
|
|
201
|
+
persistent, collapsible left sidebar (Overview · Arsenal · FAQ) replaces the
|
|
202
|
+
old top-nav + cramped drawer; the **Arsenal is now a roomy first-class view**
|
|
203
|
+
(tabs, filter, expandable cards) instead of a 340px slide-out. Same data, same
|
|
204
|
+
endpoints, same numbers — only the UI changed. The Svelte/Tailwind/Vite
|
|
205
|
+
toolchain is build-time only: it compiles to a single inlined HTML the server
|
|
206
|
+
serves exactly as before, so the installed runtime and zero-config setup are
|
|
207
|
+
unchanged (no new runtime dependencies).
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## [0.7.0] — 2026-06-15
|
|
212
|
+
|
|
213
|
+
### Added
|
|
214
|
+
|
|
215
|
+
- **Dashboard "Arsenal" drawer.** A collapsible panel (toggle in the nav) lists
|
|
216
|
+
everything Claude Code has available to you — **skills, subagents, and MCP
|
|
217
|
+
servers** — scoped project / personal / plugin, each expandable to its
|
|
218
|
+
description (agents also show tools + model). It scans your project `.claude/`,
|
|
219
|
+
your personal `~/.claude/`, and every installed plugin, so you never have to
|
|
220
|
+
drop to the CLI to remember what's in your toolkit. MCP entries are shown as
|
|
221
|
+
name / type / url only — auth headers and tokens are never read into the view.
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
## [0.6.0] — 2026-06-13
|
|
226
|
+
|
|
227
|
+
### Added
|
|
228
|
+
|
|
229
|
+
- **`graph_read` now delivers a symbol's dependency surface.** Reading a symbol
|
|
230
|
+
appends a footer built from the call graph: **Depends on** — the symbols it
|
|
231
|
+
calls, each with its full one-line signature and a `graph_read` target, so you
|
|
232
|
+
can edit against real signatures instead of guessing parameter shapes or
|
|
233
|
+
re-reading the callee files; and **Used by** — the names of the symbols that
|
|
234
|
+
call it, so a change's blast radius is visible at a glance. Budgeted via
|
|
235
|
+
`SYN_READ_DEPS_CHARS` (default 900); leaf symbols with no calls add nothing.
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## [0.5.0] — 2026-06-13
|
|
240
|
+
|
|
241
|
+
### Added
|
|
242
|
+
|
|
243
|
+
- **`graph_read` hands you the cheap edit recipe.** Reading a symbol slice now
|
|
244
|
+
ends with the exact targeted `Read(path, offset, limit)` (covering the symbol
|
|
245
|
+
plus a little headroom) that satisfies Claude Code's Edit read-gate, plus a
|
|
246
|
+
"do not re-read the whole file" nudge. A `graph_read` slice doesn't satisfy
|
|
247
|
+
the gate on its own, so editing a symbol used to force a whole-file Read —
|
|
248
|
+
and the same large file would get re-read many times across a session.
|
|
249
|
+
Delivering the recipe at the point of use (not just once in the session
|
|
250
|
+
primer) keeps edits cheap.
|
|
251
|
+
|
|
252
|
+
### Changed
|
|
253
|
+
|
|
254
|
+
- **The Moat stops wasting blocks on styling searches.** Grep/Glob patterns for
|
|
255
|
+
CSS custom properties (`var(--brand)`, `--sidebar`), hex color literals
|
|
256
|
+
(`#fff`), and all-kebab class names (`cw-code-chip`) now pass through instead
|
|
257
|
+
of being blocked and redirected to a graph the symbol index can't answer.
|
|
258
|
+
Mixed queries that also name a real symbol still block.
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## [0.4.1] — 2026-06-10
|
|
263
|
+
|
|
264
|
+
### Added
|
|
265
|
+
|
|
266
|
+
- **Claude Fable model family.** Fable turns (`claude-fable-5`, including the
|
|
267
|
+
`[1m]` long-context variant) were bucketed as "Other" in the model donut and
|
|
268
|
+
billed at the Sonnet fallback rates. The dashboard now prices Fable at its
|
|
269
|
+
published rates ($10/M input, $50/M output, $1/M cache read, $12.50/M cache
|
|
270
|
+
write) and gives it its own donut segment, legend entry, turn pill, color,
|
|
271
|
+
and FAQ rate-table column. Historical Fable turns reprice correctly on the
|
|
272
|
+
next dashboard load — cost is computed at read time from the raw model IDs
|
|
273
|
+
in the token log.
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
## [0.4.0] — 2026-06-10
|
|
278
|
+
|
|
279
|
+
### Changed
|
|
280
|
+
|
|
281
|
+
- **The Moat's block messages now deliver the answer, not just directions.**
|
|
282
|
+
When the gate blocks a Grep/Glob, the deny reason used to name the relevant
|
|
283
|
+
file paths — and agents responded by Reading those files whole, erasing the
|
|
284
|
+
savings the block was meant to create. The block message now carries
|
|
285
|
+
copy-pasteable `mcp__synthra__graph_read("file::symbol")` targets with
|
|
286
|
+
one-line signatures for the query's best-matching symbols (~300 tokens,
|
|
287
|
+
signatures only), plus a `graph_continue` pointer for the full pack. The
|
|
288
|
+
cheap path is now the path of least resistance. Budget tunable via
|
|
289
|
+
`SYN_GATE_HINT_CHARS` (default 1200 chars). Gate decisions are unchanged —
|
|
290
|
+
only the message got smarter.
|
|
291
|
+
- **Policy v7 — full namespaced tool names.** Agents wasted tool-discovery
|
|
292
|
+
round-trips searching for short names like `graph_continue` that don't
|
|
293
|
+
resolve. The CLAUDE.md policy block now states the `mcp__synthra__` namespace
|
|
294
|
+
requirement up front, provides a ready ToolSearch `select:` line for the
|
|
295
|
+
graph tools, and uses the full form in every invocation example. Existing
|
|
296
|
+
policy blocks upgrade automatically on the next `syn .`.
|
|
297
|
+
|
|
298
|
+
---
|
|
299
|
+
|
|
300
|
+
## [0.3.1] — 2026-06-09
|
|
301
|
+
|
|
302
|
+
### Changed
|
|
303
|
+
|
|
304
|
+
- **Dashboard layout.** The Total-spend (cost) hero now sits beside the Savings
|
|
305
|
+
card in a responsive two-column row at the top of the center column (collapsing
|
|
306
|
+
to one column on narrow viewports), and the new "Hot files" list is height-capped
|
|
307
|
+
with its own scrollbar so a long list never crowds the Moat card beneath it.
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
## [0.3.0] — 2026-06-09
|
|
312
|
+
|
|
313
|
+
### Added
|
|
314
|
+
|
|
315
|
+
- **Incremental scanner.** `syn .` now re-parses only the files whose content
|
|
316
|
+
changed since the last scan, reusing cached parses (symbols, imports, calls)
|
|
317
|
+
for everything else via a content-hash parse cache. Rescans of a large repo
|
|
318
|
+
after editing a handful of files are dramatically faster; the resulting graph
|
|
319
|
+
is byte-identical to a full scan. `syn . --full` forces a clean rebuild. This
|
|
320
|
+
makes the long-standing "updated incrementally" claim actually true.
|
|
321
|
+
- **Call-graph edges.** Function and method call sites are now captured during
|
|
322
|
+
parsing and resolved (name-based, precision-first: same-file wins, else the
|
|
323
|
+
unique repo-wide symbol; ambiguous/external calls are skipped) into
|
|
324
|
+
symbol→symbol `calls` edges. `blast_radius` therefore surfaces **callers**,
|
|
325
|
+
not just importers and tests — so the impact of changing a function includes
|
|
326
|
+
the code that calls it. Captured across 14 languages (TypeScript, Python, Go,
|
|
327
|
+
Rust, Java, C, C++, C#, plus best-effort Kotlin/PHP/Ruby and Svelte/Vue
|
|
328
|
+
passthrough); this makes the "call relationships" claim honest.
|
|
329
|
+
- **Dashboard "Hot files" card.** The dashboard now surfaces the usage-learning
|
|
330
|
+
layer directly: the active project's hottest files by recent, decayed access.
|
|
331
|
+
- **Dashboard favicon.** The dashboard tab now carries the Synthra S mark.
|
|
332
|
+
|
|
333
|
+
### Internal
|
|
334
|
+
|
|
335
|
+
- The scanner is now under test — directory walker, parser dispatch, a
|
|
336
|
+
per-language symbol/call smoke suite, and the context packer — alongside the
|
|
337
|
+
call-resolution and incremental-equivalence tests. CI runs on Node 24 actions
|
|
338
|
+
with the test matrix on Node 22 (ubuntu + windows).
|
|
339
|
+
|
|
340
|
+
---
|
|
341
|
+
|
|
342
|
+
## [0.2.1] — 2026-06-06
|
|
343
|
+
|
|
344
|
+
### Changed
|
|
345
|
+
|
|
346
|
+
- **Keyword retrieval is now IDF-weighted (BM25's term-rarity component).** A
|
|
347
|
+
query token that's rare across the repo counts for more than a common one, so
|
|
348
|
+
on a multi-term query the files matching the *specific* terms rank above those
|
|
349
|
+
matching generic ones — instead of every keyword match counting the same. The
|
|
350
|
+
weighting is normalized to the query's mean IDF, so a typical match scores the
|
|
351
|
+
same as before: overall ranking magnitude — and the confidence / Moat gating
|
|
352
|
+
that depends on it — is unchanged. Purely an in-repo ranking refinement, no API
|
|
353
|
+
or data-model change. (TF-saturation / length-norm parts of full BM25 don't
|
|
354
|
+
apply to the deduped top-N keyword representation.)
|
|
355
|
+
|
|
356
|
+
---
|
|
357
|
+
|
|
358
|
+
## [0.2.0] — 2026-06-06
|
|
359
|
+
|
|
360
|
+
### Added
|
|
361
|
+
|
|
362
|
+
- **Cross-session "second brain" — a resume digest at session start.** Synthra
|
|
363
|
+
now captures a snapshot at session end (open next-steps/decisions, files
|
|
364
|
+
touched, and commits since your last session) and, on the next session, leads
|
|
365
|
+
the SessionStart primer with a budget-bounded **"Since you were last here"**
|
|
366
|
+
digest. A fresh session arrives already oriented instead of re-paying tokens
|
|
367
|
+
to rediscover recent work. The snapshot lives in `.synthra-graph/`
|
|
368
|
+
(machine-local) and falls back to the normal primer when there's nothing to
|
|
369
|
+
show.
|
|
370
|
+
- **Usage learning — retrieval that gets smarter the more you use it.** Files
|
|
371
|
+
you actually open (`graph_read`) or edit (`graph_register_edit`) accrue a
|
|
372
|
+
time-decayed weight (7-day half-life), and retrieval gives genuinely "hot"
|
|
373
|
+
files a small, capped re-rank boost. It's anchored to files that already match
|
|
374
|
+
your query and capped below the existing seed boost, so it sharpens ranking
|
|
375
|
+
without ever overriding relevance. Purely local, per-developer; degrades to
|
|
376
|
+
the exact prior ranking when there's no usage history. Tunable via
|
|
377
|
+
`SYN_LEARN_HALFLIFE_DAYS` and `SYN_LEARN_BOOST_CAP`.
|
|
378
|
+
- **CLAUDE.md policy v6** — teaches the assistant to trust the resume digest and
|
|
379
|
+
pull concrete next steps via `context_recall({kind:"next"})` instead of
|
|
380
|
+
re-exploring the codebase.
|
|
381
|
+
|
|
382
|
+
### Fixed
|
|
383
|
+
|
|
384
|
+
- **`pre-compact.sh` now parses the primer with `jq`, not a greedy `sed`
|
|
385
|
+
capture** — completing the `jq` migration across all four bash hooks (matches
|
|
386
|
+
the Stop/Prime/PreToolUse fixes). The multi-line resume digest contains quotes
|
|
387
|
+
and newlines the old `sed` capture would have mangled.
|
|
388
|
+
|
|
389
|
+
### Internal
|
|
390
|
+
|
|
391
|
+
- **CI (GitHub Actions), Biome (lint + format), and coverage** added. CI runs on
|
|
392
|
+
an ubuntu + windows matrix, so cross-platform hook regressions are caught
|
|
393
|
+
automatically. `.gitattributes` enforces LF line endings on every platform.
|
|
394
|
+
|
|
395
|
+
---
|
|
396
|
+
|
|
397
|
+
## [0.1.25] — 2026-06-06
|
|
398
|
+
|
|
399
|
+
### Fixed
|
|
400
|
+
|
|
401
|
+
- **PreToolUse (Moat) bash hook now parses the gate response with `jq`, not a
|
|
402
|
+
greedy `sed` capture (issue #13).** `src/hooks/scripts/pre-tool-use.sh`
|
|
403
|
+
extracted the block `reason` via `sed -n 's/.*"reason"…\(.*\)".*/\1/p'`. The
|
|
404
|
+
greedy `\(.*\)"` capture over-ran into the trailing JSON fields, and because a
|
|
405
|
+
block `reason` legitimately contains double quotes (it quotes the searched
|
|
406
|
+
query, e.g. `"login"`), the captured text broke the deny JSON when embedded
|
|
407
|
+
raw in the output heredoc — so on a real block Claude Code received malformed
|
|
408
|
+
`hookSpecificOutput` and the deny was silently dropped. The hook now reads
|
|
409
|
+
`.decision` / `.reason` with `jq -r '… // empty'` and re-emits the deny object
|
|
410
|
+
with `jq -nc --arg` (correct escaping), behind a `command -v jq` guard that
|
|
411
|
+
silently no-ops when `jq` is absent — mirroring the Stop/Prime hooks fixed in
|
|
412
|
+
#1. Gate/Moat decision logic is unchanged. This completes the `jq` migration
|
|
413
|
+
across all three bash hooks (the last v0.2 item). Verified end-to-end under
|
|
414
|
+
bash on Linux: SessionStart primer injection, Grep/Glob Moat blocks with
|
|
415
|
+
well-formed escaped deny JSON, and Stop-hook token totals reaching the
|
|
416
|
+
dashboard.
|
|
417
|
+
|
|
418
|
+
---
|
|
419
|
+
|
|
420
|
+
## [0.1.24] — 2026-06-06
|
|
421
|
+
|
|
422
|
+
### Added
|
|
423
|
+
|
|
424
|
+
- **`syn doctor [path]` — setup and environment health check (issue #9).** New
|
|
425
|
+
read-only CLI subcommand that runs a one-shot checklist and exits. Checks: Node
|
|
426
|
+
version, `jq` availability (bash Stop/Prime hooks silently no-op without it),
|
|
427
|
+
`claude` CLI on PATH, graph freshness (symbol count, schema version, scan age),
|
|
428
|
+
`.mcp.json` project-scope registration (required for Synthra tools to appear in
|
|
429
|
+
the Claude Code IDE), CLAUDE.md policy-block version, and hook installation
|
|
430
|
+
status. Warnings surface with the exact `syn .` command needed to resolve them.
|
|
431
|
+
The command mutates nothing — safe to run at any time.
|
|
432
|
+
|
|
433
|
+
- **Graph-tool usage metric on the dashboard (issue #2).** The MCP server now
|
|
434
|
+
appends a record to `.synthra-graph/tool_log.jsonl` on every Synthra tool call
|
|
435
|
+
(`graph_continue`, `graph_read`, `graph_register_edit`, etc.). `delta.ts`
|
|
436
|
+
aggregates per-tool call counts into `ProjectStats.tool_calls` (per-project) and
|
|
437
|
+
`global.tool_calls` (cross-project totals). The dashboard shows a new "Graph
|
|
438
|
+
tools used" card in the right column with per-tool counts. This is a positive
|
|
439
|
+
signal complementing the Moat's blocked-Grep count: it captures Synthra pivots
|
|
440
|
+
that happen before a Grep fires, which the block counter misses entirely.
|
|
441
|
+
|
|
442
|
+
- **Session-aware routing — `graph_continue` seeds retrieval with the session's
|
|
443
|
+
touched files (issue #14).** Files the human recently saved (last 15 min) and
|
|
444
|
+
files the AI registered via `graph_register_edit` now get a ranking boost in
|
|
445
|
+
`graph_continue` results, so the returned context tracks what you're actually
|
|
446
|
+
working on. Mirrors the `/pack` route, which already seeded retrieval this way.
|
|
447
|
+
|
|
448
|
+
---
|
|
449
|
+
|
|
450
|
+
## [0.1.23] — 2026-06-06
|
|
451
|
+
|
|
452
|
+
### Added
|
|
453
|
+
|
|
454
|
+
- **Dashboard token-log dedupe can now be disabled via `SYN_DASHBOARD_DEDUPE=0`.**
|
|
455
|
+
By default, `delta.ts` deduplicates `token_log.jsonl` entries that share the
|
|
456
|
+
same project, usage totals, and second-rounded timestamp — collapsing the
|
|
457
|
+
duplicate writes that a co-installed AI tool's Stop hook may produce. Set
|
|
458
|
+
`SYN_DASHBOARD_DEDUPE=0` (also accepts `off` or `false`) to see every raw
|
|
459
|
+
entry. Useful when debugging multi-tool coexistence or auditing raw log data.
|
|
460
|
+
|
|
461
|
+
- **Graph schema-migration check on load.** A new `SCHEMA_VERSION` constant is
|
|
462
|
+
exported from `src/graph/types.ts` and stamped into `info_graph.json` by
|
|
463
|
+
`buildGraph`. On server start, `http.ts` compares the stored graph's
|
|
464
|
+
`schema_version` to the current constant; if they differ it triggers an
|
|
465
|
+
automatic one-time rescan instead of serving an incompatible graph. No
|
|
466
|
+
behavior change today — all graphs are v1 and schema_version matches — but
|
|
467
|
+
this is the forward-safety mechanism for future schema bumps so existing
|
|
468
|
+
graphs are never silently misread.
|
|
469
|
+
|
|
470
|
+
### Fixed
|
|
471
|
+
|
|
472
|
+
- **JS/TS parser now captures member-assigned functions** (`exports.handler = fn`,
|
|
473
|
+
`module.exports.route = () => {}`, `this.x = () => {}`). Previously these
|
|
474
|
+
CommonJS/member-export patterns were invisible to the query, so modules that
|
|
475
|
+
exclusively use this style extracted zero symbols and degraded to whole-file
|
|
476
|
+
reads via `graph_read`. A member-assignment capture has been added to both
|
|
477
|
+
`JS_QUERY` and `TS_QUERY` in `src/scanner/parsers/typescript.ts`. Note: a
|
|
478
|
+
pure-wiring `server.js` whose only structure is anonymous inline-callback
|
|
479
|
+
arguments (e.g. `io.use(...)` / `socket.on(event, fn)`) is genuinely
|
|
480
|
+
symbol-less — that is correct, and the gate's symbol-hit guard already
|
|
481
|
+
prevents blocking such files.
|
|
482
|
+
|
|
483
|
+
### Changed
|
|
484
|
+
|
|
485
|
+
- **Policy block v4 → v5.** Adds a "large file — pull the symbol, don't
|
|
486
|
+
chunk" nudge to address recurring dogfood friction: on large files Claude
|
|
487
|
+
was reading successive line-range chunks instead of fetching the specific
|
|
488
|
+
symbol via `graph_read("file::symbol")`. The v5 block now explicitly
|
|
489
|
+
instructs: when a file is large, use `graph_read("file/path.ts::SymbolName")`
|
|
490
|
+
to pull the symbol directly rather than reading successive line-range chunks.
|
|
491
|
+
`POLICY_VERSION` bumped `4 → 5`; existing v4 blocks auto-upgrade on the
|
|
492
|
+
next `syn .` run.
|
|
493
|
+
|
|
494
|
+
---
|
|
495
|
+
|
|
496
|
+
## [0.1.22] — 2026-06-06
|
|
497
|
+
|
|
498
|
+
### Fixed
|
|
499
|
+
|
|
500
|
+
- **`graph_read` now resolves shortened file paths (path-suffix fallback).** Previously
|
|
501
|
+
`graph_read` performed an exact `path === target` match only. Passing a shortened path
|
|
502
|
+
like `appsettings.json` returned "file not found" even when
|
|
503
|
+
`connectwarev2/.../appsettings.json` was indexed. A new `resolveFileTarget` helper (now
|
|
504
|
+
exported) tries an exact match first; on a miss it looks for a unique path-suffix match
|
|
505
|
+
and serves that file; if multiple files share the suffix it reports them as ambiguous with
|
|
506
|
+
candidate paths rather than guessing. Symbol lookups use the resolved path. No API or
|
|
507
|
+
protocol change. Roadmap item #11.
|
|
508
|
+
|
|
509
|
+
- **Gate content-keyword relaxation now intersects file contents, not just file paths.**
|
|
510
|
+
The Moat's recent-activity relaxation previously matched query tokens against the paths of
|
|
511
|
+
recently-touched files only. A query like `Grep "login"` would not relax on a recent save
|
|
512
|
+
of `auth.ts` unless the word "login" appeared in the path. Now the relaxation also checks
|
|
513
|
+
the recently-touched file's graph-node keywords (its indexed content), so a recent save
|
|
514
|
+
relaxes a Grep whenever the file *contains* the queried term — not just when the path
|
|
515
|
+
matches it. Completes roadmap item #3.
|
|
516
|
+
|
|
517
|
+
### Changed
|
|
518
|
+
|
|
519
|
+
- **Dashboard Projects card shows a first-run hint in the empty state.** When no projects
|
|
520
|
+
have run `syn .` yet, the Projects card now displays "No projects yet — run `syn .` in a
|
|
521
|
+
project to start" instead of a blank card. The Recent-turns card already carried this
|
|
522
|
+
hint; Projects now matches it. Roadmap item #10.
|
|
523
|
+
|
|
524
|
+
- **`bin` path normalization (chore).** Ran `npm pkg fix` to normalize `bin` entries from
|
|
525
|
+
`./bin/syn` to `bin/syn`. Silences the cosmetic publish warnings
|
|
526
|
+
(`"bin[syn]" script name was cleaned`). `syn` and `synthra` still resolve to the same
|
|
527
|
+
entry point. Roadmap item #4.
|
|
528
|
+
|
|
529
|
+
---
|
|
530
|
+
|
|
531
|
+
## [0.1.21] — 2026-06-06
|
|
532
|
+
|
|
533
|
+
### Added
|
|
534
|
+
|
|
535
|
+
- **HubL (HubSpot CMS) symbol extraction for `.html` and `.hubl` files.**
|
|
536
|
+
Previously `.html` files were content-indexed only — keyword search and
|
|
537
|
+
whole-file reads, no symbol-level granularity. On HubSpot projects this
|
|
538
|
+
meant the graph contributed nothing: zero `graph_continue`/`graph_read`
|
|
539
|
+
calls resolved to symbol slices all session. Now `.html` and `.hubl` files
|
|
540
|
+
run through a new **regex-based** parser (`parsers/hubl.ts`; there is no
|
|
541
|
+
tree-sitter grammar for HubL):
|
|
542
|
+
- `{% macro name(args) %}` → extracted as a `function` symbol
|
|
543
|
+
- `{% block name %}` → extracted as a `component` symbol
|
|
544
|
+
- `{% include / extends / import / from "path" %}` → import edges (relative
|
|
545
|
+
paths resolve to local templates; `.html`/`.hubl` added to the resolver's
|
|
546
|
+
extension list)
|
|
547
|
+
|
|
548
|
+
Plain HTML with no HubL tags is unaffected — the parser yields zero symbols
|
|
549
|
+
and zero imports, identical to before. No API, protocol, or policy-block
|
|
550
|
+
change. Roadmap item #12.
|
|
551
|
+
|
|
552
|
+
---
|
|
553
|
+
|
|
554
|
+
## [0.1.20] — 2026-06-06
|
|
555
|
+
|
|
556
|
+
### Fixed
|
|
557
|
+
|
|
558
|
+
- **Gate (Moat) no longer blocks Grep/Glob queries the graph cannot answer with a symbol.**
|
|
559
|
+
Previously, the PreToolUse gate blocked whenever retrieval confidence was `medium` or `high`,
|
|
560
|
+
but confidence is driven by keyword and path hits too — not only by symbol matches. This meant
|
|
561
|
+
literal/attribute/CSS-selector patterns (`data-tour=`, `class=`, `: 100%`, `.filter-bar`,
|
|
562
|
+
`<div>`) and path-only Globs were blocked and redirected to `graph_read`, which has no symbol
|
|
563
|
+
slice to return for those queries, so Claude fell back to Grep or a whole-file Read anyway —
|
|
564
|
+
a wasted round-trip. Found across multiple dogfood sessions including well-indexed Svelte
|
|
565
|
+
repos. Two new guards close the gap:
|
|
566
|
+
- **Query-shape pre-filter** — Grep patterns that target markup, CSS, attributes, or string
|
|
567
|
+
literals are allowed through up front, before the retrieval step runs.
|
|
568
|
+
- **Symbol-hit requirement** — the gate now only blocks when retrieval matched a symbol whose
|
|
569
|
+
name the query mentions exactly. `RetrievalResult` gained a `symbolMatched` flag; the scorer
|
|
570
|
+
exposes `exactSym`.
|
|
571
|
+
|
|
572
|
+
Net effect: genuine symbol lookups still block (verified: `fetchWith429Retry`,
|
|
573
|
+
`MAX_ROWS_PER_TABLE`, `verifyPin`, `SOCKET_AUTH_SECRET`, `seedCredentials`); queries that
|
|
574
|
+
could never have been answered by the graph now allow through without the wasted redirect.
|
|
575
|
+
No API, protocol, or policy-block change — purely server-side gate behavior.
|
|
576
|
+
|
|
577
|
+
- **Gate and rank test coverage added** (`tests/gate.test.ts`, `tests/rank.test.ts`).
|
|
578
|
+
Chips at the v0.2 backlog item to fill vitest tests beyond `it.todo` placeholders.
|
|
579
|
+
|
|
580
|
+
---
|
|
581
|
+
|
|
582
|
+
## [0.1.19] — 2026-06-01
|
|
583
|
+
|
|
584
|
+
### Changed
|
|
585
|
+
|
|
586
|
+
- **Policy block v4: targeted Read-before-Edit for graph-discovered files.**
|
|
587
|
+
Claude Code's `Edit` tool requires a file to have been opened with its own
|
|
588
|
+
`Read` tool; a `graph_read` slice does not satisfy that gate. Previously,
|
|
589
|
+
editing a file known only through `graph_read` would fail with *"File has
|
|
590
|
+
not been read yet"* and force a whole-file `Read` — eroding token savings on
|
|
591
|
+
edit-heavy sessions. The v4 policy now instructs: take the line range already
|
|
592
|
+
reported in the `graph_read` header (e.g. `…::handler (L120-168)`), do a
|
|
593
|
+
targeted `Read` with matching `offset`/`limit`, then `Edit`. This satisfies
|
|
594
|
+
the gate while keeping the read small. Existing v3 blocks auto-upgrade on the
|
|
595
|
+
next `syn .` run.
|
|
596
|
+
|
|
597
|
+
---
|
|
598
|
+
|
|
599
|
+
## [0.1.18] — 2026-06-01
|
|
600
|
+
|
|
601
|
+
### Fixed
|
|
602
|
+
|
|
603
|
+
- **Stop hook on Linux/macOS no longer posts zero tokens to the dashboard.** The bash
|
|
604
|
+
`stop.sh` hook extracted `transcript_path` from the Claude Code Stop payload using a
|
|
605
|
+
greedy `sed` capture (`\(.*\)"`). Because the real payload has additional fields after
|
|
606
|
+
`transcript_path`, the capture grabbed those trailing fields and produced a
|
|
607
|
+
non-existent path string. The `-f` file check therefore always failed, totals were
|
|
608
|
+
never POSTed to `/log`, and the dashboard stayed stuck at 0 on every turn (GitHub
|
|
609
|
+
issue #1). Fixed by parsing with `jq -r '.transcript_path // empty'` and moving the
|
|
610
|
+
`command -v jq` guard above the parse so the hook exits cleanly when `jq` is absent.
|
|
611
|
+
- **SessionStart/PreCompact primer hook (`prime.sh`) hardened the same way.** The
|
|
612
|
+
`/prime` response is `{"primer":"…","port":…}`, so the old greedy capture accidentally
|
|
613
|
+
injected trailing `","port":…` junk into the primer string. Because primer text can
|
|
614
|
+
contain inner quotes, a negated-class fix (`[^"]*`) would have truncated it at the
|
|
615
|
+
first quote — `jq -r '.primer // empty'` is the correct parse. Switched `printf '%b'`
|
|
616
|
+
to `printf '%s'` since `jq -r` already decodes JSON escapes.
|
|
617
|
+
- Both fixes are **bash-only**. The Windows PowerShell hooks (`stop.ps1`, `prime.ps1`)
|
|
618
|
+
use `ConvertFrom-Json` and were already correct.
|
|
619
|
+
|
|
620
|
+
---
|
|
621
|
+
|
|
622
|
+
## [0.1.17] — 2026-05-29
|
|
623
|
+
|
|
624
|
+
### Added
|
|
625
|
+
|
|
626
|
+
- **`syn .` scaffolds an agent-onboarding CLAUDE.md on brand-new projects.**
|
|
627
|
+
When a project has no CLAUDE.md, Synthra now writes a lean skeleton —
|
|
628
|
+
`Build & test`, `Conventions`, `Key decisions`, `Gotchas` (with TODO
|
|
629
|
+
prompts) — *above* its managed policy block, instead of a bare policy
|
|
630
|
+
block. This is the durable "why/how" layer the graph can't infer; the
|
|
631
|
+
graph still owns "what/where." Fill it in, or run `/init` to auto-draft.
|
|
632
|
+
The skeleton is written **once** and lives outside the
|
|
633
|
+
`<!-- synthra-policy -->` markers, so re-running `syn .` (which
|
|
634
|
+
refreshes the policy block) never clobbers what you've written.
|
|
635
|
+
Projects that already have a CLAUDE.md are untouched — no skeleton is
|
|
636
|
+
injected.
|
|
637
|
+
|
|
638
|
+
---
|
|
639
|
+
|
|
640
|
+
## [0.1.16] — 2026-05-29
|
|
641
|
+
|
|
642
|
+
### Changed
|
|
643
|
+
|
|
644
|
+
- **Moat card shows 50 recent gate decisions** (was 12). The inline list
|
|
645
|
+
already scrolls within the card, and the `/data` payload already carries
|
|
646
|
+
up to 500 gates, so this just renders more of them. The headline block
|
|
647
|
+
count was always all-time/uncapped — unchanged.
|
|
648
|
+
|
|
649
|
+
---
|
|
650
|
+
|
|
651
|
+
## [0.1.15] — 2026-05-29
|
|
652
|
+
|
|
653
|
+
### Changed
|
|
654
|
+
|
|
655
|
+
- **Recent turns are paginated.** The dashboard now carries up to 500 turns
|
|
656
|
+
(was 25) and shows them 25 per page with Prev/Next controls — so you can
|
|
657
|
+
browse history instead of only seeing the last 25. Configurable via
|
|
658
|
+
`SYN_DASHBOARD_RECENT_N` (default 500).
|
|
659
|
+
- **Model-usage donut is now all-time, not last-25.** It was tallying models
|
|
660
|
+
from the capped recent-turns window, so a run of >25 same-model turns showed
|
|
661
|
+
that model at 100% and hid the rest. It now sums the uncapped per-project
|
|
662
|
+
model counts, so it always reflects your true all-time split.
|
|
663
|
+
- **Dashboard poll slowed 2s → 10s.** Lighter on resources and steadier to
|
|
664
|
+
read; pagination stays live (the current page re-renders each poll).
|
|
665
|
+
|
|
666
|
+
---
|
|
667
|
+
|
|
668
|
+
## [0.1.14] — 2026-05-29
|
|
669
|
+
|
|
670
|
+
### Changed
|
|
671
|
+
|
|
672
|
+
- **Dashboard visual refresh.** No API surface change — all visual / UX.
|
|
673
|
+
- Removed the hero strip and the standalone Legend card. Date + active
|
|
674
|
+
project now live as compact chips inside the top nav (active-project
|
|
675
|
+
path uses RTL truncation so the folder name stays visible).
|
|
676
|
+
- New **Projects bar chart** in the left column — colored bars ranked
|
|
677
|
+
by turn count. Stable per-name OKLCH palette (8 colors, hash-keyed)
|
|
678
|
+
so a project keeps the same color across sessions. Click any row to
|
|
679
|
+
open its full breakdown.
|
|
680
|
+
- **Donut legend** gains a turn-count column alongside the percentage.
|
|
681
|
+
- **Savings card** elevated: radial green backdrop, money figure 40px,
|
|
682
|
+
soft glow — makes the "what Synthra saved you" number the visual
|
|
683
|
+
anchor of the dashboard.
|
|
684
|
+
- **Recent turns column headers** are now hover-explainable.
|
|
685
|
+
- Active-project chip tightens + month name hides under 1100px width.
|
|
686
|
+
|
|
687
|
+
---
|
|
688
|
+
|
|
689
|
+
## [0.1.13] — 2026-05-29
|
|
690
|
+
|
|
691
|
+
### Fixed
|
|
692
|
+
|
|
693
|
+
- **Dashboard footer version is now dynamic.** Was hardcoded to `v0.1.8`
|
|
694
|
+
in the HTML and never updated. The dashboard server now injects the
|
|
695
|
+
running binary's version (from `package.json`) into the footer on every
|
|
696
|
+
`GET /` via a `__SYN_VERSION__` placeholder. Re-run `syn .` after an
|
|
697
|
+
update and the dashboard reflects the new version automatically.
|
|
698
|
+
|
|
699
|
+
---
|
|
700
|
+
|
|
701
|
+
## [0.1.12] — 2026-05-29
|
|
702
|
+
|
|
703
|
+
### Fixed
|
|
704
|
+
|
|
705
|
+
- **`Language.query is deprecated` spam at scan time.** Every parsed file
|
|
706
|
+
printed the warning — 57 prints on a Flutter codebase, one per parsed
|
|
707
|
+
file. Switched all four parsers (TypeScript, JavaScript, Python, Dart,
|
|
708
|
+
plus the generic helper) from the deprecated `language.query(QUERY)`
|
|
709
|
+
to `new Query(language, QUERY)`. No behavior change, just clean
|
|
710
|
+
terminal output.
|
|
711
|
+
|
|
712
|
+
---
|
|
713
|
+
|
|
714
|
+
## [0.1.11] — 2026-05-29
|
|
715
|
+
|
|
716
|
+
### Fixed
|
|
717
|
+
|
|
718
|
+
- **Dart parser actually runs now.** Was silently broken since v0.1 due to an
|
|
719
|
+
ABI mismatch (shipped wasm was ABI v15, pinned `web-tree-sitter` only
|
|
720
|
+
supported v13–v14). Every `.dart` file got zero symbols, zero imports —
|
|
721
|
+
the exception was swallowed by the parser's try/catch. Bumped
|
|
722
|
+
`web-tree-sitter` to `^0.25.10` to fix.
|
|
723
|
+
- **Real Dart symbol extraction.** Classes, mixins, extensions, enums,
|
|
724
|
+
typedefs, top-level functions, methods, getters, setters, constructors.
|
|
725
|
+
- **Dart import normalization.** `package:foo/bar.dart` and `dart:async` are
|
|
726
|
+
stripped (cross-project); bare `'sibling.dart'` is rewritten to
|
|
727
|
+
`./sibling.dart` so the project resolver can complete them.
|
|
728
|
+
|
|
729
|
+
### Changed
|
|
730
|
+
|
|
731
|
+
- **Update check runs on every `syn .`** (no more 24h cache). If you're on
|
|
732
|
+
latest, stays silent. If outdated, prompts `[y/N]` as before.
|
|
733
|
+
- **Auto-update now shows a changelog.** After `npm install -g …@latest`
|
|
734
|
+
succeeds, Synthra prints the new version's section from this file before
|
|
735
|
+
telling you to re-run. Catches `npm install` outside of `syn .` too —
|
|
736
|
+
next startup compares your current version to `~/.synthra/last-seen-version.json`
|
|
737
|
+
and prints if it's newer.
|
|
738
|
+
|
|
739
|
+
---
|
|
740
|
+
|
|
741
|
+
## [0.1.10] — 2026-05-29
|
|
742
|
+
|
|
743
|
+
### Changed
|
|
744
|
+
|
|
745
|
+
- **CLAUDE.md policy v2 → v3.** Session-end now goes through
|
|
746
|
+
`context_remember({kind: "task"|"decision"|"next"})` instead of writing
|
|
747
|
+
`.synthra/CONTEXT.md` directly. The Stop hook always re-rendered CONTEXT.md
|
|
748
|
+
from `context-store.json` — under v2 Claude's direct writes were getting
|
|
749
|
+
wiped on session end. Existing v2 blocks auto-upgrade.
|
|
750
|
+
|
|
751
|
+
### Added
|
|
752
|
+
|
|
753
|
+
- **Scanner ignores more build caches.** `.dart_tool/`, `.flutter-plugins`,
|
|
754
|
+
`.flutter-plugins-dependencies`, `.gradle/`, `target/`, `Pods/`,
|
|
755
|
+
`DerivedData/`, `__pycache__/`, `.venv/`, `venv/`, `.tox/`,
|
|
756
|
+
`.pytest_cache/`, `.mypy_cache/`, `.ruff_cache/`, `obj/`, `.vs/`.
|
|
757
|
+
|
|
758
|
+
---
|
|
759
|
+
|
|
760
|
+
## [0.1.9] — 2026-05-29
|
|
761
|
+
|
|
762
|
+
### Fixed
|
|
763
|
+
|
|
764
|
+
- **Crash on prototype-colliding symbol names.** `buildSymbolIndex` built
|
|
765
|
+
the lookup on a plain `{}`, so a symbol named `toString` (which every
|
|
766
|
+
Dart class overrides), `constructor`, `valueOf`, etc. resolved to the
|
|
767
|
+
inherited `Object.prototype` member and crashed on `.push`. Now uses
|
|
768
|
+
`Object.create(null)` on both fresh-build and load-from-disk paths.
|
|
769
|
+
|
|
770
|
+
---
|
|
771
|
+
|
|
772
|
+
## [0.1.8] — 2026-05-29
|
|
773
|
+
|
|
774
|
+
### Added
|
|
775
|
+
|
|
776
|
+
- **Interactive auto-update.** `syn .` checks npm at startup; if a newer
|
|
777
|
+
version is available, prompts `[y/N]`. On `y`, runs
|
|
778
|
+
`npm install -g @jefuriiij/synthra@latest` with stdio inherited and
|
|
779
|
+
exits with re-run instructions. Non-TTY runs (CI, piped stdin) fall
|
|
780
|
+
back to a silent one-line hint. `SYN_NO_UPDATE_CHECK=1` opts out.
|
|
781
|
+
|
|
782
|
+
---
|
|
783
|
+
|
|
784
|
+
## [0.1.7] — 2026-05-29
|
|
785
|
+
|
|
786
|
+
### Fixed
|
|
787
|
+
|
|
788
|
+
- **JS parser missed CommonJS imports + JS class names.** Unified TS/JS
|
|
789
|
+
query only matched ES `import_statement`, and used `(type_identifier)`
|
|
790
|
+
for class names — which is TS-grammar-only. Result: every `.js`/`.cjs`/
|
|
791
|
+
`.mjs` file silently produced zero imports, and any class in a JS file
|
|
792
|
+
was skipped. Split into `TS_QUERY` and `JS_QUERY`; JS query adds a
|
|
793
|
+
`require()` capture and uses `(identifier)` for class names.
|
|
794
|
+
|
|
795
|
+
---
|
|
796
|
+
|
|
797
|
+
## [0.1.6] — 2026-05-29
|
|
798
|
+
|
|
799
|
+
### Fixed
|
|
800
|
+
|
|
801
|
+
- **MCP registration now uses `--scope project`** so the Claude Code IDE
|
|
802
|
+
extension actually sees Synthra. The previous `--scope local` wrote to
|
|
803
|
+
a per-project section of `~/.claude.json` that only the `claude` CLI
|
|
804
|
+
reads — invisible to the IDE.
|
|
805
|
+
|
|
806
|
+
---
|
|
807
|
+
|
|
808
|
+
## [0.1.5] and earlier
|
|
809
|
+
|
|
810
|
+
See [GitHub commits](https://github.com/jefuriiij/synthra/commits/main) for
|
|
811
|
+
detail. v0.1.5 introduced the v2 policy template with namespace + skip rules;
|
|
812
|
+
v0.1.4 fixed a DEP0190 deprecation on Windows; v0.1.3 was the dashboard
|
|
813
|
+
redesign (Cool Marine palette, FAQ modal, savings audit row).
|