claudeos-core 2.2.0 → 2.3.1
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 +1664 -907
- package/CONTRIBUTING.md +92 -92
- package/README.de.md +28 -0
- package/README.es.md +28 -0
- package/README.fr.md +28 -0
- package/README.hi.md +28 -0
- package/README.ja.md +28 -0
- package/README.ko.md +1014 -986
- package/README.md +1016 -987
- package/README.ru.md +28 -0
- package/README.vi.md +1015 -987
- package/README.zh-CN.md +28 -0
- package/bin/cli.js +152 -148
- package/bin/commands/init.js +1673 -1554
- package/bin/commands/lint.js +62 -0
- package/bin/commands/memory.js +438 -438
- package/bin/lib/cli-utils.js +206 -206
- package/claude-md-validator/index.js +184 -0
- package/claude-md-validator/reporter.js +66 -0
- package/claude-md-validator/structural-checks.js +528 -0
- package/content-validator/index.js +666 -441
- package/lib/expected-guides.js +23 -23
- package/lib/expected-outputs.js +90 -90
- package/lib/language-config.js +35 -35
- package/lib/memory-scaffold.js +1058 -1054
- package/lib/plan-parser.js +165 -165
- package/lib/staged-rules.js +118 -118
- package/manifest-generator/index.js +174 -174
- package/package.json +90 -87
- package/pass-json-validator/index.js +337 -337
- package/pass-prompts/templates/common/claude-md-scaffold.md +52 -10
- package/pass-prompts/templates/common/pass3-footer.md +402 -224
- package/pass-prompts/templates/common/pass3b-core-header.md +43 -0
- package/pass-prompts/templates/common/pass4.md +375 -305
- package/pass-prompts/templates/common/staging-override.md +26 -26
- package/pass-prompts/templates/node-vite/pass1.md +117 -117
- package/pass-prompts/templates/node-vite/pass2.md +78 -78
- package/pass-prompts/templates/python-flask/pass1.md +119 -119
- package/pass-prompts/templates/python-flask/pass2.md +85 -85
- package/plan-installer/domain-grouper.js +76 -76
- package/plan-installer/index.js +137 -137
- package/plan-installer/prompt-generator.js +188 -145
- package/plan-installer/scanners/scan-frontend.js +505 -473
- package/plan-installer/scanners/scan-java.js +226 -226
- package/plan-installer/scanners/scan-node.js +57 -57
- package/plan-installer/scanners/scan-python.js +85 -85
- package/plan-installer/stack-detector.js +482 -482
- package/plan-installer/structure-scanner.js +65 -65
- package/sync-checker/index.js +177 -177
package/CHANGELOG.md
CHANGED
|
@@ -1,908 +1,1665 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
## [2.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
-
the
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
section
|
|
233
|
-
|
|
234
|
-
`
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
Pass
|
|
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
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
CLAUDE.md
|
|
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
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
###
|
|
799
|
-
|
|
800
|
-
- **
|
|
801
|
-
-
|
|
802
|
-
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
-
|
|
828
|
-
|
|
829
|
-
-
|
|
830
|
-
|
|
831
|
-
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
-
|
|
835
|
-
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
- **
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
-
|
|
861
|
-
- **
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
- **`
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
- **`
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [2.3.1] — 2026-04-23
|
|
4
|
+
|
|
5
|
+
Patch release. Fixes Windows CI breakage in `npm test`.
|
|
6
|
+
|
|
7
|
+
- **CI — cross-platform `npm test`**. Windows cmd.exe does not expand `*`
|
|
8
|
+
glob patterns, so `node --test tests/*.test.js` received the literal
|
|
9
|
+
string and exited 1 on every Windows runner. Replaced with a thin
|
|
10
|
+
`scripts/run-tests.js` wrapper that uses the existing `glob` dep to
|
|
11
|
+
enumerate test files before forwarding to `node --test`. Also replaced
|
|
12
|
+
the `pretest` `2>/dev/null` stderr redirect (which spuriously triggered
|
|
13
|
+
"The system cannot find the path specified" on Windows) with a Node
|
|
14
|
+
`try/catch` so the probe is silent on all platforms. No new dependencies.
|
|
15
|
+
|
|
16
|
+
No source, template, or test changes. Test count unchanged at 662.
|
|
17
|
+
|
|
18
|
+
## [2.3.0] — 2026-04-23
|
|
19
|
+
|
|
20
|
+
Adds language-invariant structural validation for generated `CLAUDE.md`.
|
|
21
|
+
Dogfooding v2.2.0 on a Korean-output Vite + React project (`frontend-react-A`)
|
|
22
|
+
surfaced the §9 L4-memory re-declaration anti-pattern *despite* the scaffold,
|
|
23
|
+
expanded blocklist, and post-generation self-check all being present in the
|
|
24
|
+
embedded Pass 3 prompt. Root cause: forbidden-section enforcement depended
|
|
25
|
+
on the LLM matching English canonical labels (`"Memory Layer (L4)"`) against
|
|
26
|
+
its own translated output (`"메모리 (L4)"`, `"メモリ (L4)"`, etc.) — a
|
|
27
|
+
natural-language equivalence judgment the LLM does not perform reliably
|
|
28
|
+
across 10 supported languages.
|
|
29
|
+
|
|
30
|
+
Dogfooding v2.3.0's initial build on a sibling project (`frontend-react-B`,
|
|
31
|
+
same organization, same language, same stack family) then surfaced a second
|
|
32
|
+
multi-repo invariant failure: the §9 problem was fixed, but the *wording*
|
|
33
|
+
of section headings drifted freely. One project's §7 read
|
|
34
|
+
`"DO NOT Read (직접 읽지 말아야 할 파일)"` while the sibling's read
|
|
35
|
+
`"읽지 말 것 (Files Not to Be Read Directly)"`. Both were "equivalent in
|
|
36
|
+
meaning" per the scaffold, but `grep "## 7. DO NOT Read"` matched the
|
|
37
|
+
first and missed the second — multi-repo discoverability broken.
|
|
38
|
+
|
|
39
|
+
v2.3.0 addresses both failures by shifting structural enforcement from
|
|
40
|
+
LLM self-check to deterministic code-level validation that does not depend
|
|
41
|
+
on natural-language matching, and adds a cross-repo title-determinism
|
|
42
|
+
invariant (English canonical primary + optional translation parenthetical).
|
|
43
|
+
|
|
44
|
+
Continued dogfooding on `frontend-react-B` then surfaced two more failure
|
|
45
|
+
classes unrelated to CLAUDE.md structure:
|
|
46
|
+
|
|
47
|
+
1. **Path hallucination in rules/standard**. Pass 3 generated rule files
|
|
48
|
+
referencing `src/feature/routers/featureRoutePath.ts` when the actual
|
|
49
|
+
file was `src/feature/routers/routePath.ts`. Root cause: the LLM saw
|
|
50
|
+
the parent directory `src/feature/` and a TypeScript constant
|
|
51
|
+
`FEATURE_ROUTE_PATH` and "renormalized" the filename to match. Pre-v2.3.0
|
|
52
|
+
validation did not check whether path claims resolved to real files.
|
|
53
|
+
|
|
54
|
+
2. **MANIFEST ↔ CLAUDE.md §6 Skills drift**. Four skills registered in
|
|
55
|
+
`claudeos-core/skills/00.shared/MANIFEST.md`, only one of them
|
|
56
|
+
mentioned in CLAUDE.md §6. No existing tool detected the mismatch.
|
|
57
|
+
|
|
58
|
+
Both are now detected by a new `content-validator [10/10] path-claim
|
|
59
|
+
verification` check. The check uses only structural signals (backticked
|
|
60
|
+
paths, file-system existence, MANIFEST vs CLAUDE.md cross-reference) —
|
|
61
|
+
no natural-language matching, so it works identically for all 10 output
|
|
62
|
+
languages.
|
|
63
|
+
|
|
64
|
+
Running the initial v2.3.0 build against `frontend-react-B` surfaced a
|
|
65
|
+
third, upstream issue in the frontend domain scanner. The project has
|
|
66
|
+
a single-SPA layout (`src/admin/{api,context,dto,routers,pages/*}/`,
|
|
67
|
+
plus a separate `src/guide/` for documentation). The subapp scanner,
|
|
68
|
+
designed for dual-platform layouts (`src/pc/admin/` + `src/mobile/admin/`),
|
|
69
|
+
interpreted `admin` as a platform keyword and emitted the architectural
|
|
70
|
+
layers beneath it as pseudo-domains: `admin-api`, `admin-context`,
|
|
71
|
+
`admin-dto`, `admin-routers`. That fragmented one SPA into 5+ spurious
|
|
72
|
+
domains and, critically, primed Pass 3 to fabricate filenames with the
|
|
73
|
+
`admin` prefix — the root cause of the `featureRoutePath.ts` hallucination
|
|
74
|
+
pattern. v2.3.0 adds a single-SPA detection rule: when only ONE distinct
|
|
75
|
+
platform keyword matches across the project tree, subapp emission is
|
|
76
|
+
suppressed by default, and feature domains are left to the downstream
|
|
77
|
+
page/FSD/components scanners to discover correctly.
|
|
78
|
+
|
|
79
|
+
Running the v2.3.0 build against `backend-java-spring` then surfaced a
|
|
80
|
+
long-standing resume bug in the init pipeline. When a prior `init` run
|
|
81
|
+
is interrupted mid-Pass-3 — most commonly a stream idle timeout during
|
|
82
|
+
the 3d-aux (database + mcp-guide) stage — `pass3-complete.json` is
|
|
83
|
+
persisted in partial form (`mode: "split"`, `groupsCompleted: [...]`,
|
|
84
|
+
no `completedAt`). On the next run, the init orchestrator branched
|
|
85
|
+
solely on `fileExists(pass3Marker)` and fell into the "skip" branch
|
|
86
|
+
for any existing marker, even partial ones. The result: remaining
|
|
87
|
+
Pass 3 stages never ran, `database/` and `mcp-guide/` directories
|
|
88
|
+
were left empty, and the final `pass3-complete.json` retained the
|
|
89
|
+
partial shape — which `pass-json-validator` later caught as a
|
|
90
|
+
`MISSING_KEY: completedAt` error after the fact. v2.3.0 fixes the
|
|
91
|
+
orchestrator to inspect marker contents: when the marker is partial,
|
|
92
|
+
`runPass3Split` is re-invoked and its internal `groupsCompleted`
|
|
93
|
+
logic resumes from the next unstarted stage; only fully-completed
|
|
94
|
+
markers are skipped.
|
|
95
|
+
|
|
96
|
+
Finally, the full v2.3.0 pipeline run against `frontend-react-B` (14
|
|
97
|
+
domains, Korean output) surfaced a structural regression the validator
|
|
98
|
+
itself caught and flagged: `## 9. 메모리 운영 (L4)` appeared in
|
|
99
|
+
`CLAUDE.md` as a re-declaration of the memory file table already
|
|
100
|
+
present in Section 8. This was the exact anti-pattern v2.3.0 was
|
|
101
|
+
designed to prevent, now reappearing despite the scaffold's explicit
|
|
102
|
+
constraints. Root-cause analysis traced it to a legacy Pass 4
|
|
103
|
+
behavior preserved from pre-v2.3.0: `pass4.md` instructed the LLM to
|
|
104
|
+
**append** a new `## N. ... (L4)` section to `CLAUDE.md`, and
|
|
105
|
+
`init.js` also called `appendClaudeMdL4Memory()` from
|
|
106
|
+
`lib/memory-scaffold.js` as a static fallback doing the same. Both
|
|
107
|
+
predated the current Pass 3 scaffold design where Section 8 "Common
|
|
108
|
+
Rules & Memory (L4)" is authored directly by Pass 3 and is the single
|
|
109
|
+
canonical home for both the Common Rules table and the L4 Memory
|
|
110
|
+
file table + workflow. With Pass 3 already writing that content,
|
|
111
|
+
every additional Pass 4 append produced the [S1]/[M-*]/[F2-*]
|
|
112
|
+
duplications the validator was built to catch. The validator was
|
|
113
|
+
working correctly; the generator was self-contradicting. v2.3.0 fix:
|
|
114
|
+
retire the Pass 4 CLAUDE.md append path completely. Pass 4 continues
|
|
115
|
+
to generate memory files, memory rules, and the doc-writing guide,
|
|
116
|
+
but never touches `CLAUDE.md`. The `appendClaudeMdL4Memory()` export
|
|
117
|
+
is preserved as a no-op for any external caller depending on its
|
|
118
|
+
signature.
|
|
119
|
+
|
|
120
|
+
Post-retirement dogfooding on `frontend-react-B` surfaced a final class
|
|
121
|
+
of issue: four `STALE_PATH` errors in Pass 4-generated rule and
|
|
122
|
+
standard files (`src/feature/main.tsx` assumed from Vite convention;
|
|
123
|
+
`src/feature/routers/featureRoutePath.ts` invented by prepending the
|
|
124
|
+
parent directory name to the filename; `src/components/utils/classNameMaker.ts`
|
|
125
|
+
fabricated as a plausible-sounding utility). The root cause was
|
|
126
|
+
parallel to the §9 issue: Pass 3's path grounding rules live in
|
|
127
|
+
`pass3-footer.md`, which Pass 4 never reads. Pass 4 was invoking
|
|
128
|
+
prior training knowledge to fabricate concrete paths instead of
|
|
129
|
+
grounding them in `pass3a-facts.md`. v2.3.0 adds `pass3a-facts.md`
|
|
130
|
+
as a mandatory read for Pass 4, plus a dedicated "Path fact
|
|
131
|
+
grounding" CRITICAL section in the prompt with all three flagship
|
|
132
|
+
hallucination anti-patterns documented as explicit ❌ examples.
|
|
133
|
+
The guidance also teaches the positive pattern: when in doubt,
|
|
134
|
+
scope a rule to a directory (`src/admin/api/`) rather than
|
|
135
|
+
inventing a specific filename.
|
|
136
|
+
|
|
137
|
+
Re-running `init` on `backend-java-spring` with the Fix A build proved
|
|
138
|
+
path-grounding works in practice — STALE_PATH dropped from the
|
|
139
|
+
expected 4 to 0 across all Pass 4-generated rule and standard
|
|
140
|
+
files — but left 8 MANIFEST_DRIFT errors in place. Analysis
|
|
141
|
+
traced these to a structural ordering problem, not an LLM
|
|
142
|
+
compliance problem: Pass 3b writes CLAUDE.md Section 6 BEFORE
|
|
143
|
+
Pass 3c generates the skills directory + `MANIFEST.md`. When a
|
|
144
|
+
skill ships as an orchestrator + sub-skills pair — e.g.
|
|
145
|
+
`10.backend-crud/01.scaffold-crud-feature.md` plus eight
|
|
146
|
+
sub-skills under `scaffold-crud-feature/` — Pass 3b cannot
|
|
147
|
+
enumerate the sub-skills because they don't exist yet, and
|
|
148
|
+
forcing it to predict filenames would just move the problem
|
|
149
|
+
into a new form of hallucination (it would write
|
|
150
|
+
`01.entity.md` while Pass 3c emits `01.dto.md`, etc.).
|
|
151
|
+
|
|
152
|
+
The correct design is role-separated: `CLAUDE.md` Section 6 is an
|
|
153
|
+
**entry point** that names categories and orchestrators; `MANIFEST.md`
|
|
154
|
+
is the **authoritative registry** for the full sub-skill list. v2.3.0
|
|
155
|
+
implements both halves of this split:
|
|
156
|
+
|
|
157
|
+
1. `content-validator [10/10]` gains an orchestrator-aware
|
|
158
|
+
exception: a registered sub-skill is suppressed from
|
|
159
|
+
`MANIFEST_DRIFT` when its orchestrator (matching
|
|
160
|
+
`{category}/{*}.{parent-stem}.md`) is referenced anywhere in
|
|
161
|
+
CLAUDE.md. Integrity checks (`STALE_SKILL_ENTRY` for missing
|
|
162
|
+
files, unrelated-parent drift) are preserved.
|
|
163
|
+
|
|
164
|
+
2. `pass3b-core-header.md` gains a "CLAUDE.md Section 6 — Skills
|
|
165
|
+
sub-section (entry point only)" guidance block that tells the
|
|
166
|
+
LLM to list only MANIFEST + orchestrators, never to predict
|
|
167
|
+
sub-skill filenames, and that cites the v2.3.0 validator's
|
|
168
|
+
exception so the instruction and the detection layer remain
|
|
169
|
+
in lockstep.
|
|
170
|
+
|
|
171
|
+
Together, Fix A (Pass 4 path grounding) and Fix B
|
|
172
|
+
(orchestrator/sub-skill exception + §6 guidance) close the last
|
|
173
|
+
two classes of dogfood-observed content-validator errors. The
|
|
174
|
+
remaining validator surface continues to enforce the strict
|
|
175
|
+
invariants — fabricated paths, missing skill files, unrelated-
|
|
176
|
+
parent drift, §9 re-declaration, T1 heading drift, etc. — without
|
|
177
|
+
relaxation.
|
|
178
|
+
|
|
179
|
+
Re-running `init` on `frontend-react-B` with the Fix A + Fix B
|
|
180
|
+
build produced `0 MANIFEST_DRIFT` (Fix B suppressed all 8
|
|
181
|
+
sub-skill drift rows) but left 1 residual `STALE_PATH` in
|
|
182
|
+
`claudeos-core/standard/50.verification/02.testing-strategy.md`
|
|
183
|
+
referencing `src/__mocks__/handlers.ts`. Analysis showed a
|
|
184
|
+
library-convention hallucination class that the original three
|
|
185
|
+
anti-patterns did not cover: testing documents reach for MSW /
|
|
186
|
+
Vitest / Jest / React Testing Library conventional paths even
|
|
187
|
+
when the project has zero test coverage and no such files exist.
|
|
188
|
+
Analogous traps exist for `styling-patterns.md` (global
|
|
189
|
+
stylesheet/theme files) and `state-management.md` (store
|
|
190
|
+
bootstrap files). v2.3.0 adds a "Library-convention hallucination
|
|
191
|
+
class" block to both `pass3-footer.md` and `pass4.md` documenting
|
|
192
|
+
the four concrete MSW/testing anti-patterns plus the three
|
|
193
|
+
trigger document types, and the positive pattern: when
|
|
194
|
+
`pass3a-facts.md` has no concrete test/style/store files listed,
|
|
195
|
+
describe testing/styling/state guidance in abstract terms
|
|
196
|
+
(directory scope or role-based) without naming a specific path.
|
|
197
|
+
|
|
198
|
+
Final validation pass on both dogfood projects with the complete
|
|
199
|
+
v2.3.0 build:
|
|
200
|
+
|
|
201
|
+
- `frontend-react-B` (Korean output, 14 frontend domains,
|
|
202
|
+
dual-entry Vite + React 19, single-SPA admin layout,
|
|
203
|
+
scaffold-page-feature orchestrator with 8 sub-skills):
|
|
204
|
+
**12 errors → 0 errors** (100% improvement), full health
|
|
205
|
+
check green, 25/25 CLAUDE.md lint checks passed.
|
|
206
|
+
- `backend-java-spring` (Korean output, 8 backend domains,
|
|
207
|
+
Java 17 + Spring Boot + MyBatis, scaffold-crud-feature
|
|
208
|
+
orchestrator with 8 sub-skills, multi-dialect DB migration
|
|
209
|
+
in progress): **8 errors → 0 errors** (100% improvement),
|
|
210
|
+
full health check green, complete first-try run in 45m 29s
|
|
211
|
+
including the resume-from-partial-marker code path hitting
|
|
212
|
+
for the first time from a real-world partial Pass 3 run.
|
|
213
|
+
|
|
214
|
+
Both projects exercise distinct v2.3.0 code paths (Fix A + Fix B,
|
|
215
|
+
single-SPA rule, Pass 3 resume, library-convention anti-pattern,
|
|
216
|
+
orchestrator/sub-skill exception), and both settled at 0 errors
|
|
217
|
+
without any manual file edits to the generated output. This is
|
|
218
|
+
the first release where the full end-to-end pipeline produces a
|
|
219
|
+
clean `content-validator [10/10]` report on real-world sibling
|
|
220
|
+
Korean projects — the core criterion for v2.3.0 being
|
|
221
|
+
publish-ready.
|
|
222
|
+
|
|
223
|
+
### Added
|
|
224
|
+
|
|
225
|
+
- **`claude-md-validator/`** (new package, ~430 lines across 3 files).
|
|
226
|
+
Post-generation structural validator for `CLAUDE.md`. Every check uses
|
|
227
|
+
only signals that survive translation:
|
|
228
|
+
- **Markdown syntax**: `^## `, `^### `, `^#### `, `^```` — not localized.
|
|
229
|
+
- **Literal file names**: `decision-log.md`, `failure-patterns.md`,
|
|
230
|
+
`compaction.md`, `auto-rule-update.md` — never translated.
|
|
231
|
+
- **Counts and table-row positions**: section count, sub-section count
|
|
232
|
+
per section, memory-file table-row count inside vs outside Section 8.
|
|
233
|
+
The same validator, byte-for-byte, produces identical verdicts on a
|
|
234
|
+
`CLAUDE.md` generated in English, Korean, Japanese, Vietnamese, Hindi,
|
|
235
|
+
Russian, etc. — proven by cross-language bad-case fixtures in the test
|
|
236
|
+
suite.
|
|
237
|
+
- `structural-checks.js` — individual check functions (`checkH2Count`,
|
|
238
|
+
`checkH3Counts`, `checkH4Counts`, `checkMemoryFileUniqueness`,
|
|
239
|
+
`checkMemoryScopedToSection8`, `checkSectionsHaveContent`,
|
|
240
|
+
`checkCanonicalHeadings`) plus a fence-aware section splitter
|
|
241
|
+
(`splitByH2`) that correctly ignores `##` lines inside ``` and
|
|
242
|
+
`~~~` code blocks.
|
|
243
|
+
- `index.js` — high-level `validate(path)` API and standalone CLI entry.
|
|
244
|
+
Transparently strips a leading UTF-8 BOM (U+FEFF) from the input
|
|
245
|
+
before running checks, so CLAUDE.md files written by Windows editors
|
|
246
|
+
or cross-platform generators validate identically to those without
|
|
247
|
+
a BOM (otherwise the first `## ` reads as `\ufeff## ` and silently
|
|
248
|
+
under-counts by one).
|
|
249
|
+
- `reporter.js` — human-readable report formatter with remediation
|
|
250
|
+
guidance for every failure class.
|
|
251
|
+
|
|
252
|
+
- **`npx claudeos-core lint`** command. Runs the structural validator
|
|
253
|
+
against `CLAUDE.md` at the project root. Exit code 0 on pass, 1 on fail
|
|
254
|
+
— suitable for CI pipelines. The command renders per-failure remediation
|
|
255
|
+
guidance so users can fix issues directly without re-running the full
|
|
256
|
+
4-Pass pipeline.
|
|
257
|
+
|
|
258
|
+
- **`bin/commands/lint.js`** (new). Wraps the validator for CLI use;
|
|
259
|
+
delegates to `claude-md-validator/` so the validator remains usable
|
|
260
|
+
as a library from other contexts (future `init` auto-lint, CI action,
|
|
261
|
+
etc.).
|
|
262
|
+
|
|
263
|
+
- **T1 — Canonical heading invariant (cross-repo title determinism).**
|
|
264
|
+
Each of the 8 `## N.` section headings in every generated `CLAUDE.md`
|
|
265
|
+
must contain the English canonical token for that section, regardless
|
|
266
|
+
of the `--lang` output language. A native-language translation may be
|
|
267
|
+
appended in parentheses but MUST NOT replace the English canonical as
|
|
268
|
+
primary text. Required tokens:
|
|
269
|
+
`§1=Role Definition, §2=Project Overview, §3=Build, §4=Core Architecture,
|
|
270
|
+
§5=Directory Structure, §6=Standard, §7=DO NOT Read, §8=Memory`.
|
|
271
|
+
The validator enforces this via `checkCanonicalHeadings` (IDs `T1-1`
|
|
272
|
+
through `T1-8`), and the scaffold documents it as a mandatory format
|
|
273
|
+
rule reinforced by Pass 3 POST-GEN CHECK step 4b. This closes a
|
|
274
|
+
multi-repo discoverability gap discovered during `frontend-react-B`
|
|
275
|
+
dogfooding: sibling projects generated §7 as `"DO NOT Read (직접 읽지
|
|
276
|
+
말아야 할 파일)"` and `"읽지 말 것 (Files Not to Be Read Directly)"`
|
|
277
|
+
respectively — both "equivalent in meaning" but breaking
|
|
278
|
+
`grep "## 7. DO NOT Read"` across the organization's repos.
|
|
279
|
+
|
|
280
|
+
- **`content-validator [10/10]` — path-claim + MANIFEST drift.**
|
|
281
|
+
A new check appended to the existing 9-stage validator in
|
|
282
|
+
`content-validator/index.js`. Single check, two failure classes:
|
|
283
|
+
- **`STALE_PATH`** — any `src/...\.(ts|tsx|js|jsx)` reference
|
|
284
|
+
appearing in `.claude/rules/**/*.md` or
|
|
285
|
+
`claudeos-core/standard/**/*.md` must resolve to a real file on
|
|
286
|
+
disk. Fenced code blocks (``` and ~~~) and placeholder paths
|
|
287
|
+
(`src/{domain}/feature.ts`) are excluded, matching the scaffold
|
|
288
|
+
convention that placeholders stand for scaffold examples, not
|
|
289
|
+
actual project paths.
|
|
290
|
+
- **`STALE_SKILL_ENTRY`** — every skill path registered in
|
|
291
|
+
`claudeos-core/skills/00.shared/MANIFEST.md` (extracted from
|
|
292
|
+
backticked `claudeos-core/skills/...` references) must exist on
|
|
293
|
+
disk. `MANIFEST.md` itself is excluded from the set to avoid
|
|
294
|
+
self-reference false positives.
|
|
295
|
+
- **`MANIFEST_DRIFT`** — every skill registered in MANIFEST must be
|
|
296
|
+
mentioned somewhere in CLAUDE.md. The check looks at the whole
|
|
297
|
+
body (not just §6 Skills) to avoid depending on sub-section
|
|
298
|
+
heading wording, which varies by output language.
|
|
299
|
+
The check is intentionally language-invariant: it uses literal
|
|
300
|
+
file-path patterns and file-system existence, never parsing section
|
|
301
|
+
headings or reasoning about Korean/Japanese/etc. text.
|
|
302
|
+
|
|
303
|
+
- **`bin/commands/init.js` — Guard 4 (non-blocking).** After Pass 4 and
|
|
304
|
+
structural lint, init runs `content-validator` in a child process
|
|
305
|
+
and surfaces the summary inline. If drift is detected, init prints a
|
|
306
|
+
pointer to `stale-report.json` and the standalone command to re-run
|
|
307
|
+
— but does NOT throw, unset `pass3-complete.json`, or abort the run.
|
|
308
|
+
This is a deliberate choice: LLM hallucinations may not be
|
|
309
|
+
deterministically fixable by re-running Pass 3, so a blocking guard
|
|
310
|
+
would deadlock users in an `init --force` loop. The detection signal
|
|
311
|
+
(non-zero `content-validator` exit code + stale-report entry) is
|
|
312
|
+
sufficient for CI pipelines and human triage.
|
|
313
|
+
|
|
314
|
+
- **`pass-prompts/templates/common/pass3-footer.md` — Path fact
|
|
315
|
+
grounding (MANDATORY).** Two new CRITICAL blocks added:
|
|
316
|
+
- The parent-directory prefix anti-pattern (the exact
|
|
317
|
+
`featureRoutePath.ts` case from frontend-react-B dogfooding) is
|
|
318
|
+
documented with ✅/❌ examples and explanation of *why* the LLM
|
|
319
|
+
mis-infers (TypeScript identifier name vs filename are
|
|
320
|
+
independent — the constant `FEATURE_ROUTE_PATH` does not imply
|
|
321
|
+
filename `featureRoutePath.ts`).
|
|
322
|
+
- The MANIFEST ↔ CLAUDE.md §6 symmetry rule is stated explicitly,
|
|
323
|
+
with post-generation enforcement noted (`content-validator [10/10]
|
|
324
|
+
→ MANIFEST_DRIFT`).
|
|
325
|
+
|
|
326
|
+
- **`plan-installer/scanners/scan-frontend.js` — Single-SPA detection
|
|
327
|
+
rule.** The subapp scanner was designed for dual-platform layouts
|
|
328
|
+
(same subapp implemented for two platforms, e.g., `src/pc/admin/`
|
|
329
|
+
+ `src/mobile/admin/` → `pc-admin`, `mobile-admin`). When applied
|
|
330
|
+
to a single-SPA project (only one platform keyword matches, as in
|
|
331
|
+
`frontend-react-B`'s `src/admin/...`), the scanner misinterpreted the
|
|
332
|
+
SPA's architectural layers (`api`, `context`, `dto`, `routers`) as
|
|
333
|
+
subapps and emitted them as pseudo-domains — both cluttering the
|
|
334
|
+
domain plan and priming Pass 3 toward filename hallucinations with
|
|
335
|
+
the platform-name prefix.
|
|
336
|
+
- **New behavior**: before the subapp-emission loop, count the
|
|
337
|
+
number of distinct platform keywords present in the project.
|
|
338
|
+
When the count is ≤ 1, skip subapp emission entirely and let
|
|
339
|
+
downstream scanners (pages, FSD, components, fallback) identify
|
|
340
|
+
real feature domains within the single SPA.
|
|
341
|
+
- **Opt-out**: `.claudeos-scan.json` accepts a new override
|
|
342
|
+
`frontendScan.forceSubappSplit: true` to restore the legacy
|
|
343
|
+
single-platform emission for projects that genuinely treat the
|
|
344
|
+
lone platform's children as feature domains.
|
|
345
|
+
- **No change to multi-platform behavior**: two or more distinct
|
|
346
|
+
platform keywords (e.g., `pc` + `mobile`) trigger subapp
|
|
347
|
+
emission exactly as before.
|
|
348
|
+
|
|
349
|
+
- **`bin/commands/init.js` — Pass 3 split-partial resume fix.** The
|
|
350
|
+
orchestrator previously decided whether to invoke `runPass3Split`
|
|
351
|
+
by checking only `fileExists(pass3-complete.json)`. Any existing
|
|
352
|
+
marker — including partial markers from a prior run's timeout —
|
|
353
|
+
fell into the "skip" branch, causing the remaining Pass 3 stages
|
|
354
|
+
to never execute on re-run. The detection block at the top of
|
|
355
|
+
that function already identified partial markers and logged
|
|
356
|
+
"runPass3Split will resume" but the actual call was gated by the
|
|
357
|
+
broken check, so the log was misleading.
|
|
358
|
+
- Now the orchestrator inspects the marker body: if
|
|
359
|
+
`mode === "split"` and `completedAt` is absent, `runPass3Split`
|
|
360
|
+
is invoked and its existing `groupsCompleted` tracking resumes
|
|
361
|
+
from the next unstarted stage. Only markers with `completedAt`
|
|
362
|
+
set are skipped.
|
|
363
|
+
- This repairs the dogfood case where Pass 3d-aux timed out
|
|
364
|
+
mid-stream on `backend-java-spring`: on the next `init`, stages 3a-3c
|
|
365
|
+
were correctly preserved but 3d-aux was silently skipped,
|
|
366
|
+
leaving `claudeos-core/database/` and `claudeos-core/mcp-guide/`
|
|
367
|
+
empty and the marker stuck in partial shape.
|
|
368
|
+
|
|
369
|
+
- **`tests/pass3-marker.test.js` — 6 new regression tests** covering
|
|
370
|
+
the resume-decision classification function: absent marker → fresh
|
|
371
|
+
run; split-partial (no `completedAt`) → resume; fully completed →
|
|
372
|
+
skip; empty `groupsCompleted` still counts as partial; malformed
|
|
373
|
+
JSON → safe skip; non-split mode → skip.
|
|
374
|
+
|
|
375
|
+
- **Pass 4 CLAUDE.md append retirement.** Changes span three files:
|
|
376
|
+
- `pass-prompts/templates/common/pass4.md` — the "Append a new
|
|
377
|
+
section to existing `CLAUDE.md`" instruction block is removed
|
|
378
|
+
wholesale and replaced with a mandatory prohibition block
|
|
379
|
+
("CLAUDE.md MUST NOT BE MODIFIED") that names the exact
|
|
380
|
+
validator errors ([S1], [M-*], [F2-*]) that this prohibition
|
|
381
|
+
prevents, and explains that Section 8 in Pass 3's output is the
|
|
382
|
+
single canonical home for the Common Rules table and the L4
|
|
383
|
+
Memory table/workflow. The remaining output sections are
|
|
384
|
+
renumbered (section 12 → 11). The Output Discipline section
|
|
385
|
+
loses its "Do NOT overwrite CLAUDE.md content — **append only**"
|
|
386
|
+
bullet, which is replaced with "Do NOT touch CLAUDE.md."
|
|
387
|
+
- `bin/commands/init.js` — the two call sites of
|
|
388
|
+
`appendClaudeMdL4Memory()` (inside `applyStaticFallback()` and
|
|
389
|
+
inside the Pass 4 gap-fill path) are removed. The
|
|
390
|
+
`gapResults` reporting no longer includes a `CLAUDE.md#(L4)`
|
|
391
|
+
entry. The `require` destructure drops the function.
|
|
392
|
+
- `lib/memory-scaffold.js` — `appendClaudeMdL4Memory()` is
|
|
393
|
+
converted to a 3-line no-op that returns `true`
|
|
394
|
+
unconditionally. The function's public signature, name, and
|
|
395
|
+
module export are preserved so any external caller continues
|
|
396
|
+
to work; an extensive deprecation comment documents why the
|
|
397
|
+
behavior was retired and points at the validator errors it
|
|
398
|
+
was causing. The `CLAUDE_MD_APPEND` template constant is left
|
|
399
|
+
exported for test compatibility but is now unreferenced by
|
|
400
|
+
production code.
|
|
401
|
+
This fix closes the final regression surfaced by end-to-end
|
|
402
|
+
dogfooding on `frontend-react-B`: the validator was correctly
|
|
403
|
+
reporting an `S1` (9 sections) and four `M-*`/`F2-*` errors
|
|
404
|
+
against a `CLAUDE.md` whose second memory table had been
|
|
405
|
+
appended by Pass 4, not written by Pass 3. The fix keeps the
|
|
406
|
+
validator strict and removes the duplication at its source.
|
|
407
|
+
|
|
408
|
+
- **`tests/pass4-claude-md-untouched.test.js`** (new, 5 tests). A
|
|
409
|
+
dedicated suite guarding the retirement against regression. Tests
|
|
410
|
+
cover: the `pass4.md` prompt no longer contains the "Append a new
|
|
411
|
+
section" instruction and DOES contain the "MUST NOT BE MODIFIED"
|
|
412
|
+
prohibition; `init.js` neither imports nor calls
|
|
413
|
+
`appendClaudeMdL4Memory`; the retired function's contract (always
|
|
414
|
+
returns `true`, never mutates `CLAUDE.md`) holds under happy path,
|
|
415
|
+
missing-file, and empty/structured-input variants.
|
|
416
|
+
Complementary updates: 8 legacy `appendClaudeMdL4Memory` tests in
|
|
417
|
+
`tests/memory-scaffold.test.js` are consolidated into a single
|
|
418
|
+
retirement contract test; 3 lang-aware tests in
|
|
419
|
+
`tests/lang-aware-fallback.test.js` are rewritten to verify the
|
|
420
|
+
lang-invariant no-op semantics; one `generatePrompts` test in
|
|
421
|
+
`tests/pass4-prompt.test.js` is flipped from "prompt contains
|
|
422
|
+
CLAUDE.md append instructions" to "prompt contains the
|
|
423
|
+
prohibition and does NOT contain the legacy append header".
|
|
424
|
+
|
|
425
|
+
- **Pass 4 path fact grounding (MANDATORY).** `pass4.md` now includes
|
|
426
|
+
`pass3a-facts.md` in its required-reads list at the top of the
|
|
427
|
+
prompt (previously only `project-analysis.json` and
|
|
428
|
+
`pass2-merged.json` were listed), and adds a full `## CRITICAL —
|
|
429
|
+
Path fact grounding (MANDATORY)` section below the header. The
|
|
430
|
+
section states the rule first — every `src/...` path written in a
|
|
431
|
+
rule or standard file must appear verbatim in `pass3a-facts.md` or
|
|
432
|
+
`pass2-merged.json` — then documents the three flagship
|
|
433
|
+
hallucination anti-patterns observed in `frontend-react-B`
|
|
434
|
+
dogfooding: Vite-convention assumption (`src/feature/main.tsx`),
|
|
435
|
+
parent-directory prefix (`src/feature/routers/featureRoutePath.ts`),
|
|
436
|
+
and plausible-but-unverified utility (`src/components/utils/classNameMaker.ts`).
|
|
437
|
+
Each anti-pattern is accompanied by the concrete mechanism that
|
|
438
|
+
caused it ("invented based on Vite's stock convention";
|
|
439
|
+
"prepending the parent directory name to the filename"; etc.) so
|
|
440
|
+
the LLM sees both the output to avoid and the reasoning to avoid.
|
|
441
|
+
The positive pattern — "when in doubt, scope a rule to a
|
|
442
|
+
directory (`src/admin/api/`) rather than inventing a filename" —
|
|
443
|
+
is documented explicitly, and the section cross-references the
|
|
444
|
+
downstream enforcement (`content-validator [10/10]` →
|
|
445
|
+
`STALE_PATH`) so the LLM understands the validator will reject
|
|
446
|
+
fabricated paths. Guarded in tests by a new `generatePrompts`
|
|
447
|
+
assertion that all three anti-patterns, the MANDATORY tag, the
|
|
448
|
+
positive pattern, and the validator cross-reference are present
|
|
449
|
+
in the rendered pass4 prompt.
|
|
450
|
+
|
|
451
|
+
- **Orchestrator/sub-skill MANIFEST-drift exception.** Changes
|
|
452
|
+
span two files:
|
|
453
|
+
- `content-validator/index.js` — Stage 2 of the MANIFEST drift
|
|
454
|
+
check (MANIFEST ↔ CLAUDE.md cross-reference) now recognizes
|
|
455
|
+
the orchestrator/sub-skill layout pattern. A registered skill
|
|
456
|
+
whose path matches
|
|
457
|
+
`claudeos-core/skills/{category}/{parent-stem}/{NN}.{name}.md`
|
|
458
|
+
is considered covered when CLAUDE.md mentions an orchestrator
|
|
459
|
+
file anywhere under the same `{category}/` whose basename
|
|
460
|
+
(minus any leading `NN.`) equals `{parent-stem}`. The
|
|
461
|
+
exception is scoped narrowly: it applies ONLY to
|
|
462
|
+
`MANIFEST_DRIFT`, and ONLY to sub-skills under a confirmed
|
|
463
|
+
orchestrator match. Integrity checks continue to fire at full
|
|
464
|
+
strength — `STALE_SKILL_ENTRY` for registered sub-skills
|
|
465
|
+
whose files are missing from disk, and `MANIFEST_DRIFT` for
|
|
466
|
+
standalone skills (sub-skill paths whose parent stem does not
|
|
467
|
+
match any referenced orchestrator).
|
|
468
|
+
- `pass-prompts/templates/common/pass3b-core-header.md` — a new
|
|
469
|
+
"CLAUDE.md Section 6 — Skills sub-section (entry point only)"
|
|
470
|
+
block tells Pass 3b to list only `MANIFEST.md` plus
|
|
471
|
+
orchestrator files in Section 6, never to predict sub-skill
|
|
472
|
+
filenames (which don't exist yet at Pass 3b time because
|
|
473
|
+
Pass 3c hasn't run). The guidance explains both failure modes
|
|
474
|
+
— hallucinated filenames and silent staleness — and cites the
|
|
475
|
+
`content-validator` exception so the prompt-side and detector-
|
|
476
|
+
side are consistent.
|
|
477
|
+
This fix closes the final class of dogfood-observed errors on
|
|
478
|
+
`backend-java-spring` (8 MANIFEST_DRIFT rows, all for
|
|
479
|
+
`scaffold-crud-feature/0N.*.md` sub-skills) and the equivalent
|
|
480
|
+
shape on `frontend-react-B` (8 rows under
|
|
481
|
+
`scaffold-page-feature/0N.*.md`). The structural
|
|
482
|
+
`CLAUDE.md §6 = entry, MANIFEST = registry` split also
|
|
483
|
+
eliminates the recurring regeneration churn where adding or
|
|
484
|
+
renaming a sub-skill in Pass 3c would otherwise have required
|
|
485
|
+
CLAUDE.md to be rewritten.
|
|
486
|
+
|
|
487
|
+
- **`tests/content-validator.test.js` — 5 new orchestrator/sub-skill
|
|
488
|
+
exception tests.** Coverage: (1) orchestrator mentioned +
|
|
489
|
+
sub-skills registered → 0 drift (backend-java-spring replica);
|
|
490
|
+
(2) orchestrator mentioned + one sub-skill file deleted → still
|
|
491
|
+
emits 1 `STALE_SKILL_ENTRY` (integrity not suppressed);
|
|
492
|
+
(3) orchestrator NOT mentioned → all 5 registered skills drift
|
|
493
|
+
(control case — exception requires orchestrator reference);
|
|
494
|
+
(4) sub-skill under a parent stem that does NOT match any
|
|
495
|
+
referenced orchestrator → still drifts (guard against
|
|
496
|
+
over-exception); (5) sibling layout — a standalone "playground"
|
|
497
|
+
skill, not a sub-skill of the referenced orchestrator — still
|
|
498
|
+
drifts (guard against conflating one-level-deep standalone
|
|
499
|
+
skills with sub-skills).
|
|
500
|
+
|
|
501
|
+
- **Library-convention hallucination class (MSW / Vitest / Jest /
|
|
502
|
+
RTL hotfix).** Extends the Fix A anti-pattern block in
|
|
503
|
+
`pass4.md` and mirrors the same guidance into `pass3-footer.md`
|
|
504
|
+
so Pass 3b and Pass 4 both observe the same rule when they
|
|
505
|
+
generate `testing-strategy.md`, `styling-patterns.md`, or
|
|
506
|
+
`state-management.md`. The block documents four concrete
|
|
507
|
+
library-convention traps — `src/__mocks__/handlers.ts`,
|
|
508
|
+
`src/test/setup.ts`, `src/test-utils.tsx`, `src/setupTests.ts` —
|
|
509
|
+
and explicitly names the three trigger document types that
|
|
510
|
+
most often produce this class of hallucination. The positive
|
|
511
|
+
rule: if `pass3a-facts.md` has no concrete test/style/store
|
|
512
|
+
file listed, describe guidance by role (a shared setup module
|
|
513
|
+
under a test directory of your choice) rather than by name,
|
|
514
|
+
and defer concrete paths until the files actually exist.
|
|
515
|
+
Regression-guarded by expanded assertions in
|
|
516
|
+
`tests/pass4-prompt.test.js` that verify all four MSW/testing
|
|
517
|
+
anti-patterns, the library-ecosystem naming, the
|
|
518
|
+
testing-specific positive pattern, and the
|
|
519
|
+
pass3a-facts.md-based negation ("these paths do not exist")
|
|
520
|
+
are all present in the rendered prompt.
|
|
521
|
+
|
|
522
|
+
- **`tests/content-validator.test.js`** (new, ~270 lines). 10
|
|
523
|
+
regression tests across 3 describe blocks:
|
|
524
|
+
- Path-claim positive and negative cases (hallucination detected;
|
|
525
|
+
fenced examples, placeholders, and existing paths do not trigger).
|
|
526
|
+
- MANIFEST drift scenarios (stale entry, drift, referenced skill,
|
|
527
|
+
self-reference exclusion, absent MANIFEST).
|
|
528
|
+
- Full frontend-react-B simulation: 2 STALE_PATH + 2 STALE_SKILL_ENTRY
|
|
529
|
+
+ 3 MANIFEST_DRIFT, asserted with exact counts to prevent silent
|
|
530
|
+
regression as the validator evolves.
|
|
531
|
+
|
|
532
|
+
- **`tests/claude-md-validator.test.js`** — structural invariant tests
|
|
533
|
+
parameterized across all 10 supported output languages. Coverage includes:
|
|
534
|
+
valid fixtures for each `--lang` code; bad fixtures in 6 languages
|
|
535
|
+
demonstrating identical error signatures (§9 anti-pattern detected
|
|
536
|
+
byte-for-byte the same regardless of script); fence-aware section
|
|
537
|
+
splitting against both ``` and ~~~ fences; table-row vs prose-mention
|
|
538
|
+
disambiguation; file-not-found handling; and T1 title-determinism
|
|
539
|
+
coverage (scaffold/validator token alignment, English-only acceptance,
|
|
540
|
+
anti-pattern rejection, case-insensitivity, graceful skip when section
|
|
541
|
+
count is wrong).
|
|
542
|
+
|
|
543
|
+
- **Language-independence proof fixtures** under `tests/fixtures/claude-md/`
|
|
544
|
+
covering all 10 supported output languages:
|
|
545
|
+
- Valid fixtures (same 8-section structure, different languages, all
|
|
546
|
+
following the T1 canonical-heading format `## N. <English canonical>
|
|
547
|
+
(<translation>)`): `valid-en.md`, `valid-ja.md`, `valid-zh-CN.md`,
|
|
548
|
+
`valid-es.md`, `valid-vi.md`, `valid-hi.md`, `valid-ru.md`,
|
|
549
|
+
`valid-fr.md`, `valid-de.md`, plus `frontend-react-A-fixed.md`
|
|
550
|
+
(Korean, real dogfooding case with §9 removed and headings
|
|
551
|
+
retrofitted to T1 format). Each passes the same 25 structural
|
|
552
|
+
checks — empirical proof of language invariance across CJK,
|
|
553
|
+
Cyrillic, Devanagari, Latin, and Vietnamese scripts.
|
|
554
|
+
- Bad fixtures (same valid structure + §9 memory re-declaration
|
|
555
|
+
appended): `frontend-react-A-bad.md` (Korean, real), `bad-ja.md`,
|
|
556
|
+
`bad-zh-CN.md`, `bad-ru.md`, `bad-hi.md`, `bad-es.md`. All six
|
|
557
|
+
produce a **byte-for-byte identical 9-error signature**
|
|
558
|
+
(1 S1 + 4 M-* + 4 F2-*), confirming the validator detects the
|
|
559
|
+
same anti-pattern independently of output language and script.
|
|
560
|
+
|
|
561
|
+
### Changed
|
|
562
|
+
|
|
563
|
+
- **`bin/cli.js`** — registers the `lint` command, help text updated,
|
|
564
|
+
examples include the new command.
|
|
565
|
+
|
|
566
|
+
- **`bin/commands/init.js`** — automatically invokes the structural
|
|
567
|
+
validator after Pass 4 completes. Failures are reported inline but
|
|
568
|
+
do NOT abort the run; the generated content is preserved and the
|
|
569
|
+
user is pointed at `npx claudeos-core lint` for full remediation
|
|
570
|
+
guidance or `init --force` for regeneration. This design choice
|
|
571
|
+
follows Rule B (idempotency): lint is informational at install time,
|
|
572
|
+
advisory at lint time, blocking only in CI contexts.
|
|
573
|
+
|
|
574
|
+
- **`package.json`**:
|
|
575
|
+
- `version` → 2.3.0.
|
|
576
|
+
- `files` includes `claude-md-validator/` so the module ships with
|
|
577
|
+
the npm package.
|
|
578
|
+
- `scripts.lint` convenience alias for `node bin/cli.js lint`.
|
|
579
|
+
- `scripts.test` pattern updated to `node --test tests/*.test.js`
|
|
580
|
+
(was the bare directory form, which fails on Node 22+).
|
|
581
|
+
|
|
582
|
+
### Prevention layer (prompt-time improvements)
|
|
583
|
+
|
|
584
|
+
Detection alone (the validator above) catches §9 after it is already
|
|
585
|
+
written. v2.3.0 also reduces the probability that LLMs write §9 in the
|
|
586
|
+
first place, by reshaping the Pass 3 prompt so the structural signal is
|
|
587
|
+
less ambiguous. These changes are complementary to the validator: the
|
|
588
|
+
validator is the guaranteed safety net, the prompt improvements lower
|
|
589
|
+
how often that net is needed.
|
|
590
|
+
|
|
591
|
+
- **`plan-installer/prompt-generator.js`** — `demoteScaffoldMetaHeaders()`
|
|
592
|
+
utility added. When embedding `claude-md-scaffold.md` into the Pass 3
|
|
593
|
+
prompt, scaffold meta-section headings (`## Why this scaffold exists`,
|
|
594
|
+
`## Hard constraints`, `## Per-section generation rules`,
|
|
595
|
+
`## Validation checks`, `## Examples`, `## Usage from pass3 prompts`,
|
|
596
|
+
etc.) are demoted from `##` to `###`. The demotion is code-block-aware:
|
|
597
|
+
`##` lines inside ``` or ~~~ fences are preserved so the scaffold's
|
|
598
|
+
Template structure example (`## 1. Role Definition` ... `## 8. Common
|
|
599
|
+
Rules & Memory (L4)`) remains intact.
|
|
600
|
+
|
|
601
|
+
Rationale: a pre-v2.3.0 Pass 3 prompt contained **40+ `##` headings**
|
|
602
|
+
(scaffold meta + footer sections + phase instructions + 8 canonical
|
|
603
|
+
example headings). The LLM, tasked with writing a CLAUDE.md whose
|
|
604
|
+
target structure has exactly 8 `##` sections, was pattern-matching
|
|
605
|
+
against a prompt that modeled `##` as a very common structural unit —
|
|
606
|
+
an implicit signal that extra `##` sections were natural. After
|
|
607
|
+
demotion the Pass 3 prompt contains approximately 12 `##` headings,
|
|
608
|
+
of which **exactly 8 are the scaffold's canonical target inside the
|
|
609
|
+
fenced Template example**. The LLM now sees "the ## level is used for
|
|
610
|
+
exactly 8 things in this prompt, and those 8 things are the sections
|
|
611
|
+
I must write" — a far cleaner mapping between prompt structure and
|
|
612
|
+
desired output structure.
|
|
613
|
+
|
|
614
|
+
- **`pass-prompts/templates/common/pass3-footer.md`** —
|
|
615
|
+
`POST-GENERATION CHECK` block rewritten as an imperative 5-STEP
|
|
616
|
+
procedure (count → assert → repair → verify → external validation),
|
|
617
|
+
with `LANGUAGE-INVARIANT and TITLE-INVARIANT` explicitly named as
|
|
618
|
+
a core property. The repair step supplies a concrete action matrix
|
|
619
|
+
keyed to the surplus section's content type (memory-file references →
|
|
620
|
+
DELETE; rule-summary content → MERGE into Section 8 sub-section 1;
|
|
621
|
+
procedural/enforcement content → MOVE to `.claude/rules/*`). STEP 5
|
|
622
|
+
announces the v2.3.0+ external validator as a safety net while
|
|
623
|
+
clarifying the LLM should not rely on it — structure must be correct
|
|
624
|
+
at write time.
|
|
625
|
+
|
|
626
|
+
- **`pass-prompts/templates/common/pass3-footer.md`** — FORBIDDEN
|
|
627
|
+
`##`-level section list rewritten to stop depending on an English-
|
|
628
|
+
label blocklist. The new framing states the RULE first (no `##` may
|
|
629
|
+
have a title whose semantic category is "rules", "memory", "L4",
|
|
630
|
+
"guardrails", or any rephrasing), then gives concrete **translated
|
|
631
|
+
examples in Korean, Japanese, and Chinese** (`메모리 (L4)`,
|
|
632
|
+
`メモリ (L4)`, `记忆层 (L4)`, and analogues for Common Rules). The
|
|
633
|
+
goal is to make the LLM's translation decision explicit: it must
|
|
634
|
+
apply the forbidden rule to its translated heading, not just the
|
|
635
|
+
English original. A DECISION RULE block at the end gives a 3-step
|
|
636
|
+
check the LLM runs before writing any `##` heading.
|
|
637
|
+
|
|
638
|
+
- **`pass-prompts/templates/common/claude-md-scaffold.md`** — the
|
|
639
|
+
"L4 Memory Files (Re-declaration)" anti-pattern reference (which,
|
|
640
|
+
by naming the anti-pattern explicitly, paradoxically risked priming
|
|
641
|
+
the LLM to reproduce it — a "pink elephant" failure mode) was
|
|
642
|
+
replaced with a positively-phrased "Section 8 single-occurrence
|
|
643
|
+
rule": the L4 Memory Files table, Memory Workflow, and Common Rules
|
|
644
|
+
meta-summary table each appear EXACTLY ONCE, with their canonical
|
|
645
|
+
home named explicitly. Two `no "Re-declaration" duplicate` phrases
|
|
646
|
+
in the validation checklist were similarly simplified to
|
|
647
|
+
`appear EXACTLY ONCE in the whole document`.
|
|
648
|
+
|
|
649
|
+
- **`tests/prompt-generator.test.js`** — 3 new tests covering the
|
|
650
|
+
demotion utility:
|
|
651
|
+
- Meta-section `##` headers outside fences are demoted to `###`
|
|
652
|
+
- `##` headers inside ``` and ~~~ fenced blocks are preserved
|
|
653
|
+
- Real scaffold embedded into real pass3-prompt produces < 25 `##`
|
|
654
|
+
headings total and preserves all 8 canonical example sections.
|
|
655
|
+
|
|
656
|
+
- **`tests/claude-md-validator.test.js`** — parameterized across all
|
|
657
|
+
10 supported languages. 10 valid-fixture tests (one per `--lang` code)
|
|
658
|
+
plus 5 bad-fixture tests (ko/ja/zh-CN/ru/hi/es each asserting the
|
|
659
|
+
identical 9-error signature).
|
|
660
|
+
|
|
661
|
+
Total tests: **662. All pass.**
|
|
662
|
+
(v2.2.0 baseline 602 + v2.3.0 net additions 60 = 662. The "net"
|
|
663
|
+
accounting reflects that 8 legacy `appendClaudeMdL4Memory` behavior
|
|
664
|
+
tests were consolidated into a single no-op contract test when that
|
|
665
|
+
function was retired; the full set of new tests added across v2.3.0
|
|
666
|
+
totals 68 across path-claim verification, single-SPA scanner,
|
|
667
|
+
Pass 3 resume classification, Pass 4 CLAUDE.md immutability,
|
|
668
|
+
Pass 4 path fact grounding, and the orchestrator/sub-skill
|
|
669
|
+
MANIFEST-drift exception.)
|
|
670
|
+
|
|
671
|
+
### Why this matters
|
|
672
|
+
|
|
673
|
+
The §9 re-declaration anti-pattern was the flagship problem v2.2.0 aimed
|
|
674
|
+
to solve, and the scaffold + prompt-level blocklist reduced incidence
|
|
675
|
+
substantially. Dogfooding on a real Korean-output project produced a
|
|
676
|
+
`CLAUDE.md` with `## 9. 메모리 (L4)` anyway — the LLM successfully matched
|
|
677
|
+
`## 8. 공통 규칙 및 메모리 (L4)` as its Section 8, then created a §9
|
|
678
|
+
section whose title (`메모리 (L4)`) was not semantically recognized as
|
|
679
|
+
equivalent to the blocklisted English `"Memory Layer (L4)"`.
|
|
680
|
+
|
|
681
|
+
Extending the fix by maintaining per-language blocklists would create
|
|
682
|
+
unbounded maintenance surface: 10 supported languages × 6-8 forbidden
|
|
683
|
+
labels × every future phrasing variant. Each new language addition
|
|
684
|
+
would require re-auditing the entire translation table. Each miss
|
|
685
|
+
re-introduces the bug.
|
|
686
|
+
|
|
687
|
+
The v2.3.0 approach sidesteps this entirely. A post-generation code-level
|
|
688
|
+
validator that reasons about markdown syntax and literal file names does
|
|
689
|
+
not need a per-language dictionary. The same 22 checks run identically on
|
|
690
|
+
Korean, Japanese, English, or any future language added to the `--lang`
|
|
691
|
+
flag. Proof: the validator produces a byte-for-byte identical 9-error
|
|
692
|
+
signature when applied to synthesized Japanese §9 and the actual Korean
|
|
693
|
+
§9 that triggered this investigation. See the fixtures for reproducible
|
|
694
|
+
evidence.
|
|
695
|
+
|
|
696
|
+
This also aligns the final Pass of the pipeline with claudeos-core's core
|
|
697
|
+
principle **"LLMs guess, code confirms"**. Earlier passes already enforce
|
|
698
|
+
this: stack-detector confirms LLM-guessed ports via `.env.example` parsing
|
|
699
|
+
(v2.2.0), pass2-merged.json grounds the stack facts in real files (v2.0).
|
|
700
|
+
Pass 3/4 output structure was the remaining gap — LLM generates it, and
|
|
701
|
+
no code confirmed the result. v2.3.0 closes that gap without sacrificing
|
|
702
|
+
Pass 3/4's generative flexibility: LLM still writes content; code now
|
|
703
|
+
confirms the structural invariants hold.
|
|
704
|
+
|
|
705
|
+
v2.3.0 ships both a detection layer (the validator) and a prevention
|
|
706
|
+
layer (the prompt-time improvements listed under "Prevention layer"
|
|
707
|
+
above). The prevention layer reshapes the Pass 3 prompt so the LLM
|
|
708
|
+
sees a cleaner mapping between prompt structure and target output
|
|
709
|
+
structure — primarily by demoting scaffold meta-section `##` headers
|
|
710
|
+
to `###` when embedded, cutting the prompt's total `##` count from
|
|
711
|
+
40+ down to about 12, of which exactly 8 are the canonical section
|
|
712
|
+
examples the LLM must reproduce. This does not eliminate structural
|
|
713
|
+
drift (LLM output is probabilistic), but it reduces the rate at which
|
|
714
|
+
the detection layer has to fire. The two layers together form a belt-
|
|
715
|
+
and-suspenders design: prevention lowers baseline incidence, detection
|
|
716
|
+
guarantees a clear user-visible signal when incidence > 0.
|
|
717
|
+
|
|
718
|
+
### Migration
|
|
719
|
+
|
|
720
|
+
No regeneration required. v2.3.0 is purely additive — the validator
|
|
721
|
+
runs on existing v2.2.0-generated `CLAUDE.md` files and flags drift
|
|
722
|
+
where present.
|
|
723
|
+
|
|
724
|
+
- **For new projects**: `npx claudeos-core init --lang <code>` runs lint
|
|
725
|
+
automatically at the end; inspect any flagged drift before committing.
|
|
726
|
+
- **For existing v2.2.0 projects**: `npx claudeos-core lint` runs the
|
|
727
|
+
validator against the current `CLAUDE.md` and reports issues. No code
|
|
728
|
+
changes to `CLAUDE.md`, `.claude/rules/`, or `claudeos-core/*` are made
|
|
729
|
+
— the validator is read-only.
|
|
730
|
+
- **For projects with flagged drift**: regenerate via
|
|
731
|
+
`npx claudeos-core init --force`, or hand-edit using the per-failure
|
|
732
|
+
remediation guidance the validator emits.
|
|
733
|
+
|
|
734
|
+
CI-friendly exit codes: `lint` returns 0 on pass and 1 on fail, suitable
|
|
735
|
+
for a GitHub Actions step or pre-commit hook.
|
|
736
|
+
|
|
737
|
+
### Notes
|
|
738
|
+
|
|
739
|
+
- The validator is deliberately narrow in scope: it verifies *structural*
|
|
740
|
+
invariants, not semantic correctness. Content quality (Section 1 Level-2
|
|
741
|
+
abstraction discipline, Section 4 pattern-naming accuracy, etc.) remains
|
|
742
|
+
the scaffold's and the LLM's responsibility. A future release may add
|
|
743
|
+
complementary content-level checks.
|
|
744
|
+
- The table-row-based detector distinguishes the L4 Memory Files *table*
|
|
745
|
+
declaration from prose mentions of memory filenames in Section 8's
|
|
746
|
+
workflow steps. A prior iteration during implementation flagged every
|
|
747
|
+
mention as a duplicate (false-positive on normal valid output); the
|
|
748
|
+
final design matches only markdown table-row patterns (`| \`...memory/X\` |`),
|
|
749
|
+
which produce clean true-positive signals on the real bad fixture and
|
|
750
|
+
zero flags on all three good fixtures.
|
|
751
|
+
- Fenced code block handling in `splitByH2` was validated against the
|
|
752
|
+
embedded scaffold in `pass3-prompt.md` itself, which contains an
|
|
753
|
+
example CLAUDE.md structure (`## 1. Role Definition` ... `## 8. ...`)
|
|
754
|
+
inside a ```markdown fence. Without fence-awareness, this would inflate
|
|
755
|
+
any section count run against the prompt — a reminder that markdown
|
|
756
|
+
validators must understand markdown, not just regex-match headings.
|
|
757
|
+
|
|
758
|
+
---
|
|
759
|
+
|
|
760
|
+
## [2.2.0] — 2026-04-21
|
|
761
|
+
|
|
762
|
+
Adds deterministic CLAUDE.md structure. Generated `CLAUDE.md` files now follow
|
|
763
|
+
an 8-section scaffold with fixed titles and order, driven by `pass-prompts/
|
|
764
|
+
templates/common/claude-md-scaffold.md`. Content within each section still
|
|
765
|
+
adapts to the project, but the structural skeleton no longer drifts between
|
|
766
|
+
projects or runs.
|
|
767
|
+
|
|
768
|
+
### Added
|
|
769
|
+
|
|
770
|
+
- **`pass-prompts/templates/common/claude-md-scaffold.md`** (new, ~630 lines).
|
|
771
|
+
Single source of truth for CLAUDE.md structure. Defines the 8 sections
|
|
772
|
+
(Role Definition / Project Overview / Build & Run Commands / Core
|
|
773
|
+
Architecture / Directory Structure / Standard · Rules · Skills
|
|
774
|
+
Reference / DO NOT Read / Common Rules & Memory (L4); titles are
|
|
775
|
+
emitted in the project's output language), per-section generation
|
|
776
|
+
rules, dynamic substitution variables (`{PROJECT_NAME}`,
|
|
777
|
+
`{OUTPUT_LANG}`, `{PROJECT_CONTEXT}`), and a post-generation validation
|
|
778
|
+
checklist. Section 8 has TWO required sub-sections: a Common Rules
|
|
779
|
+
sub-section (meta-summary table of `paths: ["**/*"]` universal rules)
|
|
780
|
+
and an L4 Memory sub-section (memory file table + workflow). All 12 stack-specific Pass 3 prompts
|
|
781
|
+
now delegate CLAUDE.md structure to this scaffold and supply only
|
|
782
|
+
stack-specific hints (2-4 lines each).
|
|
783
|
+
|
|
784
|
+
- **`lib/env-parser.js`** (new). Parses `.env*` files into structured
|
|
785
|
+
`{port, host, apiTarget, vars, source}` used by stack-detector. Search
|
|
786
|
+
order prefers `.env.example` (committed, canonical) over local `.env`
|
|
787
|
+
variants. Port detection recognizes 16+ convention variable names across
|
|
788
|
+
Vite, Next.js, Nuxt, Angular, Node, and Python frameworks. Exposes
|
|
789
|
+
utilities (`parseEnvContent`, `extractPort`, `extractHost`,
|
|
790
|
+
`extractApiTarget`, `readStackEnvInfo`) plus a sensitive-variable
|
|
791
|
+
filter (`isSensitiveVarName`, `redactSensitiveVars`) that redacts
|
|
792
|
+
values of PASSWORD/SECRET/TOKEN/API_KEY/CREDENTIAL/PRIVATE_KEY-style
|
|
793
|
+
variables to a `***REDACTED***` sentinel before the vars map reaches
|
|
794
|
+
any downstream consumer. DATABASE_URL is whitelisted for
|
|
795
|
+
stack-detector back-compat. 39 unit tests in `tests/env-parser.test.js`
|
|
796
|
+
(30 core + 9 redaction).
|
|
797
|
+
|
|
798
|
+
### Changed
|
|
799
|
+
|
|
800
|
+
- **All 12 Pass 3 prompts** (`angular/`, `java-spring/`, `kotlin-spring/`,
|
|
801
|
+
`node-express/`, `node-fastify/`, `node-nestjs/`, `node-nextjs/`,
|
|
802
|
+
`node-vite/`, `python-django/`, `python-fastapi/`, `python-flask/`,
|
|
803
|
+
`vue-nuxt/`). Two separate changes per file:
|
|
804
|
+
1. The previous 5-bullet CLAUDE.md generation block (`- Role definition`,
|
|
805
|
+
`- Build & Run Commands`, `- Core architecture diagram`, `- {stack item}`,
|
|
806
|
+
`- Standard/Skills/Guide reference table`) is replaced by a scaffold
|
|
807
|
+
reference plus stack-specific hints. The `CRITICAL — CLAUDE.md Reference
|
|
808
|
+
Table Completeness` warning above the block is also removed (the
|
|
809
|
+
scaffold's validation checklist supersedes it).
|
|
810
|
+
2. The `40.infra/*` `paths` frontmatter spec is split per-file. Previously
|
|
811
|
+
all three infra rules (environment-config, logging-monitoring, cicd-
|
|
812
|
+
deployment) received the same category-level `paths` value, which caused
|
|
813
|
+
the logging-monitoring rule to never auto-load on source code edits
|
|
814
|
+
(its `paths` only matched `.env`, `*.config.*`, `*.json`, `*.yml`,
|
|
815
|
+
`Dockerfile*` — none of which are source files). Per-file paths now
|
|
816
|
+
match each rule's actual guardrail target: environment-config → env/
|
|
817
|
+
config files, logging-monitoring → source code extensions (`.ts`/`.tsx`/
|
|
818
|
+
`.py`/`.java`/`.kt` per stack), cicd-deployment → CI YAML + source.
|
|
819
|
+
|
|
820
|
+
- **`pass-prompts/templates/common/pass3-footer.md`** — five new `CRITICAL`
|
|
821
|
+
blocks added:
|
|
822
|
+
- **`00.standard-reference.md` Composition**: scopes the mechanical
|
|
823
|
+
standards index strictly. REQUIRES a forward reference to
|
|
824
|
+
`claudeos-core/standard/00.core/04.doc-writing-guide.md` (generated
|
|
825
|
+
by Pass 4 but indexed at Pass 3 time to prevent a gap between passes).
|
|
826
|
+
FORBIDS a redundant "DO NOT Read / context waste" section inside
|
|
827
|
+
`00.standard-reference.md` — that information belongs solely in
|
|
828
|
+
CLAUDE.md Section 7, which is both more complete (includes project-
|
|
829
|
+
specific build-output and external-module paths) and not reloaded
|
|
830
|
+
on every edit. The 6 stacks (java-spring, kotlin-spring, node-express,
|
|
831
|
+
node-nextjs, python-django, python-fastapi) whose Pass 3 prompts
|
|
832
|
+
previously hardcoded a `## DO NOT Read` block in the reference file
|
|
833
|
+
have been cleaned up.
|
|
834
|
+
- **`.env` Is the Source of Truth for Runtime Configuration**: when
|
|
835
|
+
`pass2-merged.json` contains `stack.envInfo`, ports/hosts/API targets
|
|
836
|
+
declared in the project's `.env.example` MUST be used over framework
|
|
837
|
+
defaults. Affects Section 2's table, Section 3's inline run-command
|
|
838
|
+
comments, and any rule referencing port values (e.g., CORS origins
|
|
839
|
+
in auth rules).
|
|
840
|
+
- **Rule `paths` Must Match Rule Content**: enforces that each rule's
|
|
841
|
+
`paths` frontmatter matches the file types its guardrails actually
|
|
842
|
+
target. Explicitly prohibits copying `paths` across sibling rule files
|
|
843
|
+
in the same category, and tells the LLM to re-verify "when should
|
|
844
|
+
Claude Code auto-load this rule?" as the criterion for paths. Added
|
|
845
|
+
because a category-level paths shortcut in earlier Pass 3 prompts
|
|
846
|
+
caused the logging-monitoring rule to never match source code edits.
|
|
847
|
+
- **CLAUDE.md Scaffold Compliance**: enforces the 8-section structure at
|
|
848
|
+
generation time. Explicitly forbids adding sections with titles like
|
|
849
|
+
"Required to Observe While Working", "Rules Summary", "Documentation
|
|
850
|
+
Writing Rules", "AI Common Rules", "L4 Memory Integration Rules",
|
|
851
|
+
"Common Rules", or any title whose category meaning is "rules"
|
|
852
|
+
beyond the 8 fixed section names (the same blocklist is applied in
|
|
853
|
+
every output language, matching on the translated equivalents).
|
|
854
|
+
Adds a mandatory post-generation check (count `^## ` headings; must
|
|
855
|
+
equal 8; merge surplus into the correct section or move to `rules/*`
|
|
856
|
+
/ `standard/*`). The expanded blocklist closes a rename loophole
|
|
857
|
+
discovered during dogfooding on a Vite + React frontend project
|
|
858
|
+
where the LLM appended a §9 whose title combined "Documentation
|
|
859
|
+
Writing + AI Common Rules + Memory Layer (L4)" to collect
|
|
860
|
+
rule-related content.
|
|
861
|
+
- **CLAUDE.md Does Not Duplicate Rules**: clarifies that CLAUDE.md
|
|
862
|
+
describes structure, not enforcement. Lists four categories of content
|
|
863
|
+
that do NOT belong in CLAUDE.md (coding rules, domain-specific rules,
|
|
864
|
+
multi-file sync rules, work procedures) and points each to its proper
|
|
865
|
+
home in rules/standard/skills/guide.
|
|
866
|
+
|
|
867
|
+
- **`pass-prompts/templates/common/claude-md-scaffold.md`** (in addition to
|
|
868
|
+
the new-file Add above) was tightened after initial dogfooding:
|
|
869
|
+
- Hard constraints section now leads with **"EXACTLY 8 SECTIONS. No more,
|
|
870
|
+
no less."** plus a recovery procedure for surplus sections.
|
|
871
|
+
- Section 6 Rules sub-section explicitly notes that the
|
|
872
|
+
`.claude/rules/00.core/*` wildcard row already COVERS
|
|
873
|
+
`51.doc-writing-rules.md` and `52.ai-work-rules.md` — eliminating the
|
|
874
|
+
perceived need to create a separate section enumerating those rules.
|
|
875
|
+
- Validation checks section lists common surplus section patterns with
|
|
876
|
+
target destinations so the LLM can act rather than just detect.
|
|
877
|
+
|
|
878
|
+
- **`plan-installer/prompt-generator.js`** — embeds the scaffold inline
|
|
879
|
+
into `pass3-prompt.md` at generation time. The 12 stack-specific Pass 3
|
|
880
|
+
templates and `pass3-footer.md` both reference
|
|
881
|
+
`pass-prompts/templates/common/claude-md-scaffold.md` by path, but that
|
|
882
|
+
path is relative to the claudeos-core package, not the user project.
|
|
883
|
+
The generator now reads the scaffold and inserts it between the Phase 1
|
|
884
|
+
fact-table block and the stack-specific body, wrapped in explicit
|
|
885
|
+
`# === EMBEDDED: claude-md-scaffold.md ===` markers so the LLM can locate
|
|
886
|
+
it. Without this embed the scaffold references would point to a file
|
|
887
|
+
Claude Code cannot resolve at runtime. Load is optional (`existsSafe`)
|
|
888
|
+
so a missing scaffold does not crash generation — the rest of the
|
|
889
|
+
prompt is still produced, just without the deterministic structure
|
|
890
|
+
enforcement.
|
|
891
|
+
|
|
892
|
+
- **`plan-installer/stack-detector.js`** — now calls `readStackEnvInfo`
|
|
893
|
+
before returning and attaches the result as `stack.envInfo` on
|
|
894
|
+
project-analysis.json. When the project's `.env.example` (or fallback
|
|
895
|
+
`.env`) declares a port AND no earlier detector won (Spring Boot
|
|
896
|
+
application.yml still takes precedence), the parsed port is promoted
|
|
897
|
+
to `stack.port`. This closes a long-standing gap where Vite projects
|
|
898
|
+
that customized their dev port via `.env` (e.g., `VITE_DESKTOP_PORT=3000`)
|
|
899
|
+
received the framework-default 5173 in CLAUDE.md.
|
|
900
|
+
Host and API target values are also captured for downstream use.
|
|
901
|
+
|
|
902
|
+
- **`plan-installer/index.js`** — port resolution precedence documented
|
|
903
|
+
in code comments. The existing `defaultPort` fallback chain (Vite 5173,
|
|
904
|
+
Next.js 3000, Django 8000, etc.) is now explicitly labeled "last resort"
|
|
905
|
+
and runs only when neither stack-detector's direct detection (Spring
|
|
906
|
+
application.yml) nor the env-parser populated `stack.port`.
|
|
907
|
+
|
|
908
|
+
- **`pass-prompts/templates/common/claude-md-scaffold.md`** Section 2
|
|
909
|
+
(Project Overview) and Section 3 (Build & Run Commands) rules now
|
|
910
|
+
reference `stack.envInfo` as authoritative for port/host/API-target
|
|
911
|
+
values. Section 2 requires env-annotated rows in the project overview
|
|
912
|
+
table when the project declares them (e.g., `| Dev Server Port | 3000
|
|
913
|
+
(VITE_DESKTOP_PORT) |`), and Section 3 requires inline port comments
|
|
914
|
+
next to run commands to match the env-declared value. Framework defaults
|
|
915
|
+
are explicitly labeled "last resort" in both rules.
|
|
916
|
+
|
|
917
|
+
### Why this matters
|
|
918
|
+
|
|
919
|
+
When claudeos-core was applied to three sibling projects in the same
|
|
920
|
+
organization (one Spring Boot backend, two Vite + React frontends), the
|
|
921
|
+
generated files were content-correct — standards, rules, and skills
|
|
922
|
+
accurately captured each project's patterns — but the `CLAUDE.md` files
|
|
923
|
+
had different section counts (8, 8, 9), different section names, and
|
|
924
|
+
different section orders. Claude Code reads CLAUDE.md first on every
|
|
925
|
+
session; inconsistent structure across repos made it harder for
|
|
926
|
+
developers (and Claude Code) to know where to look for a given piece of
|
|
927
|
+
information. v2.2.0 fixes the structure while leaving content
|
|
928
|
+
project-specific.
|
|
929
|
+
|
|
930
|
+
The removed "Required to Observe While Working" section was a symptom
|
|
931
|
+
of the same problem: different projects put different rules there, most
|
|
932
|
+
of which duplicated
|
|
933
|
+
content already in `.claude/rules/*` (auto-loaded) or `claudeos-core/
|
|
934
|
+
standard/*` (detailed patterns). Removing it eliminates a redundant
|
|
935
|
+
maintenance surface and reinforces the "one rule, one home" principle.
|
|
936
|
+
|
|
937
|
+
Dogfooding also uncovered a latent paths bug. The `40.infra/*` rules
|
|
938
|
+
shared a single category-level `paths` frontmatter that only matched
|
|
939
|
+
config/infra file extensions (`.env`, `*.config.*`, `*.json`, `*.yml`,
|
|
940
|
+
`Dockerfile*`). This meant the logging-monitoring rule — whose guardrails
|
|
941
|
+
cover `console.log` misuse, PII in logs, and `catch {}` swallowing —
|
|
942
|
+
never auto-loaded when editing `.ts`/`.tsx`/`.py`/`.java` files, i.e.,
|
|
943
|
+
exactly when it was needed. The rule body was correct; its activation
|
|
944
|
+
trigger was mis-scoped. v2.2.0 now specifies per-file `paths` in the Pass
|
|
945
|
+
3 prompts and adds a `Rule paths Must Match Rule Content` CRITICAL block
|
|
946
|
+
to the footer so future rules cannot inherit the wrong scope by default.
|
|
947
|
+
|
|
948
|
+
A third dogfooding finding exposed a different layer of the same
|
|
949
|
+
philosophy violation. The stack detector parsed Spring Boot's
|
|
950
|
+
`application.yml` for `server.port`, but for Node/Vite projects it
|
|
951
|
+
simply used a hardcoded framework default (Vite → 5173) whenever no
|
|
952
|
+
Spring-style config was found — even when the project declared its
|
|
953
|
+
actual port in `.env.example` (e.g., `VITE_DESKTOP_PORT=3000`). This
|
|
954
|
+
meant CLAUDE.md's §2 table and §3 run-command
|
|
955
|
+
comments showed the Vite theoretical default instead of what the project
|
|
956
|
+
actually runs. The root cause was structural: the detector had no
|
|
957
|
+
`.env` parser beyond a DATABASE_URL check for DB identification. v2.2.0
|
|
958
|
+
introduces `lib/env-parser.js` with convention-aware port/host/API-target
|
|
959
|
+
extraction, and the scaffold and footer now treat `.env.example` as the
|
|
960
|
+
canonical source of runtime configuration — framework defaults are
|
|
961
|
+
last-resort only. This also captures host and API-target values that
|
|
962
|
+
previously never appeared in generated CLAUDE.md at all.
|
|
963
|
+
|
|
964
|
+
A fourth dogfooding iteration on a Spring Boot backend project
|
|
965
|
+
(regenerated with the interim v2.2.0 scaffold that only allowed a single
|
|
966
|
+
Section 8 titled "Memory (L4)") found the LLM producing a §9 titled
|
|
967
|
+
"Common Rules & Memory (L4)" — even with the expanded blocklist from
|
|
968
|
+
the earlier frontend-project fix.
|
|
969
|
+
The §9 contained both (a) a meta-summary table of `paths: ["**/*"]`
|
|
970
|
+
rules (51.doc-writing-rules + 52.ai-work-rules) and (b) a restated L4
|
|
971
|
+
memory table labeled "L4 Memory Files (Re-declaration)". Close
|
|
972
|
+
inspection showed (a) was genuinely useful content the scaffold had no
|
|
973
|
+
legitimate home for — a developer-facing summary of which rules
|
|
974
|
+
auto-load on every edit, complementary to Section 6's directory index.
|
|
975
|
+
The LLM kept inventing §9 because the information it wanted to convey
|
|
976
|
+
was real. v2.2.0 resolves this by promoting Section 8 to "Common Rules
|
|
977
|
+
& Memory (L4)" with two required sub-sections: one for common rules
|
|
978
|
+
auto-loaded on every edit (meta-summary only, not rule bodies) and one
|
|
979
|
+
for L4 memory referenced on-demand. This acknowledges that "which rules
|
|
980
|
+
auto-load universally" is a legitimate meta-information category that
|
|
981
|
+
deserves a visible home, while keeping the always-8-sections contract
|
|
982
|
+
intact. The duplicate §9 "re-declaration" anti-pattern is now
|
|
983
|
+
explicitly named and forbidden in both the scaffold
|
|
984
|
+
and the footer.
|
|
985
|
+
|
|
986
|
+
Finally, the same backend-project inspection also surfaced two smaller
|
|
987
|
+
but real bugs in `00.standard-reference.md` generation. First, 6 of the
|
|
988
|
+
12 Pass 3 stack prompts hardcoded a `## DO NOT Read (context waste)`
|
|
989
|
+
section at the bottom of the reference file — a shadow of CLAUDE.md
|
|
990
|
+
Section 7 that was less complete (missed project-specific paths like
|
|
991
|
+
`build/` or external modules) and lived at the wrong layer: `00.standard-
|
|
992
|
+
reference.md` reloads on every edit via `paths: ["**/*"]`, while
|
|
993
|
+
Section 7 loads once per session. Second, `claudeos-core/standard/00.
|
|
994
|
+
core/04.doc-writing-guide.md` is generated by Pass 4 (Required output
|
|
995
|
+
#12) but never appeared in the Pass 3-generated reference index, creating
|
|
996
|
+
a gap the moment Pass 4 ran. v2.2.0 adds a `00.standard-reference.md
|
|
997
|
+
Composition` CRITICAL block to the footer that codifies: (a) always
|
|
998
|
+
include the Pass 4 forward reference, (b) never include a DO NOT Read
|
|
999
|
+
section (Section 7 is the single source of truth), (c) keep the per-
|
|
1000
|
+
edit payload minimal (paths only, no descriptions — descriptions live
|
|
1001
|
+
in Section 6 which is session-time budget). The 6 inline hardcoded
|
|
1002
|
+
DO NOT Read blocks have been removed from the stack prompts and
|
|
1003
|
+
replaced with explicit inline notes pointing to the footer rule.
|
|
1004
|
+
|
|
1005
|
+
Three additional risks surfaced during pre-release cross-checking
|
|
1006
|
+
and were addressed in the same release cycle. **First**, the scaffold's
|
|
1007
|
+
"Section 6 Rules: Always include 60.memory/*" directive, added during
|
|
1008
|
+
Section 8 redesign, was not echoed in the 12 stack Pass 3 prompts'
|
|
1009
|
+
rule-category listings — so the LLM received conflicting signals
|
|
1010
|
+
(scaffold says include, stack prompt doesn't mention it). Real dogfooding
|
|
1011
|
+
on the backend project confirmed the category was being omitted from
|
|
1012
|
+
the generated CLAUDE.md §6 Rules table. v2.2.0 fixes both sides: each stack
|
|
1013
|
+
Pass 3 prompt now explicitly lists `60.memory/*` as a forward-reference
|
|
1014
|
+
rule category (generated by Pass 4, but indexed at Pass 3 time), and the
|
|
1015
|
+
scaffold's Sub-section 2 guidance is strengthened with an example row
|
|
1016
|
+
and a "mandatory — do NOT omit" note. **Second**, the existing Migration
|
|
1017
|
+
guidance mentioned `--force` but did not explain why `npx claudeos-core
|
|
1018
|
+
init` (without `--force`) silently fails to adopt v2.2.0 improvements on
|
|
1019
|
+
upgrades. Under Rule B idempotency, existing generated files are skipped
|
|
1020
|
+
as "already exists", meaning users running plain `init` on a v2.1.x
|
|
1021
|
+
project see no visible change. v2.2.0 adds (a) a dedicated "upgrade
|
|
1022
|
+
detected" warning in bin/commands/init.js that fires when a pre-v2.2.0
|
|
1023
|
+
CLAUDE.md is detected before the resume/fresh prompt, and (b) an expanded
|
|
1024
|
+
Migration section in CHANGELOG that makes the `--force` requirement and
|
|
1025
|
+
preservation semantics (memory/ content kept, generated files replaced)
|
|
1026
|
+
explicit. **Third**, the new `.env.example` → CLAUDE.md pipeline created
|
|
1027
|
+
a theoretical pathway for accidentally committed secrets in `.env.example`
|
|
1028
|
+
to be amplified into the project's public-facing documentation. Although
|
|
1029
|
+
`.env.example` is conventionally a placeholder file, real-world projects
|
|
1030
|
+
occasionally check in real values by mistake. v2.2.0 adds a
|
|
1031
|
+
sensitive-variable filter (`lib/env-parser.js`: `isSensitiveVarName`,
|
|
1032
|
+
`redactSensitiveVars`) that replaces values of variables matching
|
|
1033
|
+
PASSWORD/SECRET/TOKEN/API_KEY/CREDENTIAL/PRIVATE_KEY patterns with a
|
|
1034
|
+
`***REDACTED***` sentinel before the vars map reaches any downstream
|
|
1035
|
+
consumer. Port/host/API-target extraction uses a whitelist of
|
|
1036
|
+
config-relevant keys and is unaffected. The scaffold also gains an
|
|
1037
|
+
explicit SECURITY directive forbidding reference to sensitive variables
|
|
1038
|
+
in CLAUDE.md as defense-in-depth. `DATABASE_URL` remains unredacted
|
|
1039
|
+
because stack-detector's DB identification path has depended on it since
|
|
1040
|
+
v1.x — changing that would be a breaking change.
|
|
1041
|
+
|
|
1042
|
+
### Migration
|
|
1043
|
+
|
|
1044
|
+
Existing projects keep working. The prompt-generator change affects only
|
|
1045
|
+
how `pass3-prompt.md` is assembled on the next `init` or `refresh` run —
|
|
1046
|
+
installed standards, rules, skills, memory, and CLAUDE.md in existing
|
|
1047
|
+
projects are not touched until the user regenerates.
|
|
1048
|
+
|
|
1049
|
+
**⚠️ Important: `--force` is REQUIRED to adopt v2.2.0 improvements.**
|
|
1050
|
+
|
|
1051
|
+
claudeos-core's Pass 3 runs under Rule B (idempotency): if a target file
|
|
1052
|
+
already exists on disk, it is skipped during regeneration. This is
|
|
1053
|
+
designed to protect hand-edited content from being overwritten, but it
|
|
1054
|
+
means **a plain `npx claudeos-core init` on an existing v2.1.x project
|
|
1055
|
+
will NOT apply v2.2.0 improvements** because the old files (CLAUDE.md,
|
|
1056
|
+
`00.standard-reference.md`, `40.infra/*-rules.md`, memory rules, etc.)
|
|
1057
|
+
will all be skipped as "already exists".
|
|
1058
|
+
|
|
1059
|
+
To actually adopt v2.2.0's improvements (8-section CLAUDE.md, per-file
|
|
1060
|
+
`40.infra/*` paths, `.env.example`-based port accuracy, Section 8
|
|
1061
|
+
redesign, forward-referenced `04.doc-writing-guide.md`, `60.memory/*`
|
|
1062
|
+
row), regenerate via:
|
|
1063
|
+
|
|
1064
|
+
```
|
|
1065
|
+
npx claudeos-core init --force
|
|
1066
|
+
```
|
|
1067
|
+
|
|
1068
|
+
`--force` overwrites existing generated files while leaving untouched:
|
|
1069
|
+
- Your source code
|
|
1070
|
+
- `claudeos-core/memory/` content (decision-log, failure-patterns entries
|
|
1071
|
+
you've accumulated) — these are append-only and preserved
|
|
1072
|
+
- Any non-generated files under the project root
|
|
1073
|
+
|
|
1074
|
+
If you want to preview changes first, regenerate into a scratch copy of
|
|
1075
|
+
the project, diff the resulting files against your current ones, and
|
|
1076
|
+
then decide whether to `--force` on the real project. Key files to
|
|
1077
|
+
diff: `CLAUDE.md`, `.claude/rules/00.core/00.standard-reference.md`,
|
|
1078
|
+
`.claude/rules/40.infra/02.logging-monitoring-rules.md` (paths change
|
|
1079
|
+
is the most visible delta).
|
|
1080
|
+
|
|
1081
|
+
No manual edits are required after `--force`; the scaffold handles
|
|
1082
|
+
everything. Hand-edited content in `claudeos-core/standard/**` that
|
|
1083
|
+
you want preserved should be committed to version control before
|
|
1084
|
+
running `--force` so you can diff/merge any overwrites.
|
|
1085
|
+
|
|
1086
|
+
### Notes
|
|
1087
|
+
|
|
1088
|
+
- 39 new tests added in `tests/env-parser.test.js` (30 core + 9 sensitive-
|
|
1089
|
+
variable redaction). All tests continue to pass: **563 pre-existing + 39
|
|
1090
|
+
new = 602 total**.
|
|
1091
|
+
- No file-format breaking changes. Existing `claudeos-core/standard/`,
|
|
1092
|
+
`.claude/rules/`, and `claudeos-core/skills/` content in installed
|
|
1093
|
+
projects is unaffected — only the CLAUDE.md generated at the project
|
|
1094
|
+
root changes shape on regeneration. The `40.infra/*` rule `paths`
|
|
1095
|
+
values will update on next regeneration, which changes when those
|
|
1096
|
+
rules auto-load (more accurately scoped); the rule content itself
|
|
1097
|
+
does not change. `stack.envInfo` is a new additive field — older
|
|
1098
|
+
project-analysis.json files without it still work.
|
|
1099
|
+
- Discovered via dogfooding on three real production projects:
|
|
1100
|
+
- Structural drift (3 different CLAUDE.md layouts) prompted the scaffold.
|
|
1101
|
+
- A Vite + React frontend project produced a §9 surplus section under
|
|
1102
|
+
a renamed title that bypassed the initial forbidden-sections blocklist
|
|
1103
|
+
— fixed by expanding the blocklist and adding the mandatory
|
|
1104
|
+
post-generation §-count check.
|
|
1105
|
+
- The `40.infra/*` paths mismatch surfaced when inspecting a generated
|
|
1106
|
+
`02.logging-monitoring-rules.md` and confirming via grep that its
|
|
1107
|
+
guardrails (source-code-level: PII logging, silent swallow, console
|
|
1108
|
+
use) could never auto-load given the file's own paths frontmatter
|
|
1109
|
+
(config-only).
|
|
1110
|
+
- The Vite port mismatch (5173 in CLAUDE.md when `.env.example`
|
|
1111
|
+
declared 3000) exposed the absence of any `.env` parsing in
|
|
1112
|
+
stack-detector beyond DATABASE_URL — prompted the new
|
|
1113
|
+
`lib/env-parser.js` utility and the `.env Is the Source of Truth`
|
|
1114
|
+
CRITICAL footer block.
|
|
1115
|
+
- A second Spring Boot backend regeneration against the interim
|
|
1116
|
+
scaffold produced §9 "Common Rules & Memory (L4)" despite the
|
|
1117
|
+
expanded blocklist, because the LLM's desired content (a
|
|
1118
|
+
meta-summary of `paths: ["**/*"]` universal rules, complementary to
|
|
1119
|
+
Section 6's directory index) had no legitimate home in the original
|
|
1120
|
+
8-section design. Resolved by redesigning Section 8 into two
|
|
1121
|
+
sub-sections — a Common Rules sub-section for the universal-rules
|
|
1122
|
+
meta-summary and an L4 Memory sub-section for the memory
|
|
1123
|
+
table/workflow. The "L4 Memory Files (Re-declaration)" anti-pattern
|
|
1124
|
+
(duplicate memory table inside a second section) is now explicitly
|
|
1125
|
+
named and forbidden.
|
|
1126
|
+
- Inspection of the same backend-project output showed a generated
|
|
1127
|
+
`00.standard-reference.md` carrying a hardcoded `## DO NOT Read
|
|
1128
|
+
(context waste)` section (a partial duplicate of CLAUDE.md Section 7)
|
|
1129
|
+
and missing `00.core/04.doc-writing-guide.md` (created later by
|
|
1130
|
+
Pass 4). Fixed in the 6 affected Pass 3 stack prompts and formalized
|
|
1131
|
+
as the `00.standard-reference.md Composition` CRITICAL block so
|
|
1132
|
+
future stacks cannot reintroduce either defect.
|
|
1133
|
+
- Pre-release cross-check found the scaffold's `60.memory/*` "Always
|
|
1134
|
+
include" directive was not mirrored in any of the 12 stack Pass 3
|
|
1135
|
+
prompts' rule-category listings, causing the backend project's
|
|
1136
|
+
CLAUDE.md §6 Rules table to omit `60.memory/*` entirely. Fixed by adding the
|
|
1137
|
+
forward-reference row to all 12 stack prompts and strengthening the
|
|
1138
|
+
scaffold's Sub-section 2 guidance with an example row and "mandatory"
|
|
1139
|
+
wording.
|
|
1140
|
+
- Pre-release cross-check flagged that a plain `npx claudeos-core init`
|
|
1141
|
+
on an existing v2.1.x project would silently skip v2.2.0 improvements
|
|
1142
|
+
under Rule B idempotency. Added a CLAUDE.md marker-based detection
|
|
1143
|
+
in `bin/commands/init.js` that warns about the `--force` requirement
|
|
1144
|
+
before the resume/fresh prompt, plus an expanded Migration section
|
|
1145
|
+
covering preservation semantics and preview workflow.
|
|
1146
|
+
- Pre-release cross-check identified that values in `.env.example`
|
|
1147
|
+
flow through to CLAUDE.md, creating a leak pathway for accidentally
|
|
1148
|
+
committed secrets. Added sensitive-variable redaction in
|
|
1149
|
+
`lib/env-parser.js` (PASSWORD/SECRET/TOKEN/API_KEY/CREDENTIAL/
|
|
1150
|
+
PRIVATE_KEY patterns replaced with `***REDACTED***` sentinel) plus
|
|
1151
|
+
a SECURITY directive in the scaffold as defense-in-depth.
|
|
1152
|
+
|
|
1153
|
+
---
|
|
1154
|
+
|
|
1155
|
+
## [2.1.2] — 2026-04-21
|
|
1156
|
+
|
|
1157
|
+
Post-release regression fix for v2.1.0 master plan removal cleanup.
|
|
1158
|
+
|
|
1159
|
+
### Fixed
|
|
1160
|
+
|
|
1161
|
+
- **`content-validator`: `plan/` directory no longer required.** On fresh
|
|
1162
|
+
v2.1.0+ projects `npx claudeos-core health` always failed because
|
|
1163
|
+
`content-validator/index.js` pushed a `MISSING: plan directory not found`
|
|
1164
|
+
error when `claudeos-core/plan/` was absent. Master plan generation was
|
|
1165
|
+
explicitly removed in v2.1.0 — `plan-validator` (v2.1.0 `Fixed`) and
|
|
1166
|
+
`manifest-generator` (v2.1.0 `Fixed`) were both updated to tolerate a
|
|
1167
|
+
missing `plan/` directory, but `content-validator` was missed during
|
|
1168
|
+
that cleanup. It now silently skips the plan/ check when the directory
|
|
1169
|
+
is absent (with an informational `plan/ not present (expected post-v2.1.0)`
|
|
1170
|
+
log line), matching the contract established by the other validators.
|
|
1171
|
+
The directory contents are still validated when present (legacy projects
|
|
1172
|
+
or user-authored plan files are unaffected).
|
|
1173
|
+
|
|
1174
|
+
### Notes
|
|
1175
|
+
|
|
1176
|
+
- All 563 existing tests continue to pass. No new tests added — the fix
|
|
1177
|
+
is a one-line behavior change (`errors.push(...)` → `console.log(...)`)
|
|
1178
|
+
with a comment documenting the v2.1.0 context, and regression risk is
|
|
1179
|
+
covered by routine `health` runs rather than an integration test.
|
|
1180
|
+
- Discovered via dogfooding on a real Vite 6 + React 19 project: 62
|
|
1181
|
+
generated files, all Pass 1–4 stages succeeded, but `health` failed
|
|
1182
|
+
at content-validator. No other cleanup gaps found.
|
|
1183
|
+
|
|
1184
|
+
---
|
|
1185
|
+
|
|
1186
|
+
## [2.1.1] — 2026-04-20
|
|
1187
|
+
|
|
1188
|
+
Docs-only maintenance release. No runtime behavior or API changes.
|
|
1189
|
+
|
|
1190
|
+
### Changed
|
|
1191
|
+
|
|
1192
|
+
- **README: dropped `What's New in v2.1.0` section** from all 10 language
|
|
1193
|
+
READMEs (`README.md`, `README.ko.md`, `README.ja.md`, `README.zh-CN.md`,
|
|
1194
|
+
`README.es.md`, `README.vi.md`, `README.hi.md`, `README.ru.md`,
|
|
1195
|
+
`README.fr.md`, `README.de.md`). Post-release cleanup — the section's
|
|
1196
|
+
job is done once the release ships, and the same content is preserved
|
|
1197
|
+
in `CHANGELOG.md` for anyone who wants the historical detail.
|
|
1198
|
+
|
|
1199
|
+
- **README: dropped the `Real production case: 18-domain admin frontend
|
|
1200
|
+
(2026-04-20)` subsection** under _Auto-scaling by Project Size_ across
|
|
1201
|
+
all 10 language READMEs. The per-stage breakdown table (9 rows) and its
|
|
1202
|
+
surrounding prose are removed. The trailing empirical reference in the
|
|
1203
|
+
FAQ "What is Pass 3 split mode" answer (the `Empirically verified up
|
|
1204
|
+
to 18 domains × 101 files × 102 minutes …` sentence with its now-dead
|
|
1205
|
+
link) is also removed so no orphan reference remains.
|
|
1206
|
+
|
|
1207
|
+
### Notes
|
|
1208
|
+
|
|
1209
|
+
- Each README drops ~33 lines; total net change across translations is
|
|
1210
|
+
~330 lines removed. No code, tests, prompts, or generated artifacts
|
|
1211
|
+
are touched — `npm pack` contents are identical to v2.1.0 apart from
|
|
1212
|
+
the README files and `package.json`/`package-lock.json` version bump.
|
|
1213
|
+
|
|
1214
|
+
---
|
|
1215
|
+
|
|
1216
|
+
## [2.1.0] — 2026-04-20
|
|
1217
|
+
|
|
1218
|
+
This release addresses the primary cause of `Prompt is too long` failures in
|
|
1219
|
+
Pass 3 on large multi-module projects. The fix is structural: Pass 3 is
|
|
1220
|
+
re-architected into multiple sequential `claude -p` calls with fresh context
|
|
1221
|
+
each, so output-accumulation overflow is no longer possible regardless of
|
|
1222
|
+
project size.
|
|
1223
|
+
|
|
1224
|
+
### Added
|
|
1225
|
+
|
|
1226
|
+
- **Phase 1 "Read Once, Extract Facts" prompt block** (always on). A new
|
|
1227
|
+
common block `pass-prompts/templates/common/pass3-phase1.md` is prepended
|
|
1228
|
+
to every generated `pass3-prompt.md`. It instructs Claude to read
|
|
1229
|
+
`pass2-merged.json` exactly once into a compact in-context fact table and
|
|
1230
|
+
reference that table for all subsequent file generation. The block defines
|
|
1231
|
+
five rules:
|
|
1232
|
+
- **Rule A** — Reference the fact table, don't re-read pass2-merged.json.
|
|
1233
|
+
- **Rule B** — Idempotent file writing (skip if target exists with real
|
|
1234
|
+
content), making Pass 3 safely re-runnable after interruption.
|
|
1235
|
+
- **Rule C** — Cross-file consistency enforced via the fact table as
|
|
1236
|
+
single source of truth.
|
|
1237
|
+
- **Rule D** — Output conciseness: one line (`[WRITE]`/`[SKIP]`) between
|
|
1238
|
+
file writes, no restating the fact table, no echoing file content.
|
|
1239
|
+
Addresses output-accumulation overflow where verbose narration between
|
|
1240
|
+
30-50 files adds 15-30K tokens of pure accumulation.
|
|
1241
|
+
- **Rule E** — Batch idempotent check: one `Glob` at PHASE 2 start
|
|
1242
|
+
instead of per-target `Read` calls.
|
|
1243
|
+
|
|
1244
|
+
- **`pass3-context.json` slim summary builder** (always on). A new file
|
|
1245
|
+
`claudeos-core/generated/pass3-context.json` is built after Pass 2 from
|
|
1246
|
+
`project-analysis.json` plus `pass2-merged.json` signals (size, top-level
|
|
1247
|
+
keys). Stays under 5 KB even for large projects vs. `pass2-merged.json`
|
|
1248
|
+
which can exceed 500 KB. Pass 3 prompts reference this as the preferred
|
|
1249
|
+
entry point, falling back to `pass2-merged.json` only for specific
|
|
1250
|
+
details (response wrapper method, util class FQN, MyBatis mapper path).
|
|
1251
|
+
Emits a warning when `pass2-merged.json` exceeds 300 KB.
|
|
1252
|
+
|
|
1253
|
+
- **Batch sub-division for large projects** (automatic, ≥16 domains).
|
|
1254
|
+
Stages 3b and 3c are sub-divided into batches of 15 domains each,
|
|
1255
|
+
preceded by dedicated `3b-core` / `3c-core` stages that handle
|
|
1256
|
+
project-wide common files. Ensures no single stage generates more than
|
|
1257
|
+
~50 files, keeping output within the empirical safe range on projects
|
|
1258
|
+
up to 100+ domains. Batch count is `ceil(totalDomains / 15)`; domain
|
|
1259
|
+
order comes from `domain-groups.json` (size-balanced by plan-installer).
|
|
1260
|
+
|
|
1261
|
+
- **Split-mode partial marker protection**. `pass3-complete.json` gains
|
|
1262
|
+
`mode: "split"` and `groupsCompleted` array. A run that completes 3a+3b
|
|
1263
|
+
and crashes during 3c leaves a partial marker; on re-run, the stale-check
|
|
1264
|
+
detects the partial-marker shape and defers to the split runner's resume
|
|
1265
|
+
logic instead of deleting the marker — otherwise the run would restart
|
|
1266
|
+
from 3a and double the token cost.
|
|
1267
|
+
|
|
1268
|
+
- **7 regression tests** pinning the master plan no-op contract
|
|
1269
|
+
(`tests/master-plan-removal.test.js`).
|
|
1270
|
+
|
|
1271
|
+
- **`scaffoldSkillsManifest` gap-fill for Pass 4**. Auto-creates
|
|
1272
|
+
`claudeos-core/skills/00.shared/MANIFEST.md` with a minimal stub if
|
|
1273
|
+
Pass 3c omits it (the stack pass3.md templates list it among targets but
|
|
1274
|
+
without REQUIRED marking, so skill-sparse projects sometimes ended up
|
|
1275
|
+
with `.claude/rules/50.sync/03.skills-sync.md` pointing at a
|
|
1276
|
+
non-existent file). Idempotent: skips if the file already has real
|
|
1277
|
+
content (>20 chars).
|
|
1278
|
+
|
|
1279
|
+
### Changed
|
|
1280
|
+
|
|
1281
|
+
- **Pass 3 now always runs in split mode.** Each stage starts with a fresh
|
|
1282
|
+
context window; cross-stage consistency is preserved by `pass3a-facts.md`.
|
|
1283
|
+
No user-facing configuration — applies to every `npx claudeos-core init`
|
|
1284
|
+
run automatically.
|
|
1285
|
+
|
|
1286
|
+
Stage structure:
|
|
1287
|
+
- **3a** — Read analysis files once, write `pass3a-facts.md` (5-10 KB
|
|
1288
|
+
distilled fact sheet).
|
|
1289
|
+
- **3b** — Generate `CLAUDE.md`, `standard/`, and `.claude/rules/`.
|
|
1290
|
+
Sub-divided into `3b-core` + `3b-1..N` on projects with ≥16 domains.
|
|
1291
|
+
- **3c** — Generate `skills/` and `guide/`. Sub-divided into `3c-core`
|
|
1292
|
+
+ `3c-1..N` on projects with ≥16 domains.
|
|
1293
|
+
- **3d-aux** — Generate `database/` + `mcp-guide/` stubs.
|
|
1294
|
+
|
|
1295
|
+
Single-batch projects keep flat `"3b"`/`"3c"` marker names
|
|
1296
|
+
(backward-compatible); multi-batch projects use `"3b-core"`, `"3b-1"`,
|
|
1297
|
+
etc. Resume works at stage granularity.
|
|
1298
|
+
|
|
1299
|
+
- **Stage count by project size** (1–15 domains: 4 stages; 16–30: 8; 31–45:
|
|
1300
|
+
10; 46–60: 12; 61–75: 14; 91–105: 18).
|
|
1301
|
+
|
|
1302
|
+
- `package-lock.json` synced to `2.1.0`. The v2.0.2 release had a stale
|
|
1303
|
+
lockfile at `2.0.0` which caused `npm ci` to fail lockfile integrity
|
|
1304
|
+
checks.
|
|
1305
|
+
|
|
1306
|
+
### Removed
|
|
1307
|
+
|
|
1308
|
+
- **Master plan generation** (`claudeos-core/plan/*-master.md` files).
|
|
1309
|
+
Master plans were an internal tool backup not consumed by Claude Code
|
|
1310
|
+
at runtime, and aggregating many files in a single Pass 3d session was
|
|
1311
|
+
a primary source of `Prompt is too long` failures on mid-sized projects.
|
|
1312
|
+
Claude Code runtime is unaffected — it reads `CLAUDE.md` + `rules/`
|
|
1313
|
+
directly. Use `git` for backup/restore instead.
|
|
1314
|
+
|
|
1315
|
+
- **Pass 3d sub-stages `3d-standard` / `3d-rules` / `3d-skills` /
|
|
1316
|
+
`3d-guide`**. Only `3d-aux` (database + mcp-guide stubs) remains as a
|
|
1317
|
+
fixed-size task independent of domain count.
|
|
1318
|
+
|
|
1319
|
+
- **`CLAUDEOS_PASS3_SPLIT` environment variable and single-call mode.**
|
|
1320
|
+
Single-call had failed reliably on projects with more than ~5 domains
|
|
1321
|
+
because output-accumulation overflow is not predictable from input size.
|
|
1322
|
+
Split mode is structurally immune and is now the only supported path.
|
|
1323
|
+
|
|
1324
|
+
- **`claudeos-core/plan/` directory creation in `init`**. Directory is no
|
|
1325
|
+
longer created during bootstrap (honors the master-plan-removal contract).
|
|
1326
|
+
|
|
1327
|
+
### Deprecated
|
|
1328
|
+
|
|
1329
|
+
- `scaffoldMasterPlans` in `lib/memory-scaffold.js` is kept as a
|
|
1330
|
+
backward-compatible no-op (returns `[]`, writes nothing). External
|
|
1331
|
+
callers keep working; no files are produced.
|
|
1332
|
+
|
|
1333
|
+
### Fixed
|
|
1334
|
+
|
|
1335
|
+
- `bootstrap.sh` line endings normalized from CRLF to LF. v2.0.2 shipped
|
|
1336
|
+
with CRLF which caused immediate `syntax error` on macOS/Linux when
|
|
1337
|
+
invoked via `bash claudeos-core-tools/bootstrap.sh`.
|
|
1338
|
+
|
|
1339
|
+
- `pass3-context-builder.js`: removed unused `p2Size` placeholder variable
|
|
1340
|
+
(refactoring leftover, no behavior change).
|
|
1341
|
+
|
|
1342
|
+
- `init.js`: Pass 4 progress ticker `totalExpected` corrected from 6 to 5
|
|
1343
|
+
to reflect master plan removal. The 6th slot was counting
|
|
1344
|
+
`plan/50.memory-master.md` which is no longer generated, making the
|
|
1345
|
+
progress bar appear stuck at 83% until the run completed.
|
|
1346
|
+
|
|
1347
|
+
- `manifest-generator`: removed stale `plan-manifest.json` generation.
|
|
1348
|
+
Master plans were removed in v2.1.0; a manifest with an empty `plans`
|
|
1349
|
+
array (62 B) was noise. Nothing reads it, nothing validates it.
|
|
1350
|
+
`sync-map.json` is retained (with empty `mappings`) for
|
|
1351
|
+
`sync-checker` backward compatibility.
|
|
1352
|
+
|
|
1353
|
+
- `plan-validator`: `plan-sync-status.json` is now skipped when the
|
|
1354
|
+
`plan/` directory is absent or empty. Previously wrote a 147 B
|
|
1355
|
+
all-zeros status file on every health check for master-plan-free
|
|
1356
|
+
projects. `stale-report.json` still records a passing no-op so
|
|
1357
|
+
`health-checker` reports a clean result.
|
|
1358
|
+
|
|
1359
|
+
- `plan-parser` placeholder filtering regression in sync-checker
|
|
1360
|
+
on projects with `<...>` style tokens in plan files.
|
|
1361
|
+
|
|
1362
|
+
- `cli.js`: `npx claudeos-core memory --help` now displays the memory
|
|
1363
|
+
subcommand help instead of the top-level usage. `parseArgs` previously
|
|
1364
|
+
promoted `--help` to a top-level command even when it appeared after a
|
|
1365
|
+
command name, so `memory --help` was indistinguishable from `--help`
|
|
1366
|
+
alone. The fix: `--help` only becomes the top-level command when no
|
|
1367
|
+
other command has been seen yet. `memory --help`, `memory -h` now
|
|
1368
|
+
route to the subcommand's own help.
|
|
1369
|
+
|
|
1370
|
+
- `memory score`: the first `score` run no longer leaves two `importance`
|
|
1371
|
+
lines in each entry. The previous implementation inserted the
|
|
1372
|
+
auto-scored line at the top but left the user's original
|
|
1373
|
+
`- importance: N` line below it, producing a file with two conflicting
|
|
1374
|
+
values per entry. `cmdScore` now strips every importance line
|
|
1375
|
+
(bold or plain) before inserting the new auto-scored line, so there is
|
|
1376
|
+
always exactly one importance line per entry and repeated `score` runs
|
|
1377
|
+
remain idempotent.
|
|
1378
|
+
|
|
1379
|
+
- `memory compact`: the Stage 1 summary marker is now a proper markdown
|
|
1380
|
+
list item (`- _Summarized on YYYY-MM-DD — original body dropped._`).
|
|
1381
|
+
Previously the marker was emitted as a bare italic string without the
|
|
1382
|
+
`- ` prefix, which broke the surrounding list in markdown renderers
|
|
1383
|
+
and caused `parseEntries` to misclassify it on subsequent compactions.
|
|
1384
|
+
The default `fixLine` fallback was also updated to `- (fix omitted)`
|
|
1385
|
+
for the same consistency reason.
|
|
1386
|
+
|
|
1387
|
+
### Test coverage
|
|
1388
|
+
|
|
1389
|
+
- 563 tests pass, 0 skip (3 runs confirmed no flakes). +165 tests vs v2.0.0
|
|
1390
|
+
across Pass 3 context builder, output accumulation, batch subdivision,
|
|
1391
|
+
master plan removal, scaffoldSkillsManifest, and memory score/compact
|
|
1392
|
+
formatting regression suites.
|
|
1393
|
+
|
|
1394
|
+
## [2.0.2] — 2026-04-20
|
|
1395
|
+
|
|
1396
|
+
### Fixed
|
|
1397
|
+
|
|
1398
|
+
- **Upgrade-path silent-skip regression for pre-v2.0.0 projects** — `npx claudeos-core health` permanently reported `content-validator: fail` with 9 × MISSING guide errors on projects that had been initialized on a pre-v2.0.0 release and then upgraded. Pass 3 wrote `pass3-complete.json` before the Pass 3 output-completeness guards (H1/H2) existed, so the marker was valid-looking on disk even though `claudeos-core/guide/` (and sometimes `standard/00.core/01.project-overview.md`, `skills/`, or `plan/`) had never been populated. On subsequent runs, `init.js` observed the marker + an existing CLAUDE.md, skipped Pass 3, and never regenerated the missing outputs — leaving the project in a stuck-fail state that only `--force` (which wipes `.claude/rules/` and loses manual edits) could recover. The Pass 3 stale-marker branch in `bin/commands/init.js` previously only detected externally-deleted CLAUDE.md; it now also drops the marker when any entry in `lib/expected-guides.js` is missing/BOM-aware-empty or when `findMissingOutputs()` (`lib/expected-outputs.js`) flags a missing standard sentinel / `skills/` / `plan/`. Mirrors the existing `dropStalePass4Marker` pattern (symmetric helper `dropStalePass3Marker` added) and reuses the same "unlink failure surfaces as `InitError` with Windows AV/file-lock guidance" contract so the recovery itself can't silently regress. Recovery is one-shot: next `init` re-runs Pass 3, which populates the missing outputs and writes a fresh marker gated by the v2.0.0 H1/H2 guards.
|
|
1399
|
+
|
|
1400
|
+
### Added
|
|
1401
|
+
|
|
1402
|
+
- **`tests/pass3-marker.test.js`** — Six new cases covering the stale-detection branches: (a) missing guide dir → drop, (b) single BOM-only guide file → drop, (c) guides present but `skills/` gone → drop, (d) guides present but standard sentinel missing → drop, (e) complete state preserves marker, (f) `init.js` source-parity tripwire asserting `dropStalePass3Marker` + both `EXPECTED_GUIDE_FILES` and `findMissingOutputs` references appear in the stale-check region (guards against refactors silently regressing to v2.0.1 behavior).
|
|
1403
|
+
|
|
1404
|
+
## [2.0.1] — 2026-04-19
|
|
1405
|
+
|
|
1406
|
+
### Fixed
|
|
1407
|
+
|
|
1408
|
+
- **CI tests failing on all OS/Node combinations** — `.gitignore` no longer excludes `package-lock.json`. The GitHub Actions workflow uses `actions/setup-node` with `cache: 'npm'` and `npm ci`, both of which require a committed lockfile; without it, all 6 matrix jobs (Ubuntu/macOS/Windows × Node 18/20) failed at the install step with `Dependencies lock file is not found`.
|
|
1409
|
+
- **`npm test` script not cross-platform** — Changed `node --test tests/*.test.js` → `node --test` in `package.json`. The `*.test.js` glob was expanded by `sh` on Linux/macOS but left literal by `cmd.exe` on Windows runners, causing `Could not find 'D:\a\...\tests\*.test.js'` on all 3 Windows matrix jobs. The `node --test` built-in auto-discovery matches `**/*.test.{cjs,mjs,js}` from cwd (skipping `node_modules`), independent of shell globbing.
|
|
1410
|
+
|
|
1411
|
+
### Changed
|
|
1412
|
+
|
|
1413
|
+
- **GitHub Actions runner compatibility** — Bumped `actions/checkout@v4` → `@v5` and `actions/setup-node@v4` → `@v5` in `.github/workflows/test.yml`. The `@v4` tags ran on Node.js 20, which GitHub deprecated on 2025-09-19 (forced Node 24 transition on 2026-06-02, full removal on 2026-09-16). The `@v5` tags ship with Node 24 support and clear the deprecation warnings.
|
|
1414
|
+
|
|
1415
|
+
## [2.0.0] — 2026-04-19
|
|
1416
|
+
|
|
1417
|
+
### Added
|
|
1418
|
+
|
|
1419
|
+
- **L4 Memory Layer** — New `claudeos-core/memory/` directory with 4 persistent files:
|
|
1420
|
+
- `decision-log.md` — "Why" behind design decisions (append-only, seeded from pass2-merged.json)
|
|
1421
|
+
- `failure-patterns.md` — Recurring errors auto-scored by `npx claudeos-core memory score`
|
|
1422
|
+
- `compaction.md` — 4-stage compaction strategy with project-specific error categories
|
|
1423
|
+
- `auto-rule-update.md` — Rule improvement proposals from `npx claudeos-core memory propose-rules`
|
|
1424
|
+
- **L4 Memory rules** — New `.claude/rules/60.memory/` directory with 4 rule files (`01.decision-log.md`, `02.failure-patterns.md`, `03.compaction.md`, `04.auto-rule-update.md`) instructing when/how to read and write memory files.
|
|
1425
|
+
- **L4 Common rules** — New `.claude/rules/00.core/51.doc-writing-rules.md` and `.claude/rules/00.core/52.ai-work-rules.md` (frontmatter requirements, hallucination prevention patterns, memory vs rules distinction).
|
|
1426
|
+
- **AI Work Rules template hardening** — `.claude/rules/00.core/52.ai-work-rules.md` substantially expanded for stack/role/scenario coverage:
|
|
1427
|
+
- **New `## Safety & Security` section** (CRITICAL — overrides every other rule in the file): destructive commands (`rm -rf`, `git reset --hard`, `git push --force`, `DROP TABLE`, `npm publish`, migration `down`/`revert`, etc.) require explicit per-command user confirmation (re-confirmed each time, not blanket); secret files (`.env*`, `*.pem`, `*.key`, `id_rsa*`, credentials JSON) referenced by variable name only — never echoed/logged/committed.
|
|
1428
|
+
- **17 Hallucination Prevention patterns** (was 13 in v1.x; net +4 after removing 3 redundant). New patterns: hallucinated import (verify package manifest), wrong-version API (verify manifest **and** lockfile — `package-lock.json`/`pnpm-lock.yaml`/`yarn.lock`/`gradle.lockfile`/`poetry.lock`/`Pipfile.lock`/`uv.lock`), cross-config drift (env/config family glob across backend `.env*`/`application-*.yml`/`*settings.py` and frontend `environment*.ts`/`next.config.*`/`vite.config.*`/`nuxt.config.*`), server/client component boundary mixing (Next.js App Router `"use client"`, Nuxt server/client composables, Remix `loader`/`action` — N/A for pure SPA/backend), component prop hallucination (read the target's `interface Props`/`defineProps<>`/function signature first), hardcoded secrets (Grep regex `(api[_-]?key|token|password|secret)\s*=\s*["']\w+["']` before commit; use `process.env.X`/`os.getenv("X")`/`@Value("${X}")` instead), historical DB migration editing (Flyway `migrations/V*.sql`, Alembic `alembic/versions/*.py`, Rails `db/migrate/*.rb`, Prisma `prisma/migrations/*/migration.sql`, TypeORM `migrations/*.ts` — append-only once applied; verify with `flyway info`/`alembic history`/`prisma migrate status`).
|
|
1429
|
+
- **Backend/frontend balanced examples** throughout — `§ No Unsolicited Work` memory-dedup bullet now lists both backend (port numbers, pool sizes, handler names, transaction propagation modes) and frontend (dev server port, build output dir, env var prefixes `VITE_`/`NEXT_PUBLIC_`/`REACT_APP_`, route definitions, bundle size budgets); `§ Code/Document Generation Accuracy` framework-shape bullet covers backend (DTOs, entity field naming, repository method signatures) and frontend (component prop interfaces, store/state shapes for Pinia/Redux/Zustand, API response types, route param types, CSS module class names).
|
|
1430
|
+
- **3 internal contradictions resolved** with Exception clauses — `§1 Accuracy First` "always read directly" narrowed to "always read **critical facts** directly" with sub-agent delegation explicitly allowed for non-critical exploration; `§ No Unsolicited Work` "do not make unsolicited suggestions" gains *Exception: factual errors in this project's own docs (wrong paths, dead references, internally contradicting rules) MUST be reported even if not asked*; "do not directly read internal document directories" gains *Exception: read directly when the user explicitly asks or when debugging requires it*.
|
|
1431
|
+
- **`Project Architecture — Hands Off` section** consolidates the previous `3-Layer Design` + `Memory vs Rules` sections (11 bullets → 7) without losing the architectural defenses (cross-layer/same-layer duplication intentional, multi-rule reinforcement, `**/*` paths protection, minor wording differences not "inconsistency").
|
|
1432
|
+
- **Empty directory rule softened with marker convention** — intent markers (`.gitkeep`, `KEEP_EMPTY.md`, dir listed in CLAUDE.md as planned, or referenced by an active plan/standard/skills doc) required to qualify as "intentional"; otherwise the AI must ask before deleting. Prevents the previous absolute "all empty dirs are intentional" rule from masking genuine neglect.
|
|
1433
|
+
- **Planned reference rule softened** — `§ Planned References` "do not label as missing" gains *Exception: if a referenced path appears in 3+ documents and doesn't exist on disk, flag for human review* (parallel to the factual-error Exception above). Prevents typos from masquerading as planned references.
|
|
1434
|
+
- **`Established codebase conventions take precedence over textbook-ideal patterns`** rule added — modernization/refactoring/"current best practices" migration proposals require explicit user request (e.g., "modernize", "migrate to v3"); otherwise follow existing pattern even if a greenfield design would differ.
|
|
1435
|
+
- **Neighbor file pattern requirement** — before writing new code, read 2-3 neighboring files in the same directory for existing patterns (naming, error handling, logging, import order, return type idioms, test structure) and match them. Greenfield/textbook idioms come second to in-codebase consistency.
|
|
1436
|
+
- **`§ Hallucination Prevention` pattern 7 audience-agnostic** — "code examples in rules are essential" rationale changed from "vibe-coding workflows" (audience-dependent) to "AI-assisted code generation — reduces hallucination risk regardless of audience experience" (universal).
|
|
1437
|
+
- **§1 cleanup** — removed `Cross-check agent results against source documents` bullet (now a weaker restatement of the narrowed §1 #2 after Exception additions).
|
|
1438
|
+
- **16 regression tests** added to `tests/memory-scaffold.test.js` (21 → 37) pinning the structure (7 sections, 17 patterns, 1..17 numbering continuity), all required tokens (frontend state libs, env prefixes, lockfiles, migration patterns), Exception clauses, and removed-pattern guards to prevent silent reversion.
|
|
1439
|
+
- **Pass 4 pipeline stage** — Generates L4 Memory scaffolding (memory files, 60.memory rules, doc-writing guide, CLAUDE.md append, master plan `50.memory-master.md`) from pass2-merged.json; Claude-driven with static fallback on failure.
|
|
1440
|
+
- **New CLI subcommand**:
|
|
1441
|
+
- `memory compact | score | propose-rules`
|
|
1442
|
+
- **Pass 3 completion marker** (`pass3-complete.json`) — Prevents regeneration of CLAUDE.md on subsequent `init` runs.
|
|
1443
|
+
- **Pass 4 completion marker** (`pass4-memory.json`) — Tracks memory scaffold completion; enables resume/skip behavior across init runs.
|
|
1444
|
+
- **Stale marker recovery** — Automatically detects and removes stale Pass 3/4 markers when underlying files (CLAUDE.md or memory/) are externally deleted.
|
|
1445
|
+
- **v1.7.x migration** — Auto-backfills Pass 3 marker when upgrading from v1.7.x with existing CLAUDE.md to prevent overwrite.
|
|
1446
|
+
- **New verification coverage** — content-validator section [9/9] checks memory scaffold integrity (file presence, entry structure, required fields with fence-aware parsing); pass-json-validator [5a] validates pass3-complete.json and [5b] validates pass4-memory.json.
|
|
1447
|
+
- **Master plan file** — `plan/50.memory-master.md` aggregates all 4 memory files using `<file path="...">` blocks.
|
|
1448
|
+
- **New library module** — `lib/memory-scaffold.js` (1006 LOC) containing memory/rule/plan/CLAUDE.md scaffolding with built-in multi-language translation via Claude CLI and strict translation validation (length, headings, code fences, frontmatter, CLI-parsed keywords).
|
|
1449
|
+
- **Translation cache** — Scaffold translations are cached per-language in `claudeos-core/generated/.i18n-cache-<lang>.json` to avoid repeated Claude CLI calls on subsequent init runs.
|
|
1450
|
+
- **Confidence scoring rewrite** — `memory propose-rules` replaces v1 saturating formula (`min(1, freq/10 + imp/20)`) with sigmoid on weighted evidence plus anchor-match multiplier (unanchored patterns × 0.6, missing importance caps evidence at 6).
|
|
1451
|
+
- **Staged-rules workaround for `.claude/` sensitive-path block** — Pass 3 and Pass 4 now write rule files to `claudeos-core/generated/.staged-rules/**` instead of `.claude/rules/**`, because Claude Code's sensitive-path policy refuses direct `.claude/` writes from the `claude -p` subprocess (even with `--dangerously-skip-permissions`). The Node.js orchestrator (not subject to that policy) moves the staged tree into `.claude/rules/` after each pass via `lib/staged-rules.js`, with rename + copy-fallback for Windows cross-volume/overwrite edge cases.
|
|
1452
|
+
- **`pass-prompts/templates/common/staging-override.md`** — Prepended to Pass 3/4 prompts as an absolute write-target redirect directive (preserves subpaths, leaves prose references and frontmatter `paths:` globs untouched).
|
|
1453
|
+
- **Pass 3 silent-failure guards** — Four post-generation guards prevent writing `pass3-complete.json` on a partial success. All guards run AFTER the staged-rules move, BEFORE the marker write:
|
|
1454
|
+
- **Guard 1 (partial move):** if any staged file failed to move into `.claude/rules/`, throw `InitError` with retry guidance — next `init` re-runs Pass 3 automatically.
|
|
1455
|
+
- **Guard 2 (zero rules):** if `.claude/rules/` is empty after the move, treat it as Claude having ignored the `staging-override.md` directive and throw, instructing the user to re-run with `--force`.
|
|
1456
|
+
- **Guard 3 (H2 — incomplete guide/):** reject when any of the 9 expected guide files (list in `lib/expected-guides.js`) is missing or empty. Uses BOM-aware emptiness check (`.replace(/^\uFEFF/, "").trim().length === 0`) because `String.prototype.trim` doesn't remove U+FEFF (not in Unicode White_Space) — a BOM-only file would otherwise silently pass.
|
|
1457
|
+
- **Guard 3 (H1 — incomplete output):** reject when (a) `claudeos-core/standard/00.core/01.project-overview.md` sentinel is missing/empty, OR (b) `claudeos-core/skills/` has zero non-empty `.md` files, OR (c) `claudeos-core/plan/` has zero non-empty `.md` files. List in `lib/expected-outputs.js`. `database/` and `mcp-guide/` intentionally excluded (content-validator treats them WARNING-level; stacks legitimately skip).
|
|
1458
|
+
- **Pass 2 resume validation (H3)** — On resume, `pass2-merged.json` is parsed and validated to have ≥5 top-level keys (mirrors `pass-json-validator`'s `INSUFFICIENT_KEYS` threshold) before Pass 2 is skipped. Skeleton `{}` or malformed JSON triggers file deletion + Pass 2 re-run instead of silently poisoning Pass 3's analysis input.
|
|
1459
|
+
- **Pass 4 marker content validation (M1)** — `isValidPass4Marker` helper validates JSON shape + `passNum === 4` + non-empty `memoryFiles` array in both stale-detection and post-Claude-run gate. Rejects malformed bodies like `{"error":"timeout"}` that Claude could emit on partial failure; previously existence-only check would accept garbage and silently skip Pass 4 forever.
|
|
1460
|
+
- **`dropStalePass4Marker` helper (M1)** — Pass 4 stale-marker unlink failures now surface as `InitError` with Windows file-lock guidance instead of being swallowed by `catch (_e) { /* ignore */ }`. Previously a locked file (AV scanner / editor holding the handle) would leave the stale marker in place, and the subsequent `fileExists(pass4Marker)` check would accept it → silent Pass 4 skip.
|
|
1461
|
+
- **Pass 3 stale-marker unlink strictness** — Symmetric with Pass 4 above: `pass3-complete.json` cleanup (when CLAUDE.md is externally deleted) now throws `InitError` on unlink failure instead of being swallowed. Closes the same silent-skip class for Pass 3.
|
|
1462
|
+
- **`CLAUDEOS_SKIP_TRANSLATION=1` env guard (M2)** — `lib/memory-scaffold.js` `translateIfNeeded()` short-circuits to throw with a clear lang-specific message when this env var is set, before any `claude -p` invocation. Intended as a test-only escape hatch so translation-dependent tests (e.g. `tests/lang-aware-fallback.test.js`) assert the "translation must throw" contract deterministically regardless of whether the `claude` CLI is authenticated in the test env. Strict `=== "1"` check (not truthy-coerce) to avoid surprise-triggering on common env conventions.
|
|
1463
|
+
- **Early fail-fast for env+lang incompatibility** — `init.js` detects `CLAUDEOS_SKIP_TRANSLATION=1` combined with `--lang ≠ en` at language-selection time and throws `InitError` immediately with remediation (`unset CLAUDEOS_SKIP_TRANSLATION` or `--lang en`). Previously this combination would let the pipeline proceed and crash mid-Pass-4 with a confusing "translation skipped" error deep in the scaffolding stack.
|
|
1464
|
+
- **CI workflow (M3)** — `.github/workflows/test.yml` runs `npm test` on `ubuntu-latest × windows-latest × macos-latest × Node 18/20` matrix with `CLAUDEOS_SKIP_TRANSLATION=1` set on the test step so translation tests pass without requiring `claude` CLI in the runner. Uses `npm ci` against the committed `package-lock.json`.
|
|
1465
|
+
- **New shared library modules** — Single sources of truth for Pass 3 output expectations, preventing drift between enforcement and validation:
|
|
1466
|
+
- `lib/expected-guides.js` — 9 guide file paths. Imported by `init.js` Guard 3 H2 and `content-validator/index.js` `[5/9]` (no more hardcoded duplicates).
|
|
1467
|
+
- `lib/expected-outputs.js` — 3 additional Pass 3 outputs (standard sentinel, `skills/`, `plan/`) with `findMissingOutputs(projectRoot)` + `hasNonEmptyMdRecursive(dir)` helpers (BOM-aware). Imported by `init.js` Guard 3 H1.
|
|
1468
|
+
- **Async claude execution + progress ticker** — `cli-utils.js` adds `runClaudePromptAsync` (spawn-based, non-blocking; lets a `setInterval` ticker run concurrently with the Claude subprocess) and `runClaudeCapture` (execSync wrapper that captures stdout, used by the translation engine in `memory-scaffold.js`). `init.js` adds `makePassTicker` with three display modes — elapsed-only, file-delta, and fixed-target (`N/M files (P%)`) — driving the per-pass `⏳`/`📝` progress line in TTY (`\r`-rewritten) and CI/piped (periodic newlines) environments.
|
|
1469
|
+
- **`--force` and "fresh" resume cleanup** — Now also wipes `claudeos-core/generated/.staged-rules/` (leftover from a prior crashed Pass 3/4 run) and `.claude/rules/` (so Guard 2's zero-rules detection can't false-negative on stale rules from a previous run); under `"fresh"` mode the `pass3-complete.json` and `pass4-memory.json` markers are also unlinked so both passes re-execute. Manual edits to `.claude/rules/` are lost — acceptable under the explicit `--force`/`fresh` choice.
|
|
1470
|
+
- **190+ new tests** (296 → 489) — New/expanded suites: `memory-scaffold.test.js`, `memory-command.test.js`, `pass4-prompt.test.js`, `pass3-marker.test.js`, `pass3-guards.test.js` (Guards 1/2 + Guard 3 H1/H2 with BOM coverage), `pass2-validation.test.js` (H3 structural check), `pass4-marker-validation.test.js` (M1 `isValidPass4Marker` + `dropStalePass4Marker` regression guards), `translation-skip-env.test.js` (M2 env guard + M3 CI workflow presence), `staged-rules.test.js`, `lang-aware-fallback.test.js` (sets `CLAUDEOS_SKIP_TRANSLATION=1` at module top to make translation-throw assertions deterministic), `placeholder-substitution.test.js`, plus expansions to existing suites.
|
|
1471
|
+
- **Progress bar with ETA** — Pass 1/2/3/4 execution shows a progress bar with percentage, elapsed time, and ETA based on average step duration (carried over and extended from v1.7.0; Pass 4 added).
|
|
1472
|
+
- **Platform/tier-split frontend detection (framework-agnostic)** — `scan-frontend.js` now recognizes `src/{platform}/{subapp}/` layouts where `{platform}` is either a device/target-environment keyword (`desktop`, `pc`, `web`, `mobile`, `mc`, `mo`, `sp`, `tablet`, `tab`, `pwa`, `tv`, `ctv`, `ott`, `watch`, `wear`) or an access-tier keyword (`admin`, `cms`, `backoffice`, `back-office`, `portal`) — covers English names plus common Korean corporate abbreviations. The short `adm` abbreviation is deliberately excluded as too ambiguous in isolation; projects using `src/adm/` as an admin root should rename to `admin` or wait for the override-file mechanism planned for a future release. Emits one domain per (platform, subapp) pair named `{platform}-{subapp}`, with per-domain counts for `routes`/`components`/`layouts`/`hooks`. Runs as a shared pattern across **all** detected frontends (Angular, Next.js, React, Vue/Nuxt) — the glob uses a multi-extension filter (`{tsx,jsx,ts,js,vue}`) so Angular `.component.ts` files and Vue `.vue` files are captured alongside React `.tsx`. A minimum of 2 source files per subapp is required before a domain is emitted — single-file dirs under a platform root are almost always accidental and would otherwise produce noisy 1-file "domains" in the Pass 1 group plan. Subapp name is always read from the filesystem via `path.basename` at scan time — no project/brand identifiers are hardcoded. Structural dirs (`components`, `hooks`, `layouts`), FSD layers (`widgets`, `features`, `entities`), and framework router dirs (`app`, `pages`, `routes`, `views`, `screens`, `containers`, `modules`, `domains`) are skipped at the subapp level so deeper structures still reach their dedicated scanners. Ambiguous names like `store` are deliberately allowed because e-commerce projects legitimately use them as subapp names. **Behavior note:** the change is additive for projects whose `src/{platform}/{subapp}/` dirs were previously unreachable by the primary/FSD/components scanners — those projects now gain the new domains; projects whose content was already being captured by other scanners see no change (the skip list ensures `src/admin/pages/*`, `src/admin/components/*`, etc. still fall through to their existing scanners).
|
|
1473
|
+
- **Deep routes-file fallback (Fallback E, framework-agnostic)** — Catches React Router file-routing projects (CRA/Vite + `react-router`) that don't match Next.js `page.tsx` or FSD layouts. When all primary scanners and Fallback A–D return 0, globs `**/routes/*.{tsx,jsx,ts,js,vue}` and groups by the parent-of-`routes` directory name. Also runs across all frontends (Angular/Next/React/Vue), not gated to any single framework. Generic parent names (`src`, `app`, `pages`) are filtered so the fallback emits meaningful feature/subapp names rather than framework-convention placeholders.
|
|
1474
|
+
- **Shared scanner ignore lists** — `BUILD_IGNORE_DIRS` (node_modules, build, dist, out, .next, .nuxt, .svelte-kit, .angular, .turbo, .cache, .parcel-cache, coverage, storybook-static, .vercel, .netlify) and `TEST_FILE_IGNORE` (spec/test/stories/e2e/cy + `__snapshots__`/`__tests__` dirs) extracted as module-level constants. Both the platform scan and Fallback E consume these so build outputs and test fixtures don't inflate per-domain file counts or create spurious Fallback E hits.
|
|
1475
|
+
- **Monorepo platform split** — Platform scan now matches three layouts: `src/{platform}/{subapp}/` (standalone), `{apps,packages}/*/src/{platform}/{subapp}/` (Turborepo/pnpm workspace with `src/`), and `{apps,packages}/{platform}/{subapp}/` (workspaces without a `src/` wrapper). Platform segment is located via `parts.findIndex` on the keyword list, so paths like `src/pc/admin/` correctly split into `pc` (platform) + `admin` (subapp) without mistaking the subapp name for another platform keyword.
|
|
1476
|
+
- **Windows path glob fix across all scanners** — `dirGlobPrefix()` helper extracted to module scope and applied to every `${dir}**/*.ext` pattern (Angular primary + deep fallback, Next/React/Vue primary, FSD, components/*, Fallback C, Fallback D, platform scan). On Windows, glob v10+ returns backslash paths without a trailing slash, so the old `${dir.replace(/\\/g,"/")}**/*.tsx` pattern became `foo**/*.tsx` and only matched one level deep — silently missing nested files like `foo/routes/X.tsx` and (in some cases) spuriously matching sibling directories sharing the same prefix. The helper normalizes to `foo/**/*.tsx`, producing correct matches at any depth. Per-domain file counts may shift slightly in existing projects where this bug was masking under- or over-counts.
|
|
1477
|
+
- **Skip-list tightening in primary scanners** — To keep deep fallbacks (Angular deep fallback, Fallback C) effective, structural container names now short-circuit the primary scans: `modules`/`features`/`pages`/`views` added to `skipAngularDirs`; `components`/`hooks`/`widgets`/`entities`/`features`/`modules`/`lib`/`libs`/`utils`/`util`/`config`/`types`/`shared`/`common`/`assets` added to the Next/React/Vue `skipPages` list. A path like `src/desktop/app/components/order/` now correctly emits `order` via Fallback C instead of the generic `components` domain from the primary pattern.
|
|
1478
|
+
- **Project override file `.claudeos-scan.json`** — Optional file at project root allows extending scanner defaults without editing the tool:
|
|
1479
|
+
```json
|
|
1480
|
+
{
|
|
1481
|
+
"frontendScan": {
|
|
1482
|
+
"platformKeywords": ["kiosk"],
|
|
1483
|
+
"skipSubappNames": ["legacy"],
|
|
1484
|
+
"minSubappFiles": 3
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
```
|
|
1488
|
+
All fields additive (user entries extend defaults, never replace). `minSubappFiles` overrides the default `2`. Missing file or malformed JSON silently falls back to defaults. Resolves the `src/adm/` → `admin` rename requirement raised when the `adm` short abbreviation was excluded from the built-in keyword list.
|
|
1489
|
+
|
|
1490
|
+
### Changed
|
|
1491
|
+
|
|
1492
|
+
- **4-Pass pipeline** — `init` now runs Pass 1 → Pass 2 → Pass 3 → Pass 4 (previously 3-Pass). Init banner updated to `Bootstrap (4-Pass)` and `totalSteps` recomputed as `totalGroups + 3`.
|
|
1493
|
+
- **Directory count** — `init` now creates 28 directories (previously 26) with `claudeos-core/memory/` and `.claude/rules/60.memory/` added.
|
|
1494
|
+
- **Verification tools extended** — sync-checker now tracks 7 directories (added `memory/`); manifest-generator scans and indexes the memory layer with `totalMemory` in the summary.
|
|
1495
|
+
- **content-validator section count** — `[1/8]`–`[8/8]` re-numbered to `[1/9]`–`[9/9]` with a new section `[9/9] claudeos-core/memory/` performing fence-aware structural validation (decision-log heading dates, failure-pattern required fields).
|
|
1496
|
+
- **CLAUDE.md output** — Pass 4 appends a new `## Memory (L4)` section (the `(L4)` marker is language-independent so the CLI fallback can detect it across all 10 supported languages).
|
|
1497
|
+
- **Pass-3/Pass-4 prompts** — `pass3-footer.md` and the new `pass4.md` template are now wrapped with the `staging-override.md` directive so Claude redirects all `.claude/rules/` writes to the staging dir without dropping or rewriting prose references.
|
|
1498
|
+
- **`bin/cli.js`** — `cmdInit` is now `async` and `await`ed; init flow uses the new async claude executor end-to-end so the per-pass tickers actually fire.
|
|
1499
|
+
|
|
1500
|
+
### Fixed
|
|
1501
|
+
|
|
1502
|
+
- **Glob pattern false-anchoring in memory preservation** — `isPreserved()` and `propose-rules` now skip glob patterns (`**/*`, `src/**/*.java`) when matching rule anchors against pattern bodies; a literal glob inside an entry's Fix line no longer makes every matching low-importance entry permanently preserved.
|
|
1503
|
+
- **Fence-aware entry parsing** — memory.js `parseEntries()` and content-validator's memory checks now ignore `## ...` lines inside ```` ``` ```` / `~~~` code fences; example markdown inside a decision's body text is no longer parsed as a new entry.
|
|
1504
|
+
- **Anchored regex for metadata fields** — `parseField()` and `parseDate()` require start-of-line + hyphen prefix for `frequency:` / `last seen:` / `importance:`; verbose prose containing these words (e.g., "set the frequency: 10 in config") is no longer picked up as the entry's meta value.
|
|
1505
|
+
- **Fix line detection** — matches only `- Fix:` / `- **fix**:` / `- solution:` field format (not arbitrary `fix`/`prefix` substrings); a verbose line containing "fixing" no longer falsely satisfies the Stage 1 fix-line preservation check.
|
|
1506
|
+
- **Stage 2 duplicate-merge persistence** — merged `frequency` sum and `lastSeen` max are now rewritten back into body lines before serialization; previously the in-memory merge was silently discarded on disk.
|
|
1507
|
+
- **Stage 3 drop respects anchors** — low-importance aged entries anchored by an active rule path (concrete file path match) are no longer silently dropped.
|
|
1508
|
+
- **Compaction section preservation** — `memory compact` only replaces the `## Last Compaction` section; user-added content that follows (e.g., project notes) is preserved.
|
|
1509
|
+
- **Pass 3 marker write validation** — `init` now throws `InitError` if `pass3-complete.json` write fails (previously silently succeeded, causing next run to regenerate CLAUDE.md).
|
|
1510
|
+
- **Silent Pass 3 marker on incomplete output** — `pass3-complete.json` could be written even when Claude truncated mid-response and `claudeos-core/guide/` was entirely empty (9 files missing). Root cause: step [8] content-validator ran with `ignoreError:true` so the 9 MISSING errors didn't block the "✅ Complete" banner; the next `init` run saw the marker + skipped Pass 3 permanently. Fixed by Guard 3 H2 (see Added). Also covers the same truncation pattern affecting `standard/`, `skills/`, `plan/` via Guard 3 H1.
|
|
1511
|
+
- **Silent Pass 4 skip on malformed marker** — Claude can emit a partial-failure marker body like `{"error":"timeout"}` that still satisfies `fileExists()`. Previously this gated subsequent runs into skipping Pass 4 forever. Fixed by `isValidPass4Marker` content validation (see Added M1).
|
|
1512
|
+
- **Silent Pass 3/4 skip on Windows file-lock** — Stale-marker `fs.unlinkSync` calls were wrapped in `catch (_e) { /* ignore */ }`. If antivirus or an editor held the file handle, the unlink threw, was silently swallowed, and the subsequent `fileExists(marker)` check accepted the stale marker → silent pass-skip. Both Pass 3 and Pass 4 now surface unlink failures as `InitError` with actionable "close the editor/AV scanner" guidance (see Added `dropStalePass4Marker` + Pass 3 symmetric fix).
|
|
1513
|
+
- **Pass 2 resume accepting skeleton `{}`** — `init.js` previously only `fileExists()`-checked `pass2-merged.json` on resume. A prior crashed run that left a skeleton `{}` or malformed JSON would be accepted, poisoning Pass 3's analysis. Fixed by H3 (see Added).
|
|
1514
|
+
- **Translation fallback safety** — when `--lang` is non-English, translation failures in the static fallback path now throw `InitError` instead of silently writing English content (contradicting the user's `--lang` choice).
|
|
1515
|
+
- **Translation validation** — memory-scaffold rejects translations that lose ≥40% content length, drop >40% of headings, break code-fence count, lose required CLI-parsed keywords (`frequency:`, `last seen:`, `importance:`, `(L4)`), or break YAML frontmatter markers.
|
|
1516
|
+
- **Placeholder substitution safety** — Pass 1 prompt placeholder substitution (`{{DOMAIN_GROUP}}`, `{{PASS_NUM}}`) and `injectProjectRoot`'s `{{PROJECT_ROOT}}` substitution both now use replacement functions so `$`, `$1`, `$&`, `$$` in domain names or project paths are preserved as literal characters rather than interpreted as regex back-references (same bug class as v1.6.x's `replaceFileBlock`).
|
|
1517
|
+
- **Stale `.staged-rules/` from prior crashed runs** — Pass 3 and Pass 4 now wipe any leftover staging directory before running Claude, so a crashed prior run can't smuggle stale rule files into the move step alongside the fresh output.
|
|
1518
|
+
- **Windows shell-escape warning (DEP0190)** — `runClaudePromptAsync` builds the spawn command as a single string with `shell: true` on Windows (so `claude.cmd`/`.ps1` shims resolve via PATH) and as separate args on Unix (no shell), eliminating Node 18+'s deprecation warning about mixing `shell:true` with an args array. Flags are hardcoded literals — no injection surface either way.
|
|
1519
|
+
- **Pass 3 skipped under `--force` / "fresh" resume mode** — The v1.7.x→v2.0.0 backfill guard fired whenever `CLAUDE.md + pass2-merged.json` existed and the `pass3-complete.json` marker was missing, even when the marker was missing *because* `--force` or `"fresh"` had just deleted it. The guard re-wrote the marker, Pass 3 was skipped, and the project was left with a stale `CLAUDE.md` alongside freshly-regenerated `pass1/2` artifacts and wiped `.claude/rules/` — which then failed both `sync-checker` (Master Plan orphans) and `content-validator` (missing sections). `init.js` now tracks a `wasFreshClean` flag set by the `--force` and `"fresh"` cleanup branches and gates the backfill with `!wasFreshClean`, so explicit fresh requests always run Pass 3. The existing guard still covers the intended v1.7.x upgrade path. Regression test added in `tests/pass3-marker.test.js`.
|
|
1520
|
+
|
|
1521
|
+
### Migration notes
|
|
1522
|
+
|
|
1523
|
+
Existing v1.7.x projects are automatically migrated on the first `v2.0.0` `init` run:
|
|
1524
|
+
- If `CLAUDE.md` and `pass2-merged.json` exist, `pass3-complete.json` is backfilled to preserve the existing `CLAUDE.md`.
|
|
1525
|
+
- `claudeos-core/memory/` and `.claude/rules/60.memory/` are scaffolded by Pass 4 (or static fallback with Claude-driven translation when `--lang` is non-English).
|
|
1526
|
+
- A new `## Memory (L4)` section is appended to the existing `CLAUDE.md`.
|
|
1527
|
+
- No manual steps required.
|
|
1528
|
+
- To force full regeneration, use `npx claudeos-core init --force`. Note that under v2.0.0, `--force` and `"fresh"` resume mode now also wipe `.claude/rules/` and `claudeos-core/generated/.staged-rules/` — manual edits to existing rule files will be lost. Back them up first if needed.
|
|
1529
|
+
|
|
1530
|
+
### Known constraints
|
|
1531
|
+
|
|
1532
|
+
- **`claude` CLI is now a hard requirement for non-English languages.** v1.7.x silently fell back to English when translation failed; v2.0.0 throws `InitError` instead. If `--lang` is non-`en`, ensure `claude` is installed and authenticated before running `init`. Use `--lang en` to bypass the translation requirement.
|
|
1533
|
+
- **`.claude/rules/` writes from Claude `-p` are blocked by Claude Code's sensitive-path policy.** v2.0.0 works around this with the staged-rules mechanism. If you author custom Pass 3/4 prompts, prepend `pass-prompts/templates/common/staging-override.md` so writes are redirected to the staging dir.
|
|
1534
|
+
- **`CLAUDEOS_SKIP_TRANSLATION=1` is a test-only escape hatch.** It short-circuits `translateIfNeeded()` to throw before invoking `claude -p`. If set in your shell accidentally (e.g. leftover from CI/test setup), `init` will fail fast when `--lang` is non-`en`. Remedy: `unset CLAUDEOS_SKIP_TRANSLATION` or run with `--lang en`. CI workflows can set it to keep translation tests deterministic without installing `claude`.
|
|
1535
|
+
|
|
1536
|
+
## [1.7.1] — 2026-04-11
|
|
1537
|
+
|
|
1538
|
+
### Added
|
|
1539
|
+
|
|
1540
|
+
- **Java scanner unit tests** — New `tests/scan-java.test.js` with 18 tests covering all 5 patterns (A/B/C/D/E), supplementary scan, skip list, root package extraction, MyBatis XML detection, DDD infrastructure/ detection, and full fallback
|
|
1541
|
+
- **Flask dedicated template** — New `pass-prompts/templates/python-flask/` with pass1/pass2/pass3 prompts tailored for Flask (Blueprint, @app.route, application factory, g/current_app, before_request, WTForms, Flask-SQLAlchemy, Flask-Login, Jinja2); Flask no longer shares python-fastapi template
|
|
1542
|
+
- **FastAPI/Flask flat project fallback** — `scan-python.js` now detects flat projects with `main.py` or `app.py` at root (or `app/main.py`) when no router files or subdomain structure exists; covers FastAPI official tutorial structure
|
|
1543
|
+
- **Vite SPA primary path scanning** — `scan-frontend.js` now detects `src/views/*/`, `src/screens/*/`, `src/routes/*/` in primary scan; Vite SPA projects no longer fall through to Fallback D
|
|
1544
|
+
- **296 tests** (287 → 296) — Added 9 new tests: Flask template selection, flat project fallback (5 cases), Vite SPA primary paths (3 cases)
|
|
1545
|
+
|
|
1546
|
+
### Fixed
|
|
1547
|
+
|
|
1548
|
+
- **Java scanner Windows path normalization** — `scan-java.js` added `norm()` function and `.map(norm)` to 9 glob calls; regex matching failed on Windows backslash paths for Pattern E (DDD/Hexagonal), root package extraction, and supplementary scan
|
|
1549
|
+
- **Pattern E missing infrastructure/ detection** — `scan-java.js` Pattern E `mprGlob` now includes `{domain}/infrastructure/*.java` in addition to `adapter/out/{persistence,repository}/`
|
|
1550
|
+
- **Flask misusing FastAPI template** — `selectTemplates()` now routes `framework: "flask"` to dedicated `python-flask` instead of `python-fastapi`
|
|
1551
|
+
- **Completion banner alignment** — `Total time:` label spacing fixed to align with other rows
|
|
1552
|
+
|
|
1553
|
+
## [1.7.0] — 2026-04-11
|
|
1554
|
+
|
|
1555
|
+
### Added
|
|
1556
|
+
|
|
1557
|
+
- **Vite SPA support** — Full Vite detection pipeline: `stack-detector.js` detects `vite` from package.json dependencies and `vite.config.ts/js` fallback; `selectTemplates()` routes to dedicated `node-vite` template; `determineActiveDomains()` correctly classifies Vite as frontend-only
|
|
1558
|
+
- **`node-vite` template** — New `pass-prompts/templates/node-vite/` with pass1/pass2/pass3 prompts tailored for Vite SPA (client-side routing, VITE_ env prefix, Vitest, static hosting deployment — no RSC/Server Actions/next.config)
|
|
1559
|
+
- **Non-standard nested path scanning** — `scan-frontend.js` now detects pages, components, and FSD layers under `src/*/` paths (e.g., `src/admin/pages/dashboard/`, `src/admin/components/form/`, `src/admin/features/billing/`)
|
|
1560
|
+
- **No-hallucination guardrail** — `pass3-footer.md` enforces that Pass 3 may only reference technologies explicitly present in `project-analysis.json` or `pass2-merged.json`; inference from other detected libraries is prohibited
|
|
1561
|
+
- **Skill orchestrator completeness guardrail** — `pass3-footer.md` enforces that orchestrator execution tables must list all sub-skill files with no gaps in the sequence
|
|
1562
|
+
- **Progress bar with ETA** — Pass 1/2/3 execution now shows a progress bar with percentage, elapsed time, and estimated remaining time based on average step duration
|
|
1563
|
+
- **Angular/Next.js default ports** — `defaultPort` logic now assigns 4200 for Angular and 3000 for frontend-only Next.js projects
|
|
1564
|
+
- **Enriched Node.js scanner** — `scan-node.js` now classifies entities, modules, guards, pipes, and interceptors (NestJS-aware) in addition to controllers/services/dtos
|
|
1565
|
+
- **Enriched Python scanner** — `scan-python.js` now classifies admin, forms, urls, and tasks (Django/Celery-aware) in addition to views/models/serializers
|
|
1566
|
+
- **Fastify handler detection** — `scan-node.js` now counts `handler` files as controllers alongside controller/router/route
|
|
1567
|
+
|
|
1568
|
+
### Fixed
|
|
1569
|
+
|
|
1570
|
+
- **Vite SPA misclassified as Next.js** — `selectTemplates()` now routes `frontend: "react"` + `framework: "vite"` to `node-vite` instead of `node-nextjs`
|
|
1571
|
+
- **Vite incorrectly assigned backend template** — Backend template fallback (`node-express`) now excludes `framework: "vite"`
|
|
1572
|
+
- **Vite SPA marked as backend project** — `determineActiveDomains()` now excludes `framework: "vite"` from backend activation
|
|
1573
|
+
- **Vite default port** — Port 5173 assigned for Vite instead of falling back to 8080
|
|
1574
|
+
- **Vite triggers unnecessary backend scan** — `structure-scanner.js` now skips Node.js backend scanning when `framework: "vite"`
|
|
1575
|
+
- **Frontend-only security-db activation** — `determineActiveDomains()` now activates `30.security-db` for frontend-only projects (auth/token/XSS standards are relevant); previously required a backend framework
|
|
1576
|
+
- **FSD glob deduplication** — `scan-frontend.js` FSD layer scanning now uses Set-based deduplication matching the existing components pattern
|
|
1577
|
+
- **269 tests** (256 → 269) — Added 13 new tests for Vite detection, template selection, non-standard paths, and active domain classification
|
|
1578
|
+
|
|
1579
|
+
## [1.6.2] — 2026-04-09
|
|
1580
|
+
|
|
1581
|
+
### Fixed
|
|
1582
|
+
|
|
1583
|
+
- **Sync command crash bypass** — `cli.js` sync throw from `cmdHealth`/`cmdValidate`/`cmdRestore`/`cmdRefresh` now correctly caught by `.catch()` handler; previously caused unhandled exception
|
|
1584
|
+
- **`init.js` group.domains crash** — Null guard added for `group.domains` and `group.estimatedFiles` in domain-groups iteration; prevents TypeError on malformed `domain-groups.json`
|
|
1585
|
+
- **Kotlin shared query resolution failure** — `scan-kotlin.js` full key (`__` separator) module names now converted back to path form (`/`) before file matching; `resolveSharedQueryDomains` was silently failing to find any files
|
|
1586
|
+
- **Python scanner Windows glob failure** — `scan-python.js` added `dir.replace(/\\/g, "/")` for Django and FastAPI/Flask glob patterns; Windows `path.dirname` returns backslashes that break glob (same fix `scan-node.js` already had)
|
|
1587
|
+
- **`prompt-generator.js` langData.labels crash** — Added null guard for `langData.labels` access; prevents TypeError when `lang-instructions.json` has `instructions` but missing `labels` key
|
|
1588
|
+
- **Plan parser heading description leakage** — `plan-parser.js` `parseCodeBlocks` now strips trailing ` — description` / ` – description` / ` - description` from heading; previously included in `filePath`
|
|
1589
|
+
- **Content validator regex escape** — `content-validator/index.js` regex character class now correctly escapes `[` and `]`; previously `[` was unescaped, causing runtime error when keyword contains `[`
|
|
1590
|
+
- **Manifest generator CODE_BLOCK_PLANS count** — `plan-manifest.json` now uses `extractCodeBlockPathsFromFile` for code-block-format plans (e.g., `21.sync-rules-master.md`); `fileBlocks` count was always 0
|
|
1591
|
+
- **Resume pass1/pass2 inconsistency** — When "continue" is selected but no pass1 files exist while pass2 does, pass2 is now deleted to force re-run; previously new pass1 + stale pass2 caused data mismatch
|
|
1592
|
+
- **`--force` incomplete cleanup** — Now deletes all `.json` and `.md` files in `generated/` directory (not just pass1/pass2); ensures truly fresh start including stale prompts, manifests, and reports
|
|
1593
|
+
- **Workspace path without wildcard** — `stack-detector.js` now handles concrete workspace paths (e.g., `packages/backend`) by scanning both direct and child `package.json` files; previously only glob patterns with `*` worked
|
|
1594
|
+
- **Framework-less Python projects skipped** — `structure-scanner.js` now triggers Python scanner for all `language === "python"` projects; previously required `framework` to be `django`/`fastapi`/`flask`
|
|
1595
|
+
- **Root directory router.py false domain** — `scan-python.js` now skips `name === "."` when `router.py` is in project root; previously created a domain named `.`
|
|
1596
|
+
- **Sync checker null sourcePath** — `sync-checker/index.js` now skips mappings with null/undefined `sourcePath`; previously produced `path.join(ROOT, undefined)` = `"ROOT/undefined"`
|
|
1597
|
+
- **Java Pattern B/D detection instability** — `scan-java.js` `detectedPattern` now determined by majority vote across all domains; previously depended on first `Object.keys` insertion order
|
|
1598
|
+
- **Duplicate pass1 prompt overwrite** — `prompt-generator.js` deduplicates `activeTemplates` via `Set`; when backend and frontend share the same template, pass1 is generated once instead of being overwritten
|
|
1599
|
+
- **Health checker stale-report overwrite** — Removed redundant `generatedAt` write that was overwriting `manifest-generator`'s `summaryPatch`; manifest-generator (run as prerequisite) already sets this key
|
|
1600
|
+
- **Plan validator empty file creation** — `--execute` mode now skips file creation when plan block has empty/whitespace-only content; previously created blank files
|
|
1601
|
+
|
|
1602
|
+
## [1.6.1] — 2026-04-09
|
|
1603
|
+
|
|
1604
|
+
### Fixed
|
|
1605
|
+
|
|
1606
|
+
- **Path traversal hardening (Windows)** — `plan-validator` and `sync-checker` now use case-insensitive path comparison on Windows, preventing UNC/case-mismatch bypass of root boundary check
|
|
1607
|
+
- **Null pointer crash in `stack-detector.js`** — `readFileSafe()` return value for `pnpm-workspace.yaml` now guarded; prevents crash when file exists but is unreadable
|
|
1608
|
+
- **Empty pass3 prompt generation** — `prompt-generator.js` now early-returns with warning when pass3 template is missing, instead of silently writing header+footer-only prompt
|
|
1609
|
+
- **Domain group boundary off-by-one** — `splitDomainGroups` changed `>=` to `>` for file count threshold; groups now fill up to exactly `MAX_FILES_PER_GROUP` (40) instead of flushing one file early
|
|
1610
|
+
- **Perl regex injection in `bootstrap.sh`** — All placeholder substitution migrated from `perl -pi -e` to Node.js `String.replace()`; eliminates regex special character risk in domain names; `perl` is no longer a prerequisite
|
|
1611
|
+
- **Flask default port** — `plan-installer` now maps Flask to port 5000 (was falling through to 8080)
|
|
1612
|
+
- **Health-checker dependency chain** — `sync-checker` is now automatically skipped when `manifest-generator` fails, instead of running against missing `sync-map.json`
|
|
1613
|
+
- **`pass-json-validator` null template crash** — Added null guard before `typeof` check; `null` no longer passes `typeof === "object"` gate
|
|
1614
|
+
- **`pass-json-validator` missing backend frameworks** — Added `"fastify"` and `"flask"` to backend framework list; these stacks previously skipped backend section validation
|
|
1615
|
+
- **Init error messages** — Pass 1/2/3 failure messages now include actionable guidance (check output above, retry with `--force`, verify prompt file)
|
|
1616
|
+
- **Manifest-generator error context** — `.catch()` handler now prefixes error with tool name
|
|
1617
|
+
- **Line counting off-by-one** — `statSafe()` and `manifest-generator stat()` no longer count trailing newline as an extra line
|
|
1618
|
+
- **Windows CRLF drift** — `plan-validator` now normalizes `\r\n` → `\n` before content comparison; prevents false drift on Windows
|
|
1619
|
+
- **`stale-report.js` mutation** — `Object.assign(ex.summary, patch)` replaced with spread operator to avoid in-place mutation
|
|
1620
|
+
- **Undefined in sync-checker Set** — Malformed mappings with missing `sourcePath` no longer insert `undefined` into the registered paths Set
|
|
1621
|
+
- **BOM frontmatter detection** — `content-validator` now strips UTF-8 BOM (`\uFEFF`) before checking `---` frontmatter marker
|
|
1622
|
+
- **Health-checker stderr loss** — Error output now combines both `stdout` and `stderr` instead of preferring one
|
|
1623
|
+
- **`bootstrap.sh` exit code preservation** — EXIT trap now captures and restores `$?` instead of always exiting 0
|
|
1624
|
+
- **`bootstrap.sh` NODE_MAJOR stderr** — `node -e` stderr redirected to `/dev/null` to prevent parse failure from noise
|
|
1625
|
+
|
|
1626
|
+
## [1.6.0] — 2026-04-08
|
|
1627
|
+
|
|
1628
|
+
### Added
|
|
1629
|
+
|
|
1630
|
+
- **JS/TS monorepo support** — Auto-detect `turbo.json`, `pnpm-workspace.yaml`, `lerna.json`, `package.json#workspaces`; scan sub-package `package.json` for framework/ORM/DB dependencies; domain scanning covers `apps/*/src/` and `packages/*/src/` patterns
|
|
1631
|
+
- **NestJS dedicated template (`node-nestjs`)** — Separate analysis prompts for `@Module`, `@Injectable`, `@Controller`, Guards, Pipes, Interceptors, DI container, CQRS, `Test.createTestingModule`; previously shared `node-express` template
|
|
1632
|
+
- **Vue/Nuxt dedicated template (`vue-nuxt`)** — Separate analysis prompts for Composition API, `<script setup>`, Pinia, `useFetch`/`useAsyncData`, Nitro server routes, `@nuxt/test-utils`; previously shared `node-nextjs` template
|
|
1633
|
+
- **Elapsed time tracking** — CLI shows per-pass elapsed time and total time in completion banner
|
|
1634
|
+
- **169 new tests** (87 → 256) — Full coverage for `scan-frontend.js` (4-stage fallback), `scan-kotlin.js` (CQRS, shared query resolution), `scan-node.js`, `scan-python.js`, `prompt-generator.js` (multi-stack), `lang-selector.js`, `resume-selector.js`, `init.js`, `plan-parser.js`, monorepo detection
|
|
1635
|
+
- **README updates (10 languages)** — Updated all README files (en, ko, zh-CN, ja, es, vi, hi, ru, fr, de) to reflect new stacks table (NestJS/Vue split), monorepo root execution, facade/usecase/orchestrator detection, template structure, 3 new FAQ entries, 256 test count
|
|
1636
|
+
|
|
1637
|
+
### Fixed
|
|
1638
|
+
|
|
1639
|
+
- **Windows backslash glob in `scan-kotlin.js`** — glob returns backslash paths on Windows, causing multi-module detection to silently fail; added `norm()` normalization (no-op on Unix)
|
|
1640
|
+
- **Kotlin module key collision** — When same module name exists under different parents (e.g., `servers/command/api-server` + `servers/query/api-server`), both entries now upgrade to full key; `domainMap` merges counts instead of overwriting
|
|
1641
|
+
- **Java facade/usecase/orchestrator detection** — `scan-java.js` now detects `facade/`, `usecase/`, `orchestrator/` directories as service-layer (previously only `aggregator/`)
|
|
1642
|
+
- **Verification tools exit code** — 4 tools (`content-validator`, `plan-validator`, `sync-checker`, `pass-json-validator`) now exit(1) on unexpected errors instead of exit(0); `health-checker` wrapped in try/catch
|
|
1643
|
+
|
|
1644
|
+
### Changed
|
|
1645
|
+
|
|
1646
|
+
- **`lib/plan-parser.js`** (new) — Extracted shared `parseFileBlocks`, `parseCodeBlocks`, `replaceFileBlock`, `replaceCodeBlock`, `CODE_BLOCK_PLANS` from `manifest-generator` and `plan-validator`; eliminates duplicate code across 2 files
|
|
1647
|
+
- **`lib/stale-report.js`** (new) — Extracted shared `updateStaleReport()` from 6 verification tools; eliminates copy-paste pattern
|
|
1648
|
+
- **`cli-utils.js`** — `ensureDir` and `fileExists` now delegate to `lib/safe-fs.js` (single source of truth)
|
|
1649
|
+
- **`prompt-generator.js`** — Removed dead strip regex (no template matched these patterns)
|
|
1650
|
+
- **`init.js` process.exit refactoring** — `process.exit(1)` replaced with `throw InitError`; `lang-selector.js` and `resume-selector.js` return `null` instead of calling `process.exit()`; all errors handled centrally in `cli.js`
|
|
1651
|
+
|
|
1652
|
+
## [1.5.1] — 2026-04-06
|
|
1653
|
+
|
|
1654
|
+
### Fixed
|
|
1655
|
+
- **Remove 13 bare catch blocks** — `catch { }` → `catch (_e) { }` across 9 files; enables error variable access during debugging
|
|
1656
|
+
- **Windows backslash glob fix (3 locations)** — `scan-frontend.js` missing `dir.replace(/\\/g, "/")` at App/Pages Router (line 63), FSD (line 84), and components (line 98) scans; other locations already had this fix
|
|
1657
|
+
- **Pattern C flat MyBatis XML detection** — `scan-java.js` xmlGlob now matches flat XML layout (e.g., `mapper/OrderMapper.xml`) in addition to domain subdirectory layout for Pattern C projects
|
|
1658
|
+
- **Next.js reserved segment false positives** — Added `not-found`, `error`, `loading` to `skipPages` in `scan-frontend.js` to prevent Next.js App Router reserved directories from being detected as domains
|
|
1659
|
+
- **cap variable shadowing** — Renamed outer-scope `cap` to `capDn` in `scan-java.js` to avoid shadowing the block-scoped `cap` in Pattern C branch
|
|
1660
|
+
|
|
1661
|
+
### Changed
|
|
1662
|
+
- **Gradle DB detection comment** — Added 2-line comment explaining postgres/sqlite exclusion rationale in `stack-detector.js` line 118
|
|
1663
|
+
|
|
1664
|
+
## [1.5.0] — 2026-04-05
|
|
908
1665
|
- feat: initial release claudeos-core v1.5.0
|