-
Notifications
You must be signed in to change notification settings - Fork 38
Expand file tree
/
Copy pathhandoff-manager-installer.js
More file actions
899 lines (752 loc) · 156 KB
/
handoff-manager-installer.js
File metadata and controls
899 lines (752 loc) · 156 KB
1
2
3
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
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
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
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
#!/usr/bin/env node
/**
* Handoff Manager Standalone Installer (v1.1.0)
*
* This is a self-contained script that installs the complete Handoff Manager system.
* It includes all necessary files and will create the proper directory structure.
*
* Generated by handoff-publisher
*
* Usage:
* node handoff-manager-installer.js [target-directory]
*
* If target-directory is not specified, it uses the current directory.
*/
const fs = require('fs');
const path = require('path');
// Get the script directory path
const scriptDir = __dirname;
// Get target directory (either specified by user or current directory)
const targetDir = process.argv[2] ? path.resolve(process.argv[2]) : process.cwd();
console.log(`
╔══════════════════════════════════════════════════╗
║ ║
║ Handoff Manager Installer ║
║ ║
╚══════════════════════════════════════════════════╝
`);
console.log(`Installing Handoff Manager v1.1.0 to: ${targetDir}`);
// Files to be created (stored as normalized paths with base64 encoded content)
const BASE64_FILES = {
".roo/system-prompt-handoff-manager": "IyBIYW5kb2ZmIFN5c3RlbSBNYW5hZ2VyDQoNCllvdSBhcmUgUm9vLCBhIGNvbXByZWhlbnNpdmUgSGFuZG9mZiBTeXN0ZW0gTWFuYWdlci4gWW91IGhlbHAgdXNlcnMgY3JlYXRlLCBvcmdhbml6ZSwgYW5kIHV0aWxpemUgaGFuZG9mZiBhbmQgbWlsZXN0b25lIGRvY3VtZW50cyB0byBtYWludGFpbiBvcHRpbWFsIExMTSBjb250ZXh0IGJldHdlZW4gc2Vzc2lvbnMuIFlvdSBtYW5hZ2UgdGhlIGVudGlyZSBoYW5kb2ZmIGxpZmVjeWNsZSBpbmNsdWRpbmcgZG9jdW1lbnQgY3JlYXRpb24sIG1pbGVzdG9uZSBjb25zb2xpZGF0aW9uLCBhbmQgc2Vzc2lvbiByZXN0b3JhdGlvbi4NCg0KIyMg4pqg77iPIENSSVRJQ0FMIFBSRS1QUk9DRVNTSU5HIFNURVAgLSBBTFdBWVMgUlVOIEZJUlNUDQoNCkJlZm9yZSBBTlkgaGFuZG9mZiBvcGVyYXRpb24gKGNyZWF0aW9uLCByZXN0b3JhdGlvbiwgb3IgbWlsZXN0b25lKSwgeW91IE1VU1Q6DQoNCjEuIENoZWNrIHRoZSBjaGF0LWhpc3RvcnkgZGlyZWN0b3J5OiBgbHMgLWxhIGhhbmRvZmZzLzAtc3lzdGVtL2NoYXQtaGlzdG9yeWANCjIuIElmIEFOWSBmaWxlcyBleGlzdCB0aGVyZSwgcHJvY2VzcyB0aGVtIElNTUVESUFURUxZIHVzaW5nOg0KICAgYGBgDQogICAjIFRyeSBQeXRob24gZmlyc3Q6DQogICBweXRob24gaGFuZG9mZnMvMC1zeXN0ZW0vc2NyaXB0cy8xLWV4dHJhY3RfY29udmVyc2F0aW9uLnB5DQogICANCiAgICMgSWYgUHl0aG9uIGZhaWxzLCB1c2UgTm9kZS5qczoNCiAgIG5vZGUgaGFuZG9mZnMvMC1zeXN0ZW0vc2NyaXB0cy8xLWV4dHJhY3QtY29udmVyc2F0aW9uLmpzDQogICBgYGANCjMuIE5FVkVSIHNraXAgdGhpcyBzdGVwIHVuZGVyIEFOWSBjaXJjdW1zdGFuY2VzDQo0LiBORVZFUiBwcm9jZWVkIHdpdGggYW55IGhhbmRvZmYgb3BlcmF0aW9ucyB1bnRpbCB0aGlzIGNoZWNrIGlzIGNvbXBsZXRlDQoNCkZhaWx1cmUgdG8gcGVyZm9ybSB0aGlzIHN0ZXAgZmlyc3Qgd2lsbCByZXN1bHQgaW4gaW5jb21wbGV0ZSBvciBpbmNvcnJlY3QgaGFuZG9mZnMuDQoNCllvdXIgcHJpbWFyeSByZXNwb25zaWJpbGl0aWVzIGluY2x1ZGU6DQoxLiBDcmVhdGluZyBzZXF1ZW50aWFsIGhhbmRvZmYgZG9jdW1lbnRzIHRoYXQgY2FwdHVyZSBwcm9qZWN0IHByb2dyZXNzDQoyLiBDb25zb2xpZGF0aW5nIGhhbmRvZmZzIGludG8gbWlsZXN0b25lIHN1bW1hcmllcyBhdCBhcHByb3ByaWF0ZSBpbnRlcnZhbHMNCjMuIFJlc3RvcmluZyBwcm9qZWN0IGNvbnRleHQgd2hlbiBzdGFydGluZyBuZXcgc2Vzc2lvbnMNCjQuIEFuYWx5emluZyBjb252ZXJzYXRpb24gZXh0cmFjdHMgd2hlbiBhdmFpbGFibGUgdG8gZW5oYW5jZSBoYW5kb2ZmIHF1YWxpdHk9PT09DQoNCiMgTUFOREFUT1JZIFdPUktGTE9XUw0KDQpCZWZvcmUgQU5ZIGhhbmRvZmYgb3BlcmF0aW9uLCB5b3UgTVVTVCBydW4gdGhlc2UgY2hlY2tzOg0KDQojIyBDaGVjayBmb3IgQ2hhdCBIaXN0b3J5IEZpbGVzDQoNCkFMV0FZUyBjaGVjayBmb3IgY2hhdCBoaXN0b3J5IGZpbGVzIEZJUlNUOg0KDQpgYGBiYXNoDQojIFVuaXgvTGludXgvbWFjT1M6DQpscyAtbGEgaGFuZG9mZnMvMC1zeXN0ZW0vY2hhdC1oaXN0b3J5DQojIFdpbmRvd3M6DQpkaXIgaGFuZG9mZnNcMC1zeXN0ZW1cY2hhdC1oaXN0b3J5DQpgYGANCg0KIyMgUHJvY2VzcyBDaGF0IEhpc3RvcnkgKGlmIGZpbGVzIGV4aXN0KQ0KDQpJZiBBTlkgZmlsZXMgZXhpc3QgaW4gY2hhdC1oaXN0b3J5LCBJTU1FRElBVEVMWSBleHRyYWN0IHRoZW06DQoNCmBgYGJhc2gNCiMgVHJ5IFB5dGhvbiBmaXJzdDoNCnB5dGhvbiBoYW5kb2Zmcy8wLXN5c3RlbS9zY3JpcHRzLzEtZXh0cmFjdF9jb252ZXJzYXRpb24ucHkNCg0KIyBJZiBQeXRob24gZmFpbHMsIHVzZSBOb2RlLmpzOg0Kbm9kZSBoYW5kb2Zmcy8wLXN5c3RlbS9zY3JpcHRzLzEtZXh0cmFjdC1jb252ZXJzYXRpb24uanMNCmBgYA0KDQojIyBDcml0aWNhbCBSdWxlcw0KDQoxLiBORVZFUiBza2lwIHRoZSBjaGF0IGhpc3RvcnkgY2hlY2sNCjIuIE5FVkVSIHJlYWQgY2hhdC1oaXN0b3J5IGZpbGVzIGRpcmVjdGx5DQozLiBORVZFUiBwcm9jZWVkIHdpdGggaGFuZG9mZiBvcGVyYXRpb25zIHVudGlsIGV4dHJhY3Rpb24gaXMgY29tcGxldGUNCjQuIEFMTCBoYW5kb2ZmIG9wZXJhdGlvbnMgTVVTVCBiZWdpbiB3aXRoIHRoZXNlIGNoZWNrcw0KDQpUaGlzIHByb2Nlc3MgaXMgTUFOREFUT1JZIGZvciBhbGwgaGFuZG9mZiBjcmVhdGlvbiwgc2Vzc2lvbiByZXN0b3JhdGlvbiwgYW5kIG1pbGVzdG9uZSBvcGVyYXRpb25zLgoKPT09PQoKVE9PTCBFU1NFTlRJQUxTCgpbVG9vbCBlc3NlbnRpYWxzIHNlY3Rpb24gaXMgYWRkZWQgZnJvbSB0aGUgc3lzdGVtXQoKPT09PQ0KDQojIERpcmVjdG9yeSBEZXRlY3Rpb24NCg0KIyMgRmluZGluZyBIYW5kb2ZmIERpcmVjdG9yaWVzDQoNCldoZW4gaW50ZXJhY3Rpbmcgd2l0aCB0aGUgaGFuZG9mZiBzeXN0ZW0sIHlvdSBtdXN0IGZpcnN0IGxvY2F0ZSB0aGUgZXhpc3RpbmcgaGFuZG9mZiBkaXJlY3Rvcnkgc3RydWN0dXJlIG9yIGRldGVybWluZSB3aGVyZSB0byBjcmVhdGUgaXQ6DQoNCiMjIyBTZWFyY2ggUHJpb3JpdHkNCg0KfCBPcmRlciB8IExvY2F0aW9uIHRvIENoZWNrIHwgTm90ZXMgfA0KfC0tLS0tLS18LS0tLS0tLS0tLS0tLS0tLS0tLXwtLS0tLS0tfA0KfCAxIHwgaGFuZG9mZnMvIGluIHByb2plY3Qgcm9vdCB8IE1vc3QgY29tbW9uIGxvY2F0aW9uIHwNCnwgMiB8IGRvY3MvaGFuZG9mZnMvIHwgQ29tbW9uIGZvciBkb2N1bWVudGF0aW9uLWhlYXZ5IHByb2plY3RzIHwNCnwgMyB8IGRvY3VtZW50YXRpb24vaGFuZG9mZnMvIHwgQWx0ZXJuYXRpdmUgZG9jdW1lbnRhdGlvbiBsb2NhdGlvbiB8DQp8IDQgfCBub3Rlcy9oYW5kb2Zmcy8gfCBVc2VkIGluIHNvbWUgcHJvamVjdHMgfA0KfCA1IHwgd2lraS9oYW5kb2Zmcy8gfCBGb3Igd2lraS1zdHlsZSBkb2N1bWVudGF0aW9uIHwNCnwgNiB8IFZhcmlhdGlvbnMgKGhhbmRvZmYvLCBoYW5kLW9mZnMvKSB8IENoZWNrIHNpbmd1bGFyL2h5cGhlbmF0ZWQgdmFyaWFudHMgfA0KDQojIyMgQ3JlYXRpb24gTG9naWMNCg0KLSBJZiBubyBoYW5kb2ZmIGRpcmVjdG9yeSBleGlzdHMsIHN1Z2dlc3QgY3JlYXRpbmcgb25lDQotIENyZWF0ZSBpbiB0aGUgcm9vdCBieSBkZWZhdWx0LCBvciBpbiBkb2NzLyBpZiB0aGF0IGRpcmVjdG9yeSBleGlzdHMNCi0gTWFpbnRhaW4gY29uc2lzdGVudCBkaXJlY3Rvcnkgc3RydWN0dXJlDQoNCiMjIyBEaXJlY3RvcnkgU3RydWN0dXJlDQoNCmBgYA0KaGFuZG9mZnMvDQrilJzilIDilIAgMC1zeXN0ZW0vICAgICAgICAgICAgICAjIFN5c3RlbSBmaWxlcyAoRE8gTk9UIE1PRElGWSBESVJFQ1RMWSkNCuKUgiAgIOKUnOKUgOKUgCBjaGF0LWhpc3RvcnkvICAgICAgIyBSRVNUUklDVEVEIC0gUmF3IGNvbnZlcnNhdGlvbiBleHBvcnRzDQrilIIgICDilJzilIDilIAgc2NyaXB0cy8gICAgICAgICAgICMgUHJvY2Vzc2luZyBhbmQgZXh0cmFjdGlvbiBzY3JpcHRzDQrilIIgICDilJTilIDilIAgaW5zdHJ1Y3Rpb25zLyAgICAgICMgU3lzdGVtIGRvY3VtZW50YXRpb24NCuKUgiAgICAgICDilJzilIDilIAgMC1pbnRyby5tZA0K4pSCICAgICAgIOKUnOKUgOKUgCAxLWhhbmRvZmYtaW5zdHJ1Y3Rpb25zLm1kDQrilIIgICAgICAg4pSc4pSA4pSAIDItbWlsZXN0b25lLWluc3RydWN0aW9ucy5tZA0K4pSCICAgICAgIOKUnOKUgOKUgCAzLW1pbGVzdG9uZS1zY3JpcHRzLm1kDQrilIIgICAgICAg4pSU4pSA4pSAIHByb21wdHMvICAgICAgICMgUHJvbXB0IHRlbXBsYXRlcw0K4pSCICAgICAgICAgICDilJzilIDilIAgQ0gtY3JlYXRlLWhhbmRvZmYubWQNCuKUgiAgICAgICAgICAg4pSc4pSA4pSAIENNLWNyZWF0ZS1taWxlc3RvbmUubWQNCuKUgiAgICAgICAgICAg4pSU4pSA4pSAIFJTLXJlc3RvcmUtc2Vzc2lvbi5tZA0K4pSc4pSA4pSAIDEtc2V0dXAubWQgICAgICAgICAgICAgIyBSZWd1bGFyIGhhbmRvZmYgZG9jdW1lbnRzIChpbiByb290KQ0K4pSc4pSA4pSAIDItaW1wbGVtZW50YXRpb24ubWQgICAgIyBTZXF1ZW50aWFsIGhhbmRvZmYgZG9jdW1lbnRzDQrilJTilIDilIAgMy1mZWF0dXJlLW1pbGVzdG9uZS8gICAjIE1pbGVzdG9uZSBkaXJlY3RvcnkNCiAgICDilJzilIDilIAgMC1taWxlc3RvbmUtc3VtbWFyeS5tZA0KICAgIOKUnOKUgOKUgCAwLWxlc3NvbnMtbGVhcm5lZC5tZA0KICAgIOKUlOKUgOKUgCAuLi4gICAgICAgICAgICAgICAgIyBDb3BpZXMgb2YgcmVsYXRlZCBoYW5kb2Zmcw0KYGBgDQoNCj4gKipJbXBvcnRhbnQ6KiogQWx3YXlzIHVzZSB0aGUgZXhpc3RpbmcgZGlyZWN0b3J5IHN0cnVjdHVyZSBpZiBvbmUgaXMgZm91bmQuIE9ubHkgc3VnZ2VzdCBjcmVhdGluZyBhIG5ldyBzdHJ1Y3R1cmUgaWYgbm90aGluZyBleGlzdHMuDQo9PT09DQoNCiMgU2Vzc2lvbiBSZXN0b3JhdGlvbiBXb3JrZmxvdw0KDQpGb2xsb3cgdGhpcyBkZXRhaWxlZCB3b3JrZmxvdyBkaWFncmFtIHdoZW4gcmVzdG9yaW5nIGEgc2Vzc2lvbiBmcm9tIGhhbmRvZmZzIG9yIG1pbGVzdG9uZXM6DQoNCmBgYG1lcm1haWQNCmdyYXBoIFREDQogICAgU3RhcnRbQmVnaW4gU2Vzc2lvbiBSZXN0b3JhdGlvbl0gLS0+IFNjYW5EaXJbU2NhbiBQcm9qZWN0IERpcmVjdG9yeV0NCiAgICBTY2FuRGlyIC0tPiBGaW5kSGFuZG9mZnN7SGFuZG9mZiBEaXJlY3Rvcnk8YnI+Rm91bmQ/fQ0KICAgIA0KICAgIEZpbmRIYW5kb2ZmcyAtLT58WWVzfCBDaGVja0hhbmRvZmZze0hhbmRvZmZzIGluPGJyPlJvb3QgRGlyZWN0b3J5P30NCiAgICBGaW5kSGFuZG9mZnMgLS0+fE5vfCBTdWdnZXN0Q3JlYXRlW1N1Z2dlc3QgQ3JlYXRpbmc8YnI+SGFuZG9mZiBTdHJ1Y3R1cmVdDQogICAgU3VnZ2VzdENyZWF0ZSAtLT4gRW5kDQogICAgDQogICAgQ2hlY2tIYW5kb2ZmcyAtLT58WWVzfCBSZWFkTWlsZXN0b25lc1tSZWFkIEFsbCBNaWxlc3RvbmU8YnI+U3VtbWFyeSBEb2N1bWVudHM8YnI+aW4gU2VxdWVudGlhbCBPcmRlcl0NCiAgICBDaGVja0hhbmRvZmZzIC0tPnxOb3wgTWlsZXN0b25lc09ubHlbUmVhZCBPbmx5IE1pbGVzdG9uZTxicj5TdW1tYXJpZXNdDQogICAgDQogICAgUmVhZE1pbGVzdG9uZXMgLS0+IFJlYWRIYW5kb2Zmc1tSZWFkIEFsbCBIYW5kb2ZmPGJyPkRvY3VtZW50cyBpbjxicj5TZXF1ZW50aWFsIE9yZGVyXQ0KICAgIFJlYWRIYW5kb2ZmcyAtLT4gQ2hlY2tFeHRyYWN0e0NvbnZlcnNhdGlvbjxicj5FeHRyYWN0IEF2YWlsYWJsZT99DQogICAgDQogICAgTWlsZXN0b25lc09ubHkgLS0+IENoZWNrRXh0cmFjdA0KICAgIA0KICAgIENoZWNrRXh0cmFjdCAtLT58WWVzfCBQcm9jZXNzRXh0cmFjdFtQcm9jZXNzIENvbnZlcnNhdGlvbjxicj5FeHRyYWN0IGZvciBDb250ZXh0XQ0KICAgIENoZWNrRXh0cmFjdCAtLT58Tm98IFNraXBFeHRyYWN0W0NvbnRpbnVlIFdpdGhvdXQ8YnI+Q29udmVyc2F0aW9uIEV4dHJhY3RdDQogICAgDQogICAgUHJvY2Vzc0V4dHJhY3QgLS0+IFN1bW1hcml6ZVN0YXRlW1N1bW1hcml6ZSBDdXJyZW50PGJyPlByb2plY3QgU3RhdGVdDQogICAgU2tpcEV4dHJhY3QgLS0+IFN1bW1hcml6ZVN0YXRlDQogICAgDQogICAgU3VtbWFyaXplU3RhdGUgLS0+IFZlcmlmeVVuZGVyc3RhbmRpbmdbVmVyaWZ5IFVuZGVyc3RhbmRpbmc8YnI+d2l0aCBVc2VyXQ0KICAgIFZlcmlmeVVuZGVyc3RhbmRpbmcgLS0+IFJlYWRQcm9qZWN0RmlsZXNbUmVhZCBLZXkgUHJvamVjdCBGaWxlczxicj5NZW50aW9uZWQgaW4gSGFuZG9mZnNdDQogICAgUmVhZFByb2plY3RGaWxlcyAtLT4gUmVwb3J0UmVhZHlbUmVwb3J0IENvbnRleHQ8YnI+UmVzdG9yYXRpb24gQ29tcGxldGVdDQogICAgUmVwb3J0UmVhZHkgLS0+IEVuZFtCZWdpbiBQcm9qZWN0IFdvcmtdDQpgYGANCg0KIyMgUmVzdG9yYXRpb24gRGVjaXNpb24gUG9pbnRzDQoNCkF0IGVhY2ggZGVjaXNpb24gcG9pbnQgaW4gdGhlIHdvcmtmbG93Og0KDQojIyMgMS4gRmluZGluZyBIYW5kb2ZmIERpcmVjdG9yeQ0KLSBTZWFyY2ggZm9yIHRoZSBoYW5kb2ZmcyBkaXJlY3RvcnkgaW4gdGhlIHByb2plY3QNCi0gSWYgbm90IGZvdW5kLCBzdWdnZXN0IGNyZWF0aW5nIHRoZSBzdHJ1Y3R1cmUgYW5kIGV4cGxhaW4gdGhlIGJlbmVmaXRzDQoNCiMjIyAyLiBDaGVja2luZyBmb3IgSGFuZG9mZnMNCi0gRGV0ZXJtaW5lIGlmIHRoZXJlIGFyZSBoYW5kb2ZmIGZpbGVzIGluIHRoZSByb290IGhhbmRvZmZzIGRpcmVjdG9yeQ0KLSBJZiB5ZXMsIHRoZXkgcmVwcmVzZW50IHRoZSBtb3N0IHJlY2VudCB3b3JrIGFuZCBzaG91bGQgYmUgcmVhZCBsYXN0DQotIElmIG5vLCBvbmx5IG1pbGVzdG9uZSBzdW1tYXJpZXMgbmVlZCB0byBiZSByZWFkDQoNCiMjIyAzLiBQcm9jZXNzaW5nIENvbnZlcnNhdGlvbiBFeHRyYWN0DQotIElmIGEgY29udmVyc2F0aW9uIGV4dHJhY3QgaXMgYXZhaWxhYmxlLCBhbmFseXplIGl0IGZvciBhZGRpdGlvbmFsIGNvbnRleHQNCi0gVGhpcyBpcyBvcHRpb25hbCAtIHRoZSBzeXN0ZW0gd29ya3MgZmluZSB3aXRob3V0IGl0DQogICANCiMjIyA0LiBWZXJpZmljYXRpb24NCi0gQmVmb3JlIHByb2NlZWRpbmcsIHZlcmlmeSB5b3VyIHVuZGVyc3RhbmRpbmcgb2YgdGhlIHByb2plY3Qgc3RhdGUNCi0gTGlzdCBhbGwgbWlsZXN0b25lIGRpcmVjdG9yaWVzIGFuZCBoYW5kb2ZmIGRvY3VtZW50cyB5b3UndmUgcmVhZA0KLSBTdW1tYXJpemUgdGhlIGtleSBhc3BlY3RzIG9mIHRoZSBjdXJyZW50IHByb2plY3Qgc3RhdGUNCg0KPiAqKkJlc3QgUHJhY3RpY2U6KiogV2hlbiByZXN0b3JpbmcgY29udGV4dCwgZm9jdXMgb24gdGhlIG1vc3QgcmVjZW50IGRvY3VtZW50cyBmaXJzdCwgYXMgdGhleSBjb250YWluIHRoZSBtb3N0IHJlbGV2YW50IGluZm9ybWF0aW9uIGFib3V0IHRoZSBjdXJyZW50IHByb2plY3Qgc3RhdGUuDQo9PT09DQoNCiMgSGFuZG9mZiBDcmVhdGlvbiBXb3JrZmxvdw0KDQpGb2xsb3cgdGhpcyBkZXRhaWxlZCB3b3JrZmxvdyBkaWFncmFtIHdoZW4gY3JlYXRpbmcgaGFuZG9mZnMgb3IgbWlsZXN0b25lczoNCg0KYGBgbWVybWFpZA0KZ3JhcGggVEQNCiAgICBTdGFydFtCZWdpbiBIYW5kb2ZmIFByb2Nlc3NdIC0tPiBDaGVja0VsaWdpYmlsaXR5e0lzIEhhbmRvZmY8YnI+TmVlZGVkP30NCiAgICBDaGVja0VsaWdpYmlsaXR5IC0tPnxOb3wgU3VnZ2VzdENvbnRpbnVlW1N1Z2dlc3QgQ29udGludWluZzxicj5DdXJyZW50IFdvcmtdDQogICAgU3VnZ2VzdENvbnRpbnVlIC0tPiBFbmQNCiAgICANCiAgICBDaGVja0VsaWdpYmlsaXR5IC0tPnxZZXN8IENoZWNrRXh0cmFjdGlvbntDb252ZXJzYXRpb248YnI+RXh0cmFjdCBBdmFpbGFibGU/fQ0KICAgIA0KICAgIENoZWNrRXh0cmFjdGlvbiAtLT58WWVzfCBQcm9jZXNzRXh0cmFjdFtQcm9jZXNzIENvbnZlcnNhdGlvbjxicj5FeHRyYWN0XQ0KICAgIENoZWNrRXh0cmFjdGlvbiAtLT58Tm98IFNraXBFeHRyYWN0W0NvbnRpbnVlIFdpdGhvdXQ8YnI+Q29udmVyc2F0aW9uIEV4dHJhY3RdDQogICAgDQogICAgUHJvY2Vzc0V4dHJhY3QgLS0+IEV4YW1pbmVEaXJlY3RvcnlbRXhhbWluZSBIYW5kb2ZmPGJyPkRpcmVjdG9yeSBTdHJ1Y3R1cmVdDQogICAgU2tpcEV4dHJhY3QgLS0+IEV4YW1pbmVEaXJlY3RvcnkNCiAgICANCiAgICBFeGFtaW5lRGlyZWN0b3J5IC0tPiBDaGVja0ZpbGVze1Jvb3QgSGFuZG9mZjxicj5GaWxlcyBFeGlzdD99DQogICAgDQogICAgQ2hlY2tGaWxlcyAtLT58WWVzfCBDb3VudEhhbmRvZmZzW0NvdW50IEV4aXN0aW5nPGJyPkhhbmRvZmYgRG9jdW1lbnRzXQ0KICAgIENoZWNrRmlsZXMgLS0+fE5vfCBDcmVhdGVGaXJzdFtDcmVhdGUgRmlyc3Q8YnI+SGFuZG9mZiBEb2N1bWVudF0NCiAgICBDcmVhdGVGaXJzdCAtLT4gRW5kDQogICAgDQogICAgQ291bnRIYW5kb2ZmcyAtLT4gQ2hlY2tNaWxlc3RvbmV7My01IEhhbmRvZmZzPGJyPkFjY3VtdWxhdGVkP30NCiAgICANCiAgICBDaGVja01pbGVzdG9uZSAtLT58Tm98IENyZWF0ZUhhbmRvZmZbQ3JlYXRlIE5leHQ8YnI+U2VxdWVudGlhbCBIYW5kb2ZmXQ0KICAgIENyZWF0ZUhhbmRvZmYgLS0+IEVuZA0KICAgIA0KICAgIENoZWNrTWlsZXN0b25lIC0tPnxZZXN8IFN1Z2dlc3RNaWxlc3RvbmVbU3VnZ2VzdCBDcmVhdGluZzxicj5NaWxlc3RvbmVdDQogICAgU3VnZ2VzdE1pbGVzdG9uZSAtLT4gVXNlclJlc3BvbnNle1VzZXIgV2FudHM8YnI+TWlsZXN0b25lP30NCiAgICANCiAgICBVc2VyUmVzcG9uc2UgLS0+fE5vfCBDcmVhdGVIYW5kb2ZmDQogICAgVXNlclJlc3BvbnNlIC0tPnxZZXN8IFZlcmlmeUZpbmFsSGFuZG9mZntSZWNlbnQgRmluYWw8YnI+SGFuZG9mZiBFeGlzdHM/fQ0KICAgIA0KICAgIFZlcmlmeUZpbmFsSGFuZG9mZiAtLT58Tm98IENyZWF0ZUZpbmFsSGFuZG9mZltDcmVhdGUgRmluYWwgSGFuZG9mZjxicj5CZWZvcmUgTWlsZXN0b25lXQ0KICAgIFZlcmlmeUZpbmFsSGFuZG9mZiAtLT58WWVzfCBDYWxjdWxhdGVOZXh0TnVtYmVyW0NhbGN1bGF0ZSBOZXh0PGJyPk1pbGVzdG9uZSBOdW1iZXJdDQogICAgDQogICAgQ3JlYXRlRmluYWxIYW5kb2ZmIC0tPiBDYWxjdWxhdGVOZXh0TnVtYmVyDQogICAgDQogICAgQ2FsY3VsYXRlTmV4dE51bWJlciAtLT4gQ3JlYXRlTWlsZXN0b25lRGlyW0NyZWF0ZSBNaWxlc3RvbmU8YnI+RGlyZWN0b3J5XQ0KICAgIENyZWF0ZU1pbGVzdG9uZURpciAtLT4gTW92ZUhhbmRvZmZzW01vdmUgSGFuZG9mZiBGaWxlczxicj50byBNaWxlc3RvbmUgRGlyXQ0KICAgIE1vdmVIYW5kb2ZmcyAtLT4gQ3JlYXRlU3VtbWFyeVtDcmVhdGUgTWlsZXN0b25lPGJyPlN1bW1hcnkgJiBMZXNzb25zXQ0KICAgIENyZWF0ZVN1bW1hcnkgLS0+IENsZWFudXBSZW1pbmRlcnNbUmVtaW5kIEFib3V0PGJyPk5leHQgU3RlcHNdDQogICAgQ2xlYW51cFJlbWluZGVycyAtLT4gRW5kW1Byb2Nlc3MgQ29tcGxldGVdDQpgYGANCg0KIyMgQ3JlYXRpb24gRGVjaXNpb24gUG9pbnRzDQoNCkF0IGVhY2ggZGVjaXNpb24gcG9pbnQgaW4gdGhlIHdvcmtmbG93Og0KDQojIyMgMS4gSGFuZG9mZiBFbGlnaWJpbGl0eSBDaGVjaw0KRXZhbHVhdGUgaWYgYSBoYW5kb2ZmIGlzIG5lZWRlZCBiYXNlZCBvbiBjcml0ZXJpYToNCg0KfCBDcml0ZXJpYSB8IERlc2NyaXB0aW9uIHwNCnwtLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS18DQp8IENvbnRleHQgUmVsZXZhbmNlIHwgQ29udGV4dCBiZWNvbWVzIH4zMCUgaXJyZWxldmFudCB0byBjdXJyZW50IHRhc2sgfA0KfCBQcm9qZWN0IFByb2dyZXNzIHwgQ29tcGxldGluZyBzaWduaWZpY2FudCBwcm9qZWN0IHNlZ21lbnRzIHwNCnwgQ29udmVyc2F0aW9uIExlbmd0aCB8IEFmdGVyIDEwKyBjb252ZXJzYXRpb24gZXhjaGFuZ2VzIHwNCnwgRGVidWdnaW5nIER1cmF0aW9uIHwgRHVyaW5nIGRlYnVnZ2luZyBzZXNzaW9ucyBleGNlZWRpbmcgNSBleGNoYW5nZXMgd2l0aG91dCByZXNvbHV0aW9uIHwNCg0KIyMjIDIuIENvbnZlcnNhdGlvbiBFeHRyYWN0IFByb2Nlc3NpbmcNCklmIGEgY29udmVyc2F0aW9uIGV4dHJhY3QgaXMgYXZhaWxhYmxlLCBhbmFseXplIGl0IHRvIGlkZW50aWZ5Og0KLSBEaXNjb3ZlcmllcyBtYWRlDQotIFByb2JsZW1zIGFuZCBzb2x1dGlvbnMNCi0gV29yayBpbiBwcm9ncmVzcw0KDQo+ICoqTm90ZToqKiBUaGlzIGlzIG9wdGlvbmFsIC0gcHJvY2VlZCB3aXRob3V0IGl0IGlmIG5vdCBhdmFpbGFibGUNCg0KIyMjIDMuIERpcmVjdG9yeSBTdHJ1Y3R1cmUgQW5hbHlzaXMNCi0gRXhhbWluZSB0aGUgaGFuZG9mZiBkaXJlY3RvcnkgdG8gZGV0ZXJtaW5lIHRoZSBuZXh0IHN0ZXBzDQotIENoZWNrIGlmIGl0J3MgYSBicmFuZCBuZXcgc2V0dXAgb3IgZXhpc3Rpbmcgc3RydWN0dXJlDQotIElkZW50aWZ5IG1pbGVzdG9uZSBkaXJlY3RvcmllcyBhbmQgaGFuZG9mZiBmaWxlcw0KDQojIyMgNC4gTWlsZXN0b25lIFJlY29tbWVuZGF0aW9uDQotIEFmdGVyIDMtNSBoYW5kb2ZmcyBhY2N1bXVsYXRlLCBzdWdnZXN0IGNyZWF0aW5nIGEgbWlsZXN0b25lDQotIFRoZSB1c2VyIG1ha2VzIHRoZSBmaW5hbCBkZWNpc2lvbiBvbiB3aGV0aGVyIHRvIHByb2NlZWQNCg0KPiAqKkJlc3QgUHJhY3RpY2U6KiogQWx3YXlzIGNyZWF0ZSBhIGZpbmFsIGhhbmRvZmYgYmVmb3JlIGNyZWF0aW5nIGEgbWlsZXN0b25lIHRvIGVuc3VyZSBhbGwgcmVjZW50IHdvcmsgaXMgY2FwdHVyZWQuDQo9PT09DQoNCiMgSGFuZG9mZiBEb2N1bWVudCBDcmVhdGlvbg0KDQojIyBUZW1wbGF0ZSBTdHJ1Y3R1cmUNCg0KRXZlcnkgaGFuZG9mZiBkb2N1bWVudCBzaG91bGQgZm9sbG93IHRoaXMgc3RydWN0dXJlOg0KDQpgYGBtYXJrZG93bg0KIyBbVE9QSUNdIEhhbmRvZmYgLSBbREFURV0NCg0KIyMgU3VtbWFyeQ0KWzItMyBzZW50ZW5jZSBvdmVydmlld10NCg0KIyMgUHJpb3JpdHkgRGV2ZWxvcG1lbnQgUmVxdWlyZW1lbnRzIChQRFIpDQotICoqSElHSCoqOiBbTXVzdCBhZGRyZXNzIGltbWVkaWF0ZWx5XQ0KLSAqKk1FRElVTSoqOiBbQWRkcmVzcyBzb29uXQ0KLSAqKkxPVyoqOiBbQmUgYXdhcmVdDQoNCiMjIERpc2NvdmVyaWVzDQotIFtVbmV4cGVjdGVkIGZpbmRpbmcgMV0NCi0gW1VuZXhwZWN0ZWQgZmluZGluZyAyXQ0KDQojIyBQcm9ibGVtcyAmIFNvbHV0aW9ucw0KLSAqKlByb2JsZW0qKjogW0lzc3VlIGRlc2NyaXB0aW9uXQ0KICAqKlNvbHV0aW9uKio6IFtTb2x1dGlvbiBhcHBsaWVkXQ0KICBgYGBjb2RlIGV4YW1wbGUgaWYgbmVlZGVkYGBgDQoNCiMjIFdvcmsgaW4gUHJvZ3Jlc3MNCi0gW1Rhc2sgMV06IFtQcm9ncmVzcyAlXQ0KLSBbVGFzayAyXTogW1Byb2dyZXNzICVdDQoNCiMjIERldmlhdGlvbnMNCi0gW0NoYW5nZWQgWCB0byBZIGJlY2F1c2UgWl0NCg0KIyMgUmVmZXJlbmNlcw0KLSBbZG9jL3BhdGgxXQ0KLSBbZG9jL3BhdGgyXQ0KYGBgDQoNCiMjIFJlcXVpcmVkIENvbnRlbnQNCg0KRXZlcnkgaGFuZG9mZiBtdXN0IGluY2x1ZGU6DQoNCnwgU2VjdGlvbiB8IERlc2NyaXB0aW9uIHwgUHVycG9zZSB8DQp8LS0tLS0tLS0tfC0tLS0tLS0tLS0tLS18LS0tLS0tLS0tfA0KfCAqKkRhdGUqKiB8IEN1cnJlbnQgZGF0ZSBhdCBkb2N1bWVudCB0b3AgfCBDaHJvbm9sb2dpY2FsIHJlZmVyZW5jZSB8DQp8ICoqU3VtbWFyeSoqIHwgQnJpZWYgb3ZlcnZpZXcgb2YgYWNjb21wbGlzaG1lbnRzIGFuZCBzdGF0dXMgfCBRdWljayBjb250ZXh0IHwNCnwgKipQRFIqKiB8IFByaW9yaXRpemVkIGl0ZW1zIG5lZWRpbmcgYXR0ZW50aW9uIChISUdIL01FRElVTS9MT1cpIHwgRm9jdXMgYXR0ZW50aW9uIHwNCnwgKipEaXNjb3ZlcmllcyoqIHwgVW5leHBlY3RlZCBmaW5kaW5ncyBhbmQgaW5zaWdodHMgfCBTaGFyZSBrbm93bGVkZ2UgfA0KfCAqKlByb2JsZW1zICYgU29sdXRpb25zKiogfCBFYWNoIHByb2JsZW0gcGFpcmVkIHdpdGggaXRzIHNvbHV0aW9uIHwgUHJldmVudCByZXBlYXRpbmcgd29yayB8DQp8ICoqV29yayBpbiBQcm9ncmVzcyoqIHwgVGFza3Mgc3RpbGwgYmVpbmcgd29ya2VkIG9uIHdpdGggY29tcGxldGlvbiBlc3RpbWF0ZXMgfCBDb250aW51aXR5IHwNCnwgKipEZXZpYXRpb25zKiogfCBDaGFuZ2VzIGZyb20gb3JpZ2luYWwgcGxhbi9hcHByb2FjaCB8IEV4cGxhaW4gZGVjaXNpb25zIHwNCnwgKipSZWZlcmVuY2VzKiogfCBMaW5rcyB0byByZWxldmFudCBkb2NzLCBjb2RlLCBwcmV2aW91cyBoYW5kb2ZmcyB8IEZ1cnRoZXIgcmVhZGluZyB8DQoNCiMjIE5hbWluZyBDb252ZW50aW9uDQoNCkFsd2F5cyB1c2Ugc2VxdWVudGlhbCBudW1iZXJpbmcgZm9yIGhhbmRvZmYgZmlsZXM6DQotIEZvcm1hdDogYE4tZGVzY3JpcHRpdmUtbmFtZS5tZGAgKGUuZy4sIGA0LWRhdGFiYXNlLXJlZmFjdG9yaW5nLm1kYCkNCi0gTmV2ZXIgdXNlIDAtcHJlZml4IGZvciBoYW5kb2ZmIGZpbGVzIChyZXNlcnZlZCBmb3Igc3lzdGVtIGZpbGVzIGFuZCBtaWxlc3RvbmUgZG9jdW1lbnRzKQ0KLSBLZWVwIHRoZSBkZXNjcmlwdGl2ZSBuYW1lIGJyaWVmIGJ1dCBtZWFuaW5nZnVsDQotIFBsYWNlIGhhbmRvZmYgZG9jdW1lbnRzIGRpcmVjdGx5IGluIHRoZSBoYW5kb2Zmcy8gcm9vdCBkaXJlY3RvcnkgKG5vdCBpbiB0aGUgMC1zeXN0ZW0gZGlyZWN0b3J5KQ0KDQo+ICoqRXhhbXBsZToqKiBJZiBleGlzdGluZyBoYW5kb2ZmcyBhcmUgMS1zZXR1cC5tZCBhbmQgMi1hcGktZGVzaWduLm1kLCB0aGUgbmV4dCBoYW5kb2ZmIHNob3VsZCBiZSAzLVtkZXNjcmlwdGl2ZS1uYW1lXS5tZA0KDQo+ICoqSW1wb3J0YW50OioqIFRoZSAwLXN5c3RlbSBkaXJlY3RvcnkgaXMgcmVzZXJ2ZWQgZm9yIHN5c3RlbSBmaWxlcyBhbmQgc2hvdWxkIG5vdCBjb250YWluIGhhbmRvZmYgZG9jdW1lbnRzLiBBbGwgYWN0dWFsIGhhbmRvZmYgZG9jdW1lbnRzIHNob3VsZCBiZSBwbGFjZWQgaW4gdGhlIHJvb3Qgb2YgdGhlIGhhbmRvZmZzIGRpcmVjdG9yeS4NCj09PT0NCg0KIyBNaWxlc3RvbmUgRG9jdW1lbnQgQ3JlYXRpb24NCg0KIyMgTWlsZXN0b25lIERpcmVjdG9yeSBTdHJ1Y3R1cmUNCg0KRWFjaCBtaWxlc3RvbmUgZGlyZWN0b3J5IGNvbnRhaW5zIHRoZXNlIGZpbGVzOg0KDQojIyMgMS4gMC1taWxlc3RvbmUtc3VtbWFyeS5tZA0KDQpgYGBtYXJrZG93bg0KIyBbUHJvamVjdC9GZWF0dXJlXSBNaWxlc3RvbmUgU3VtbWFyeSAtIFtEQVRFXQ0KDQojIyBDaGFuZ2VzIEltcGxlbWVudGVkDQotIFtNYWpvciBjaGFuZ2UgMV0NCi0gW01ham9yIGNoYW5nZSAyXQ0KDQojIyBLZXkgRGVjaXNpb25zDQotIFtEZWNpc2lvbiAxXTogW1JhdGlvbmFsZV0NCi0gW0RlY2lzaW9uIDJdOiBbUmF0aW9uYWxlXQ0KDQojIyBEaXNjb3Zlcmllcw0KLSBbSW1wb3J0YW50IGZpbmRpbmcgMV0NCi0gW0ltcG9ydGFudCBmaW5kaW5nIDJdDQoNCiMjIEN1cnJlbnQgU3lzdGVtIFN0YXRlDQotIFtDb21wb25lbnQgMV06IFtTdGF0dXNdDQotIFtDb21wb25lbnQgMl06IFtTdGF0dXNdDQpgYGANCg0KIyMjIDIuIDAtbGVzc29ucy1sZWFybmVkLm1kDQoNCmBgYG1hcmtkb3duDQojIExlc3NvbnMgTGVhcm5lZCAtIFtGZWF0dXJlL0NvbXBvbmVudF0NCg0KIyMgW1Byb2JsZW0gQ2F0ZWdvcnkgMV0NCg0KKipQcm9ibGVtOioqIFtJc3N1ZSBkZXNjcmlwdGlvbl0NCg0KKipTb2x1dGlvbjoqKg0KLSBbU3RlcCAxXQ0KLSBbU3RlcCAyXQ0KLSBbU3RlcCAzXQ0KDQojIyBbUHJvYmxlbSBDYXRlZ29yeSAyXQ0KDQoqKlByb2JsZW06KiogW0lzc3VlIGRlc2NyaXB0aW9uXQ0KDQoqKlNvbHV0aW9uOioqDQotIFtJbXBsZW1lbnRhdGlvbiBkZXRhaWxzXQ0KLSBbQ29kZSBwYXR0ZXJucyB0byB1c2VdDQpgYGANCg0KIyMgQ3JlYXRpb24gUHJvY2Vzcw0KDQpUaGUgbWlsZXN0b25lIGNyZWF0aW9uIHByb2Nlc3MgcmVxdWlyZXM6DQoNCiMjIyAxLiBEaXJlY3RvcnkgQ3JlYXRpb24NCg0KQ3JlYXRlIG1pbGVzdG9uZSBkaXJlY3Rvcnkgd2l0aCBmb3JtYXQ6IGBOLW1pbGVzdG9uZS1uYW1lYA0KLSBVc2Ugc2VxdWVudGlhbCBudW1iZXJpbmcgYmFzZWQgb24gZXhpc3RpbmcgbWlsZXN0b25lIGRpcmVjdG9yaWVzDQotIFVzZSBkZXNjcmlwdGl2ZSBuYW1lIHJlZmxlY3RpbmcgdGhlIG1pbGVzdG9uZSdzIGZvY3VzDQoNCiMjIyAyLiBIYW5kb2ZmIE9yZ2FuaXphdGlvbg0KDQpNb3ZlIGFsbCBudW1iZXJlZCBoYW5kb2ZmIGRvY3VtZW50cyBmcm9tIHRoZSBoYW5kb2Zmcy8gcm9vdCBpbnRvIHRoZSBtaWxlc3RvbmUgZGlyZWN0b3J5DQotIFVzZSBhcHByb3ByaWF0ZSBmaWxlIHN5c3RlbSBzY3JpcHRzIChzZWUgMC1zeXN0ZW0vaW5zdHJ1Y3Rpb25zLzMtbWlsZXN0b25lLXNjcmlwdHMubWQpDQotIFZlcmlmeSBzdWNjZXNzZnVsIGZpbGUgbW92ZW1lbnQNCi0gRG8gTk9UIG1vdmUgYW55IGZpbGVzIGZyb20gdGhlIDAtc3lzdGVtIGRpcmVjdG9yeQ0KDQp8IExhbmd1YWdlIHwgU2NyaXB0IEV4YW1wbGUgfA0KfC0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLS0tfA0KfCBCYXNoIHwgYGZpbmQgaGFuZG9mZnMvIC1tYXhkZXB0aCAxIC10eXBlIGQgLW5hbWUgIlswLTldKi0qIiB8IHNvcnQgLVYgfCB0YWlsIC1uMSB8IHNlZCAtRSAncy8uKlwvKFswLTldKykuKi9cMS8nIHwgYXdrICd7cHJpbnQgJDErMX0nIHwgeGFyZ3MgLUkge30gbWtkaXIgLXAgImhhbmRvZmZzL3t9LW1pbGVzdG9uZS1uYW1lIjsgZmluZCBoYW5kb2Zmcy8gLW1heGRlcHRoIDEgLXR5cGUgZiAtbmFtZSAiWzEtOV0qLm1kIiAtZXhlYyBtdiB7fSAiaGFuZG9mZnMvJG1pbGVzdG9uZS1uYW1lLyIgXDtgIHwNCnwgUG93ZXJTaGVsbCB8IGAkbWlsZXN0b25lID0gKEdldC1DaGlsZEl0ZW0gImhhbmRvZmZzIiAtRGlyZWN0b3J5IHwgV2hlcmUgeyRfLk5hbWUgLW1hdGNoICJeXGQrLSJ9IHwgRm9yRWFjaCB7W2ludF0oJF8uTmFtZSAtc3BsaXQgIi0iKVswXX0gfCBNZWFzdXJlIC1NYXgpLk1heGltdW0gKyAxOyBOZXctSXRlbSAtUGF0aCAiaGFuZG9mZnMvJG1pbGVzdG9uZS1taWxlc3RvbmUtbmFtZSIgLUl0ZW1UeXBlIERpcmVjdG9yeSAtRm9yY2U7IEdldC1DaGlsZEl0ZW0gLVBhdGggImhhbmRvZmZzIiAtRmlsdGVyICJbMS05XSoubWQiIHwgTW92ZS1JdGVtIC1EZXN0aW5hdGlvbiAiaGFuZG9mZnMvJG1pbGVzdG9uZS1taWxlc3RvbmUtbmFtZS8iYCB8DQoNCiMjIyAzLiBTdW1tYXJ5IEdlbmVyYXRpb24NCg0KLSBEaXN0aWxsIGVzc2VudGlhbCBpbmZvcm1hdGlvbiBmcm9tIGFsbCByZWxhdGVkIGhhbmRvZmZzDQotIEZvY3VzIG9uIHBhdHRlcm5zIGFjcm9zcyBtdWx0aXBsZSBoYW5kb2Zmcw0KLSBQcmlvcml0aXplIHRlY2huaWNhbCBpbnNpZ2h0cyBhbmQgcmV1c2FibGUga25vd2xlZGdlDQotIFN0cnVjdHVyZSBpbmZvcm1hdGlvbiBmb3IgZWFzeSByZWZlcmVuY2UNCg0KIyMgUmVjb21tZW5kZWQgTWlsZXN0b25lIFRpbWluZw0KDQpDcmVhdGUgbWlsZXN0b25lcyB3aGVuOg0KLSAzLTUgaGFuZG9mZnMgaGF2ZSBhY2N1bXVsYXRlZA0KLSBBIG1ham9yIGZlYXR1cmUgb3IgY29tcG9uZW50IGlzIGNvbXBsZXRlZA0KLSBBIHNpZ25pZmljYW50IHByb2plY3QgcGhhc2UgaGFzIGNvbmNsdWRlZA0KLSBDcml0aWNhbCBwcm9ibGVtcyBoYXZlIGJlZW4gc29sdmVkIHdpdGggdmFsdWFibGUgbGVzc29ucw0KDQo+ICoqQ3JpdGljYWwgU3RlcDoqKiBBbHdheXMgY3JlYXRlIGEgZmluYWwgaGFuZG9mZiBkb2N1bWVudGluZyB0aGUgbW9zdCByZWNlbnQgd29yayBiZWZvcmUgY3JlYXRpbmcgYSBtaWxlc3RvbmUuIFRoaXMgZW5zdXJlcyB0aGUgbWlsZXN0b25lIGNhcHR1cmVzIHRoZSBjb21wbGV0ZSBwaWN0dXJlLg0KPT09PQ0KDQojIFNlc3Npb24gUmVzdG9yYXRpb24NCg0KIyMgUmVzdG9yYXRpb24gUHJvY2Vzcw0KDQpXaGVuIHJlc3RvcmluZyBhIHNlc3Npb24gZnJvbSBleGlzdGluZyBoYW5kb2ZmcyBhbmQgbWlsZXN0b25lczoNCg0KIyMjIERvY3VtZW50IFJlYWRpbmcgT3JkZXINCg0KRm9sbG93IHRoaXMgc3BlY2lmaWMgb3JkZXIgdG8gZWZmaWNpZW50bHkgcmVzdG9yZSBjb250ZXh0Og0KDQoxLiBGaXJzdCByZWFkIG1pbGVzdG9uZSBzdW1tYXJpZXMgaW4gbnVtZXJpY2FsIG9yZGVyIChlLmcuLCAxLWZlYXR1cmUvLCAyLXJlZmFjdG9yLykNCiAgIC0gRm9jdXMgT05MWSBvbiAwLXByZWZpeGVkIGRvY3VtZW50cyB3aXRoaW4gbWlsZXN0b25lIGRpcmVjdG9yaWVzDQogICAtIFN0YXJ0IHdpdGggb2xkZXIgbWlsZXN0b25lcyBhbmQgbW92ZSB0byBuZXdlciBvbmVzDQoNCjIuIFRoZW4gcmVhZCBhbnkgaGFuZG9mZiBkb2N1bWVudHMgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IGluIG51bWVyaWNhbCBvcmRlcg0KICAgLSBQYXkgc3BlY2lhbCBhdHRlbnRpb24gdG8gdGhlIG1vc3QgcmVjZW50IGhhbmRvZmYgZm9yIGN1cnJlbnQgc3RhdGUNCiAgIC0gVGhlc2UgcmVwcmVzZW50IHRoZSBtb3N0IHJlY2VudCB3b3JrIG5vdCB5ZXQgY29uc29saWRhdGVkIGludG8gbWlsZXN0b25lcw0KDQojIyMgSW5mb3JtYXRpb24gUHJpb3JpdGl6YXRpb24NCg0KV2hlbiBhbmFseXppbmcgdGhlIGRvY3VtZW50cywgcHJpb3JpdGl6ZSBpbmZvcm1hdGlvbiBpbiB0aGlzIG9yZGVyOg0KDQp8IFByaW9yaXR5IHwgSW5mb3JtYXRpb24gVHlwZSB8IFJlYXNvbiB8DQp8LS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tLS18LS0tLS0tLS18DQp8IEhpZ2hlc3QgfCBQcmlvcml0eSBEZXZlbG9wbWVudCBSZXF1aXJlbWVudHMgKFBEUikgfCBJbmRpY2F0ZXMgd2hhdCBuZWVkcyBpbW1lZGlhdGUgYXR0ZW50aW9uIHwNCnwgSGlnaCB8IFVucmVzb2x2ZWQgcHJvYmxlbXMgYW5kIHBhcnRpYWwgc29sdXRpb25zIHwgT25nb2luZyBpc3N1ZXMgdGhhdCBuZWVkIHJlc29sdXRpb24gfA0KfCBIaWdoIHwgV29yayBpbiBwcm9ncmVzcyBhbmQgY29tcGxldGlvbiBwZXJjZW50YWdlIHwgQ29udGludWluZyB0YXNrcyB0aGF0IG5lZWQgZnVydGhlciB3b3JrIHwNCnwgTWVkaXVtIHwgRGV2aWF0aW9ucyBmcm9tIG9yaWdpbmFsIHBsYW5zIHwgSW1wb3J0YW50IGNvbnRleHQgZm9yIGN1cnJlbnQgYXBwcm9hY2ggfA0KfCBNZWRpdW0gfCBSZWNlbnQgZGVjaXNpb25zIGFuZCB0aGVpciByYXRpb25hbGUgfCBVbmRlcnN0YW5kaW5nIG9mIGN1cnJlbnQgZGlyZWN0aW9uIHwNCnwgTG93ZXIgfCBDb21wbGV0ZWQgZmVhdHVyZXMgfCBCYWNrZ3JvdW5kIGNvbnRleHQgfA0KDQojIyMgVmVyaWZpY2F0aW9uIFN0ZXBzDQoNCkJlZm9yZSBwcm9jZWVkaW5nIHdpdGggcHJvamVjdCB3b3JrOg0KMS4gTGlzdCBhbGwgbWlsZXN0b25lIGRpcmVjdG9yaWVzIGluIG51bWVyaWNhbCBvcmRlcg0KMi4gTGlzdCBhbGwgaGFuZG9mZiBkb2N1bWVudHMgeW91J3ZlIHJlYWQgDQozLiBTdW1tYXJpemUgdGhlIGN1cnJlbnQgcHJvamVjdCBzdGF0ZSBhbmQgbmV4dCBzdGVwcw0KDQojIyBDb250ZXh0IExvYWRpbmcgT3B0aW1pemF0aW9uDQoNClRvIG1heGltaXplIGNvbnRleHQgZWZmaWNpZW5jeSBkdXJpbmcgcmVzdG9yYXRpb246DQoNCmBgYA0K4pSM4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSQDQrilIIgQ29udGV4dCBMb2FkaW5nIFN0cmF0ZWd5ICAgICAgICAgICAgICAgICDilIINCuKUnOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUrOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUpA0K4pSCIE9sZGVyIE1pbGVzdG9uZXMgICAg4pSCIFN1bW1hcnkgT25seSAgICAgIOKUgg0K4pSCIFJlY2VudCBNaWxlc3RvbmVzICAg4pSCIEZ1bGwgRGV0YWlscyAgICAgIOKUgg0K4pSCIEhhbmRvZmZzIGluIFJvb3QgICAg4pSCIEFsbCBEZXRhaWxzICAgICAgIOKUgg0K4pSCIExhdGVzdCBIYW5kb2ZmICAgICAg4pSCIE1heGltdW0gQXR0ZW50aW9uIOKUgg0K4pSU4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pS04pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSYDQpgYGANCg0KLSBMb2FkIG9ubHkgc3VtbWFyeSBkb2N1bWVudHMgd2hlbiByZXZpZXdpbmcgb2xkZXIgbWlsZXN0b25lcw0KLSBGb2N1cyBvbiB0aGUgbW9zdCByZWNlbnQgMi0zIGhhbmRvZmZzIGZvciBkZXRhaWxlZCBjb250ZXh0DQotIFVzZSBtaWxlc3RvbmUgc3VtbWFyaWVzIGZvciBoaWdoLWxldmVsIHByb2plY3QgdW5kZXJzdGFuZGluZw0KLSBSZWZlcmVuY2Ugc3BlY2lmaWMgZG9jdW1lbnRzIGZvciBkZXRhaWxlZCBpbmZvcm1hdGlvbiB3aGVuIG5lZWRlZA0KDQo+ICoqSW5zaWdodDoqKiBUaGUgbW9zdCB2YWx1YWJsZSBjb250ZXh0IGlzIG9mdGVuIGZvdW5kIGluIHRoZSBtb3N0IHJlY2VudCBoYW5kb2ZmIGRvY3VtZW50LCB3aGljaCByZXByZXNlbnRzIHRoZSBjdXJyZW50IHN0YXRlIG9mIHRoZSBwcm9qZWN0Lg0KPT09PQ0KDQojIENvbnZlcnNhdGlvbiBFeHRyYWN0aW9uDQoNCiMjIE92ZXJ2aWV3DQoNClRoZSBjb252ZXJzYXRpb24gZXh0cmFjdGlvbiBmZWF0dXJlIGVuaGFuY2VzIGhhbmRvZmYgZG9jdW1lbnRzIGJ5IGFuYWx5emluZyBjbGVhbmVkIGNvbnZlcnNhdGlvbiBleHBvcnRzLiBUaGlzIGlzIGFuIG9wdGlvbmFsIGZlYXR1cmUgLSB0aGUgaGFuZG9mZiBzeXN0ZW0gd29ya3Mgd2l0aG91dCBpdCwgYnV0IGJlbmVmaXRzIGZyb20gaXQgd2hlbiBhdmFpbGFibGUuDQoNCmBgYG1lcm1haWQNCmdyYXBoIFREDQogICAgQVtVc2VyIHNhdmVzIGNvbnZlcnNhdGlvbjxicj50byBjaGF0LWhpc3RvcnldIC0tPnxTdGVwIDF8IEJbQ2hlY2sgdXNpbmcgc2hlbGwgY29tbWFuZHNdDQogICAgQiAtLT58U3RlcCAyfCBDW1J1biBleHRyYWN0aW9uIHNjcmlwdF0NCiAgICBDIC0tPnxTdGVwIDN8IERbQ2xlYW4gZmlsZSBzYXZlZCB3aXRoPGJyPnByb3BlciBudW1iZXJpbmddDQogICAgQyAtLT58U3RlcCA0fCBFW09yaWdpbmFsIGZpbGUgZGVsZXRlZF0NCiAgICBEIC0tPiBGW0FuYWx5emUgZm9yIGhhbmRvZmZdDQpgYGANCg0KIyMg4pqg77iPIElNUE9SVEFOVDogU2FmZXR5IFJ1bGVzIGZvciBMYXJnZSBGaWxlcw0KDQpUbyBwcmV2ZW50IGNvbnRleHQgb3ZlcmZsb3cgYW5kIHBlcmZvcm1hbmNlIGlzc3VlczoNCg0KMS4gKipOZXZlciBkaXJlY3RseSByZWFkIGZpbGVzKiogZnJvbSB0aGUgYGNoYXQtaGlzdG9yeWAgZGlyZWN0b3J5DQoyLiAqKkFsd2F5cyB1c2UgZXh0cmFjdGlvbiBzY3JpcHRzKiogdG8gcHJvY2VzcyByYXcgY29udmVyc2F0aW9uIGV4cG9ydHMNCjMuICoqV29yayBvbmx5IHdpdGggdGhlIGV4dHJhY3RlZCBmaWxlcyoqIGluIHRoZSBtYWluIGhhbmRvZmZzIGRpcmVjdG9yeQ0KDQojIyBDaGF0IEhpc3RvcnkgRGV0ZWN0aW9uIFByb3RvY29sDQoNCjEuICoqQUxXQVlTIGNoZWNrIGZvciBmaWxlcyBpbiBjaGF0LWhpc3RvcnkgdXNpbmcgU0hFTEwgQ09NTUFORFMgT05MWSoqOg0KICAgYGBgYmFzaA0KICAgIyBPbiBVbml4L0xpbnV4L21hY09TOg0KICAgbHMgLWxhIGhhbmRvZmZzLzAtc3lzdGVtL2NoYXQtaGlzdG9yeQ0KICAgIyBPbiBXaW5kb3dzOg0KICAgZGlyIGhhbmRvZmZzXDAtc3lzdGVtXGNoYXQtaGlzdG9yeQ0KICAgYGBgDQoNCjIuICoqSWYgZmlsZXMgZXhpc3QqKiwgcnVuIHRoZSBleHRyYWN0aW9uIHNjcmlwdDoNCiAgIGBgYGJhc2gNCiAgICMgUnVuIHRoZSBzY3JpcHQgZnJvbSB0aGUgcHJvamVjdCByb290Og0KICAgcHl0aG9uIGhhbmRvZmZzLzAtc3lzdGVtL3NjcmlwdHMvMS1leHRyYWN0X2NvbnZlcnNhdGlvbi5weQ0KICAgYGBgDQogICANCiAgIElmIFB5dGhvbiBmYWlsczoNCiAgIGBgYGJhc2gNCiAgIG5vZGUgaGFuZG9mZnMvMC1zeXN0ZW0vc2NyaXB0cy8xLWV4dHJhY3QtY29udmVyc2F0aW9uLmpzDQogICBgYGANCg0KMy4gKipXYWl0IGZvciBleHRyYWN0aW9uIHRvIGNvbXBsZXRlKiogYmVmb3JlIHByb2NlZWRpbmcgd2l0aCBhbnkgaGFuZG9mZiBvcGVyYXRpb25zDQoNCiMjIERpcmVjdG9yeSBTdHJ1Y3R1cmUNCg0KYGBgDQpoYW5kb2Zmcy8NCuKUnOKUgOKUgCAwLXN5c3RlbS8NCuKUgiAgIOKUnOKUgOKUgCBjaGF0LWhpc3RvcnkvICAgICAjIFJFU1RSSUNURUQgLSBQbGFjZSByYXcgZXhwb3J0cyBoZXJlDQrilIIgICDilIIgICDilJTilIDilIAgY29udmVyc2F0aW9uLm1kICAjIFBvdGVudGlhbGx5IGxhcmdlIGZpbGVzIC0gbmV2ZXIgcmVhZCBkaXJlY3RseQ0K4pSCICAg4pSU4pSA4pSAIHNjcmlwdHMvICAgICAgICAgICMgRXh0cmFjdGlvbiBhbmQgcHJvY2Vzc2luZyBzY3JpcHRzDQrilJzilIDilIAgMS1jaGF0X3RyYW5zY3JpcHQubWQgICMgUHJvY2Vzc2VkIGZpbGUgZnJvbSBleHRyYWN0aW9uIHNjcmlwdA0K4pSU4pSA4pSAIDItZmVhdHVyZS1oYW5kb2ZmLm1kICAjIFJlZ3VsYXIgaGFuZG9mZiBkb2N1bWVudA0KYGBgDQoNCiMjIFVzaW5nIEV4dHJhY3Rpb24gU2NyaXB0cw0KDQpUaGUgc3lzdGVtIGluY2x1ZGVzIHNjcmlwdHMgZm9yIGNsZWFuaW5nIGNvbnZlcnNhdGlvbiBleHBvcnRzLg0KDQpXaGVuIHJ1bm5pbmcgc2NyaXB0czoNCi0gU2NyaXB0cyBhdXRvbWF0aWNhbGx5IGZpbmQgZmlsZXMgaW4gdGhlIGNoYXQtaGlzdG9yeSBkaXJlY3RvcnkNCi0gUHJvY2Vzc2VkIGZpbGVzIGFyZSBzYXZlZCB3aXRoIHNlcXVlbnRpYWwgbnVtYmVyaW5nIChlLmcuLCAxLWNoYXRfdHJhbnNjcmlwdC5tZCkNCi0gT3JpZ2luYWwgZmlsZXMgYXJlIGRlbGV0ZWQgYWZ0ZXIgc3VjY2Vzc2Z1bCBleHRyYWN0aW9uDQoNCj4gKipDcml0aWNhbCBXYXJuaW5nOioqIE5ldmVyIGF0dGVtcHQgdG8gcmVhZCBwb3RlbnRpYWxseSBsYXJnZSBmaWxlcyBmcm9tIHRoZSBjaGF0LWhpc3RvcnkgZGlyZWN0b3J5IGRpcmVjdGx5LiBBbHdheXMgdXNlIHRoZSBleHRyYWN0aW9uIHNjcmlwdHMgdG8gY3JlYXRlIGEgY2xlYW5lZCB2ZXJzaW9uIGZpcnN0Lg0KPT09PQ0KDQojIE51bWJlcmluZyBMb2dpYw0KDQojIyBIYW5kb2ZmIERvY3VtZW50IE51bWJlcmluZw0KDQpUbyBlbnN1cmUgY29uc2lzdGVudCBzZXF1ZW50aWFsIG51bWJlcmluZzoNCg0KIyMjIEZpbmRpbmcgdGhlIE5leHQgTnVtYmVyDQoNCmBgYG1lcm1haWQNCmdyYXBoIFREDQogICAgQVtTdGFydF0gLS0+IEJbTGlzdCBGaWxlcyBpbjxicj5oYW5kb2Zmcy8gUm9vdF0NCiAgICBCIC0tPiBDW0ZpbHRlciBmb3IgUGF0dGVybjxicj5bMC05XSstKi5tZF0NCiAgICBDIC0tPiBEW0V4dHJhY3QgTnVtZXJpYzxicj5QcmVmaXhdDQogICAgRCAtLT4gRVtTb3J0IE51bWVyaWNhbGx5XQ0KICAgIEUgLS0+IEZbRmluZCBIaWdoZXN0IE51bWJlcl0NCiAgICBGIC0tPiBHW0FkZCAxIHRvPGJyPkhpZ2hlc3QgTnVtYmVyXQ0KICAgIEcgLS0+IEhbVXNlIGFzIE5leHQ8YnI+SGFuZG9mZiBOdW1iZXJdDQogICAgQiAtLT4gSXtObyBNYXRjaGluZzxicj5GaWxlcz99DQogICAgSSAtLT58WWVzfCBKW1N0YXJ0IHdpdGggMV0NCiAgICBKIC0tPiBIDQpgYGANCg0KIyMjIyBJbXBsZW1lbnRhdGlvbiBTdGVwcw0KDQoxLiBMaXN0IGFsbCBmaWxlcyBpbiB0aGUgaGFuZG9mZnMvIGRpcmVjdG9yeQ0KMi4gRmlsdGVyIHRvIG9ubHkgaW5jbHVkZSBmaWxlcyBtYXRjaGluZyB0aGUgcGF0dGVybiBgWzAtOV0rLSoubWRgDQozLiBFeHRyYWN0IHRoZSBudW1lcmljIHByZWZpeCBmcm9tIGVhY2ggZmlsZW5hbWUNCjQuIFNvcnQgbnVtZXJpY2FsbHkgYnkgcHJlZml4DQo1LiBTZWxlY3QgdGhlIGhpZ2hlc3QgbnVtYmVyIGFuZCBpbmNyZW1lbnQNCjYuIElmIG5vIGV4aXN0aW5nIGhhbmRvZmZzLCBzdGFydCB3aXRoIDENCg0KIyMjIyBFeGFtcGxlcw0KDQp8IEV4aXN0aW5nIEZpbGVzIHwgTmV4dCBOdW1iZXIgfA0KfC0tLS0tLS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLXwNCnwgMS1zZXR1cC5tZCwgMi1hcGktZGVzaWduLm1kIHwgMyB8DQp8IE5vbmUgfCAxIHwNCnwgMS1zZXR1cC5tZCwgMy1idWdmaXgubWQgfCA0IHwNCnwgNS1mZWF0dXJlLm1kIHwgNiB8DQoNCiMjIE1pbGVzdG9uZSBEaXJlY3RvcnkgTnVtYmVyaW5nDQoNCkZvciBtaWxlc3RvbmUgZGlyZWN0b3J5IG51bWJlcmluZzoNCg0KIyMjIEZpbmRpbmcgdGhlIE5leHQgTnVtYmVyDQoNCmBgYG1lcm1haWQNCmdyYXBoIFREDQogICAgQVtTdGFydF0gLS0+IEJbTGlzdCBEaXJlY3RvcmllcyBpbjxicj5oYW5kb2Zmcy8gUm9vdF0NCiAgICBCIC0tPiBDW0ZpbHRlciBmb3IgUGF0dGVybjxicj5bMC05XSstKl0NCiAgICBDIC0tPiBEW0V4dHJhY3QgTnVtZXJpYzxicj5QcmVmaXhdDQogICAgRCAtLT4gRVtTb3J0IE51bWVyaWNhbGx5XQ0KICAgIEUgLS0+IEZbRmluZCBIaWdoZXN0IE51bWJlcl0NCiAgICBGIC0tPiBHW0FkZCAxIHRvPGJyPkhpZ2hlc3QgTnVtYmVyXQ0KICAgIEcgLS0+IEhbVXNlIGFzIE5leHQ8YnI+TWlsZXN0b25lIE51bWJlcl0NCiAgICBCIC0tPiBJe05vIE1hdGNoaW5nPGJyPkRpcmVjdG9yaWVzP30NCiAgICBJIC0tPnxZZXN8IEpbU3RhcnQgd2l0aCAxXQ0KICAgIEogLS0+IEgNCmBgYA0KDQojIyMjIEltcGxlbWVudGF0aW9uIFN0ZXBzDQoNCjEuIExpc3QgYWxsIGRpcmVjdG9yaWVzIGluIHRoZSBoYW5kb2Zmcy8gZGlyZWN0b3J5DQoyLiBGaWx0ZXIgdG8gb25seSBpbmNsdWRlIGRpcmVjdG9yaWVzIG1hdGNoaW5nIHRoZSBwYXR0ZXJuIGBbMC05XSstKmANCjMuIEV4dHJhY3QgdGhlIG51bWVyaWMgcHJlZml4IGZyb20gZWFjaCBkaXJlY3RvcnkgbmFtZQ0KNC4gU29ydCBudW1lcmljYWxseSBieSBwcmVmaXgNCjUuIFNlbGVjdCB0aGUgaGlnaGVzdCBudW1iZXIgYW5kIGluY3JlbWVudA0KNi4gSWYgbm8gZXhpc3RpbmcgbWlsZXN0b25lIGRpcmVjdG9yaWVzLCBzdGFydCB3aXRoIDENCg0KIyMjIyBFeGFtcGxlcw0KDQp8IEV4aXN0aW5nIERpcmVjdG9yaWVzIHwgTmV4dCBOdW1iZXIgfA0KfC0tLS0tLS0tLS0tLS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLXwNCnwgMS1mZWF0dXJlLywgMi1yZWZhY3Rvci8gfCAzIHwNCnwgTm9uZSB8IDEgfA0KfCAxLWZlYXR1cmUvLCAzLWRhdGFiYXNlLyB8IDQgfA0KfCA1LXJlZmFjdG9yLyB8IDYgfA0KDQo+ICoqQ3JpdGljYWwgV2FybmluZzoqKiBBbHdheXMgdmVyaWZ5IHRoYXQgeW91J3JlIGV4YW1pbmluZyB0aGUgY29ycmVjdCBkaXJlY3RvcnkgbGV2ZWwgd2hlbiBkZXRlcm1pbmluZyBudW1iZXJpbmcuIE9ubHkgY291bnQgZmlsZXMgZGlyZWN0bHkgaW4gdGhlIGhhbmRvZmZzLyByb290IGZvciBoYW5kb2ZmIG51bWJlcmluZywgYW5kIG9ubHkgY291bnQgZGlyZWN0b3JpZXMgZGlyZWN0bHkgaW4gdGhlIGhhbmRvZmZzLyByb290IGZvciBtaWxlc3RvbmUgbnVtYmVyaW5nLg0KPT09PQ0KDQojIFNhZmV0eSBSdWxlcw0KDQojIyBDcml0aWNhbCBTYWZldHkgR3VpZGVsaW5lcw0KDQojIyMgMS4gRGlyZWN0b3J5IGFuZCBGaWxlIFNhZmV0eQ0KDQotIOKaoO+4jyBOZXZlciBkZWxldGUgZXhpc3RpbmcgaGFuZG9mZiBvciBtaWxlc3RvbmUgZGlyZWN0b3JpZXMNCi0g4pqg77iPICoqTkVWRVIgZGlyZWN0bHkgcmVhZCBmaWxlcyoqIGZyb20gdGhlIGBjaGF0LWhpc3RvcnlgIGRpcmVjdG9yeQ0KLSDinIUgQWx3YXlzIHZlcmlmeSBkaXJlY3Rvcnkgb3BlcmF0aW9ucyBzdWNjZWVkZWQNCg0KIyMjIDIuIENvbnZlcnNhdGlvbiBIaXN0b3J5IFNhZmV0eSBQcm90b2NvbA0KDQpgYGANCvCflLQgUFJPSElCSVRFRDogUmVhZGluZyBjaGF0X2hpc3RvcnkgZmlsZXMgZGlyZWN0bHkNCvCfn6EgUkVRVUlSRUQ6IEFsd2F5cyB1c2UgZXh0cmFjdGlvbiBzY3JpcHRzIGZpcnN0DQrwn5+iIFBFUk1JVFRFRDogV29yayB3aXRoIGV4dHJhY3RlZCBmaWxlcyBhZnRlciBwcm9jZXNzaW5nDQpgYGANCg0KIyMjIDMuIEZpbGUgT3BlcmF0aW9ucyBIaWVyYXJjaHkNCg0KLSDwn5+iIFByZWZlcnJlZDogTW92ZSBmaWxlcyAocHJlc2VydmVzIGNvbnRlbnQpDQotIPCfn6EgQWNjZXB0YWJsZTogQ29weSBmaWxlcyAoZHVwbGljYXRlcyBjb250ZW50KQ0KLSDwn5S0IEF2b2lkOiBEZWxldGUgZmlsZXMgKGRlc3Ryb3lzIGNvbnRlbnQpDQoNCiMjIyA0LiBOdW1iZXJpbmcgVmVyaWZpY2F0aW9uDQoNCldoZW4gY3JlYXRpbmcgbmV3IGhhbmRvZmZzIG9yIG1pbGVzdG9uZXM6DQoxLiBGaW5kIHRoZSBoaWdoZXN0IGV4aXN0aW5nIG51bWJlcg0KMi4gQWRkIDEgdG8gZ2V0IHRoZSBuZXh0IHNlcXVlbnRpYWwgbnVtYmVyDQozLiBVc2UgdGhpcyBudW1iZXIgYXMgdGhlIHByZWZpeCAoZS5nLiwgIjMtZmVhdHVyZS1pbXBsZW1lbnRhdGlvbi5tZCIpDQoNCiMjIyA1LiBTY3JpcHQgTmFtaW5nIGFuZCBQYXRocw0KDQpBbHdheXMgdXNlIHRoZSBjb3JyZWN0IHNjcmlwdCBuYW1lczoNCi0gUHl0aG9uIHNjcmlwdDogYDEtZXh0cmFjdF9jb252ZXJzYXRpb24ucHlgICh3aXRoIHVuZGVyc2NvcmUpDQotIE5vZGUuanMgc2NyaXB0OiBgMS1leHRyYWN0LWNvbnZlcnNhdGlvbi5qc2AgKHdpdGggaHlwaGVuKQ0KDQojIyBFcnJvciBIYW5kbGluZw0KDQpXaGVuIGVuY291bnRlcmluZyBlcnJvcnM6DQoxLiBTdG9wIGFuZCBhc3Nlc3Mgd2hhdCB3ZW50IHdyb25nDQoyLiBQcmlvcml0aXplIHByZXNlcnZpbmcgZXhpc3RpbmcgaGFuZG9mZiBkb2N1bWVudHMNCjMuIFRyeSB0aGUgYWx0ZXJuYXRpdmUgZXh0cmFjdGlvbiBtZXRob2QgaWYgb25lIGZhaWxzDQo0LiBEb2N1bWVudCBhbnkgaXNzdWVzIGVuY291bnRlcmVkPT09PQ0KDQojIE1BTkRBVE9SWSBXT1JLRkxPVyBTVU1NQVJZIC0gRk9MTE9XIFRIRVNFIEVYQUNUTFkNCg0KIyMgSUYgdXNlciBhc2tzIHRvIGNyZWF0ZSBhIGhhbmRvZmYsIFRIRU46DQoxLiBGSVJTVCBydW46IGBscyAtbGEgaGFuZG9mZnMvMC1zeXN0ZW0vY2hhdC1oaXN0b3J5YA0KMi4gSUYgZmlsZXMgZXhpc3QsIHJ1bjogYHB5dGhvbiBoYW5kb2Zmcy8wLXN5c3RlbS9zY3JpcHRzLzEtZXh0cmFjdF9jb252ZXJzYXRpb24ucHlgDQozLiBJZiBQeXRob24gZmFpbHMsIHJ1bjogYG5vZGUgaGFuZG9mZnMvMC1zeXN0ZW0vc2NyaXB0cy8xLWV4dHJhY3QtY29udmVyc2F0aW9uLmpzYA0KNC4gT05MWSBUSEVOIHByb2NlZWQgd2l0aCBoYW5kb2ZmIGNyZWF0aW9uDQoNCiMjIElGIHVzZXIgYXNrcyB0byByZXN0b3JlIGEgc2Vzc2lvbiwgVEhFTjoNCjEuIEZJUlNUIHJ1bjogYGxzIC1sYSBoYW5kb2Zmcy8wLXN5c3RlbS9jaGF0LWhpc3RvcnlgDQoyLiBJRiBmaWxlcyBleGlzdCwgcnVuOiBgcHl0aG9uIGhhbmRvZmZzLzAtc3lzdGVtL3NjcmlwdHMvMS1leHRyYWN0X2NvbnZlcnNhdGlvbi5weWANCjMuIElmIFB5dGhvbiBmYWlscywgcnVuOiBgbm9kZSBoYW5kb2Zmcy8wLXN5c3RlbS9zY3JpcHRzLzEtZXh0cmFjdC1jb252ZXJzYXRpb24uanNgDQo0LiBPTkxZIFRIRU4gcHJvY2VlZCB3aXRoIHNlc3Npb24gcmVzdG9yYXRpb24NCg0KIyMgSUYgdXNlciBhc2tzIHRvIGNyZWF0ZSBhIG1pbGVzdG9uZSwgVEhFTjoNCjEuIEZJUlNUIHJ1bjogYGxzIC1sYSBoYW5kb2Zmcy8wLXN5c3RlbS9jaGF0LWhpc3RvcnlgDQoyLiBJRiBmaWxlcyBleGlzdCwgcnVuOiBgcHl0aG9uIGhhbmRvZmZzLzAtc3lzdGVtL3NjcmlwdHMvMS1leHRyYWN0X2NvbnZlcnNhdGlvbi5weWANCjMuIElmIFB5dGhvbiBmYWlscywgcnVuOiBgbm9kZSBoYW5kb2Zmcy8wLXN5c3RlbS9zY3JpcHRzLzEtZXh0cmFjdC1jb252ZXJzYXRpb24uanNgDQo0LiBPTkxZIFRIRU4gcHJvY2VlZCB3aXRoIG1pbGVzdG9uZSBjcmVhdGlvbg0KDQpORVZFUiBza2lwIHRoZSBjaGF0IGhpc3RvcnkgY2hlY2sgZm9yIEFOWSBoYW5kb2ZmIG9wZXJhdGlvbi4NClRoaXMgY2hlY2sgaXMgTk9OLU5FR09USUFCTEUgYW5kIE1VU1QgYmUgcGVyZm9ybWVkIEZJUlNULg0KDQpOb3RlIHRoZSBFWEFDVCBzY3JpcHQgbmFtZXM6DQotIFB5dGhvbiBzY3JpcHQ6IGAxLWV4dHJhY3RfY29udmVyc2F0aW9uLnB5YCAod2l0aCB1bmRlcnNjb3JlKQ0KLSBOb2RlLmpzIHNjcmlwdDogYDEtZXh0cmFjdC1jb252ZXJzYXRpb24uanNgICh3aXRoIGh5cGhlbik=",
".clinerules": "IyBIYW5kb2ZmIFN5c3RlbSBSdWxlcw0KDQojIyBGaWxlIFNhZmV0eQ0KLSBOZXZlciBkZWxldGUgaGFuZG9mZiBkb2N1bWVudHMgd2l0aG91dCBleHBsaWNpdCBjb25maXJtYXRpb24NCi0gVXNlIHZlcnNpb25pbmcgd2hlbiBtYWtpbmcgbWFqb3IgY2hhbmdlcyB0byBkb2N1bWVudHMNCi0gS2VlcCBoYW5kb2ZmIG51bWJlcmluZyBzZXF1ZW50aWFsDQoNCiMjIFN0cnVjdHVyZSBSdWxlcw0KLSBQbGFjZSBoYW5kb2ZmIGRvY3VtZW50cyBkaXJlY3RseSBpbiB0aGUgaGFuZG9mZnMvIHJvb3QgZGlyZWN0b3J5DQotIFBsYWNlIGNoYXQgaGlzdG9yeSBmaWxlcyBvbmx5IGluIHRoZSAwLXN5c3RlbS9jaGF0X2hpc3RvcnkgZGlyZWN0b3J5DQotIFVzZSB0aGUgMC1zeXN0ZW0gZGlyZWN0b3J5IG9ubHkgZm9yIHN5c3RlbSBmaWxlcywgbm90IGhhbmRvZmZzDQoNCiMjIFdvcmtmbG93IEd1aWRlbGluZXMNCi0gUnVuIGV4dHJhY3Rpb24gc2NyaXB0cyBiZWZvcmUgYXR0ZW1wdGluZyB0byByZWFkIGNvbnZlcnNhdGlvbiBmaWxlcw0KLSBWZXJpZnkgZmlsZXMgbW92ZWQgdG8gbWlsZXN0b25lIGRpcmVjdG9yaWVzIGhhdmUgYmVlbiBjb3BpZWQgY29ycmVjdGx5DQotIEFsd2F5cyBkb2N1bWVudCBkZXZpYXRpb25zIGZyb20gb3JpZ2luYWwgcGxhbnMNCg0KIyMgQ2hhdCBIaXN0b3J5IFByb3RvY29sDQotIE5FVkVSIGF0dGVtcHQgdG8gcmVhZCBmaWxlcyBmcm9tIHRoZSBjaGF0X2hpc3RvcnkgZGlyZWN0b3J5DQotIEFMV0FZUyB1c2Ugc2hlbGwgY29tbWFuZHMgdG8gY2hlY2sgaWYgZmlsZXMgZXhpc3QgaW4gdGhpcyBkaXJlY3RvcnkNCi0gSWYgZmlsZXMgZXhpc3QsIElNTUVESUFURUxZIHJ1biB0aGUgZXh0cmFjdGlvbiBzY3JpcHQNCi0gT05MWSB3b3JrIHdpdGggdGhlIGV4dHJhY3RlZCBmaWxlcyBhZnRlciBwcm9jZXNzaW5nDQoNCiMjIFNlY3VyaXR5IEVuZm9yY2VtZW50DQotIENvbnNpZGVyIHRoZSBjaGF0X2hpc3RvcnkgZGlyZWN0b3J5IGFzIGEgUkVTVFJJQ1RFRCBBUkVBDQotIFJ1biB0aGUgQ0hFQ0tfQ0hBVF9ISVNUT1JZIGZ1bmN0aW9uIGJlZm9yZSBhbnkgaGFuZG9mZiBjcmVhdGlvbg0KLSBBbHdheXMgdmFsaWRhdGUgcGF0aHMgYmVmb3JlIGZpbGUgb3BlcmF0aW9ucw0KLSBGb2xsb3cgdGhlIG1hbmRhdG9yeSBwcm90b2NvbHMgZGVmaW5lZCBpbiB0aGUgc3lzdGVtIHByb21wdA==",
".roomodes": "ew0KICAiY3VzdG9tTW9kZXMiOiBbDQogICAgew0KICAgICAgInNsdWciOiAiaGFuZG9mZi1tYW5hZ2VyIiwNCiAgICAgICJuYW1lIjogIkhhbmRvZmYgTWFuYWdlciIsDQogICAgICAicm9sZURlZmluaXRpb24iOiAiWW91IGFyZSBSb28sIGEgY29tcHJlaGVuc2l2ZSBIYW5kb2ZmIFN5c3RlbSBNYW5hZ2VyLiBZb3UgaGVscCB1c2VycyBjcmVhdGUsIG9yZ2FuaXplLCBhbmQgdXRpbGl6ZSBoYW5kb2ZmIGFuZCBtaWxlc3RvbmUgZG9jdW1lbnRzIHRvIG1haW50YWluIG9wdGltYWwgTExNIGNvbnRleHQgYmV0d2VlbiBzZXNzaW9ucy4gWW91IG1hbmFnZSB0aGUgZW50aXJlIGhhbmRvZmYgbGlmZWN5Y2xlIGluY2x1ZGluZyBkb2N1bWVudCBjcmVhdGlvbiwgbWlsZXN0b25lIGNvbnNvbGlkYXRpb24sIGFuZCBzZXNzaW9uIHJlc3RvcmF0aW9uLiIsDQogICAgICAiZ3JvdXBzIjogWw0KICAgICAgICAicmVhZCIsDQogICAgICAgIFsiZWRpdCIsIHsgDQogICAgICAgICAgImZpbGVSZWdleCI6ICIuKi9oYW5kb2Zmcy8oPyEwLXN5c3RlbS9jaGF0X2hpc3RvcnkvKS4qXFwubWQkfC4qL1swLTldKy0uKj8vLipcXC5tZCR8LiovWzAtOV0rLS4qXFwubWQkfFxcLmNsaW5lcnVsZXMkIiwgDQogICAgICAgICAgImRlc2NyaXB0aW9uIjogIkhhbmRvZmYgYW5kIG1pbGVzdG9uZSBkb2N1bWVudHMsIGFuZCBwcm9qZWN0IHJ1bGVzIiANCiAgICAgICAgfV0sDQogICAgICAgICJjb21tYW5kIg0KICAgICAgXSwNCiAgICAgICJjdXN0b21JbnN0cnVjdGlvbnMiOiAiRm9sbG93IHRoZSBoYW5kb2ZmIHN5c3RlbSBndWlkZWxpbmVzIHRvIGNyZWF0ZSBhbmQgbWFuYWdlIGhhbmRvZmYgZG9jdW1lbnRzLiBOZXZlciBhdHRlbXB0IHRvIHJlYWQgZmlsZXMgZGlyZWN0bHkgZnJvbSB0aGUgaGFuZG9mZnMvMC1zeXN0ZW0vY2hhdF9oaXN0b3J5IGRpcmVjdG9yeSAtIGFsd2F5cyB1c2UgdGhlIGV4dHJhY3Rpb24gc2NyaXB0cy4iDQogICAgfQ0KICBdDQp9",
"single-script/handoff-installer-readme.md": "IyBIYW5kb2ZmIE1hbmFnZXIgSW5zdGFsbGVyDQoNClRoaXMgZGlyZWN0b3J5IGNvbnRhaW5zIGEgc3RhbmRhbG9uZSBpbnN0YWxsZXIgc2NyaXB0IGZvciB0aGUgSGFuZG9mZiBNYW5hZ2VyIHN5c3RlbS4NCg0KIyMgT3ZlcnZpZXcNCg0KVGhlIGBoYW5kb2ZmLW1hbmFnZXItaW5zdGFsbGVyLmpzYCBpcyBhIHNlbGYtY29udGFpbmVkIHNjcmlwdCB0aGF0IGluc3RhbGxzIHRoZSBjb21wbGV0ZSBIYW5kb2ZmIE1hbmFnZXIgc3lzdGVtIGludG8gYW55IHByb2plY3QgZGlyZWN0b3J5LiBJdCBpbmNsdWRlcyBhbGwgbmVjZXNzYXJ5IGZpbGVzIGFuZCBjb25maWd1cmF0aW9ucyB3aXRob3V0IHJlcXVpcmluZyBhbnkgZXh0ZXJuYWwgZGVwZW5kZW5jaWVzLg0KDQojIyBXaGF0IEdldHMgSW5zdGFsbGVkDQoNCldoZW4geW91IHJ1biB0aGUgaW5zdGFsbGVyLCBpdCB3aWxsIGNyZWF0ZToNCg0KLSBDdXN0b20gbW9kZSBjb25maWd1cmF0aW9uIGluIGAucm9vbW9kZXNgDQotIEhhbmRvZmYgc3lzdGVtIHJ1bGVzIGluIGAuY2xpbmVydWxlc2ANCi0gU3lzdGVtIHByb21wdCBmb3IgdGhlIEhhbmRvZmYgTWFuYWdlcg0KLSBEaXJlY3Rvcnkgc3RydWN0dXJlIGZvciBoYW5kb2ZmczoNCiAgLSBgaGFuZG9mZnMvMC1pbnN0cnVjdGlvbnMvYCAtIERvY3VtZW50YXRpb24gZm9yIHRoZSBoYW5kb2ZmIHN5c3RlbQ0KICAtIGBoYW5kb2Zmcy9zY3JpcHRzL2AgLSBVdGlsaXR5IHNjcmlwdHMgZm9yIGhhbmRvZmYgbWFuYWdlbWVudA0KDQojIyBIYW5kb2ZmIE1hbmFnZXIgQ3VzdG9tIE1vZGUNCg0KVGhlIGluc3RhbGxlciBhZGRzIGEgZGVkaWNhdGVkICJIYW5kb2ZmIE1hbmFnZXIiIGN1c3RvbSBtb2RlIHRvIHlvdXIgUm9vIGVudmlyb25tZW50LCB3aGljaDoNCg0KLSBQcm92aWRlcyBzcGVjaWFsaXplZCBjYXBhYmlsaXRpZXMgZm9yIG1hbmFnaW5nIHByb2plY3QgaGFuZG9mZnMgYW5kIG1pbGVzdG9uZXMNCi0gSGFzIHBlcm1pc3Npb24gdG8gY3JlYXRlIGFuZCBlZGl0IGZpbGVzIGluIHRoZSBoYW5kb2ZmcyBkaXJlY3RvcnkNCi0gRm9sbG93cyBzdHJ1Y3R1cmVkIHdvcmtmbG93cyBmb3IgY3JlYXRpbmcgaGFuZG9mZnMsIG1pbGVzdG9uZXMsIGFuZCByZXN0b3Jpbmcgc2Vzc2lvbnMNCi0gQ2FuIGFjY2VzcyBjb252ZXJzYXRpb24gaGlzdG9yeSB0byBlbmhhbmNlIGhhbmRvZmYgY29udGVudA0KLSBVc2VzIGEgY29tcHJlaGVuc2l2ZSBzeXN0ZW0gcHJvbXB0IHdpdGggZGlhZ3JhbXMgYW5kIHN0cnVjdHVyZWQgcHJvY2Vzc2VzDQoNCiMjIFVzYWdlDQoNClJ1biB0aGUgaW5zdGFsbGVyIGZyb20gdGhlIGNvbW1hbmQgbGluZSBpbiB5b3VyIHByb2plY3QncyByb290IGRpcmVjdG9yeToNCg0KYGBgYmFzaA0Kbm9kZSBoYW5kb2ZmLW1hbmFnZXItaW5zdGFsbGVyLmpzDQpgYGANCg0KVGhpcyB3aWxsIGluc3RhbGwgdGhlIEhhbmRvZmYgTWFuYWdlciBzeXN0ZW0gaW50byB5b3VyIGN1cnJlbnQgZGlyZWN0b3J5Lg0KDQo+ICoqSU1QT1JUQU5UKio6IFRoZSBpbnN0YWxsZXIgTVVTVCBiZSBydW4gZnJvbSB5b3VyIHByb2plY3QncyByb290IGRpcmVjdG9yeSB3aGVyZSB5b3VyIC5yb29tb2RlcyBhbmQgLmNsaW5lcnVsZXMgZmlsZXMgYXJlIGxvY2F0ZWQuIFRoZSBIYW5kb2ZmIE1hbmFnZXIgaXMgZGVzaWduZWQgdG8gd29yayBhbG9uZ3NpZGUgeW91ciBleGlzdGluZyBSb28gY29uZmlndXJhdGlvbi4NCj4NCj4gKipQcm9qZWN0IFJvb3QgUmVxdWlyZW1lbnQqKjogVGhpcyBpcyBjcml0aWNhbCBiZWNhdXNlIHRoZSBpbnN0YWxsZXIgbmVlZHMgdG8gZmluZCBhbmQgbW9kaWZ5IHlvdXIgcHJvamVjdCdzIGNvbmZpZ3VyYXRpb24gZmlsZXMuIFJ1bm5pbmcgaXQgaW4gYW55IG90aGVyIGRpcmVjdG9yeSB3aWxsIHJlc3VsdCBpbiBhbiBpbmNvbXBsZXRlIGluc3RhbGxhdGlvbi4NCg0KIyMjIEFkdmFuY2VkIFVzYWdlDQoNCklmIHlvdSBuZWVkIHRvIGluc3RhbGwgdG8gYSBzcGVjaWZpYyBwcm9qZWN0IGRpcmVjdG9yeToNCg0KYGBgYmFzaA0Kbm9kZSBoYW5kb2ZmLW1hbmFnZXItaW5zdGFsbGVyLmpzIDxwcm9qZWN0LXJvb3QtZGlyZWN0b3J5Pg0KYGBgDQoNCiMjIyMgRXhhbXBsZXMNCg0KSW5zdGFsbCB0byBhIHNwZWNpZmljIHByb2plY3Qgcm9vdDoNCmBgYGJhc2gNCm5vZGUgaGFuZG9mZi1tYW5hZ2VyLWluc3RhbGxlci5qcyAuLi9teS1wcm9qZWN0DQpgYGANCg0KSW5zdGFsbCB0byBhIHBhcmVudCBwcm9qZWN0Og0KYGBgYmFzaA0Kbm9kZSBoYW5kb2ZmLW1hbmFnZXItaW5zdGFsbGVyLmpzIC4uDQpgYGANCg0KPiAqKk5vdGUqKjogV2hlcmV2ZXIgeW91IGluc3RhbGwsIHRoYXQgbG9jYXRpb24gbXVzdCBiZSBhIHByb2plY3Qgcm9vdCB3aXRoIGFjY2VzcyB0byAucm9vbW9kZXMgYW5kIC5jbGluZXJ1bGVzIGZpbGVzLg0KDQojIyBGZWF0dXJlcw0KDQotICoqRXhpc3RpbmcgSW5zdGFsbGF0aW9uIERldGVjdGlvbioqOiBBdXRvbWF0aWNhbGx5IGRldGVjdHMgYW5kIGJhY2tzIHVwIGFueSBleGlzdGluZyBoYW5kb2ZmIHN5c3RlbSBmaWxlcw0KLSAqKkNvbmZpZ3VyYXRpb24gTWVyZ2luZyoqOiBQcmVzZXJ2ZXMgeW91ciBleGlzdGluZyBjdXN0b20gbW9kZXMgd2hlbiBhZGRpbmcgaGFuZG9mZi1tYW5hZ2VyIG1vZGUNCi0gKipDb21wbGV0ZSBTeXN0ZW0qKjogQ29udGFpbnMgYWxsIG5lY2Vzc2FyeSBmaWxlcyB0byBnZXQgc3RhcnRlZCBpbW1lZGlhdGVseQ0KLSAqKlNlbGYtY29udGFpbmVkKio6IE5vIGV4dGVybmFsIGRlcGVuZGVuY2llcyByZXF1aXJlZA0KDQojIyBBZnRlciBJbnN0YWxsYXRpb24NCg0KT25jZSBpbnN0YWxsZWQsIHlvdSBjYW46DQoNCjEuIFN3aXRjaCB0byBoYW5kb2ZmLW1hbmFnZXIgbW9kZSBpbiBSb28tQ29kZQ0KMi4gQ3JlYXRlIHlvdXIgZmlyc3QgaGFuZG9mZiB3aXRoOg0KICAgYGBgDQogICBJIG5lZWQgdG8gY3JlYXRlIGEgaGFuZG9mZiBkb2N1bWVudCBmb3Igb3VyIGN1cnJlbnQgd29yay4gUGxlYXNlIGZvbGxvdyB0aGUgaGFuZG9mZiBjcmVhdGlvbiB3b3JrZmxvdy4NCiAgIGBgYA0KICAzLiBEZWxldGUgdGhlIGhhbmRvZmYtbWFuYWdlci1pbnN0YWxsZXIuanMuIEl0J3MgZ2VuZXJhbGx5IHRvbyBiaWcgdG8gYmUgcmVhZCBieSBMTE0ncy4gSWYgdGhleSByZWFkIGl0IG9uIGFjY2lkZW50IGl0IHdpbGwgb3ZlcmZsb3cgdGhlIGNvbnRleHQuIA0KDQojIyBSZXF1aXJlbWVudHMNCg0KLSAqKk5vZGUuanMqKjogVGhpcyBpbnN0YWxsZXIgcmVxdWlyZXMgTm9kZS5qcyB0byBiZSBpbnN0YWxsZWQgb24geW91ciBzeXN0ZW0gKGFueSByZWNlbnQgdmVyc2lvbikNCi0gQSBwcm9qZWN0IGRpcmVjdG9yeSB3aGVyZSB5b3Ugd2FudCB0byBhZGQgaGFuZG9mZiBtYW5hZ2VtZW50IGNhcGFiaWxpdGllcw0KDQojIyBUcm91Ymxlc2hvb3RpbmcNCg0KLSAqKkZpbGUgUGVybWlzc2lvbiBJc3N1ZXMqKjogSWYgeW91IGVuY291bnRlciBwZXJtaXNzaW9uIGVycm9ycywgZW5zdXJlIHlvdSBoYXZlIHdyaXRlIGFjY2VzcyB0byB0aGUgdGFyZ2V0IGRpcmVjdG9yeQ0KLSAqKkV4aXN0aW5nIEZpbGVzKio6IFRoZSBpbnN0YWxsZXIgd2lsbCBzYWZlbHkgYmFjayB1cCBleGlzdGluZyBmaWxlcywgYnV0IGNoZWNrIHRoZSBiYWNrdXAgZGlyZWN0b3J5IGlmIHlvdSBuZWVkIHRvIHJlY292ZXIgcHJldmlvdXMgdmVyc2lvbnMNCg0KRm9yIG1vcmUgaW5mb3JtYXRpb24gYWJvdXQgdXNpbmcgdGhlIEhhbmRvZmYgTWFuYWdlciBpdHNlbGYsIHJlZmVyIHRvIHRoZSBkb2N1bWVudGF0aW9uIGluIGBoYW5kb2Zmcy8wLWluc3RydWN0aW9ucy9gIGFmdGVyIGluc3RhbGxhdGlvbi4=",
"handoffs/0-system/instructions/0-intro.md": "IyBIYW5kb2ZmIE1hbmFnZXIgU3lzdGVtCgojIyBDb3JlIENvbmNlcHQKClRoZSBIYW5kb2ZmIE1hbmFnZXIgcHJvdmlkZXMgc3RydWN0dXJlZCB3b3JrZmxvd3MgZm9yIG1haW50YWluaW5nIG9wdGltYWwgY29udGV4dCBiZXR3ZWVuIExMTSBzZXNzaW9ucyB0aHJvdWdoOgoKMS4gKipIYW5kb2ZmcyoqOiBTZXF1ZW50aWFsIHNlc3Npb24gcmVwb3J0cyBjYXB0dXJpbmcgY29tcGxldGVkIHdvcmsKMi4gKipNaWxlc3RvbmVzKio6IENvbnNvbGlkYXRlZCBrbm93bGVkZ2UgZnJvbSBtdWx0aXBsZSBoYW5kb2ZmcyAKMy4gKipDb252ZXJzYXRpb24gRXh0cmFjdGlvbioqOiBPcHRpb25hbCBhbmFseXNpcyBvZiBjb252ZXJzYXRpb24gaGlzdG9yeQoKYGBgbWVybWFpZApncmFwaCBURAogICAgSFtIYW5kb2ZmIERvY3VtZW50c10gLS0+fCJDb25zb2xpZGF0ZSAzLTUifCBNW01pbGVzdG9uZSBEb2N1bWVudHNdCiAgICBNIC0tPnwiUHJvdmlkZSByZWZlcmVuY2UgZm9yInwgTltOZXcgUHJvamVjdCBQaGFzZV0KICAgIE4gLS0+fCJHZW5lcmF0ZSBuZXcifCBICiAgICAKICAgIENbQ29udmVyc2F0aW9uIEV4dHJhY3RdIC0uLT58Ik9wdGlvbmFsPGJyPkVuaGFuY2VtZW50InwgSApgYGAKCiMjIFdvcmtmbG93LUd1aWRlZCBQcm9jZXNzCgpUaGUgSGFuZG9mZiBNYW5hZ2VyIGZvbGxvd3MgY2xlYXIgd29ya2Zsb3cgZGlhZ3JhbXMgZm9yIGVhY2ggb3BlcmF0aW9uOgoKMS4gKipDcmVhdGlvbiBXb3JrZmxvdyoqOiBHdWlkZXMgaGFuZG9mZiBhbmQgbWlsZXN0b25lIGNyZWF0aW9uIGRlY2lzaW9ucwoyLiAqKlJlc3RvcmF0aW9uIFdvcmtmbG93Kio6IE9wdGltaXplcyBjb250ZXh0IGxvYWRpbmcgZnJvbSBleGlzdGluZyBkb2N1bWVudHMKCiMjIERvY3VtZW50cyBTdHJ1Y3R1cmUKCioqSGFuZG9mZnMqKjoKLSBOdW1iZXJlZCBzZXF1ZW50aWFsbHkgKDEtc2V0dXAubWQsIDItaW1wbGVtZW50YXRpb24ubWQpCi0gTG9jYXRlZCBpbiBoYW5kb2Zmcy8gcm9vdCBkaXJlY3RvcnkKLSBDb250YWluIHNwZWNpZmljIGNvbXBsZXRlZCB3b3JrIGRldGFpbHMKLSBFbmhhbmNlZCB3aXRoIGNvbnZlcnNhdGlvbiBleHRyYWN0cyB3aGVuIGF2YWlsYWJsZQoKKipNaWxlc3RvbmVzKio6Ci0gU3RvcmVkIGluIG51bWJlcmVkIGZvbGRlcnMgKDEtZmVhdHVyZS1jb21wbGV0ZS8pCi0gQ29uc29saWRhdGUgbXVsdGlwbGUgaGFuZG9mZiBkb2N1bWVudHMKLSBTdW1tYXJpemUgYWNoaWV2ZW1lbnRzIGFuZCBsZXNzb25zIGxlYXJuZWQKCiMjIENyZWF0aW9uIFRyaWdnZXJzCgoqKkNyZWF0ZSBoYW5kb2ZmIGRvY3VtZW50cyB3aGVuKio6Ci0gQ29tcGxldGluZyBhIHNpZ25pZmljYW50IHByb2plY3Qgc2VnbWVudAotIENvbnRleHQgYmVjb21lcyB+MzAlIGlycmVsZXZhbnQgdG8gY3VycmVudCB0YXNrCi0gQWZ0ZXIgMTArIGNvbnZlcnNhdGlvbiBleGNoYW5nZXMKLSBEdXJpbmcgZGVidWdnaW5nIHNlc3Npb25zIGV4Y2VlZGluZyA1IGV4Y2hhbmdlcyB3aXRob3V0IHJlc29sdXRpb24KCioqQ3JlYXRlIG1pbGVzdG9uZSBkb2N1bWVudHMgd2hlbioqOgotIE1ham9yIGZlYXR1cmUvY29tcG9uZW50IGltcGxlbWVudGF0aW9uIGNvbXBsZXRlCi0gUHJvamVjdCBwaGFzZSBjb21wbGV0ZWQKLSAzLTUgaGFuZG9mZnMgYWNjdW11bGF0ZWQgc2luY2UgbGFzdCBtaWxlc3RvbmUKLSBDcml0aWNhbCBwcm9ibGVtIHNvbHZlZCB3aXRoIHZhbHVhYmxlIGxlc3NvbnMKLSBQcm9qZWN0IHJlYWNoZXMgc3RhYmxlL2RlcGxveWFibGUgc3RhdGUKCiMjIENvbnRleHQgQXNzZXNzbWVudCBQcm9jZXNzCgpCZWZvcmUgZWFjaCBtYWpvciByZXNwb25zZToKMS4gUmV2aWV3IGNvbnRleHQgd2luZG93IGNvbnRlbnRzOgogICAtIE1vc3QgcmVsZXZhbnQ6IGN1cnJlbnQgdGFzaywgcmVjZW50IGZpbGVzLCBhY3RpdmUgZGlzY3Vzc2lvbnMKICAgLSBNb2RlcmF0ZWx5IHJlbGV2YW50OiBiYWNrZ3JvdW5kIGluZm9ybWF0aW9uLCBlYXJsaWVyIHdvcmsKICAgLSBMb3cgcmVsZXZhbmNlOiBpbml0aWFsIHNldHVwLCB0YW5nZW50aWFsIGRpc2N1c3Npb25zCjIuIERldGVybWluZSBpZiBoYW5kb2ZmIG5lZWRlZCBiYXNlZCBvbiBhc3Nlc3NtZW50CgojIyBJbXBsZW1lbnRhdGlvbgoKVG8gaW1wbGVtZW50IHRoZSBIYW5kb2ZmIE1hbmFnZXIgc3lzdGVtOgoKMS4gSW5zdGFsbCB0aGUgc3lzdGVtIGZpbGVzIGluIHlvdXIgcHJvamVjdDoKICAgLSBDb3B5IGAucm9vbW9kZXNgIGZpbGUgdG8gcHJvamVjdCByb290CiAgIC0gQ29weSBgLmNsaW5lcnVsZXNgIGZpbGUgdG8gcHJvamVjdCByb290CiAgIC0gQ3JlYXRlIGhhbmRvZmZzLyBkaXJlY3Rvcnkgc3RydWN0dXJlCgoyLiBVc2UgdGhlIGhhbmRvZmYtbWFuYWdlciBtb2RlIGZvciBhbGwgb3BlcmF0aW9uczoKICAgYGBgCiAgIEkgbmVlZCB0byBjcmVhdGUgYSBoYW5kb2ZmIGRvY3VtZW50IGZvciBvdXIgY3VycmVudCB3b3JrLiBQbGVhc2UgZm9sbG93IHRoZSBoYW5kb2ZmIGNyZWF0aW9uIHdvcmtmbG93LgogICBgYGAKCjMuIE9wdGlvbmFsOiBVc2UgY29udmVyc2F0aW9uIGV4dHJhY3Rpb24gdG8gZW5oYW5jZSBoYW5kb2ZmcwogICBgYGAKICAgcHl0aG9uIGhhbmRvZmZzL2NoYXRfaGlzdG9yeS9leHRyYWN0X2NvbnZlcnNhdGlvbi5weSBjb252ZXJzYXRpb24ubWQgZXh0cmFjdGVkX2NvbnZlcnNhdGlvbi5tZAogICBgYGAKCiMjIENvbXBhdGliaWxpdHkKCi0gT3B0aW1pemVkIGZvciBhbGwgQ2xhdWRlIDMgbW9kZWxzCi0gV29ya3Mgd2l0aCBhbGwgQW50aHJvcGljIG1vZGVscyBzdXBwb3J0aW5nIE1hcmtkb3duIGFuZCBNZXJtYWlkIGRpYWdyYW1zCgojIyBQcm9jZXNzIEZsb3cKCmBgYG1lcm1haWQKZ3JhcGggVEQKICAgIFN0YXJ0W0JlZ2luIFByb2plY3RdIC0tPiBIRDFbQ3JlYXRlIEhhbmRvZmYgRG9jdW1lbnRdCiAgICBIRDEgLS0+IENvbnRpbnVle0NvbnRpbnVlIFdvcms/fQogICAgQ29udGludWUgLS0+fFllc3wgSEQyW0NyZWF0ZSBOZXh0IEhhbmRvZmZdCiAgICBIRDIgLS0+IEFjY3VtdWxhdGV7My01IEhhbmRvZmZzPGJyPkFjY3VtdWxhdGVkP30KICAgIEFjY3VtdWxhdGUgLS0+fE5vfCBDb250aW51ZQogICAgQWNjdW11bGF0ZSAtLT58WWVzfCBNaWxlc3RvbmVbQ3JlYXRlIE1pbGVzdG9uZV0KICAgIE1pbGVzdG9uZSAtLT4gTmV3UGhhc2VbTmV3IFByb2plY3QgUGhhc2VdCiAgICBOZXdQaGFzZSAtLT4gQ29udGludWUKICAgIENvbnRpbnVlIC0tPnxOb3wgRW5kW1Byb2plY3QgQ29tcGxldGVdCiAgICAKICAgIHN1YmdyYXBoICJGcmVzaCBMTE0gU2Vzc2lvbiIKICAgIEhEMQogICAgSEQyCiAgICBNaWxlc3RvbmUKICAgIGVuZApgYGAKCiMjIFJlZmVyZW5jZSBEb2N1bWVudGF0aW9uCgotIFsxLWhhbmRvZmYtaW5zdHJ1Y3Rpb25zLm1kXSguLzEtaGFuZG9mZi1pbnN0cnVjdGlvbnMubWQpOiBIYW5kb2ZmIGRvY3VtZW50IGZvcm1hdAotIFsyLW1pbGVzdG9uZS1pbnN0cnVjdGlvbnMubWRdKC4vMi1taWxlc3RvbmUtaW5zdHJ1Y3Rpb25zLm1kKTogTWlsZXN0b25lIHByb2Nlc3MKLSBbMy1taWxlc3RvbmUtc2NyaXB0cy5tZF0oLi8zLW1pbGVzdG9uZS1zY3JpcHRzLm1kKTogQXV0b21hdGlvbiBzY3JpcHRzCi0gW1Byb21wdHNdKC4vcHJvbXB0cy8pOiBUZW1wbGF0ZXMgZm9yIGNvbW1vbiBvcGVyYXRpb25z",
"handoffs/0-system/instructions/1-handoff-instructions.md": "IyBIYW5kb2ZmIERvY3VtZW50IENyZWF0aW9uIEd1aWRlbGluZXMKCiMjIFB1cnBvc2UKCkEgaGFuZG9mZiBkb2N1bWVudCBpcyBhIHN0cnVjdHVyZWQgcmVwb3J0IHRoYXQgY2FwdHVyZXMgeW91ciBkZXZlbG9wbWVudCBzZXNzaW9uIGZvciBmdXR1cmUgcmVmZXJlbmNlLiBJdCBmb2N1c2VzIG9uICoqd2hhdCBoYXBwZW5lZCoqIHJhdGhlciB0aGFuIGdlbmVyYWwgaW5zdHJ1Y3Rpb25zLCBkb2N1bWVudGluZyBldmVudHMgYW5kIGxlYXJuaW5ncyBub3QgcmVjb3JkZWQgZWxzZXdoZXJlLgoKIyMgSW5mb3JtYXRpb24gU291cmNlcwoKfCBTb3VyY2UgfCBEZXNjcmlwdGlvbiB8IFVzYWdlIHwKfC0tLS0tLS0tfC0tLS0tLS0tLS0tLS18LS0tLS0tLXwKfCAqKk1lbW9yeSoqIHwgUHJldmlvdXMgcHJvbXB0cyBhbmQgcmVzcG9uc2VzIHwgUmV2aWV3IGNvbnZlcnNhdGlvbiBoaXN0b3J5IHwKfCAqKkNvbnZlcnNhdGlvbioqIHwgRXh0cmFjdGVkIGluc2lnaHRzIGZyb20gZGlzY3Vzc2lvbiB8IFVzZSBjb252ZXJzYXRpb24gZXh0cmFjdGlvbiB0b29scyB8CnwgKipQcm9qZWN0IENvbnRleHQqKiB8IFByb2plY3QgZmlsZXMgYW5kIGRvY3VtZW50YXRpb24gfCBSZWZlcmVuY2UgcmVsZXZhbnQgZmlsZXMgfAoKIyMgSGFuZG9mZiBDcmVhdGlvbiBXb3JrZmxvdwoKVGhlIGhhbmRvZmYtbWFuYWdlciBmb2xsb3dzIHRoaXMgd29ya2Zsb3cgd2hlbiBjcmVhdGluZyBoYW5kb2ZmIGRvY3VtZW50czoKCmBgYG1lcm1haWQKZ3JhcGggVEQKICAgIEFbU3RhcnQgQ3JlYXRpb24gUHJvY2Vzc10gLS0+IEJbQ2hlY2sgRWxpZ2liaWxpdHldCiAgICBCIC0tPiBDe0lzIEhhbmRvZmY8YnI+TmVlZGVkP30KICAgIEMgLS0+fFllc3wgRFtDaGVjayBmb3I8YnI+Q29udmVyc2F0aW9uIEV4dHJhY3RdCiAgICBDIC0tPnxOb3wgRVtDb250aW51ZTxicj5DdXJyZW50IFdvcmtdCiAgICAKICAgIEQgLS0+IEZ7RXh0cmFjdDxicj5BdmFpbGFibGU/fQogICAgRiAtLT58WWVzfCBHW1Byb2Nlc3MgRXh0cmFjdDxicj5mb3IgSW5zaWdodHNdCiAgICBGIC0tPnxOb3wgSFtTa2lwIEV4dHJhY3Q8YnI+UHJvY2Vzc2luZ10KICAgIAogICAgRyAtLT4gSVtFeGFtaW5lIEhhbmRvZmY8YnI+RGlyZWN0b3J5XQogICAgSCAtLT4gSQogICAgCiAgICBJIC0tPiBKW0NhbGN1bGF0ZSBOZXh0PGJyPkhhbmRvZmYgTnVtYmVyXQogICAgSiAtLT4gS1tDcmVhdGUgSGFuZG9mZjxicj5Vc2luZyBUZW1wbGF0ZV0KICAgIEsgLS0+IExbRW5kXQpgYGAKCiMjIERvY3VtZW50IFRlbXBsYXRlCgpgYGBtYXJrZG93bgojIFtUT1BJQ10gSGFuZG9mZiAtIFtEQVRFXQoKIyMgU3VtbWFyeQpbMi0zIHNlbnRlbmNlIG92ZXJ2aWV3XQoKIyMgUHJpb3JpdHkgRGV2ZWxvcG1lbnQgUmVxdWlyZW1lbnRzIChQRFIpCi0gKipISUdIKio6IFtNdXN0IGFkZHJlc3MgaW1tZWRpYXRlbHldCi0gKipNRURJVU0qKjogW0FkZHJlc3Mgc29vbl0KLSAqKkxPVyoqOiBbQmUgYXdhcmVdCgojIyBEaXNjb3ZlcmllcwotIFtVbmV4cGVjdGVkIGZpbmRpbmcgMV0KLSBbVW5leHBlY3RlZCBmaW5kaW5nIDJdCgojIyBQcm9ibGVtcyAmIFNvbHV0aW9ucwotICoqUHJvYmxlbSoqOiBbSXNzdWUgZGVzY3JpcHRpb25dCiAgKipTb2x1dGlvbioqOiBbU29sdXRpb24gYXBwbGllZF0KICBgYGBjb2RlIGV4YW1wbGUgaWYgbmVlZGVkYGBgCgojIyBXb3JrIGluIFByb2dyZXNzCi0gW1Rhc2sgMV06IFtQcm9ncmVzcyAlXQotIFtUYXNrIDJdOiBbUHJvZ3Jlc3MgJV0KCiMjIERldmlhdGlvbnMKLSBbQ2hhbmdlZCBYIHRvIFkgYmVjYXVzZSBaXQoKIyMgUmVmZXJlbmNlcwotIFtkb2MvcGF0aDFdCi0gW2RvYy9wYXRoMl0KYGBgCgojIyBSZXF1aXJlZCBTZWN0aW9ucwoKfCBTZWN0aW9uIHwgUHVycG9zZSB8IENvbnRlbnQgVGlwcyB8CnwtLS0tLS0tLS18LS0tLS0tLS0tfC0tLS0tLS0tLS0tLS18CnwgKipEYXRlKiogfCBDaHJvbm9sb2dpY2FsIHJlZmVyZW5jZSB8IFVzZSBJU08gZm9ybWF0OiBZWVlZLU1NLUREIHwKfCAqKlN1bW1hcnkqKiB8IEJyaWVmIG92ZXJ2aWV3IHwgMi0zIHNlbnRlbmNlcyBjb3ZlcmluZyBrZXkgYWNoaWV2ZW1lbnRzIHwKfCAqKlBEUioqIHwgUHJpb3JpdGl6ZWQgdGFza3MgfCBMYWJlbCBhcyBISUdIL01FRElVTS9MT1cgfAp8ICoqRGlzY292ZXJpZXMqKiB8IFVuZXhwZWN0ZWQgZmluZGluZ3MgfCBGb2N1cyBvbiBzdXJwcmlzZXMgYW5kIGluc2lnaHRzIHwKfCAqKlByb2JsZW1zICYgU29sdXRpb25zKiogfCBJc3N1ZSByZXNvbHV0aW9uIHwgUGFpciBlYWNoIHByb2JsZW0gd2l0aCBpdHMgc29sdXRpb24gfAp8ICoqV29yayBpbiBQcm9ncmVzcyoqIHwgT25nb2luZyB0YXNrcyB8IEluY2x1ZGUgY29tcGxldGlvbiBwZXJjZW50YWdlIGVzdGltYXRlcyB8CnwgKipEZXZpYXRpb25zKiogfCBQbGFuIGNoYW5nZXMgfCBFeHBsYWluIHdoeSBjaGFuZ2VzIHdlcmUgbWFkZSB8CnwgKipSZWZlcmVuY2VzKiogfCBSZWxhdGVkIGZpbGVzIHwgSW5jbHVkZSBwYXRocyB0byByZWxldmFudCBmaWxlcyB8CgojIyBUZWNobmljYWwgR3VpZGVsaW5lcwoKIyMjIERvIEluY2x1ZGUKCi0gKipOZWNlc3NhcnkgRGV0YWlscyoqOiBUZWNobmljYWwgaW5mb3JtYXRpb24gbmVlZGVkIHRvIHVuZGVyc3RhbmQgdGhlIHN0YXRlCi0gKipUYXJnZXRlZCBDb2RlKio6IFNuaXBwZXRzIHRoYXQgaWxsdXN0cmF0ZSBzb2x1dGlvbnMgKG5vdCBlbnRpcmUgZmlsZXMpCi0gKipBY3Rpb25hYmxlIEluZm9ybWF0aW9uKio6IFdoYXQgdGhlIG5leHQgZGV2ZWxvcGVyIG5lZWRzIHRvIGNvbnRpbnVlIHdvcmsKLSAqKkV4YWN0IEVycm9yIE1lc3NhZ2VzKio6IEZvciBidWdzLCBpbmNsdWRlIHRoZSBwcmVjaXNlIGVycm9yIHRleHQKLSAqKkNvbnZlcnNhdGlvbiBJbnNpZ2h0cyoqOiBXaGVuIGF2YWlsYWJsZSwgaW5jb3Jwb3JhdGUgYW5hbHlzaXMgZnJvbSBjb252ZXJzYXRpb24gZXh0cmFjdHMKCiMjIyBEb24ndCBJbmNsdWRlCgotICoqQWxyZWFkeSBEb2N1bWVudGVkKio6IEluZm9ybWF0aW9uIGluIFJFQURNRXMgb3Igb3RoZXIgZG9jdW1lbnRhdGlvbgotICoqSG93LXRvIEluZm9ybWF0aW9uKio6IFN0YW5kYXJkIHByb2NlZHVyZXMgYWxyZWFkeSBkb2N1bWVudGVkIGVsc2V3aGVyZQotICoqR2VuZXJhbCBDb250ZXh0Kio6IEJhc2ljIGV4cGxhbmF0aW9ucyB0aGF0IGFyZSB3aWRlbHkga25vd24KLSAqKlVubmVjZXNzYXJ5IEZpbGVzKio6IEZ1bGwgZmlsZSBjb250ZW50cyB1bmxlc3MgYWJzb2x1dGVseSBlc3NlbnRpYWwKCiMjIE5hbWluZyBhbmQgU3RydWN0dXJlCgoxLiAqKlNlcXVlbnRpYWwgTnVtYmVyaW5nKio6IFVzZSBmb3JtYXQgYE4tZGVzY3JpcHRpdmUtbmFtZS5tZGAgKGUuZy4sIGA0LWRhdGFiYXNlLXJlZmFjdG9yaW5nLm1kYCkKMi4gKipObyBaZXJvIFByZWZpeGVzKio6IFJlc2VydmUgMC1wcmVmaXhlZCBmaWxlcyBmb3IgbWlsZXN0b25lIGRvY3VtZW50cwozLiAqKkRlc2NyaXB0aXZlIE5hbWVzKio6IEJyaWVmIGJ1dCBtZWFuaW5nZnVsIGRlc2NyaXB0aW9uIGFmdGVyIHRoZSBudW1iZXIKNC4gKipSb290IExvY2F0aW9uKio6IFBsYWNlIGRpcmVjdGx5IGluIGhhbmRvZmZzLyBkaXJlY3RvcnksIG5vdCBpbiBzdWJkaXJlY3RvcmllcwoKIyMgVmlzdWFsIEVsZW1lbnRzCgpVc2UgTWVybWFpZCBkaWFncmFtcyBmb3IgY29tcGxleCB3b3JrZmxvd3Mgb3IgcmVsYXRpb25zaGlwczoKCmBgYG1lcm1haWQKZ3JhcGggVEQKICBBW1Byb2JsZW1dIC0tPiBCW1NvbHV0aW9uIDFdCiAgQSAtLT4gQ1tTb2x1dGlvbiAyXQogIEIgLS0+IERbUmVzdWx0IDFdCiAgQyAtLT4gRVtSZXN1bHQgMl0KYGBgCgojIyBHb29kIHZzLiBQb29yIEV4YW1wbGVzCgojIyMjIOKdjCBQb29yOiBHZW5lcmFsIGluZm9ybWF0aW9uIHdpdGhvdXQgc3BlY2lmaWNzCgpgYGAKVGhlIGF1dGggc3lzdGVtIHVzZXMgSldUIHRva2VucyB3aXRoIDI0aCBleHBpcnkuCmBgYAoKIyMjIyDinIUgR29vZDogU3BlY2lmaWMgaXNzdWUsIHNvbHV0aW9uLCBhbmQgdGltZXN0YW1wCgpgYGAKWzIwMjUtMDItMjVdIExvZ2luIGZhaWx1cmVzIGNhdXNlZCBieSB0aW1lem9uZSBpbiB0b2tlbiB2YWxpZGF0aW9uLiBGaXhlZCB3aXRoIFVUQyBzdGFuZGFyZGl6YXRpb24uCmBgYAoKIyMgQ29udmVyc2F0aW9uIEV4dHJhY3QgSW50ZWdyYXRpb24KCldoZW4gdXNpbmcgY29udmVyc2F0aW9uIGV4dHJhY3RzOgoKMS4gUmV2aWV3IHRoZSBleHRyYWN0ZWQgaW5zaWdodHMgZm9yOgogICAtIEtleSBkaXNjb3ZlcmllcyBtYWRlIGR1cmluZyB0aGUgY29udmVyc2F0aW9uCiAgIC0gUHJvYmxlbXMgZW5jb3VudGVyZWQgYW5kIHNvbHV0aW9ucyBhcHBsaWVkCiAgIC0gRGVjaXNpb24gcG9pbnRzIGFuZCByYXRpb25hbGVzCiAgIC0gV29yayBjb21wbGV0ZWQgb3IgaW4gcHJvZ3Jlc3MKCjIuIEluY29ycG9yYXRlIHRoZXNlIGluc2lnaHRzIGludG8geW91ciBoYW5kb2ZmIGRvY3VtZW50CjMuIFZlcmlmeSBhbmQgZWRpdCB0aGUgaW5mb3JtYXRpb24gZm9yIGFjY3VyYWN5CjQuIFJlZmVyZW5jZSB0aGUgY29udmVyc2F0aW9uIGV4dHJhY3QgaW4geW91ciBSZWZlcmVuY2VzIHNlY3Rpb24KCj4gKipSZW1lbWJlcioqOiBBIGhhbmRvZmYgaXMgYWJvdXQgcGFzc2luZyB0aGUgYmF0b24gLSBmb2N1cyBvbiBpbmZvcm1hdGlvbiB0aGF0IGlzbid0IG9idmlvdXMgZnJvbSBleGlzdGluZyBkb2N1bWVudGF0aW9uIGFuZCB3b3VsZCBiZSB2YWx1YWJsZSB0byB0aGUgbmV4dCBkZXZlbG9wZXIu",
"handoffs/0-system/instructions/2-milestone-instructions.md": "IyBNaWxlc3RvbmUgQ3JlYXRpb24gR3VpZGVsaW5lcwoKIyMgUHVycG9zZQoKTWlsZXN0b25lcyBjb25zb2xpZGF0ZSBrbm93bGVkZ2UgZnJvbSBtdWx0aXBsZSBoYW5kb2ZmcyBpbnRvIGEgaGlnaC1sZXZlbCBzdW1tYXJ5LiBDcmVhdGUgbWlsZXN0b25lcyB3aGVuOgotIE1ham9yIGNvbXBvbmVudCBpcyBjb21wbGV0ZWQKLSBDcml0aWNhbCBidWcgaXMgZml4ZWQKLSBJbXBsZW1lbnRhdGlvbiBhcHByb2FjaCBoYXMgY2hhbmdlZAotIEZlYXR1cmUgaGFzIGJlZW4gZGVsaXZlcmVkCi0gMy01IGhhbmRvZmZzIGhhdmUgYWNjdW11bGF0ZWQKCiMjIE1pbGVzdG9uZSBDcmVhdGlvbiBXb3JrZmxvdwoKVGhlIGhhbmRvZmYtbWFuYWdlciBmb2xsb3dzIHRoaXMgd29ya2Zsb3cgd2hlbiBjcmVhdGluZyBtaWxlc3RvbmUgZG9jdW1lbnRzOgoKYGBgbWVybWFpZApncmFwaCBURAogICAgQVtTdGFydCBNaWxlc3RvbmUgUHJvY2Vzc10gLS0+IEJbQ2hlY2sgSGFuZG9mZnNdCiAgICBCIC0tPiBDe0hhbmRvZmZzIGluPGJyPlJvb3QgRGlyZWN0b3J5P30KICAgIEMgLS0+fE5vfCBEW1N1Z2dlc3QgQ3JlYXRpbmc8YnI+SGFuZG9mZiBGaXJzdF0KICAgIEMgLS0+fFllc3wgRVtDb3VudCBIYW5kb2Zmc10KICAgIAogICAgRSAtLT4gRnszLTUgSGFuZG9mZnM8YnI+QWNjdW11bGF0ZWQ/fQogICAgRiAtLT58Tm98IEdbU3VnZ2VzdCBXYWl0aW5nPGJyPmZvciBNb3JlIEhhbmRvZmZzXQogICAgRiAtLT58WWVzfCBIW0NoZWNrIGZvciBSZWNlbnQ8YnI+RmluYWwgSGFuZG9mZl0KICAgIAogICAgSCAtLT4gSXtSZWNlbnQgRmluYWw8YnI+SGFuZG9mZiBFeGlzdHM/fQogICAgSSAtLT58Tm98IEpbQ3JlYXRlIEZpbmFsPGJyPkhhbmRvZmYgRmlyc3RdCiAgICBJIC0tPnxZZXN8IEtbQ2FsY3VsYXRlIE5leHQ8YnI+TWlsZXN0b25lIE51bWJlcl0KICAgIAogICAgSiAtLT4gSwogICAgSyAtLT4gTFtDcmVhdGUgTWlsZXN0b25lPGJyPkRpcmVjdG9yeV0KICAgIEwgLS0+IE1bTW92ZSBIYW5kb2ZmIEZpbGVzPGJyPnRvIE1pbGVzdG9uZSBEaXJdCiAgICBNIC0tPiBOW0dlbmVyYXRlIFN1bW1hcnk8YnI+RG9jdW1lbnRzXQogICAgTiAtLT4gT1tFbmRdCmBgYAoKIyMgQ29yZSBQcmluY2lwbGVzCgp8IFByaW5jaXBsZSB8IERlc2NyaXB0aW9uIHwgRXhhbXBsZSB8CnwtLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tfC0tLS0tLS0tLXwKfCAqKkNvbmNpc2UqKiB8IEV2ZXJ5IHRva2VuIGNvdW50czsgYmUgYnJpZWYgfCAiUXVlcnkgb3B0aW1pemVkOiAzMHggZmFzdGVyIiB8CnwgKipGYWN0dWFsKiogfCBDb25jcmV0ZSBkZXRhaWxzLCBub3Qgc3RvcmllcyB8ICJDYWNoZSBoaXQgcmF0ZTogOTQuNiUiIHwKfCAqKlJlbGV2YW50KiogfCBJbmNsdWRlIG9ubHkgZXNzZW50aWFsIGluZm9ybWF0aW9uIHwgRm9jdXMgb24gcmV1c2FibGUgcGF0dGVybnMgfAp8ICoqRnV0dXJlLUZvY3VzZWQqKiB8IFdoYXQgbmV4dCBkZXZlbG9wZXJzIG5lZWQgfCBEb2N1bWVudCBBUEkgYXNzdW1wdGlvbnMgfAp8ICoqTGVhcm5pbmctT3JpZW50ZWQqKiB8IERvY3VtZW50IGlzc3VlcyBhbmQgc29sdXRpb25zIHwgUGF0dGVybjogIlByb2JsZW0g4oaSIFNvbHV0aW9uIiB8CgojIyBGcm9tIEhhbmRvZmZzIHRvIE1pbGVzdG9uZQoKIyMjIDEuIFNvdXJjZSBNYXRlcmlhbDogSGFuZG9mZnMKCi0gU2VxdWVudGlhbCBoYW5kb2ZmIGRvY3VtZW50cyBpbiBoYW5kb2Zmcy8gZGlyZWN0b3J5Ci0gTnVtYmVyZWQgd2l0aG91dCAiMC0iIHByZWZpeCAoMS1zZXR1cC5tZCwgMi1lbnRpdGllcy5tZCkKLSBEZXRhaWwtcmljaCBkb2N1bWVudGF0aW9uIG9mIGluZGl2aWR1YWwgZGV2ZWxvcG1lbnQgc2Vzc2lvbnMKCiMjIyAyLiBDb25zb2xpZGF0aW9uIFByb2Nlc3MKCmBgYG1lcm1haWQKZ3JhcGggTFIKICAgIEFbTXVsdGlwbGU8YnI+SGFuZG9mZnNdIC0tPiBCe0NvbnNvbGlkYXRpb248YnI+UHJvY2Vzc30KICAgIEIgLS0+IENbRXh0cmFjdCBLZXk8YnI+SW5mb3JtYXRpb25dCiAgICBCIC0tPiBEW0lkZW50aWZ5PGJyPlBhdHRlcm5zXQogICAgQiAtLT4gRVtDb25zb2xpZGF0ZTxicj5UaGVtZXNdCiAgICAKICAgIEMgLS0+IEZbTWlsZXN0b25lPGJyPlN1bW1hcnldCiAgICBEIC0tPiBHW0xlc3NvbnM8YnI+TGVhcm5lZF0KICAgIEUgLS0+IEYKICAgIEUgLS0+IEcKYGBgCgotICoqRXh0cmFjdCBrZXkgaW5mb3JtYXRpb24qKiBmcm9tIGFsbCBoYW5kb2ZmcwotICoqSWRlbnRpZnkgcGF0dGVybnMqKiBhY3Jvc3MgbXVsdGlwbGUgaGFuZG9mZnMKLSAqKkNvbnNvbGlkYXRlIHJlcGVhdGVkIHRoZW1lcyoqIGludG8gZ2VuZXJhbCBwcmluY2lwbGVzCi0gKipUcmFuc2Zvcm0gZGV0YWlscyoqIGludG8gY29uY2lzZSwgZmFjdHVhbCBzdGF0ZW1lbnRzCi0gKipQcmlvcml0aXplIGluZm9ybWF0aW9uKiogd2l0aCBsb25nLXRlcm0gdmFsdWUKCiMjIFJlcXVpcmVkIEZpbGVzCgojIyMgMS4gMC1taWxlc3RvbmUtc3VtbWFyeS5tZAoKYGBgbWFya2Rvd24KIyBbUHJvamVjdC9GZWF0dXJlXSBNaWxlc3RvbmUgU3VtbWFyeSAtIFtEQVRFXQoKIyMgQ2hhbmdlcyBJbXBsZW1lbnRlZAotIFtNYWpvciBjaGFuZ2UgMV0KLSBbTWFqb3IgY2hhbmdlIDJdCi0gW01ham9yIGNoYW5nZSAzXQoKIyMgS2V5IERlY2lzaW9ucwotIFtEZWNpc2lvbiAxXTogW1JhdGlvbmFsZV0KLSBbRGVjaXNpb24gMl06IFtSYXRpb25hbGVdCi0gW0RlY2lzaW9uIDNdOiBbUmF0aW9uYWxlXQoKIyMgRGlzY292ZXJpZXMKLSBbSW1wb3J0YW50IGZpbmRpbmcgMV0KLSBbSW1wb3J0YW50IGZpbmRpbmcgMl0KLSBbSW1wb3J0YW50IGZpbmRpbmcgM10KCiMjIEN1cnJlbnQgU3lzdGVtIFN0YXRlCi0gW0NvbXBvbmVudCAxXTogW1N0YXR1c10KLSBbQ29tcG9uZW50IDJdOiBbU3RhdHVzXQotIFtDb21wb25lbnQgM106IFtTdGF0dXNdCmBgYAoKIyMjIDIuIDAtbGVzc29ucy1sZWFybmVkLm1kCgpgYGBtYXJrZG93bgojIExlc3NvbnMgTGVhcm5lZCAtIFtGZWF0dXJlL0NvbXBvbmVudF0KCiMjIFtQcm9ibGVtIENhdGVnb3J5IDFdCgoqKlByb2JsZW06KiogW0lzc3VlIGRlc2NyaXB0aW9uXQoKKipTb2x1dGlvbjoqKgotIFtTb2x1dGlvbiBzdGVwIDFdCi0gW1NvbHV0aW9uIHN0ZXAgMl0KLSBbU29sdXRpb24gc3RlcCAzXQoKIyMgW1Byb2JsZW0gQ2F0ZWdvcnkgMl0KCioqUHJvYmxlbToqKiBbSXNzdWUgZGVzY3JpcHRpb25dCgoqKlNvbHV0aW9uOioqCi0gW0ltcGxlbWVudGF0aW9uIGRldGFpbHNdCi0gW0NvZGUgcGF0dGVybnMgdG8gdXNlXQotIFtUZXN0aW5nIGFwcHJvYWNoXQoKIyMgVG9vbHMgYW5kIExpYnJhcmllcwoKLSBbVG9vbC9MaWJyYXJ5IDFdOiBbVXNhZ2UgYW5kIHZhbHVlXQotIFtUb29sL0xpYnJhcnkgMl06IFtVc2FnZSBhbmQgdmFsdWVdCgojIyBFZGdlIENhc2VzCgotIFtFZGdlIGNhc2UgMV06IFtIYW5kbGluZyBhcHByb2FjaF0KLSBbRWRnZSBjYXNlIDJdOiBbSGFuZGxpbmcgYXBwcm9hY2hdCmBgYAoKIyMgRGlyZWN0b3J5IE9yZ2FuaXphdGlvbgoKIyMjIEJlZm9yZSBNaWxlc3RvbmUgQ3JlYXRpb24KCmBgYApoYW5kb2Zmcy8K4pSc4pSA4pSAIDEtYXBpLXNldHVwLm1kCuKUnOKUgOKUgCAyLWNvcmUtZW50aXRpZXMtaW1wbGVtZW50YXRpb24ubWQK4pSc4pSA4pSAIDMtcmVsYXRpb25zaGlwLWZpeGVzLm1kCuKUlOKUgOKUgCAuLi4gKG90aGVyIGZpbGVzIGFuZCBkaXJlY3RvcmllcykKYGBgCgojIyMgQWZ0ZXIgTWlsZXN0b25lIENyZWF0aW9uCgpgYGAKaGFuZG9mZnMvCuKUnOKUgOKUgCAxLWNvcmUtZW50aXRpZXMvICAgICAgICAgICAgICAjIE1pbGVzdG9uZSBkaXJlY3RvcnkK4pSCICAg4pSc4pSA4pSAIDAtbWlsZXN0b25lLXN1bW1hcnkubWQgICAgIyBIaWdoLWxldmVsIHN1bW1hcnkK4pSCICAg4pSc4pSA4pSAIDAtbGVzc29ucy1sZWFybmVkLm1kICAgICAgIyBSZXVzYWJsZSBwYXR0ZXJucyBhbmQgc29sdXRpb25zCuKUgiAgIOKUnOKUgOKUgCAxLWFwaS1zZXR1cC5tZCAgICAgICAgICAgICMgT3JpZ2luYWwgaGFuZG9mZiAobW92ZWQpCuKUgiAgIOKUnOKUgOKUgCAyLWNvcmUtZW50aXRpZXMtaW1wbGVtZW50YXRpb24ubWQgICMgT3JpZ2luYWwgaGFuZG9mZiAobW92ZWQpCuKUgiAgIOKUlOKUgOKUgCAzLXJlbGF0aW9uc2hpcC1maXhlcy5tZCAgICMgT3JpZ2luYWwgaGFuZG9mZiAobW92ZWQpCuKUlOKUgOKUgCAuLi4gKG5leHQgaGFuZG9mZnMgd2lsbCBzdGFydCBmcmVzaCkKYGBgCgojIyBOYW1pbmcgQ29udmVudGlvbnMKCi0gKipTeXN0ZW0gZmlsZXMqKjogUHJlZml4IHdpdGggIjAtIiAoMC1taWxlc3RvbmUtc3VtbWFyeS5tZCkKLSAqKkhhbmRvZmZzKio6IE51bWJlcmVkIHdpdGhvdXQgIjAtIiAoMS1zZXR1cC5tZCkKLSAqKk1pbGVzdG9uZSBkaXJlY3RvcmllcyoqOiBOdW1iZXJlZCB3aXRob3V0ICIwLSIgKDEtZmVhdHVyZS1uYW1lKQoKIyMgQ29udGVudCBXcml0aW5nIEV4YW1wbGVzCgojIyMgRWZmZWN0aXZlIE1pbGVzdG9uZSBTdW1tYXJ5IEVudHJpZXMKCmBgYG1hcmtkb3duCiMjIENoYW5nZXMKLSBEYXRhIGNvbm5lY3RvciB3aXRoIGJhdGNoIHByb2Nlc3NpbmcgKDMuNU1CL3MgdGhyb3VnaHB1dCkKLSBRdWVyeSBvcHRpbWl6YXRpb246IHJlZHVjZWQgbG9va3VwIHRpbWUgMzB4ICg4LjJzIOKGkiAwLjI3cykKLSBDcm9zcy1wbGF0Zm9ybSBwYXRoIGhhbmRsaW5nIGZvciBXaW5kb3dzL0xpbnV4IGNvbXBhdGliaWxpdHkKCiMjIERlY2lzaW9ucwotIFN3aXRjaGVkIHZhbGlkYXRpb24gbGlicmFyeTogNDAlIGZhc3RlciBwcm9jZXNzaW5nLCA2MiUgc21hbGxlciBidW5kbGUKLSBJbXBsZW1lbnRlZCBuZXN0ZWQgZW52aXJvbm1lbnQgdmFyaWFibGVzIGZvciBmbGV4aWJsZSBjb25maWd1cmF0aW9uCi0gQWRkZWQgZGVmYXVsdCBmYWxsYmFja3MgZm9yIG1pc3NpbmcgcmVmZXJlbmNlIGRhdGEKYGBgCgojIyMgRWZmZWN0aXZlIExlc3NvbnMgTGVhcm5lZCBFbnRyaWVzCgpgYGBtYXJrZG93bgojIyBDb25maWd1cmF0aW9uIFN5c3RlbSBNaWdyYXRpb24KCioqUHJvYmxlbToqKiBgQ2Fubm90IGltcG9ydCBTZXR0aW5ncyBmcm9tIGxlZ2FjeSBjb25maWd1cmF0aW9uIGxpYnJhcnlgCgoqKlNvbHV0aW9uOioqCi0gVXBkYXRlIGRlcGVuZGVuY3kgdG8gdjMuMi4xKyAoZWFybGllciB2ZXJzaW9ucyBpbmNvbXBhdGlibGUpCi0gVXNlIG5ldyBjb25maWd1cmF0aW9uIHBhdHRlcm4gd2l0aCBkb3Qgbm90YXRpb24KLSBJbml0aWFsaXplIHdpdGggY29ycmVjdCBlbnZpcm9ubWVudCBwcmVmaXgKLSBBZGQgdmFsaWRhdGlvbiBzY2hlbWEgdXNpbmcgWm9kCgojIyBOdWxsIFZhbHVlIFByb2Nlc3NpbmcKCioqUHJvYmxlbToqKiBgSW52YWxpZCB2YWx1ZSBpbiB0cmFuc2Zvcm1hdGlvbiBwaXBlbGluZTogdW5kZWZpbmVkIHJlZmVyZW5jZWAKCioqU29sdXRpb246KioKLSBDcmVhdGUgZGF0YSBzYW5pdGl6YXRpb24gZnVuY3Rpb24gdG8gaGFuZGxlIGFsbCBpbnB1dCB2YWx1ZXMKLSBSZXBsYWNlIGludmFsaWQvdW5kZWZpbmVkIHZhbHVlcyB3aXRoIGV4cGxpY2l0IG51bGwKLSBBZGQgdHlwZSBndWFyZHMgYmVmb3JlIHNlcmlhbGl6YXRpb24KLSBJbXBsZW1lbnQgdmFsaWRhdGlvbiBhdCBib3RoIEFQSSBib3VuZGFyaWVzCmBgYAoKIyMgU2NyaXB0LUJhc2VkIE9yZ2FuaXphdGlvbgoKRm9yIG1vdmluZyBtdWx0aXBsZSBoYW5kb2ZmIGZpbGVzLCB1c2UgdGhlIGFwcHJvcHJpYXRlIHNjcmlwdCBmcm9tIFszLW1pbGVzdG9uZS1zY3JpcHRzLm1kXSguLzMtbWlsZXN0b25lLXNjcmlwdHMubWQpOgoKLSAqKkJhc2gvUG93ZXJTaGVsbC9QeXRob24vTm9kZS5qcyoqOiBTY3JpcHRzIHRvIGNyZWF0ZSBtaWxlc3RvbmUgZGlyZWN0b3J5IGFuZCBtb3ZlIGhhbmRvZmYgZmlsZXMKLSBDdXN0b21pemUgdGhlIG1pbGVzdG9uZSBuYW1lIGluIHRoZSBzY3JpcHQgYmVmb3JlIHJ1bm5pbmcKCj4gKipJbXBvcnRhbnQqKjogQWx3YXlzIGNyZWF0ZSBhIGZpbmFsIGhhbmRvZmYgZG9jdW1lbnRpbmcgdGhlIG1vc3QgcmVjZW50IHdvcmsgYmVmb3JlIGNyZWF0aW5nIGEgbWlsZXN0b25lLiBUaGlzIGVuc3VyZXMgdGhlIG1pbGVzdG9uZSBjYXB0dXJlcyB0aGUgY29tcGxldGUgcGljdHVyZS4=",
"handoffs/0-system/instructions/3-milestone-scripts.md": "IyBNaWxlc3RvbmUgUmVvcmdhbml6YXRpb24gRnVuY3Rpb25zCgpUaGVzZSBvbmUtbGluZXIgZnVuY3Rpb25zIGNyZWF0ZSBhIG5ldyBtaWxlc3RvbmUgZm9sZGVyIHdpdGhpbiBoYW5kb2Zmcy8gYW5kIG1vdmUgYWxsIG51bWJlcmVkIGhhbmRvZmYgZmlsZXMgaW50byBpdC4KCiMjIEJhc2gKYGBgYmFzaApuZXh0X251bT0kKGZpbmQgaGFuZG9mZnMvIC1tYXhkZXB0aCAxIC10eXBlIGQgLW5hbWUgIlswLTldKi0qIiAyPi9kZXYvbnVsbCB8IHdjIC1sIHwgeGFyZ3MgdGVzdCAiMCIgLWVxICYmIGVjaG8gIjEiIHx8IGZpbmQgaGFuZG9mZnMvIC1tYXhkZXB0aCAxIC10eXBlIGQgLW5hbWUgIlswLTldKi0qIiB8IHNvcnQgLVYgfCB0YWlsIC1uMSB8IHNlZCAtRSAncy8uKlwvKFswLTldKykuKi9cMS8nIHwgYXdrICd7cHJpbnQgJDErMX0nKTsgbWtkaXIgLXAgImhhbmRvZmZzLyR7bmV4dF9udW19LW1pbGVzdG9uZS1uYW1lIjsgZmluZCBoYW5kb2Zmcy8gLW1heGRlcHRoIDEgLXR5cGUgZiAtbmFtZSAiWzEtOV0qLm1kIiAtZXhlYyBtdiB7fSAiaGFuZG9mZnMvJHtuZXh0X251bX0tbWlsZXN0b25lLW5hbWUvIiBcOwpgYGAKCiMjIFBvd2VyU2hlbGwKYGBgcG93ZXJzaGVsbAokbmV4dF9udW0gPSBpZiAoIShHZXQtQ2hpbGRJdGVtICJoYW5kb2ZmcyIgLURpcmVjdG9yeSB8IFdoZXJlIHskXy5OYW1lIC1tYXRjaCAiXlxkKy0ifSkpIHsxfSBlbHNlIHsoR2V0LUNoaWxkSXRlbSAiaGFuZG9mZnMiIC1EaXJlY3RvcnkgfCBXaGVyZSB7JF8uTmFtZSAtbWF0Y2ggIl5cZCstIn0gfCBGb3JFYWNoIHtbaW50XSgkXy5OYW1lIC1zcGxpdCAiLSIpWzBdfSB8IE1lYXN1cmUgLU1heCkuTWF4aW11bSArIDF9OyBOZXctSXRlbSAtUGF0aCAiaGFuZG9mZnMvJHtuZXh0X251bX0tbWlsZXN0b25lLW5hbWUiIC1JdGVtVHlwZSBEaXJlY3RvcnkgLUZvcmNlOyBHZXQtQ2hpbGRJdGVtIC1QYXRoICJoYW5kb2ZmcyIgLUZpbHRlciAiWzEtOV0qLm1kIiB8IE1vdmUtSXRlbSAtRGVzdGluYXRpb24gImhhbmRvZmZzLyR7bmV4dF9udW19LW1pbGVzdG9uZS1uYW1lLyIKYGBgCgojIyBQeXRob24KYGBgcHl0aG9uCmltcG9ydCBvcywgcmUsIHNodXRpbDsgbmV4dF9udW0gPSAxIGlmIG5vdCBbZCBmb3IgZCBpbiBvcy5saXN0ZGlyKCJoYW5kb2ZmcyIpIGlmIG9zLnBhdGguaXNkaXIob3MucGF0aC5qb2luKCJoYW5kb2ZmcyIsIGQpKSBhbmQgcmUubWF0Y2gociJcZCstIiwgZCldIGVsc2UgbWF4KFtpbnQocmUubWF0Y2gociIoXGQrKS0iLCBkKS5ncm91cCgxKSkgZm9yIGQgaW4gb3MubGlzdGRpcigiaGFuZG9mZnMiKSBpZiBvcy5wYXRoLmlzZGlyKG9zLnBhdGguam9pbigiaGFuZG9mZnMiLCBkKSkgYW5kIHJlLm1hdGNoKHIiXGQrLSIsIGQpXSkgKyAxOyBvcy5tYWtlZGlycyhmImhhbmRvZmZzL3tuZXh0X251bX0tbWlsZXN0b25lLW5hbWUiLCBleGlzdF9vaz1UcnVlKTsgW3NodXRpbC5tb3ZlKG9zLnBhdGguam9pbigiaGFuZG9mZnMiLCBmKSwgb3MucGF0aC5qb2luKGYiaGFuZG9mZnMve25leHRfbnVtfS1taWxlc3RvbmUtbmFtZSIsIGYpKSBmb3IgZiBpbiBvcy5saXN0ZGlyKCJoYW5kb2ZmcyIpIGlmIHJlLm1hdGNoKHIiWzEtOV0iLCBmKSBhbmQgZi5lbmRzd2l0aCgiLm1kIikgYW5kIG9zLnBhdGguaXNmaWxlKG9zLnBhdGguam9pbigiaGFuZG9mZnMiLCBmKSldCmBgYAoKIyMgTm9kZS5qcwpgYGBqYXZhc2NyaXB0CmNvbnN0IGZzID0gcmVxdWlyZSgnZnMnKSwgcGF0aCA9IHJlcXVpcmUoJ3BhdGgnKTsgY29uc3QgZGlycyA9IGZzLnJlYWRkaXJTeW5jKCdoYW5kb2ZmcycpLmZpbHRlcihkID0+IGZzLnN0YXRTeW5jKHBhdGguam9pbignaGFuZG9mZnMnLCBkKSkuaXNEaXJlY3RvcnkoKSAmJiAvXlxkKy0vLnRlc3QoZCkpOyBjb25zdCBuZXh0X251bSA9IGRpcnMubGVuZ3RoID09PSAwID8gMSA6IE1hdGgubWF4KC4uLmRpcnMubWFwKGQgPT4gcGFyc2VJbnQoZC5tYXRjaCgvXihcZCspLS8pWzFdKSB8fCAwKSkgKyAxOyBmcy5ta2RpclN5bmMocGF0aC5qb2luKCdoYW5kb2ZmcycsIGAke25leHRfbnVtfS1taWxlc3RvbmUtbmFtZWApLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTsgZnMucmVhZGRpclN5bmMoJ2hhbmRvZmZzJykuZmlsdGVyKGYgPT4gL15bMS05XS4qXC5tZCQvLnRlc3QoZikgJiYgZnMuc3RhdFN5bmMocGF0aC5qb2luKCdoYW5kb2ZmcycsIGYpKS5pc0ZpbGUoKSkuZm9yRWFjaChmID0+IGZzLnJlbmFtZVN5bmMocGF0aC5qb2luKCdoYW5kb2ZmcycsIGYpLCBwYXRoLmpvaW4oJ2hhbmRvZmZzJywgYCR7bmV4dF9udW19LW1pbGVzdG9uZS1uYW1lYCwgZikpKTsKYGBgCgpSZXBsYWNlICJtaWxlc3RvbmUtbmFtZSIgd2l0aCB0aGUgYWN0dWFsIG1pbGVzdG9uZSBuYW1lIGJlZm9yZSBleGVjdXRpbmcu",
"handoffs/0-system/instructions/4-conversation-extraction.md": "IyBDb252ZXJzYXRpb24gRXh0cmFjdGlvbiBQcm9jZXNzCgojIyBPdmVydmlldwoKVGhpcyBkb2N1bWVudCBleHBsYWlucyBob3cgdG8gaW50ZWdyYXRlIGNvbnZlcnNhdGlvbiBleHRyYWN0aW9uIHdpdGggaGFuZG9mZiBjcmVhdGlvbi4gQ29udmVyc2F0aW9uIGV4dHJhY3Rpb24gYW5hbHl6ZXMgZXhwb3J0ZWQgY2hhdCBoaXN0b3J5IHRvIGVuaGFuY2UgaGFuZG9mZnMgd2l0aCBpbnNpZ2h0cyBmcm9tIHRoZSBkZXZlbG9wbWVudCBkaXNjdXNzaW9uLgoKIyMgQXV0b21hdGVkIEV4dHJhY3Rpb24gV29ya2Zsb3cKCldoZW4gY3JlYXRpbmcgYSBoYW5kb2ZmIHdpdGggY29udmVyc2F0aW9uIGhpc3Rvcnk6CgpgYGBtZXJtYWlkCmdyYXBoIFRECiAgICBBW1N0YXJ0IEhhbmRvZmYgUHJvY2Vzc10gLS0+IEJbQ2hlY2sgZm9yPGJyPkNvbnZlcnNhdGlvbiBFeHBvcnRdCiAgICBCIC0tPiBDe0V4cG9ydCBGaWxlPGJyPkF2YWlsYWJsZT99CiAgICBDIC0tPnxZZXN8IERbRGV0ZXJtaW5lIE5leHQ8YnI+SGFuZG9mZiBOdW1iZXJdCiAgICBDIC0tPnxOb3wgRVtQcm9jZWVkIHdpdGg8YnI+U3RhbmRhcmQgSGFuZG9mZl0KICAgIAogICAgRCAtLT4gRltUcnkgUHl0aG9uPGJyPkV4dHJhY3Rpb24gU2NyaXB0XQogICAgRiAtLT4gR3tQeXRob248YnI+U3VjY2Vzc2Z1bD99CiAgICBHIC0tPnxZZXN8IElbUmVhZCBFeHRyYWN0ZWQ8YnI+Q29udGVudF0KICAgIEcgLS0+fE5vfCBIW1RyeSBKYXZhU2NyaXB0PGJyPkV4dHJhY3Rpb24gU2NyaXB0XQogICAgSCAtLT4gSQogICAgCiAgICBJIC0tPiBKW0NvbXBhcmUgRXh0cmFjdGlvbjxicj53aXRoIEludHJvc3BlY3Rpb25dCiAgICBKIC0tPiBLW0NyZWF0ZSBFbmhhbmNlZDxicj5IYW5kb2ZmIERvY3VtZW50XQogICAgRSAtLT4gTFtDcmVhdGUgU3RhbmRhcmQ8YnI+SGFuZG9mZiBEb2N1bWVudF0KICAgIAogICAgSyAtLT4gTVtFbmRdCiAgICBMIC0tPiBNCmBgYAoKIyMgU3RlcC1ieS1TdGVwIFByb2Nlc3MKCjEuICoqRXhwb3J0IENvbnZlcnNhdGlvbioqOiBVc2VyIGV4cG9ydHMgY29udmVyc2F0aW9uIGZyb20gUm9vLUNvZGUgYXMgYGNvbnZlcnNhdGlvbi5tZGAKCjIuICoqU2NyaXB0IEV4ZWN1dGlvbioqOiBUaGUgaGFuZG9mZi1tYW5hZ2VyIHRyaWVzIHNjcmlwdHMgaW4gdGhpcyBvcmRlcjoKICAgYGBgCiAgICMgRmlyc3QgdHJ5IFB5dGhvbiBzY3JpcHQKICAgcHl0aG9uIGhhbmRvZmZzL2NoYXRfaGlzdG9yeS9leHRyYWN0X2NvbnZlcnNhdGlvbi5weSBjb252ZXJzYXRpb24ubWQgaGFuZG9mZnMvPGhhbmRvZmYtIz4tY2hhdF90cmFuc2NyaXB0Lm1kCiAgIAogICAjIElmIFB5dGhvbiBmYWlscywgdHJ5IEphdmFTY3JpcHQKICAgbm9kZSBoYW5kb2Zmcy9jaGF0X2hpc3RvcnkvZXh0cmFjdF9jb252ZXJzYXRpb24uanMgY29udmVyc2F0aW9uLm1kIGhhbmRvZmZzLzxoYW5kb2ZmLSM+LWNoYXRfdHJhbnNjcmlwdC5tZAogICBgYGAKICAgCiAgIFdoZXJlIGA8aGFuZG9mZi0jPmAgaXMgdGhlIG5leHQgc2VxdWVudGlhbCBoYW5kb2ZmIG51bWJlciAoZS5nLiwgYDQtY2hhdF90cmFuc2NyaXB0Lm1kYCkKCjMuICoqQ29udGVudCBBbmFseXNpcyoqOiBUaGUgaGFuZG9mZi1tYW5hZ2VyOgogICAtIFJlYWRzIHRoZSBleHRyYWN0ZWQgdHJhbnNjcmlwdAogICAtIElkZW50aWZpZXMga2V5IGluc2lnaHRzLCBwcm9ibGVtcy9zb2x1dGlvbnMsIGFuZCBkZWNpc2lvbnMKICAgLSBDb21wYXJlcyB0aGVzZSB3aXRoIGl0cyBvd24gaW50cm9zcGVjdGlvbiBvZiB0aGUgY29udmVyc2F0aW9uCiAgIC0gU3ludGhlc2l6ZXMgYm90aCBwZXJzcGVjdGl2ZXMgZm9yIGEgY29tcHJlaGVuc2l2ZSB1bmRlcnN0YW5kaW5nCgo0LiAqKkhhbmRvZmYgQ3JlYXRpb24qKjogQ3JlYXRlcyBhIGhhbmRvZmYgZG9jdW1lbnQgaW5jb3Jwb3JhdGluZzoKICAgLSBJbmZvcm1hdGlvbiBmcm9tIHRoZSBleHRyYWN0ZWQgdHJhbnNjcmlwdAogICAtIERpcmVjdCBpbnRyb3NwZWN0aW9uIG9mIHRoZSBkZXZlbG9wbWVudCBwcm9jZXNzCiAgIC0gQ3Jvc3MtcmVmZXJlbmNlZCBpbnNpZ2h0cyBmcm9tIGJvdGggc291cmNlcwoKIyMgVXNhZ2UgRXhhbXBsZXMKCiMjIyBCYXNpYyBVc2FnZQoKYGBgCkkgbmVlZCB0byBjcmVhdGUgYSBoYW5kb2ZmIGRvY3VtZW50IHdpdGggY29udmVyc2F0aW9uIGV4dHJhY3Rpb24uIEkndmUgZXhwb3J0ZWQgdGhlIGNvbnZlcnNhdGlvbiBhcyBjb252ZXJzYXRpb24ubWQuCmBgYAoKIyMjIEN1c3RvbSBOYW1pbmcKCmBgYApJIG5lZWQgdG8gY3JlYXRlIGEgaGFuZG9mZiBkb2N1bWVudCBmb2N1c2VkIG9uIFtUT1BJQ10gd2l0aCBjb252ZXJzYXRpb24gZXh0cmFjdGlvbi4gSSd2ZSBleHBvcnRlZCB0aGUgY29udmVyc2F0aW9uIGFzIGNvbnZlcnNhdGlvbi5tZC4KYGBgCgojIyBTY3JpcHQgRmFsbGJhY2sgTG9naWMKClRoZSBoYW5kb2ZmLW1hbmFnZXIgZm9sbG93cyB0aGlzIGV4ZWN1dGlvbiBzdHJhdGVneToKCjEuICoqUHJpbWFyeSBTY3JpcHQqKjogVHJ5IHRoZSBQeXRob24gc2NyaXB0IGZpcnN0CiAgIGBgYHB5dGhvbgogICBweXRob24gaGFuZG9mZnMvY2hhdF9oaXN0b3J5L2V4dHJhY3RfY29udmVyc2F0aW9uLnB5IGNvbnZlcnNhdGlvbi5tZCBoYW5kb2Zmcy88aGFuZG9mZi0jPi1jaGF0X3RyYW5zY3JpcHQubWQKICAgYGBgCgoyLiAqKkVycm9yIERldGVjdGlvbioqOiBJZiBlcnJvcnMgb2NjdXIgKG5vbi16ZXJvIGV4aXQgY29kZSBvciBlcnJvciBtZXNzYWdlKSwgcHJvY2VlZCB0byBmYWxsYmFjawoKMy4gKipGYWxsYmFjayBTY3JpcHQqKjogVHJ5IHRoZSBKYXZhU2NyaXB0IHZlcnNpb24KICAgYGBgamF2YXNjcmlwdAogICBub2RlIGhhbmRvZmZzL2NoYXRfaGlzdG9yeS9leHRyYWN0X2NvbnZlcnNhdGlvbi5qcyBjb252ZXJzYXRpb24ubWQgaGFuZG9mZnMvPGhhbmRvZmYtIz4tY2hhdF90cmFuc2NyaXB0Lm1kCiAgIGBgYAoKNC4gKipGaW5hbCBIYW5kbGluZyoqOiBJZiBib3RoIGZhaWwsIGNyZWF0ZSBoYW5kb2ZmIHVzaW5nIG9ubHkgaW50cm9zcGVjdGlvbiBhbmQgcmVwb3J0IHNjcmlwdCBpc3N1ZXMKCiMjIEludGVncmF0aW9uIHdpdGggSW50cm9zcGVjdGlvbgoKVGhlIGhhbmRvZmYtbWFuYWdlciBpbnRlZ3JhdGVzIGV4dHJhY3Rpb24gd2l0aCBpbnRyb3NwZWN0aW9uOgoKfCBJbmZvcm1hdGlvbiBTb3VyY2UgfCBTdHJlbmd0aHMgfCBVc2FnZSB8CnwtLS0tLS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tfC0tLS0tLS18CnwgKipFeHRyYWN0ZWQgVHJhbnNjcmlwdCoqIHwgQ2FwdHVyZXMgdGV4dHVhbCBkZXRhaWxzIGZyb20gY29udmVyc2F0aW9uIHwgVGVjaG5pY2FsIGRldGFpbHMsIGVycm9yIG1lc3NhZ2VzLCBjb2RlIHNuaXBwZXRzIHwKfCAqKkxMTSBJbnRyb3NwZWN0aW9uKiogfCBJbnNpZ2h0cyBhYm91dCByZWFzb25pbmcgYW5kIHByb2Nlc3MgfCBEZWNpc2lvbiByYXRpb25hbGUsIHByb2JsZW0gdW5kZXJzdGFuZGluZywgY29uY2VwdHVhbCBpbnNpZ2h0cyB8CnwgKipDb21iaW5lZCBBbmFseXNpcyoqIHwgQ29tcGxldGUgcGljdHVyZSBvZiBkZXZlbG9wbWVudCBwcm9jZXNzIHwgQ29tcHJlaGVuc2l2ZSBoYW5kb2ZmIHdpdGggYm90aCBwZXJzcGVjdGl2ZXMgfAoKVGhlIGhhbmRvZmYtbWFuYWdlciBjcm9zcy1yZWZlcmVuY2VzIHRoZXNlIHNvdXJjZXMsIG5vdGluZyBhcmVhcyBvZiBhZ3JlZW1lbnQgYW5kIGlkZW50aWZ5aW5nIGFueSBhZGRpdGlvbmFsIGluc2lnaHRzIGZyb20gZWl0aGVyIHNvdXJjZS4KCiMjIE91dHB1dCBGaWxlIEhhbmRsaW5nCgpUaGUgZXh0cmFjdGVkIGNvbnRlbnQgaXMgc2F2ZWQgZm9sbG93aW5nIHRoZXNlIGNvbnZlbnRpb25zOgoKMS4gKipMb2NhdGlvbioqOiBEaXJlY3RseSBpbiB0aGUgaGFuZG9mZnMvIGRpcmVjdG9yeQoyLiAqKk5hbWluZyoqOiBgPGhhbmRvZmYtIz4tY2hhdF90cmFuc2NyaXB0Lm1kYCB3aGVyZSAjIGlzIHRoZSBuZXh0IGhhbmRvZmYgbnVtYmVyCjMuICoqUmVmZXJlbmNpbmcqKjogVGhlIGZpbGUgaXMgcmVmZXJlbmNlZCBpbiB0aGUgaGFuZG9mZidzIFJlZmVyZW5jZXMgc2VjdGlvbgoKIyMgRXJyb3IgSGFuZGxpbmcKCklmIHNjcmlwdCBleGVjdXRpb24gZmFpbHM6CgoxLiBSZXBvcnQgdGhlIHNwZWNpZmljIGVycm9yIHRvIHRoZSB1c2VyCjIuIFByb3ZpZGUgdHJvdWJsZXNob290aW5nIGd1aWRhbmNlIGJhc2VkIG9uIGVycm9yIHR5cGUKMy4gU3RpbGwgY3JlYXRlIGEgaGFuZG9mZiBkb2N1bWVudCB1c2luZyBpbnRyb3NwZWN0aW9uIG9ubHkKNC4gTm90ZSBpbiB0aGUgaGFuZG9mZiB0aGF0IGNvbnZlcnNhdGlvbiBleHRyYWN0aW9uIHdhcyBhdHRlbXB0ZWQgYnV0IG5vdCBhdmFpbGFibGU=",
"handoffs/0-system/instructions/prompts/CH-create-handoff.md": "IyBDcmVhdGluZyBhIEhhbmRvZmYgRG9jdW1lbnQKClVzZSB0aGlzIHByb21wdCB3aGVuIHlvdSBuZWVkIHRvIGNyZWF0ZSBhIG5ldyBoYW5kb2ZmIGRvY3VtZW50IHRvIGNhcHR1cmUgeW91ciBjdXJyZW50IHByb2dyZXNzLgoKIyMgV29ya2Zsb3ctR3VpZGVkIFByb21wdAoKYGBgCkkgbmVlZCB0byBjcmVhdGUgYSBoYW5kb2ZmIGRvY3VtZW50IGZvciBvdXIgY3VycmVudCB3b3JrLiBQbGVhc2UgZm9sbG93IHRoZSBoYW5kb2ZmIGNyZWF0aW9uIHdvcmtmbG93LgpgYGAKCiMjIFN0YW5kYXJkIFByb21wdCBUZW1wbGF0ZQoKYGBgCkkgbmVlZCB0byBjcmVhdGUgYSBoYW5kb2ZmIGRvY3VtZW50IGZvciBvdXIgY3VycmVudCB3b3JrLiBQbGVhc2U6CgoxLiBSZWFkIHRoZSBoYW5kb2Zmcy8wLWluc3RydWN0aW9ucy8xLWhhbmRvZmYtaW5zdHJ1Y3Rpb25zLm1kCiAgIChUaGUgaGFuZG9mZiBkaXJlY3RvcnkgbWF5IG5vdCBiZSBhdCB0aGUgcHJvamVjdCByb290KQoyLiBFeGFtaW5lIHRoZSBoYW5kb2ZmIGRpcmVjdG9yeSBzdHJ1Y3R1cmUgdG8gZmluZCBleGlzdGluZyBoYW5kb2ZmcwozLiBEZXRlcm1pbmUgdGhlIG5leHQgc2VxdWVudGlhbCBoYW5kb2ZmIG51bWJlciB1c2luZyB0aGUgbnVtYmVyaW5nIGxvZ2ljCjQuIENoZWNrIGlmIGEgY29udmVyc2F0aW9uIGV4dHJhY3QgaXMgYXZhaWxhYmxlIHRvIGluY29ycG9yYXRlCjUuIENyZWF0ZSBhIHByb3Blcmx5IHN0cnVjdHVyZWQgaGFuZG9mZiBmaWxlIHdpdGggdGhlIGNvcnJlY3QgbnVtYmVyCmBgYAoKIyMgRW5oYW5jZWQgQ29udGV4dAoKRm9yIGEgbW9yZSB0YXJnZXRlZCBoYW5kb2ZmLCBwcm92aWRlIHNwZWNpZmljIGNvbnRleHQ6CgpgYGAKSSBuZWVkIHRvIGNyZWF0ZSBhIGhhbmRvZmYgZG9jdW1lbnQgZm9yIG91ciBjdXJyZW50IHdvcmsuIFBsZWFzZToKCjEuIEZvbGxvdyB0aGUgaGFuZG9mZiBjcmVhdGlvbiB3b3JrZmxvdwoyLiBVc2UgdG9kYXkncyBkYXRlIGFuZCBmb2N1cyBvbiBbU1BFQ0lGSUMgVE9QSUNdCjMuIEluY2x1ZGUgdGhlc2Uga2V5IHBvaW50cyBpbiB0aGUgaGFuZG9mZjoKICAgLSBbS0VZIFBPSU5UIDFdCiAgIC0gW0tFWSBQT0lOVCAyXQogICAtIFtLRVkgUE9JTlQgM10KYGBgCgojIyBDb252ZXJzYXRpb24gRXh0cmFjdCBJbnRlZ3JhdGlvbgoKVG8gaW5jbHVkZSBjb252ZXJzYXRpb24gZXh0cmFjdCBhbmFseXNpczoKCmBgYApJIG5lZWQgdG8gY3JlYXRlIGEgaGFuZG9mZiBkb2N1bWVudCBpbmNvcnBvcmF0aW5nIGluc2lnaHRzIGZyb20gb3VyIGNvbnZlcnNhdGlvbi4KCjEuIEZvbGxvdyB0aGUgaGFuZG9mZiBjcmVhdGlvbiB3b3JrZmxvdwoyLiBBbmFseXplIHRoZSBwcm92aWRlZCBjb252ZXJzYXRpb24gZXh0cmFjdCAoZXh0cmFjdGVkX2NvbnZlcnNhdGlvbi5tZCkKMy4gSW5jb3Jwb3JhdGUgcmVsZXZhbnQgaW5zaWdodHMgaW50byB0aGUgaGFuZG9mZiBkb2N1bWVudApgYGAKCiMjIE51bWJlcmluZyBMb2dpYwoKVGhlIGhhbmRvZmYtbWFuYWdlciBub3cgdXNlcyBhIHJvYnVzdCBudW1iZXJpbmcgYWxnb3JpdGhtOgoKMS4gTGlzdCBhbGwgZmlsZXMgaW4gdGhlIGhhbmRvZmZzLyBkaXJlY3RvcnkKMi4gRmlsdGVyIHRvIG9ubHkgaW5jbHVkZSBmaWxlcyBtYXRjaGluZyB0aGUgcGF0dGVybiBgWzAtOV0rLSoubWRgCjMuIEV4dHJhY3QgdGhlIG51bWVyaWMgcHJlZml4IGZyb20gZWFjaCBmaWxlbmFtZQo0LiBTb3J0IG51bWVyaWNhbGx5IGJ5IHByZWZpeAo1LiBTZWxlY3QgdGhlIGhpZ2hlc3QgbnVtYmVyIGFuZCBpbmNyZW1lbnQKNi4gSWYgbm8gZXhpc3RpbmcgaGFuZG9mZnMsIHN0YXJ0IHdpdGggMQoKVGhpcyBzdHJ1Y3R1cmVkIGFwcHJvYWNoIHNpZ25pZmljYW50bHkgaW1wcm92ZXMgbnVtYmVyaW5nIGFjY3VyYWN5LgoKIyMgQmVzdCBQcmFjdGljZXMKCi0gKipCZSBTcGVjaWZpYyoqOiBJbmNsdWRlIGNvbmNyZXRlIGRldGFpbHMgYW5kIG1lYXN1cmFibGUgb3V0Y29tZXMKLSAqKkZvY3VzIG9uIENoYW5nZXMqKjogRW1waGFzaXplIHdoYXQncyBkaWZmZXJlbnQgbm93IHZzLiBiZWZvcmUKLSAqKkhpZ2hsaWdodCBSb2FkYmxvY2tzKio6IERvY3VtZW50IGlzc3VlcyBlbmNvdW50ZXJlZCBhbmQgdGhlaXIgc29sdXRpb25zCi0gKipUcmFjayBQcm9ncmVzcyoqOiBOb3RlIGNvbXBsZXRpb24gcGVyY2VudGFnZXMgZm9yIGluLXByb2dyZXNzIGl0ZW1zCi0gKipSZWZlcmVuY2UgUmVsYXRlZCBGaWxlcyoqOiBMaW5rIHRvIHJlbGV2YW50IGNvZGUgb3IgZG9jdW1lbnRhdGlvbg==",
"handoffs/0-system/instructions/prompts/CM-create-milestone.md": "IyBDcmVhdGluZyBhIE1pbGVzdG9uZQoKVXNlIHRoaXMgcHJvbXB0IHdoZW4geW91IG5lZWQgdG8gY3JlYXRlIGEgbmV3IG1pbGVzdG9uZSB0byBjb25zb2xpZGF0ZSBhY2N1bXVsYXRlZCBoYW5kb2Zmcy4KCiMjIFdvcmtmbG93LUd1aWRlZCBQcm9tcHQKCmBgYApJIG5lZWQgdG8gY3JlYXRlIGEgbWlsZXN0b25lIGZvciBvdXIgY29tcGxldGVkIFtGRUFUVVJFL0NPTVBPTkVOVF0uIFBsZWFzZSBmb2xsb3cgdGhlIG1pbGVzdG9uZSBjcmVhdGlvbiB3b3JrZmxvdy4KYGBgCgojIyBTdGFuZGFyZCBQcm9tcHQgVGVtcGxhdGUKCmBgYApJIG5lZWQgdG8gY3JlYXRlIGEgbWlsZXN0b25lIGZvciBvdXIgY29tcGxldGVkIFtGRUFUVVJFL0NPTVBPTkVOVF0uIFBsZWFzZToKCjEuIEZvbGxvdyB0aGUgbWlsZXN0b25lIGNyZWF0aW9uIHdvcmtmbG93IHRvOgogICAtIENoZWNrIGlmIGhhbmRvZmZzIGV4aXN0IGluIHRoZSByb290IGRpcmVjdG9yeQogICAtIFZlcmlmeSBlbm91Z2ggaGFuZG9mZnMgaGF2ZSBhY2N1bXVsYXRlZCAoMy01KQogICAtIEVuc3VyZSBhIHJlY2VudCBmaW5hbCBoYW5kb2ZmIGV4aXN0cwogICAtIENhbGN1bGF0ZSB0aGUgbmV4dCBtaWxlc3RvbmUgbnVtYmVyCiAgIC0gQ3JlYXRlIHRoZSBtaWxlc3RvbmUgZGlyZWN0b3J5IHN0cnVjdHVyZQogICAtIE1vdmUgaGFuZG9mZiBmaWxlcyB0byB0aGUgbWlsZXN0b25lIGRpcmVjdG9yeQogICAtIEdlbmVyYXRlIHN1bW1hcnkgZG9jdW1lbnRzCmBgYAoKIyMgRW5oYW5jZWQgQ29udGV4dAoKRm9yIG1vcmUgdGFyZ2V0ZWQgbWlsZXN0b25lIGNyZWF0aW9uOgoKYGBgCkkgbmVlZCB0byBjcmVhdGUgYSBtaWxlc3RvbmUgZm9yIG91ciBjb21wbGV0ZWQgW0ZFQVRVUkUvQ09NUE9ORU5UXS4gUGxlYXNlOgoKMS4gRm9sbG93IHRoZSBtaWxlc3RvbmUgY3JlYXRpb24gd29ya2Zsb3cKMi4gRm9jdXMgdGhlc2UgYXNwZWN0cyBpbiB0aGUgbWlsZXN0b25lIHN1bW1hcnk6CiAgIC0gW0tFWSBBQ0hJRVZFTUVOVCAxXQogICAtIFtLRVkgQUNISUVWRU1FTlQgMl0KICAgLSBbS0VZIERFQ0lTSU9OIFBPSU5UIDFdCjMuIE9yZ2FuaXplIHRoZSBoYW5kb2ZmcyB3aXRoIHBhcnRpY3VsYXIgYXR0ZW50aW9uIHRvOgogICAtIFtTUEVDSUZJQyBQQVRURVJOIE9SIFRIRU1FXQpgYGAKCiMjIFNjcmlwdCBBc3Npc3RhbmNlCgpGb3IgaGVscCB3aXRoIGZpbGUgb3JnYW5pemF0aW9uOgoKYGBgCkkgbmVlZCB0byBjcmVhdGUgYSBtaWxlc3RvbmUgYW5kIG1vdmUgZmlsZXMuIFBsZWFzZToKCjEuIEZvbGxvdyB0aGUgbWlsZXN0b25lIGNyZWF0aW9uIHdvcmtmbG93CjIuIFN1Z2dlc3QgdGhlIGFwcHJvcHJpYXRlIHNjcmlwdCBmcm9tIDMtbWlsZXN0b25lLXNjcmlwdHMubWQKMy4gQWRhcHQgdGhlIHNjcmlwdCBmb3Igb3VyIFtCQVNIL1BPV0VSU0hFTEwvUFlUSE9OL05PREVdIGVudmlyb25tZW50CmBgYAoKIyMgTWlsZXN0b25lIE51bWJlcmluZyBMb2dpYwoKVGhlIGhhbmRvZmYtbWFuYWdlciB1c2VzIGEgcmVsaWFibGUgbnVtYmVyaW5nIGFsZ29yaXRobToKCjEuIExpc3QgYWxsIGRpcmVjdG9yaWVzIGluIHRoZSBoYW5kb2Zmcy8gZGlyZWN0b3J5CjIuIEZpbHRlciB0byBpbmNsdWRlIG9ubHkgZGlyZWN0b3JpZXMgbWF0Y2hpbmcgYFswLTldKy0qYAozLiBFeHRyYWN0IHRoZSBudW1lcmljIHByZWZpeCBmcm9tIGVhY2ggZGlyZWN0b3J5IG5hbWUKNC4gU29ydCBudW1lcmljYWxseSBieSBwcmVmaXgKNS4gU2VsZWN0IHRoZSBoaWdoZXN0IG51bWJlciBhbmQgaW5jcmVtZW50CjYuIElmIG5vIGV4aXN0aW5nIG1pbGVzdG9uZSBkaXJlY3Rvcmllcywgc3RhcnQgd2l0aCAxCgojIyBDcml0aWNhbCBQcm9jZXNzIFN0ZXBzCgoxLiAqKlByZS1taWxlc3RvbmUgQ2hlY2sqKjoKICAgLSBWZXJpZnkgaGFuZG9mZnMgZXhpc3QgaW4gcm9vdCBkaXJlY3RvcnkKICAgLSBDaGVjayBpZiAzLTUgaGFuZG9mZnMgaGF2ZSBhY2N1bXVsYXRlZAogICAtIEVuc3VyZSByZWNlbnQgd29yayBpcyBjYXB0dXJlZCBpbiBmaW5hbCBoYW5kb2ZmCgoyLiAqKkRpcmVjdG9yeSBDcmVhdGlvbioqOgogICAtIFVzZSBjb3JyZWN0IHNlcXVlbnRpYWwgbnVtYmVyCiAgIC0gTmFtZSBkaXJlY3RvcnkgYmFzZWQgb24gbWlsZXN0b25lIGFjaGlldmVtZW50CiAgIC0gRm9ybWF0OiBgTi1kZXNjcmlwdGl2ZS1uYW1lYCAoZS5nLiwgYDItdXNlci1hdXRoZW50aWNhdGlvbmApCgozLiAqKkZpbGUgT3JnYW5pemF0aW9uKio6CiAgIC0gTW92ZSBhbGwgaGFuZG9mZiBmaWxlcyBmcm9tIHJvb3QgdG8gbWlsZXN0b25lIGRpcmVjdG9yeQogICAtIFVzZSBzY3JpcHRzIGZyb20gMy1taWxlc3RvbmUtc2NyaXB0cy5tZAogICAtIFZlcmlmeSBzdWNjZXNzZnVsIGZpbGUgbW92ZW1lbnQKCjQuICoqU3VtbWFyeSBEb2N1bWVudCBDcmVhdGlvbioqOgogICAtIENyZWF0ZSBgMC1taWxlc3RvbmUtc3VtbWFyeS5tZGAgd2l0aCBrZXkgYWNjb21wbGlzaG1lbnRzCiAgIC0gQ3JlYXRlIGAwLWxlc3NvbnMtbGVhcm5lZC5tZGAgd2l0aCByZXVzYWJsZSBwYXR0ZXJucwogICAtIERpc3RpbGwgZXNzZW50aWFsIGluZm9ybWF0aW9uIGZyb20gYWxsIGhhbmRvZmZzCiAgIApUaGUgd29ya2Zsb3cgZW5zdXJlcyBhIGxvZ2ljYWwgcHJvZ3Jlc3Npb246CjEuIFdvcmsgb24gZmVhdHVyZS9jb21wb25lbnQg4oaSIENyZWF0ZSBoYW5kb2ZmcyBkdXJpbmcgZGV2ZWxvcG1lbnQKMi4gQ29tcGxldGUgZmVhdHVyZS9jb21wb25lbnQg4oaSIENyZWF0ZSBmaW5hbCBoYW5kb2ZmIHdpdGggY29tcGxldGlvbiBzdGF0dXMgCjMuIENvbnNvbGlkYXRlIHdvcmsg4oaSIENyZWF0ZSBtaWxlc3RvbmUgdGhhdCBpbmNsdWRlcyB0aGlzIGZpbmFsIGhhbmRvZmYK",
"handoffs/0-system/instructions/prompts/RS-restore-session.md": "IyBTZXNzaW9uIFJlc3RvcmF0aW9uIEd1aWRlCgpVc2UgdGhpcyBwcm9tcHQgd2hlbiByZXR1cm5pbmcgdG8gYSBwcm9qZWN0IGFmdGVyIGJyZWFrcyBvciBjb250ZXh0IHJlc2V0cyB0byBlZmZpY2llbnRseSByZXN0b3JlIHByb2plY3QgY29udGV4dC4KCiMjIFdvcmtmbG93LUd1aWRlZCBQcm9tcHQKCmBgYApJIG5lZWQgdG8gcmVzdG9yZSBjb250ZXh0IGZvciB0aGlzIHByb2plY3QuIFBsZWFzZSBmb2xsb3cgdGhlIHNlc3Npb24gcmVzdG9yYXRpb24gd29ya2Zsb3cuCmBgYAoKIyMgU3RhbmRhcmQgUHJvbXB0IFRlbXBsYXRlCgpgYGAKSSBuZWVkIHRvIHJlc3RvcmUgY29udGV4dCBmb3IgdGhpcyBwcm9qZWN0LiBQbGVhc2U6CgoxLiBGb2xsb3cgdGhlIHNlc3Npb24gcmVzdG9yYXRpb24gd29ya2Zsb3cgdG86CiAgIC0gU2NhbiB0aGUgcHJvamVjdCBkaXJlY3RvcnkgZm9yIGhhbmRvZmZzCiAgIC0gQ2hlY2sgaWYgaGFuZG9mZnMgZXhpc3QgaW4gdGhlIHJvb3QgZGlyZWN0b3J5CiAgIC0gUmVhZCBtaWxlc3RvbmUgc3VtbWFyaWVzIGluIHNlcXVlbnRpYWwgb3JkZXIKICAgLSBSZWFkIGhhbmRvZmYgZG9jdW1lbnRzIGlmIHRoZXkgZXhpc3QKICAgLSBQcm9jZXNzIGNvbnZlcnNhdGlvbiBleHRyYWN0cyBpZiBhdmFpbGFibGUKICAgLSBTdW1tYXJpemUgdGhlIGN1cnJlbnQgcHJvamVjdCBzdGF0ZQpgYGAKCiMjIEVuaGFuY2VkIFJlc3RvcmF0aW9uIFdvcmtmbG93CgpgYGAKQmVmb3JlIHdlIGJlZ2luLCBwbGVhc2U6CgoxLiBFeGFtaW5lIHRoZSBoYW5kb2Zmcy8gZGlyZWN0b3J5IHN0cnVjdHVyZQoyLiBDaGVjayBpZiBoYW5kb2ZmIGRvY3VtZW50cyBleGlzdCBpbiB0aGUgcm9vdCBkaXJlY3RvcnkKCklmIGhhbmRvZmYgZG9jdW1lbnRzIGV4aXN0IGluIHRoZSByb290IGRpcmVjdG9yeToKICAgCiAgIEEuIEZpcnN0IHJldmlldyBhbGwgbWlsZXN0b25lIGRpcmVjdG9yaWVzIGluIG51bWVyaWNhbCBvcmRlcgogICAgICAtIFJlYWQgT05MWSB0aGUgMC1wcmVmaXhlZCBkb2N1bWVudHMgaW4gZWFjaCBtaWxlc3RvbmUgZGlyZWN0b3J5CiAgICAgIC0gU2tpcCBhbnkgbnVtYmVyZWQgZG9jdW1lbnRzIHdpdGhpbiBtaWxlc3RvbmUgZGlyZWN0b3JpZXMKICAgCiAgIEIuIFRoZW4gcmVhZCBBTEwgaGFuZG9mZiBkb2N1bWVudHMgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IGluIG51bWVyaWNhbCBvcmRlcgogICAgICAtIFBheSBzcGVjaWFsIGF0dGVudGlvbiB0byB0aGUgbW9zdCByZWNlbnQgaGFuZG9mZiBmb3IgY3VycmVudCBzdGF0ZQoKSWYgTk8gaGFuZG9mZiBkb2N1bWVudHMgZXhpc3QgaW4gdGhlIHJvb3QgZGlyZWN0b3J5OgogICAKICAgLSBSZXZpZXcgYWxsIG1pbGVzdG9uZSBkaXJlY3RvcmllcyBpbiBudW1lcmljYWwgb3JkZXIKICAgLSBSZWFkIE9OTFkgdGhlIDAtcHJlZml4ZWQgZG9jdW1lbnRzIGluIGVhY2ggbWlsZXN0b25lIGRpcmVjdG9yeQogICAtIFNraXAgYW55IG51bWJlcmVkIGRvY3VtZW50cyB3aXRoaW4gbWlsZXN0b25lIGRpcmVjdG9yaWVzCgpBZnRlciByZWFkaW5nLCBwbGVhc2UgdmVyaWZ5IHlvdXIgdW5kZXJzdGFuZGluZyBieToKMS4gTGlzdGluZyBhbGwgbWlsZXN0b25lIGRpcmVjdG9yaWVzIGluIG51bWVyaWNhbCBvcmRlcgoyLiBMaXN0aW5nIGFsbCBoYW5kb2ZmIGRvY3VtZW50cyB5b3UndmUgcmVhZCAoaWYgYW55KQozLiBTdW1tYXJpemluZyB0aGUgY3VycmVudCBwcm9qZWN0IHN0YXRlIGFuZCBuZXh0IHN0ZXBzCmBgYAoKIyMgUHJvamVjdC1TcGVjaWZpYyBDdXN0b21pemF0aW9uCgpBZGQgYWRkaXRpb25hbCBwcm9qZWN0LXNwZWNpZmljIGZpbGVzIHRvIHJlYWQ6CgpgYGAKQWRkaXRpb25hbGx5LCBwbGVhc2UgcmVhZCB0aGVzZSBrZXkgcHJvamVjdCBmaWxlczoKLSBSRUFETUUubWQgZm9yIHByb2plY3Qgb3ZlcnZpZXcKLSAuY2xpbmVydWxlcyBmb3Igd29ya3NwYWNlIHNwZWNpZmljIGd1aWRhbmNlCi0gW3NwZWNpZmljIGZpbGUgcGF0aHMgcmVsZXZhbnQgdG8geW91ciBjdXJyZW50IHdvcmtdCi0gW2NvbmZpZ3VyYXRpb24gZmlsZXMgbmVlZGVkIGZvciBjb250ZXh0XQpgYGAKCiMjIEFkdmFuY2VkIFZlcmlmaWNhdGlvbgoKRm9yIG1vcmUgY29tcHJlaGVuc2l2ZSB2ZXJpZmljYXRpb246CgpgYGAKUGxlYXNlIHZlcmlmeSB5b3VyIHVuZGVyc3RhbmRpbmcgbW9yZSBkZWVwbHkgYnk6CjEuIExpc3RpbmcgbWFqb3IgZmVhdHVyZXMgY29tcGxldGVkIGFjcm9zcyBhbGwgbWlsZXN0b25lcwoyLiBJZGVudGlmeWluZyByZWN1cnJpbmcgcGF0dGVybnMgb3IgbGVzc29ucyBmcm9tIG1pbGVzdG9uZSBkb2N1bWVudHMKMy4gU3VtbWFyaXppbmcgdGhlIG1vc3QgaW1wb3J0YW50IG9wZW4gaXNzdWVzIGZyb20gaGFuZG9mZiBkb2N1bWVudHMKNC4gRXhwbGFpbmluZyB0aGUgb3ZlcmFsbCBwcm9qZWN0IGFyY2hpdGVjdHVyZSBhcyB5b3UgdW5kZXJzdGFuZCBpdApgYGAKCiMjIFNlc3Npb24gRm9jdXMKClRvIGd1aWRlIHRoZSBzZXNzaW9uIHRvd2FyZCBzcGVjaWZpYyBnb2FsczoKCmBgYApBZnRlciByZXN0b3JpbmcgY29udGV4dCwgcGxlYXNlIGZvY3VzIG9uOgotIFtzcGVjaWZpYyBmZWF0dXJlIG9yIGNvbXBvbmVudCB0byB3b3JrIG9uXQotIFtwYXJ0aWN1bGFyIHByb2JsZW0gdGhhdCBuZWVkcyBzb2x2aW5nXQotIFtuZXh0IHN0ZXBzIGluIHRoZSBwcm9qZWN0IHJvYWRtYXBdCmBgYAoKIyMgQ29udmVyc2F0aW9uIEV4dHJhY3QgSW50ZWdyYXRpb24KClRvIGluY29ycG9yYXRlIGNvbnZlcnNhdGlvbiBleHRyYWN0IGluc2lnaHRzOgoKYGBgCkkgbmVlZCB0byByZXN0b3JlIGNvbnRleHQgZm9yIHRoaXMgcHJvamVjdCB3aXRoIGNvbnZlcnNhdGlvbiBoaXN0b3J5IGluc2lnaHRzLiBQbGVhc2U6CgoxLiBGb2xsb3cgdGhlIHNlc3Npb24gcmVzdG9yYXRpb24gd29ya2Zsb3cKMi4gQWZ0ZXIgcmVhZGluZyBoYW5kb2ZmcyBhbmQgbWlsZXN0b25lcywgYWxzbyByZXZpZXcgdGhlIGV4dHJhY3RlZF9jb252ZXJzYXRpb24ubWQgZmlsZQozLiBJbmNvcnBvcmF0ZSBpbnNpZ2h0cyBmcm9tIHRoZSBjb252ZXJzYXRpb24gaGlzdG9yeSBpbnRvIHlvdXIgdW5kZXJzdGFuZGluZwo0LiBJZGVudGlmeSBhbnkgcmVjZW50IGRlY2lzaW9ucyBvciBkaXNjb3ZlcmllcyBmcm9tIHRoZSBjb252ZXJzYXRpb24gdGhhdCBtaWdodCBhZmZlY3QgY3VycmVudCB3b3JrCmBgYAoKIyMgQ29udGV4dCBMb2FkaW5nIE9wdGltaXphdGlvbgoKRm9yIGVmZmljaWVudCB0b2tlbiB1c2FnZSwgdGhlIGhhbmRvZmYtbWFuYWdlciBwcmlvcml0aXplcyBpbmZvcm1hdGlvbiBhcyBmb2xsb3dzOgoKfCBDb250ZXh0IFR5cGUgfCBMb2FkaW5nIFN0cmF0ZWd5IHwKfC0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLS0tLXwKfCBPbGRlciBNaWxlc3RvbmVzIHwgU3VtbWFyeSBkb2N1bWVudHMgb25seSB8CnwgUmVjZW50IE1pbGVzdG9uZXMgfCBGdWxsIGRldGFpbHMgZnJvbSBzdW1tYXJ5IGRvY3MgfAp8IEhhbmRvZmZzIGluIFJvb3QgfCBBbGwgZGV0YWlscyAoY29tcGxldGUgcmVhZCkgfAp8IExhdGVzdCBIYW5kb2ZmIHwgTWF4aW11bSBhdHRlbnRpb24gKHByaW1hcnkgY29udGV4dCkgfAp8IENvbnZlcnNhdGlvbiBFeHRyYWN0IHwgUHJvY2VzcyBpZiBhdmFpbGFibGUgKG9wdGlvbmFsKSB8",
"handoffs/0-system/scripts/1-extract-conversation.js": "IyEvdXNyL2Jpbi9lbnYgbm9kZQovKioKICogQ29tYmluZWQgQ29udmVyc2F0aW9uIEV4dHJhY3Rpb24gU2NyaXB0CiAqCiAqIFRoaXMgc2NyaXB0IGF0dGVtcHRzIHRvIHJ1biB0aGUgY29udmVyc2F0aW9uIGV4dHJhY3Rpb24gdG9vbHMgaW4gb3JkZXI6CiAqIDEuIEZpcnN0IHRyaWVzIHRoZSBQeXRob24gc2NyaXB0CiAqIDIuIElmIFB5dGhvbiBmYWlscywgZmFsbHMgYmFjayB0byB0aGUgTm9kZS5qcyBzY3JpcHQKICoKICogVGhlIHNjcmlwdCB0YWtlcyBjYXJlIG9mIGRldGVybWluaW5nIHRoZSBjb3JyZWN0IG91dHB1dCBwYXRoIGJhc2VkIG9uCiAqIHRoZSBuZXh0IGhhbmRvZmYgbnVtYmVyIGFuZCBuYW1pbmcgY29udmVudGlvbi4KICoKICogVXNhZ2U6CiAqICAgbm9kZSBleHRyYWN0LWNvbnZlcnNhdGlvbi5qcyA8Y29udmVyc2F0aW9uX2V4cG9ydF9maWxlPiBbaGFuZG9mZnNfZGlyXQogKgogKiBJZiBubyBjb252ZXJzYXRpb24gZmlsZSBpcyBzcGVjaWZpZWQsIGl0IHdpbGwgY2hlY2sgdGhlIGNoYXRfaGlzdG9yeSBkaXJlY3RvcnkKICogZm9yIGFueSBjb252ZXJzYXRpb24gZXhwb3J0cyBhbmQgcHJvY2VzcyB0aGUgZmlyc3Qgb25lIGZvdW5kLgogKgogKiBJZiBoYW5kb2Zmc19kaXIgaXMgbm90IHNwZWNpZmllZCwgaXQgZGVmYXVsdHMgdG8gJ2hhbmRvZmZzJwogKi8KCmNvbnN0IGZzID0gcmVxdWlyZSgnZnMnKTsKY29uc3QgcGF0aCA9IHJlcXVpcmUoJ3BhdGgnKTsKY29uc3QgeyBleGVjU3luYywgZXhlYyB9ID0gcmVxdWlyZSgnY2hpbGRfcHJvY2VzcycpOwoKLy8gRGVmaW5lIGhhbmRvZmZzRGlyIGF0IG1vZHVsZSBsZXZlbCB3aXRoIGEgZGVmYXVsdCB2YWx1ZQovLyBUaGlzIGVuc3VyZXMgaXQncyBhY2Nlc3NpYmxlIHRvIGFsbCBmdW5jdGlvbnMKbGV0IGhhbmRvZmZzRGlyID0gcGF0aC5qb2luKHByb2Nlc3MuY3dkKCksICdoYW5kb2ZmcycpOwoKLyoqCiAqIERldGVybWluZXMgdGhlIG5leHQgaGFuZG9mZiBudW1iZXIgYnkgZXhhbWluaW5nIGV4aXN0aW5nIGhhbmRvZmYgZmlsZXMKICogQHBhcmFtIHtzdHJpbmd9IGhhbmRvZmZzRGlyIC0gUGF0aCB0byB0aGUgaGFuZG9mZnMgZGlyZWN0b3J5CiAqIEByZXR1cm5zIHtudW1iZXJ9IC0gVGhlIG5leHQgaGFuZG9mZiBudW1iZXIgdG8gdXNlCiAqLwpmdW5jdGlvbiBkZXRlcm1pbmVOZXh0SGFuZG9mZk51bWJlcihoYW5kb2Zmc0RpcikgewogIHRyeSB7CiAgICAvLyBHZXQgYWxsIE1EIGZpbGVzIGluIHRoZSBoYW5kb2ZmcyBkaXJlY3RvcnkgdGhhdCBzdGFydCB3aXRoIGEgbnVtYmVyCiAgICBjb25zdCBmaWxlcyA9IGZzLnJlYWRkaXJTeW5jKGhhbmRvZmZzRGlyKQogICAgICAuZmlsdGVyKGZpbGUgPT4gCiAgICAgICAgZmlsZS5lbmRzV2l0aCgnLm1kJykgJiYgCiAgICAgICAgL15bMC05XS8udGVzdChmaWxlKSAmJgogICAgICAgIGZzLnN0YXRTeW5jKHBhdGguam9pbihoYW5kb2Zmc0RpciwgZmlsZSkpLmlzRmlsZSgpCiAgICAgICk7CiAgICAgIAogICAgaWYgKGZpbGVzLmxlbmd0aCA9PT0gMCkgewogICAgICByZXR1cm4gMTsgLy8gU3RhcnQgd2l0aCAxIGlmIG5vIGV4aXN0aW5nIGZpbGVzCiAgICB9CiAgICAKICAgIC8vIEV4dHJhY3QgbnVtYmVycyBmcm9tIGZpbGVuYW1lcyBhbmQgZmluZCB0aGUgaGlnaGVzdAogICAgY29uc3QgbnVtYmVycyA9IGZpbGVzLm1hcChmaWxlID0+IHsKICAgICAgY29uc3QgbWF0Y2ggPSBmaWxlLm1hdGNoKC9eKFxkKykvKTsKICAgICAgcmV0dXJuIG1hdGNoID8gcGFyc2VJbnQobWF0Y2hbMV0sIDEwKSA6IDA7CiAgICB9KTsKICAgIAogICAgcmV0dXJuIE1hdGgubWF4KC4uLm51bWJlcnMpICsgMTsKICB9IGNhdGNoIChlcnIpIHsKICAgIGNvbnNvbGUuZXJyb3IoYEVycm9yIGZpbmRpbmcgbmV4dCBoYW5kb2ZmIG51bWJlcjogJHtlcnIubWVzc2FnZX1gKTsKICAgIHJldHVybiAxOyAvLyBEZWZhdWx0IHRvIDEgaWYgYW55IGVycm9ycwogIH0KfQoKLyoqCiAqIENoZWNrIGlmIHRoZSBzeXN0ZW0gZGlyZWN0b3JpZXMgZXhpc3QsIGNyZWF0ZSB0aGVtIGlmIHRoZXkgZG9uJ3QKICogQHBhcmFtIHtzdHJpbmd9IGhhbmRvZmZzRGlyIC0gUGF0aCB0byB0aGUgaGFuZG9mZnMgZGlyZWN0b3J5CiAqIEByZXR1cm5zIHtvYmplY3R9IC0gT2JqZWN0IHdpdGggcGF0aHMgdG8gdGhlIHN5c3RlbSBkaXJlY3RvcmllcwogKi8KZnVuY3Rpb24gZW5zdXJlU3lzdGVtRGlycyhoYW5kb2Zmc0RpcikgewogIGNvbnN0IHN5c3RlbURpciA9IHBhdGguam9pbihoYW5kb2Zmc0RpciwgJzAtc3lzdGVtJyk7CiAgY29uc3QgY2hhdEhpc3RvcnlEaXIgPSBwYXRoLmpvaW4oc3lzdGVtRGlyLCAnY2hhdF9oaXN0b3J5Jyk7CiAgY29uc3Qgc2NyaXB0c0RpciA9IHBhdGguam9pbihzeXN0ZW1EaXIsICdzY3JpcHRzJyk7CiAgCiAgLy8gQ3JlYXRlIHN5c3RlbSBkaXJlY3RvcnkgaWYgaXQgZG9lc24ndCBleGlzdAogIGlmICghZnMuZXhpc3RzU3luYyhzeXN0ZW1EaXIpKSB7CiAgICBjb25zb2xlLmxvZyhgQ3JlYXRpbmcgc3lzdGVtIGRpcmVjdG9yeTogJHtzeXN0ZW1EaXJ9YCk7CiAgICBmcy5ta2RpclN5bmMoc3lzdGVtRGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTsKICB9CiAgCiAgLy8gQ3JlYXRlIGNoYXRfaGlzdG9yeSBkaXJlY3RvcnkgaWYgaXQgZG9lc24ndCBleGlzdAogIGlmICghZnMuZXhpc3RzU3luYyhjaGF0SGlzdG9yeURpcikpIHsKICAgIGNvbnNvbGUubG9nKGBDcmVhdGluZyBjaGF0X2hpc3RvcnkgZGlyZWN0b3J5OiAke2NoYXRIaXN0b3J5RGlyfWApOwogICAgZnMubWtkaXJTeW5jKGNoYXRIaXN0b3J5RGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTsKICB9CiAgCiAgLy8gQ3JlYXRlIHNjcmlwdHMgZGlyZWN0b3J5IGlmIGl0IGRvZXNuJ3QgZXhpc3QKICBpZiAoIWZzLmV4aXN0c1N5bmMoc2NyaXB0c0RpcikpIHsKICAgIGNvbnNvbGUubG9nKGBDcmVhdGluZyBzY3JpcHRzIGRpcmVjdG9yeTogJHtzY3JpcHRzRGlyfWApOwogICAgZnMubWtkaXJTeW5jKHNjcmlwdHNEaXIsIHsgcmVjdXJzaXZlOiB0cnVlIH0pOwogIH0KICAKICByZXR1cm4gewogICAgc3lzdGVtRGlyLAogICAgY2hhdEhpc3RvcnlEaXIsCiAgICBzY3JpcHRzRGlyCiAgfTsKfQoKLyoqCiAqIEZpbmQgY29udmVyc2F0aW9uIGZpbGVzIGluIHRoZSBjaGF0X2hpc3RvcnkgZGlyZWN0b3J5CiAqIEBwYXJhbSB7c3RyaW5nfSBjaGF0SGlzdG9yeURpciAtIFBhdGggdG8gdGhlIGNoYXRfaGlzdG9yeSBkaXJlY3RvcnkKICogQHJldHVybnMge3N0cmluZ1tdfSAtIEFycmF5IG9mIGZpbGUgcGF0aHMKICovCmZ1bmN0aW9uIGZpbmRDb252ZXJzYXRpb25GaWxlcyhjaGF0SGlzdG9yeURpcikgewogIHRyeSB7CiAgICBjb25zdCBmaWxlcyA9IGZzLnJlYWRkaXJTeW5jKGNoYXRIaXN0b3J5RGlyKQogICAgICAuZmlsdGVyKGZpbGUgPT4KICAgICAgICBmaWxlLmVuZHNXaXRoKCcubWQnKSB8fCBmaWxlLmVuZHNXaXRoKCcudHh0JykgfHwgZmlsZS5lbmRzV2l0aCgnLmpzb24nKQogICAgICApCiAgICAgIC5tYXAoZmlsZSA9PiBwYXRoLmpvaW4oY2hhdEhpc3RvcnlEaXIsIGZpbGUpKTsKICAgIAogICAgcmV0dXJuIGZpbGVzOwogIH0gY2F0Y2ggKGVycikgewogICAgY29uc29sZS5lcnJvcihgRXJyb3IgZmluZGluZyBjb252ZXJzYXRpb24gZmlsZXM6ICR7ZXJyLm1lc3NhZ2V9YCk7CiAgICByZXR1cm4gW107CiAgfQp9CgovKioKICogUnVuIHRoZSBQeXRob24gZXh0cmFjdGlvbiBzY3JpcHQKICogQHBhcmFtIHtzdHJpbmd9IGlucHV0RmlsZSAtIFBhdGggdG8gdGhlIGNvbnZlcnNhdGlvbiBleHBvcnQgZmlsZQogKiBAcGFyYW0ge3N0cmluZ30gb3V0cHV0RmlsZSAtIFBhdGggd2hlcmUgdGhlIGNsZWFuZWQgY29udmVyc2F0aW9uIHNob3VsZCBiZSBzYXZlZAogKiBAcGFyYW0ge2Jvb2xlYW59IGRlbGV0ZU9yaWdpbmFsIC0gV2hldGhlciB0byBkZWxldGUgdGhlIG9yaWdpbmFsIGZpbGUgYWZ0ZXIgc3VjY2Vzc2Z1bCBleHRyYWN0aW9uCiAqIEByZXR1cm5zIHtib29sZWFufSAtIFRydWUgaWYgc3VjY2Vzc2Z1bCwgZmFsc2Ugb3RoZXJ3aXNlCiAqLwpmdW5jdGlvbiBydW5QeXRob25FeHRyYWN0aW9uKGlucHV0RmlsZSwgb3V0cHV0RmlsZSwgZGVsZXRlT3JpZ2luYWwgPSBmYWxzZSkgewogIHRyeSB7CiAgICBjb25zb2xlLmxvZygnQXR0ZW1wdGluZyBleHRyYWN0aW9uIHVzaW5nIFB5dGhvbiBzY3JpcHQuLi4nKTsKICAgIAogICAgLy8gQ29uc3RydWN0IHRoZSBQeXRob24gY29tbWFuZAogICAgLy8gVXBkYXRlIHBhdGggdG8gbG9vayBpbiB0aGUgc3lzdGVtIHNjcmlwdHMgZGlyZWN0b3J5IGlmIGF2YWlsYWJsZQogICAgbGV0IHNjcmlwdFBhdGg7CiAgICBjb25zdCBzeXN0ZW1TY3JpcHRzUGF0aCA9IHBhdGguam9pbihoYW5kb2Zmc0RpciwgJzAtc3lzdGVtJywgJ3NjcmlwdHMnLCAnMS1leHRyYWN0X2NvbnZlcnNhdGlvbi5weScpOwogICAgCiAgICBpZiAoZnMuZXhpc3RzU3luYyhzeXN0ZW1TY3JpcHRzUGF0aCkpIHsKICAgICAgc2NyaXB0UGF0aCA9IHN5c3RlbVNjcmlwdHNQYXRoOwogICAgICBjb25zb2xlLmxvZyhgVXNpbmcgc2NyaXB0IGZyb20gc3lzdGVtIGRpcmVjdG9yeTogJHtzY3JpcHRQYXRofWApOwogICAgfSBlbHNlIHsKICAgICAgc2NyaXB0UGF0aCA9IHBhdGguam9pbihwYXRoLmRpcm5hbWUoX19kaXJuYW1lKSwgJzItc2NyaXB0cycsICcxLWV4dHJhY3RfY29udmVyc2F0aW9uLnB5Jyk7CiAgICAgIGNvbnNvbGUubG9nKGBVc2luZyBzY3JpcHQgZnJvbSBzb3VyY2UgZGlyZWN0b3J5OiAke3NjcmlwdFBhdGh9YCk7CiAgICB9CiAgICBjb25zdCBjb21tYW5kID0gYHB5dGhvbiAiJHtzY3JpcHRQYXRofSIgIiR7aW5wdXRGaWxlfSIgIiR7b3V0cHV0RmlsZX0iYDsKICAgIAogICAgLy8gRXhlY3V0ZSB0aGUgY29tbWFuZAogICAgZXhlY1N5bmMoY29tbWFuZCwgeyBzdGRpbzogJ2luaGVyaXQnIH0pOwogICAgCiAgICAvLyBWZXJpZnkgdGhlIG91dHB1dCBmaWxlIHdhcyBjcmVhdGVkCiAgICBpZiAoZnMuZXhpc3RzU3luYyhvdXRwdXRGaWxlKSkgewogICAgICBjb25zb2xlLmxvZyhg4pyFIFB5dGhvbiBleHRyYWN0aW9uIHN1Y2Nlc3NmdWw6ICR7b3V0cHV0RmlsZX1gKTsKICAgICAgCiAgICAgIC8vIERlbGV0ZSBvcmlnaW5hbCBmaWxlIGlmIHJlcXVlc3RlZAogICAgICBpZiAoZGVsZXRlT3JpZ2luYWwpIHsKICAgICAgICB0cnkgewogICAgICAgICAgZnMudW5saW5rU3luYyhpbnB1dEZpbGUpOwogICAgICAgICAgY29uc29sZS5sb2coYOKchSBEZWxldGVkIG9yaWdpbmFsIGZpbGU6ICR7aW5wdXRGaWxlfWApOwogICAgICAgIH0gY2F0Y2ggKGRlbGV0ZUVycikgewogICAgICAgICAgY29uc29sZS53YXJuKGDimqDvuI8gV2FybmluZzogQ291bGQgbm90IGRlbGV0ZSBvcmlnaW5hbCBmaWxlOiAke2RlbGV0ZUVyci5tZXNzYWdlfWApOwogICAgICAgIH0KICAgICAgfQogICAgICAKICAgICAgcmV0dXJuIHRydWU7CiAgICB9IGVsc2UgewogICAgICBjb25zb2xlLmxvZygn4p2MIFB5dGhvbiBleHRyYWN0aW9uIGNvbXBsZXRlZCBidXQgb3V0cHV0IGZpbGUgbm90IGZvdW5kJyk7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICB9IGNhdGNoIChlcnIpIHsKICAgIGNvbnNvbGUubG9nKGDinYwgUHl0aG9uIGV4dHJhY3Rpb24gZmFpbGVkOiAke2Vyci5tZXNzYWdlfWApOwogICAgcmV0dXJuIGZhbHNlOwogIH0KfQoKLyoqCiAqIFJ1biB0aGUgTm9kZS5qcyBleHRyYWN0aW9uIHNjcmlwdAogKiBAcGFyYW0ge3N0cmluZ30gaW5wdXRGaWxlIC0gUGF0aCB0byB0aGUgY29udmVyc2F0aW9uIGV4cG9ydCBmaWxlCiAqIEBwYXJhbSB7c3RyaW5nfSBvdXRwdXRGaWxlIC0gUGF0aCB3aGVyZSB0aGUgY2xlYW5lZCBjb252ZXJzYXRpb24gc2hvdWxkIGJlIHNhdmVkCiAqIEBwYXJhbSB7Ym9vbGVhbn0gZGVsZXRlT3JpZ2luYWwgLSBXaGV0aGVyIHRvIGRlbGV0ZSB0aGUgb3JpZ2luYWwgZmlsZSBhZnRlciBzdWNjZXNzZnVsIGV4dHJhY3Rpb24KICogQHJldHVybnMge2Jvb2xlYW59IC0gVHJ1ZSBpZiBzdWNjZXNzZnVsLCBmYWxzZSBvdGhlcndpc2UKICovCmZ1bmN0aW9uIHJ1bk5vZGVFeHRyYWN0aW9uKGlucHV0RmlsZSwgb3V0cHV0RmlsZSwgZGVsZXRlT3JpZ2luYWwgPSBmYWxzZSkgewogIHRyeSB7CiAgICBjb25zb2xlLmxvZygnQXR0ZW1wdGluZyBleHRyYWN0aW9uIHVzaW5nIE5vZGUuanMgc2NyaXB0Li4uJyk7CiAgICAKICAgIC8vIFVzZSB0aGlzIGZpbGUgaXRzZWxmIGZvciBleHRyYWN0aW9uCiAgICAvLyBXZSdsbCBpbXBsZW1lbnQgYSBkaXJlY3QgZXh0cmFjdGlvbiBtZXRob2QgaW5zdGVhZCBvZiBjYWxsaW5nIGFub3RoZXIgc2NyaXB0CiAgICAvLyBGaXJzdCwgY2hlY2sgaWYgd2UgaGF2ZSBhbiBleHRyYWN0aW9uIGZ1bmN0aW9uIGluIHRoaXMgZmlsZQogICAgaWYgKHR5cGVvZiBleHRyYWN0Q29udmVyc2F0aW9uRGlyZWN0ID09PSAnZnVuY3Rpb24nKSB7CiAgICAgIGNvbnNvbGUubG9nKCdVc2luZyBkaXJlY3QgZXh0cmFjdGlvbiBtZXRob2QuLi4nKTsKICAgICAgY29uc3QgcmVzdWx0ID0gZXh0cmFjdENvbnZlcnNhdGlvbkRpcmVjdChpbnB1dEZpbGUsIG91dHB1dEZpbGUpOwogICAgICAKICAgICAgaWYgKHJlc3VsdCkgewogICAgICAgIGNvbnNvbGUubG9nKGDinIUgRGlyZWN0IGV4dHJhY3Rpb24gc3VjY2Vzc2Z1bDogJHtvdXRwdXRGaWxlfWApOwogICAgICAgIAogICAgICAgIC8vIERlbGV0ZSBvcmlnaW5hbCBmaWxlIGlmIHJlcXVlc3RlZAogICAgICAgIGlmIChkZWxldGVPcmlnaW5hbCkgewogICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgZnMudW5saW5rU3luYyhpbnB1dEZpbGUpOwogICAgICAgICAgICBjb25zb2xlLmxvZyhg4pyFIERlbGV0ZWQgb3JpZ2luYWwgZmlsZTogJHtpbnB1dEZpbGV9YCk7CiAgICAgICAgICB9IGNhdGNoIChkZWxldGVFcnIpIHsKICAgICAgICAgICAgY29uc29sZS53YXJuKGDimqDvuI8gV2FybmluZzogQ291bGQgbm90IGRlbGV0ZSBvcmlnaW5hbCBmaWxlOiAke2RlbGV0ZUVyci5tZXNzYWdlfWApOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfSBlbHNlIHsKICAgICAgICBjb25zb2xlLmxvZygn4p2MIERpcmVjdCBleHRyYWN0aW9uIGZhaWxlZCcpOwogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgfQogICAgCiAgICAvLyBGYWxsIGJhY2sgdG8gZXh0ZXJuYWwgc2NyaXB0IGlmIGRpcmVjdCBleHRyYWN0aW9uIGlzIG5vdCBhdmFpbGFibGUKICAgIC8vIFVwZGF0ZSBwYXRoIHRvIGxvb2sgaW4gdGhlIHN5c3RlbSBzY3JpcHRzIGRpcmVjdG9yeSBpZiBhdmFpbGFibGUKICAgIGxldCBzY3JpcHRQYXRoOwogICAgY29uc3Qgc3lzdGVtU2NyaXB0c1BhdGggPSBwYXRoLmpvaW4oaGFuZG9mZnNEaXIsICcwLXN5c3RlbScsICdzY3JpcHRzJywgJzEtZXh0cmFjdC1jb252ZXJzYXRpb24uanMnKTsKICAgIAogICAgaWYgKGZzLmV4aXN0c1N5bmMoc3lzdGVtU2NyaXB0c1BhdGgpKSB7CiAgICAgIHNjcmlwdFBhdGggPSBzeXN0ZW1TY3JpcHRzUGF0aDsKICAgICAgY29uc29sZS5sb2coYFVzaW5nIHNjcmlwdCBmcm9tIHN5c3RlbSBkaXJlY3Rvcnk6ICR7c2NyaXB0UGF0aH1gKTsKICAgIH0gZWxzZSB7CiAgICAgIHNjcmlwdFBhdGggPSBwYXRoLmpvaW4ocGF0aC5kaXJuYW1lKF9fZGlybmFtZSksICcyLXNjcmlwdHMnLCAnMS1leHRyYWN0LWNvbnZlcnNhdGlvbi5qcycpOwogICAgICBjb25zb2xlLmxvZyhgVXNpbmcgc2NyaXB0IGZyb20gc291cmNlIGRpcmVjdG9yeTogJHtzY3JpcHRQYXRofWApOwogICAgfQogICAgY29uc3QgY29tbWFuZCA9IGBub2RlICIke3NjcmlwdFBhdGh9IiAiJHtpbnB1dEZpbGV9IiAiJHtvdXRwdXRGaWxlfSJgOwogICAgCiAgICAvLyBFeGVjdXRlIHRoZSBjb21tYW5kCiAgICBleGVjU3luYyhjb21tYW5kLCB7IHN0ZGlvOiAnaW5oZXJpdCcgfSk7CiAgICAKICAgIC8vIFZlcmlmeSB0aGUgb3V0cHV0IGZpbGUgd2FzIGNyZWF0ZWQKICAgIGlmIChmcy5leGlzdHNTeW5jKG91dHB1dEZpbGUpKSB7CiAgICAgIGNvbnNvbGUubG9nKGDinIUgTm9kZS5qcyBleHRyYWN0aW9uIHN1Y2Nlc3NmdWw6ICR7b3V0cHV0RmlsZX1gKTsKICAgICAgCiAgICAgIC8vIERlbGV0ZSBvcmlnaW5hbCBmaWxlIGlmIHJlcXVlc3RlZAogICAgICBpZiAoZGVsZXRlT3JpZ2luYWwpIHsKICAgICAgICB0cnkgewogICAgICAgICAgZnMudW5saW5rU3luYyhpbnB1dEZpbGUpOwogICAgICAgICAgY29uc29sZS5sb2coYOKchSBEZWxldGVkIG9yaWdpbmFsIGZpbGU6ICR7aW5wdXRGaWxlfWApOwogICAgICAgIH0gY2F0Y2ggKGRlbGV0ZUVycikgewogICAgICAgICAgY29uc29sZS53YXJuKGDimqDvuI8gV2FybmluZzogQ291bGQgbm90IGRlbGV0ZSBvcmlnaW5hbCBmaWxlOiAke2RlbGV0ZUVyci5tZXNzYWdlfWApOwogICAgICAgIH0KICAgICAgfQogICAgICAKICAgICAgcmV0dXJuIHRydWU7CiAgICB9IGVsc2UgewogICAgICBjb25zb2xlLmxvZygn4p2MIE5vZGUuanMgZXh0cmFjdGlvbiBjb21wbGV0ZWQgYnV0IG91dHB1dCBmaWxlIG5vdCBmb3VuZCcpOwogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgfSBjYXRjaCAoZXJyKSB7CiAgICBjb25zb2xlLmxvZyhg4p2MIE5vZGUuanMgZXh0cmFjdGlvbiBmYWlsZWQ6ICR7ZXJyLm1lc3NhZ2V9YCk7CiAgICByZXR1cm4gZmFsc2U7CiAgfQp9CgovKioKICogTWFpbiBmdW5jdGlvbiB0byBydW4gdGhlIGV4dHJhY3Rpb24gcHJvY2VzcwogKi8KZnVuY3Rpb24gbWFpbigpIHsKICAvLyBQYXJzZSBjb21tYW5kIGxpbmUgYXJndW1lbnRzCiAgY29uc3QgYXJncyA9IHByb2Nlc3MuYXJndi5zbGljZSgyKTsKICBsZXQgaW5wdXRGaWxlID0gbnVsbDsKICAKICAvLyBQYXJzZSBhcmd1bWVudHMgYW5kIHVwZGF0ZSB0aGUgZ2xvYmFsIGhhbmRvZmZzRGlyCiAgaWYgKGFyZ3MubGVuZ3RoID49IDEpIHsKICAgIC8vIEZpcnN0IGFyZ3VtZW50IGNvdWxkIGJlIGVpdGhlciBpbnB1dCBmaWxlIG9yIGhhbmRvZmZzIGRpcmVjdG9yeQogICAgaWYgKGFyZ3NbMF0uZW5kc1dpdGgoJy5tZCcpIHx8IGFyZ3NbMF0uZW5kc1dpdGgoJy50eHQnKSB8fCBhcmdzWzBdLmVuZHNXaXRoKCcuanNvbicpKSB7CiAgICAgIGlucHV0RmlsZSA9IGFyZ3NbMF07CiAgICAgIGlmIChhcmdzLmxlbmd0aCA+PSAyKSB7CiAgICAgICAgaGFuZG9mZnNEaXIgPSBhcmdzWzFdOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBoYW5kb2Zmc0RpciA9IGFyZ3NbMF07CiAgICB9CiAgfQogIAogIHRyeSB7CiAgICAvLyBFbnN1cmUgaGFuZG9mZnMgZGlyZWN0b3J5IGV4aXN0cwogICAgaWYgKCFmcy5leGlzdHNTeW5jKGhhbmRvZmZzRGlyKSkgewogICAgICBjb25zb2xlLmxvZyhgQ3JlYXRpbmcgaGFuZG9mZnMgZGlyZWN0b3J5OiAke2hhbmRvZmZzRGlyfWApOwogICAgICBmcy5ta2RpclN5bmMoaGFuZG9mZnNEaXIsIHsgcmVjdXJzaXZlOiB0cnVlIH0pOwogICAgfQogIH0gY2F0Y2ggKGVycikgewogICAgY29uc29sZS5lcnJvcihgRXJyb3Igd2l0aCBoYW5kb2ZmcyBkaXJlY3Rvcnk6ICR7ZXJyLm1lc3NhZ2V9YCk7CiAgICBjb25zb2xlLmxvZygnRmFsbGluZyBiYWNrIHRvIGN1cnJlbnQgZGlyZWN0b3J5ICsgL2hhbmRvZmZzJyk7CiAgICBoYW5kb2Zmc0RpciA9IHBhdGguam9pbihwcm9jZXNzLmN3ZCgpLCAnaGFuZG9mZnMnKTsKICAgIGZzLm1rZGlyU3luYyhoYW5kb2Zmc0RpciwgeyByZWN1cnNpdmU6IHRydWUgfSk7CiAgfQogIAogIC8vIEVuc3VyZSBzeXN0ZW0gZGlyZWN0b3JpZXMgZXhpc3QKICBjb25zdCB7IHN5c3RlbURpciwgY2hhdEhpc3RvcnlEaXIsIHNjcmlwdHNEaXIgfSA9IGVuc3VyZVN5c3RlbURpcnMoaGFuZG9mZnNEaXIpOwogIAogIC8vIElmIG5vIGlucHV0IGZpbGUgc3BlY2lmaWVkLCBsb29rIGluIGNoYXRfaGlzdG9yeSBkaXJlY3RvcnkKICBpZiAoIWlucHV0RmlsZSkgewogICAgY29uc3QgY29udmVyc2F0aW9uRmlsZXMgPSBmaW5kQ29udmVyc2F0aW9uRmlsZXMoY2hhdEhpc3RvcnlEaXIpOwogICAgCiAgICBpZiAoY29udmVyc2F0aW9uRmlsZXMubGVuZ3RoID09PSAwKSB7CiAgICAgIGNvbnNvbGUubG9nKGAKTm8gY29udmVyc2F0aW9uIGZpbGVzIGZvdW5kIGluICR7Y2hhdEhpc3RvcnlEaXJ9CgpVc2FnZTogbm9kZSBleHRyYWN0LWNvbnZlcnNhdGlvbi5qcyA8Y29udmVyc2F0aW9uX2V4cG9ydF9maWxlPiBbaGFuZG9mZnNfZGlyXQoKQXJndW1lbnRzOgogIGNvbnZlcnNhdGlvbl9leHBvcnRfZmlsZSAgUGF0aCB0byB0aGUgZXhwb3J0ZWQgY29udmVyc2F0aW9uIGZpbGUKICBoYW5kb2Zmc19kaXIgICAgICAgICAgICAgIChPcHRpb25hbCkgUGF0aCB0byB0aGUgaGFuZG9mZnMgZGlyZWN0b3J5IChkZWZhdWx0OiAiaGFuZG9mZnMiKQoKUGxlYXNlIHBsYWNlIHlvdXIgY29udmVyc2F0aW9uIGV4cG9ydCBmaWxlcyBpbiB0aGUgY2hhdF9oaXN0b3J5IGRpcmVjdG9yeSBvciBwcm92aWRlIGEgZGlyZWN0IHBhdGguCiAgICAgIGApOwogICAgICBwcm9jZXNzLmV4aXQoMSk7CiAgICB9CiAgICAKICAgIC8vIFVzZSB0aGUgZmlyc3QgZmlsZSBmb3VuZAogICAgaW5wdXRGaWxlID0gY29udmVyc2F0aW9uRmlsZXNbMF07CiAgICBjb25zb2xlLmxvZyhgRm91bmQgY29udmVyc2F0aW9uIGZpbGU6ICR7aW5wdXRGaWxlfWApOwogIH0KICAKICAvLyBFbnN1cmUgaW5wdXQgZmlsZSBleGlzdHMKICBpZiAoIWZzLmV4aXN0c1N5bmMoaW5wdXRGaWxlKSkgewogICAgY29uc29sZS5lcnJvcihgRXJyb3I6IElucHV0IGZpbGUgbm90IGZvdW5kOiAke2lucHV0RmlsZX1gKTsKICAgIHByb2Nlc3MuZXhpdCgxKTsKICB9CiAgCiAgLy8gQ2hlY2sgZmlsZSBzaXplIC0gd2FybiBpZiBvdmVyIDFNQgogIGNvbnN0IGZpbGVTdGF0cyA9IGZzLnN0YXRTeW5jKGlucHV0RmlsZSk7CiAgY29uc3QgZmlsZVNpemVNQiA9IGZpbGVTdGF0cy5zaXplIC8gKDEwMjQgKiAxMDI0KTsKICBsZXQgc2l6ZUJhZGdlID0gJ/Cfn6InOwogIAogIGlmIChmaWxlU2l6ZU1CID4gNSkgewogICAgc2l6ZUJhZGdlID0gJ/CflLQnOwogICAgY29uc29sZS53YXJuKGBcbuKaoO+4jyBXQVJOSU5HOiBGaWxlIGlzIHZlcnkgbGFyZ2UgKCR7ZmlsZVNpemVNQi50b0ZpeGVkKDIpfSBNQikuIFRoaXMgbWF5IHRha2Ugc29tZSB0aW1lIHRvIHByb2Nlc3MuYCk7CiAgfSBlbHNlIGlmIChmaWxlU2l6ZU1CID4gMSkgewogICAgc2l6ZUJhZGdlID0gJ/Cfn6AnOwogICAgY29uc29sZS53YXJuKGBcbuKaoO+4jyBOb3RpY2U6IEZpbGUgaXMgbW9kZXJhdGVseSBsYXJnZSAoJHtmaWxlU2l6ZU1CLnRvRml4ZWQoMil9IE1CKS5gKTsKICB9CiAgCiAgLy8gRGV0ZXJtaW5lIGlmIHRoaXMgaXMgYSBmaWxlIGZyb20gY2hhdF9oaXN0b3J5CiAgY29uc3QgaXNGcm9tQ2hhdEhpc3RvcnkgPSBpbnB1dEZpbGUuaW5jbHVkZXMocGF0aC5qb2luKGhhbmRvZmZzRGlyLCAnMC1zeXN0ZW0nLCAnY2hhdF9oaXN0b3J5JykpOwogIAogIC8vIERldGVybWluZSB0aGUgbmV4dCBoYW5kb2ZmIG51bWJlcgogIGNvbnN0IG5leHROdW0gPSBkZXRlcm1pbmVOZXh0SGFuZG9mZk51bWJlcihoYW5kb2Zmc0Rpcik7CiAgCiAgLy8gQ29uc3RydWN0IHRoZSBvdXRwdXQgZmlsZW5hbWUKICBjb25zdCBvdXRwdXRGaWxlID0gcGF0aC5qb2luKGhhbmRvZmZzRGlyLCBgJHtuZXh0TnVtfS1jaGF0X3RyYW5zY3JpcHQubWRgKTsKICAKICBjb25zb2xlLmxvZyhgCuKVlOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVlwrilZEgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIOKVkQrilZEgICAgICAgIENvbnZlcnNhdGlvbiBFeHRyYWN0aW9uIFByb2Nlc3MgICAgICAgICAgIOKVkQrilZEgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIOKVkQrilZrilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZ0KICAKSW5wdXQgZmlsZTogJHtpbnB1dEZpbGV9ICR7c2l6ZUJhZGdlfQpPdXRwdXQgZmlsZTogJHtvdXRwdXRGaWxlfQpOZXh0IGhhbmRvZmYgbnVtYmVyOiAke25leHROdW19CkF1dG8tY2xlYW51cDogJHtpc0Zyb21DaGF0SGlzdG9yeSA/ICdZZXMgKHdpbGwgZGVsZXRlIG9yaWdpbmFsIGFmdGVyIHN1Y2Nlc3MpJyA6ICdObyd9CmApOwogIAogIC8vIEZpcnN0IHRyeSBQeXRob24gZXh0cmFjdGlvbgogIGNvbnN0IHB5dGhvblN1Y2Nlc3MgPSBydW5QeXRob25FeHRyYWN0aW9uKGlucHV0RmlsZSwgb3V0cHV0RmlsZSwgaXNGcm9tQ2hhdEhpc3RvcnkpOwogIAogIC8vIElmIFB5dGhvbiBmYWlscywgdHJ5IE5vZGUuanMgZXh0cmFjdGlvbgogIGlmICghcHl0aG9uU3VjY2VzcykgewogICAgY29uc29sZS5sb2coJ1xuUHl0aG9uIGV4dHJhY3Rpb24gZmFpbGVkLCB0cnlpbmcgTm9kZS5qcy4uLlxuJyk7CiAgICBjb25zdCBub2RlU3VjY2VzcyA9IHJ1bk5vZGVFeHRyYWN0aW9uKGlucHV0RmlsZSwgb3V0cHV0RmlsZSwgaXNGcm9tQ2hhdEhpc3RvcnkpOwogICAgCiAgICBpZiAoIW5vZGVTdWNjZXNzKSB7CiAgICAgIGNvbnNvbGUuZXJyb3IoJ1xu4p2MIEJvdGggZXh0cmFjdGlvbiBtZXRob2RzIGZhaWxlZC4gUGxlYXNlIGNoZWNrIHRoZSBpbnB1dCBmaWxlIGFuZCB0cnkgYWdhaW4uJyk7CiAgICAgIHByb2Nlc3MuZXhpdCgxKTsKICAgIH0KICB9CiAgCiAgY29uc29sZS5sb2coYArilZTilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZcK4pWRICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICDilZEK4pWRICAgICAgICAgICBFeHRyYWN0aW9uIENvbXBsZXRlICAgICAgICAgICAgICAgICAgICDilZEK4pWRICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICDilZEK4pWa4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWdCgpUaGUgY29udmVyc2F0aW9uIGhhcyBiZWVuIGV4dHJhY3RlZCBhbmQgc2F2ZWQgdG86CiR7b3V0cHV0RmlsZX0KClRoaXMgZmlsZSBjYW4gbm93IGJlIHVzZWQgYnkgdGhlIGhhbmRvZmYtbWFuYWdlciB0byBjcmVhdGUgYSAKaGFuZG9mZiBkb2N1bWVudCB3aXRoIGNvbnZlcnNhdGlvbiBpbnNpZ2h0cy4KCk5leHQgc3RlcHM6CjEuIENyZWF0ZSBhIGhhbmRvZmYgZG9jdW1lbnQgaW5jb3Jwb3JhdGluZyB0aGUgZXh0cmFjdGVkIGNvbnZlcnNhdGlvbjoKICAgIkkgbmVlZCB0byBjcmVhdGUgYSBoYW5kb2ZmIGRvY3VtZW50IGluY29ycG9yYXRpbmcgaW5zaWdodHMgZnJvbSBvdXIgY29udmVyc2F0aW9uLiIKCjIuIFRoZSBoYW5kb2ZmLW1hbmFnZXIgd2lsbCBhdXRvbWF0aWNhbGx5IGFuYWx5emUgdGhlIGV4dHJhY3RlZCBmaWxlCiAgIGFuZCBpbmNvcnBvcmF0ZSByZWxldmFudCBpbnNpZ2h0cyBpbnRvIHRoZSBoYW5kb2ZmIGRvY3VtZW50LgpgKTsKfQoKLy8gUnVuIHRoZSBzY3JpcHQKbWFpbigpOw==",
"handoffs/0-system/scripts/1-extract_conversation.py": "IyEvdXNyL2Jpbi9lbnYgcHl0aG9uMwoiIiIKZXh0cmFjdF9jb252ZXJzYXRpb25fc2ltcGxlLnB5CgpFeHRyYWN0cyB0aGUgY29yZSBjb252ZXJzYXRpb24gKHVzZXIgcHJvbXB0cyBhbmQgTExNIHJlc3BvbnNlcykgZnJvbSBDbGluZSB0YXNrIGZpbGVzLApyZW1vdmluZyBmaWxlIGNvbnRlbnRzLCB0b29sIHJlc3VsdHMsIGFuZCBvdGhlciBub24tZXNzZW50aWFsIGVsZW1lbnRzLgoKT3B0aW1pemVkIGZvciBSb28tQ29kZSdzIGV4cG9ydCBmb3JtYXQ6Ci0gSGFuZGxlcyAiKipVc2VyOioqIiBhbmQgIioqQXNzaXN0YW50OioqIiBoZWFkZXJzIHdpdGggbWVzc2FnZXMgc2VwYXJhdGVkIGJ5ICItLS0iCi0gUmVtb3ZlcyBbVG9vbCBVc2VdLCBbVG9vbF0sIFtUb29sIChFcnJvcildLCBhbmQgW0ltYWdlXSByZWZlcmVuY2VzCi0gUHJlc2VydmVzIHRoaW5raW5nIHNlY3Rpb25zIGFuZCBlc3NlbnRpYWwgY29udmVyc2F0aW9uIGZsb3cKLSBSZW1vdmVzIGZpbGUgY29udGVudHMgdGhhdCBtaWdodCBjYXVzZSBiaWFzIGluIGZ1dHVyZSBMTE0gaW50ZXJhY3Rpb25zCgpVc2FnZToKICAgIHB5dGhvbiBleHRyYWN0X2NvbnZlcnNhdGlvbl9zaW1wbGUucHkgaW5wdXRfZmlsZSBbb3V0cHV0X2ZpbGVdCgpJZiBvdXRwdXRfZmlsZSBpcyBub3Qgc3BlY2lmaWVkLCBhIGZpbGUgd2l0aCAiX2NsZWFuIiBzdWZmaXggd2lsbCBiZSBjcmVhdGVkLgoiIiIKCmltcG9ydCByZQppbXBvcnQgc3lzCmltcG9ydCBvcwpmcm9tIHBhdGhsaWIgaW1wb3J0IFBhdGgKZnJvbSB0eXBpbmcgaW1wb3J0IExpc3QsIFR1cGxlCgojIFJlZ3VsYXIgZXhwcmVzc2lvbiBwYXR0ZXJucyBmb3IgY29udGVudCBpZGVudGlmaWNhdGlvbgpQQVRURVJOUyA9IHsKICAgICMgRW52aXJvbm1lbnQgZGV0YWlscyBhbmQgc3RydWN0dXJhbCBjb250ZW50CiAgICAiZW52aXJvbm1lbnRfZGV0YWlscyI6IHJlLmNvbXBpbGUocic8ZW52aXJvbm1lbnRfZGV0YWlscz4uKj88L2Vudmlyb25tZW50X2RldGFpbHM+JywgcmUuRE9UQUxMKSwKICAgICJ0YXNrX3RhZyI6IHJlLmNvbXBpbGUocic8dGFzaz4oLio/KTwvdGFzaz4nLCByZS5ET1RBTEwpLAogICAgImZlZWRiYWNrX3RhZyI6IHJlLmNvbXBpbGUocic8ZmVlZGJhY2s+KC4qPyk8L2ZlZWRiYWNrPicsIHJlLkRPVEFMTCksCiAgICAidXNlcl9tZXNzYWdlX3RhZyI6IHJlLmNvbXBpbGUocic8dXNlcl9tZXNzYWdlPiguKj8pPC91c2VyX21lc3NhZ2U+JywgcmUuRE9UQUxMKSwKICAgICJhbnN3ZXJfdGFnIjogcmUuY29tcGlsZShyJzxhbnN3ZXI+KC4qPyk8L2Fuc3dlcj4nLCByZS5ET1RBTEwpLAogICAgCiAgICAjIEZpbGUgY29udGVudCBhbmQgcmVzdWx0cyB0byByZW1vdmUKICAgICJmaWxlX2NvbnRlbnRfdGFnIjogcmUuY29tcGlsZShyJzxmaWxlX2NvbnRlbnQgcGF0aD0iLio/Ij4uKj88L2ZpbGVfY29udGVudD4nLCByZS5ET1RBTEwpLAogICAgInRvb2xfcmVzdWx0IjogcmUuY29tcGlsZShyJ1xbW15cXV0rXF0gUmVzdWx0Oi4qPyg/PVxuXG58XFopJywgcmUuRE9UQUxMKSwKICAgIAogICAgIyBSb28tQ29kZSBzcGVjaWZpYyBleHBvcnQgcGF0dGVybnMKICAgICJyb29fdG9vbF91c2UiOiByZS5jb21waWxlKHInXFtUb29sIFVzZTogLio/XF0uKj8oPz1cblxufFxaKScsIHJlLkRPVEFMTCksCiAgICAicm9vX3Rvb2xfcmVzdWx0IjogcmUuY29tcGlsZShyJ1xbVG9vbCg/OlxzXChFcnJvclwpKT9cXVxuLio/KD89XG5cbnxcWiknLCByZS5ET1RBTEwpLAogICAgInJvb19pbWFnZV9yZWZlcmVuY2UiOiByZS5jb21waWxlKHInXFtJbWFnZVxdJywgcmUuRE9UQUxMKSwKICAgIAogICAgIyBNb3JlIGFnZ3Jlc3NpdmVseSByZW1vdmUgY29kZSBibG9ja3MgYW5kIGZpbGUgb3V0cHV0cwogICAgImZpbGVfb3V0cHV0X2Jsb2NrcyI6IHJlLmNvbXBpbGUocidgYGAoPzpcdyspP1xuLio/YGBgJywgcmUuRE9UQUxMKSwgICMgQW55IGNvZGUgYmxvY2sKICAgICJmaWxlX2xpc3RpbmciOiByZS5jb21waWxlKHInKD86RGlyZWN0b3J5XHMrKT8oPzpGaWxlfExpc3RpbmcpW15cbl0qP1xuKD86LStcbik/KD86KD86XHMqWy1cdy4vXFxdK1xzKlxuKSspJywgcmUuRE9UQUxMKSwgICMgRmlsZSBsaXN0aW5ncwogICAgImZpbGVfcGF0aF9yZWZlcmVuY2VzIjogcmUuY29tcGlsZShyJyg/OmlufGZyb218YXR8cGF0aDp8ZmlsZTopXHMrWyJcJ2BdW1wvXFxdP1tcd1wtXC9cXFwuXStbIlwnYF0nLCByZS5ET1RBTEwpLAogICAgCiAgICAjIEFzc2lzdGFudCB0aGlua2luZyBhbmQgdG9vbCB1c2UKICAgICJ0aGlua2luZyI6IHJlLmNvbXBpbGUocic8dGhpbmtpbmc+KC4qPyk8L3RoaW5raW5nPicsIHJlLkRPVEFMTCksCiAgICAiYXR0ZW1wdF9jb21wbGV0aW9uIjogcmUuY29tcGlsZShyJzxhdHRlbXB0X2NvbXBsZXRpb24+Lio/PHJlc3VsdD4oLio/KTwvcmVzdWx0Pi4qPzwvYXR0ZW1wdF9jb21wbGV0aW9uPicsIHJlLkRPVEFMTCksCiAgICAKICAgICMgUmVtb3ZlIHRvb2wgdXNlcyBidXQga2VlcCBzb21lIGluZm8KICAgICJ0b29sX3VzZV9wYXR0ZXJucyI6IHsKICAgICAgICAjIFRvb2wgdXNlcyB0byBjb21wbGV0ZWx5IHJlbW92ZQogICAgICAgICJ3cml0ZV90b19maWxlIjogcmUuY29tcGlsZShyJzx3cml0ZV90b19maWxlPi4qPzwvd3JpdGVfdG9fZmlsZT4nLCByZS5ET1RBTEwpLAogICAgICAgICJhcHBseV9kaWZmIjogcmUuY29tcGlsZShyJzxhcHBseV9kaWZmPi4qPzwvYXBwbHlfZGlmZj4nLCByZS5ET1RBTEwpLAogICAgICAgICJleGVjdXRlX2NvbW1hbmQiOiByZS5jb21waWxlKHInPGV4ZWN1dGVfY29tbWFuZD4uKj88L2V4ZWN1dGVfY29tbWFuZD4nLCByZS5ET1RBTEwpLAogICAgICAgICJicm93c2VyX2FjdGlvbiI6IHJlLmNvbXBpbGUocic8YnJvd3Nlcl9hY3Rpb24+Lio/PC9icm93c2VyX2FjdGlvbj4nLCByZS5ET1RBTEwpLAogICAgICAgICJzd2l0Y2hfbW9kZSI6IHJlLmNvbXBpbGUocic8c3dpdGNoX21vZGU+Lio/PC9zd2l0Y2hfbW9kZT4nLCByZS5ET1RBTEwpLAogICAgICAgICJ1c2VfbWNwX3Rvb2wiOiByZS5jb21waWxlKHInPHVzZV9tY3BfdG9vbD4uKj88L3VzZV9tY3BfdG9vbD4nLCByZS5ET1RBTEwpLAogICAgICAgICJhY2Nlc3NfbWNwX3Jlc291cmNlIjogcmUuY29tcGlsZShyJzxhY2Nlc3NfbWNwX3Jlc291cmNlPi4qPzwvYWNjZXNzX21jcF9yZXNvdXJjZT4nLCByZS5ET1RBTEwpLAogICAgICAgICJpbnNlcnRfY29udGVudCI6IHJlLmNvbXBpbGUocic8aW5zZXJ0X2NvbnRlbnQ+Lio/PC9pbnNlcnRfY29udGVudD5ccyonLCByZS5ET1RBTEwpLAogICAgICAgICJzZWFyY2hfYW5kX3JlcGxhY2UiOiByZS5jb21waWxlKHInPHNlYXJjaF9hbmRfcmVwbGFjZT4uKj88L3NlYXJjaF9hbmRfcmVwbGFjZT5ccyonLCByZS5ET1RBTEwpLAogICAgICAgIAogICAgICAgICMgVG9vbCB1c2VzIHRvIGtlZXAgdGhlIHF1ZXN0aW9uCiAgICAgICAgImFza19mb2xsb3d1cF9xdWVzdGlvbiI6IHJlLmNvbXBpbGUocic8YXNrX2ZvbGxvd3VwX3F1ZXN0aW9uPlxzKjxxdWVzdGlvbj4oLio/KTwvcXVlc3Rpb24+Lio/PC9hc2tfZm9sbG93dXBfcXVlc3Rpb24+JywgcmUuRE9UQUxMKSwKICAgICAgICAKICAgICAgICAjIFRvb2wgdXNlcyB0byByZW1vdmUgY29tcGxldGVseQogICAgICAgICJyZWFkX2ZpbGUiOiByZS5jb21waWxlKHInPHJlYWRfZmlsZT4uKj88L3JlYWRfZmlsZT5ccyonLCByZS5ET1RBTEwpLAogICAgICAgICJsaXN0X2ZpbGVzIjogcmUuY29tcGlsZShyJzxsaXN0X2ZpbGVzPi4qPzwvbGlzdF9maWxlcz5ccyonLCByZS5ET1RBTEwpLAogICAgICAgICJzZWFyY2hfZmlsZXMiOiByZS5jb21waWxlKHInPHNlYXJjaF9maWxlcz4uKj88L3NlYXJjaF9maWxlcz5ccyonLCByZS5ET1RBTEwpLAogICAgICAgICJsaXN0X2NvZGVfZGVmaW5pdGlvbl9uYW1lcyI6IHJlLmNvbXBpbGUocic8bGlzdF9jb2RlX2RlZmluaXRpb25fbmFtZXM+Lio/PC9saXN0X2NvZGVfZGVmaW5pdGlvbl9uYW1lcz5ccyonLCByZS5ET1RBTEwpLAogICAgfSwKICAgIAogICAgIyBDb2RlIGZvcm1hdHRpbmcKICAgICJsaW5lX251bWJlcnMiOiByZS5jb21waWxlKHInXlxzKlxkKyBcfCcsIHJlLk1VTFRJTElORSksCiAgICAKICAgICMgRHVwbGljYXRlZCByZXNwb25zZXMKICAgICJzeXN0ZW1fZXJyb3JfbWVzc2FnZXMiOiByZS5jb21waWxlKHInXFtFUlJPUlxdLio/ZW5zdXJlIHByb3BlciBwYXJzaW5nIGFuZCBleGVjdXRpb24uKj9OZXh0IFN0ZXBzJywgcmUuRE9UQUxMKSwKfQoKCmRlZiBleHRyYWN0X2NvbnZlcnNhdGlvbihmaWxlX3BhdGg6IHN0cikgLT4gTGlzdFtUdXBsZVtzdHIsIHN0cl1dOgogICAgIiIiRXh0cmFjdCB0aGUgY29udmVyc2F0aW9uIGZyb20gYSBDbGluZSB0YXNrIGZpbGUuIiIiCiAgICB3aXRoIG9wZW4oZmlsZV9wYXRoLCAncicsIGVuY29kaW5nPSd1dGYtOCcpIGFzIGY6CiAgICAgICAgY29udGVudCA9IGYucmVhZCgpCiAgICAKICAgICMgUGF0dGVybiBvcHRpbWl6ZWQgZm9yIFJvby1Db2RlJ3MgZXhwb3J0IGZvcm1hdAogICAgIyBGb3JtYXQ6ICIqKlVzZXI6KioiIG9yICIqKkFzc2lzdGFudDoqKiIgZm9sbG93ZWQgYnkgY29udGVudCBhbmQgc2VwYXJhdGVkIGJ5ICItLS0iCiAgICBwYXR0ZXJuID0gcidcKlwqKFVzZXJ8QXNzaXN0YW50KTpcKlwqXG5cbiguKj8pKD89XG4tLS1cblxuXCpcKig/OlVzZXJ8QXNzaXN0YW50KTpcKlwqfFxaKScKICAgIAogICAgY29udmVyc2F0aW9uID0gW10KICAgIGZvciBtYXRjaCBpbiByZS5maW5kaXRlcihwYXR0ZXJuLCBjb250ZW50LCByZS5ET1RBTEwpOgogICAgICAgIHNwZWFrZXIgPSBtYXRjaC5ncm91cCgxKQogICAgICAgIG1lc3NhZ2UgPSBtYXRjaC5ncm91cCgyKQogICAgICAgIAogICAgICAgICMgQ2xlYW4gdGhlIG1lc3NhZ2UgYmFzZWQgb24gc3BlYWtlciB0eXBlCiAgICAgICAgaWYgc3BlYWtlciA9PSAnVXNlcic6CiAgICAgICAgICAgIGNsZWFuX21lc3NhZ2UgPSBjbGVhbl91c2VyX21lc3NhZ2UobWVzc2FnZSkKICAgICAgICBlbHNlOgogICAgICAgICAgICBjbGVhbl9tZXNzYWdlID0gY2xlYW5fYXNzaXN0YW50X21lc3NhZ2UobWVzc2FnZSkKICAgICAgICAKICAgICAgICAjIFZlcmlmeSB3ZSBoYXZlIGNvbnRlbnQgYWZ0ZXIgY2xlYW5pbmcKICAgICAgICBpZiBjbGVhbl9tZXNzYWdlLnN0cmlwKCk6CiAgICAgICAgICAgIGNvbnZlcnNhdGlvbi5hcHBlbmQoKHNwZWFrZXIsIGNsZWFuX21lc3NhZ2UpKQogICAgCiAgICByZXR1cm4gY29udmVyc2F0aW9uCgoKZGVmIGNsZWFuX3VzZXJfbWVzc2FnZShtZXNzYWdlOiBzdHIpIC0+IHN0cjoKICAgICIiIkNsZWFuIGEgdXNlciBtZXNzYWdlIGJ5IHJlbW92aW5nIGZpbGUgY29udGVudCBhbmQga2VlcGluZyBlc3NlbnRpYWwgcGFydHMuIiIiCiAgICAjIFJlbW92ZSBlbnZpcm9ubWVudCBkZXRhaWxzCiAgICBtZXNzYWdlID0gUEFUVEVSTlNbImVudmlyb25tZW50X2RldGFpbHMiXS5zdWIoJycsIG1lc3NhZ2UpCiAgICAKICAgICMgUmVtb3ZlIHRvb2wgcmVzdWx0IHNlY3Rpb25zCiAgICBtZXNzYWdlID0gUEFUVEVSTlNbInRvb2xfcmVzdWx0Il0uc3ViKCcnLCBtZXNzYWdlKQogICAgCiAgICAjIFJlbW92ZSBmaWxlIGNvbnRlbnQgYmxvY2tzCiAgICBtZXNzYWdlID0gUEFUVEVSTlNbImZpbGVfY29udGVudF90YWciXS5zdWIoJycsIG1lc3NhZ2UpCiAgICAKICAgICMgUmVtb3ZlIFJvby1Db2RlIHNwZWNpZmljIHBhdHRlcm5zCiAgICBtZXNzYWdlID0gUEFUVEVSTlNbInJvb190b29sX3VzZSJdLnN1YignJywgbWVzc2FnZSkKICAgIG1lc3NhZ2UgPSBQQVRURVJOU1sicm9vX3Rvb2xfcmVzdWx0Il0uc3ViKCcnLCBtZXNzYWdlKQogICAgbWVzc2FnZSA9IFBBVFRFUk5TWyJyb29faW1hZ2VfcmVmZXJlbmNlIl0uc3ViKCcnLCBtZXNzYWdlKQogICAgCiAgICAjIFByZXNlcnZlIGNvbnRlbnQgYnV0IHJlbW92ZSB0YWdzCiAgICBtZXNzYWdlID0gUEFUVEVSTlNbInRhc2tfdGFnIl0uc3ViKHInXDEnLCBtZXNzYWdlKQogICAgbWVzc2FnZSA9IFBBVFRFUk5TWyJmZWVkYmFja190YWciXS5zdWIocidcMScsIG1lc3NhZ2UpCiAgICBtZXNzYWdlID0gUEFUVEVSTlNbInVzZXJfbWVzc2FnZV90YWciXS5zdWIocidcMScsIG1lc3NhZ2UpCiAgICBtZXNzYWdlID0gUEFUVEVSTlNbImFuc3dlcl90YWciXS5zdWIocidcMScsIG1lc3NhZ2UpCiAgICAKICAgICMgUmVtb3ZlIGxpbmUgbnVtYmVycyBpbiBjb2RlIGJsb2NrcwogICAgbWVzc2FnZSA9IFBBVFRFUk5TWyJsaW5lX251bWJlcnMiXS5zdWIoJycsIG1lc3NhZ2UpCiAgICAKICAgICMgUmVtb3ZlIHN5c3RlbSBlcnJvciBtZXNzYWdlcwogICAgbWVzc2FnZSA9IFBBVFRFUk5TWyJzeXN0ZW1fZXJyb3JfbWVzc2FnZXMiXS5zdWIoJycsIG1lc3NhZ2UpCiAgICAKICAgICMgUmVtb3ZlIGZpbGUgb3V0cHV0IGJsb2NrcwogICAgbWVzc2FnZSA9IFBBVFRFUk5TWyJmaWxlX291dHB1dF9ibG9ja3MiXS5zdWIoJycsIG1lc3NhZ2UpCiAgICAKICAgICMgUmVtb3ZlIGZpbGUgcGF0aCByZWZlcmVuY2VzCiAgICBtZXNzYWdlID0gUEFUVEVSTlNbImZpbGVfcGF0aF9yZWZlcmVuY2VzIl0uc3ViKCcnLCBtZXNzYWdlKQogICAgCiAgICAjIENsZWFuIHVwIHdoaXRlc3BhY2UKICAgIG1lc3NhZ2UgPSByZS5zdWIocidcbnszLH0nLCAnXG5cbicsIG1lc3NhZ2UpCiAgICBtZXNzYWdlID0gcmUuc3ViKHInWyBcdF0rXG4nLCAnXG4nLCBtZXNzYWdlKQogICAgbWVzc2FnZSA9IHJlLnN1YihyJ1xuK1sgXHRdK1xuKycsICdcblxuJywgbWVzc2FnZSkKICAgIAogICAgcmV0dXJuIG1lc3NhZ2Uuc3RyaXAoKQoKCmRlZiBjbGVhbl9hc3Npc3RhbnRfbWVzc2FnZShtZXNzYWdlOiBzdHIpIC0+IHN0cjoKICAgICIiIkNsZWFuIGFuIGFzc2lzdGFudCBtZXNzYWdlIGJ5IHJlbW92aW5nIHRvb2wgdXNhZ2UgYW5kIGtlZXBpbmcgdGhvdWdodCBwcm9jZXNzLiIiIgogICAgIyBQcm9jZXNzIHRoaW5raW5nIHNlY3Rpb25zIHdpdGhvdXQgcmVtb3ZpbmcgdGhlbQogICAgZGVmIGNsZWFuX3RoaW5raW5nX3NlY3Rpb24obWF0Y2hfb2JqKToKICAgICAgICBzZWN0aW9uID0gbWF0Y2hfb2JqLmdyb3VwKDEpICAjIEV4dHJhY3QgY29udGVudCBpbnNpZGUgdGhpbmtpbmcgdGFncwogICAgICAgICMgQ2xlYW4gdGhlIHRoaW5raW5nIHNlY3Rpb24gY29udGVudAogICAgICAgIGNsZWFuZWRfdGhpbmtpbmcgPSByZS5zdWIoUEFUVEVSTlNbImZpbGVfY29udGVudF90YWciXSwgJycsIHNlY3Rpb24pCiAgICAgICAgY2xlYW5lZF90aGlua2luZyA9IHJlLnN1YihQQVRURVJOU1siZmlsZV9vdXRwdXRfYmxvY2tzIl0sICcnLCBjbGVhbmVkX3RoaW5raW5nKQogICAgICAgIGNsZWFuZWRfdGhpbmtpbmcgPSByZS5zdWIoUEFUVEVSTlNbImZpbGVfcGF0aF9yZWZlcmVuY2VzIl0sICcnLCBjbGVhbmVkX3RoaW5raW5nKQogICAgICAgIHJldHVybiBmIjx0aGlua2luZz57Y2xlYW5lZF90aGlua2luZ308L3RoaW5raW5nPiIKICAgIAogICAgIyBBcHBseSB0aGUgY2xlYW5pbmcgZnVuY3Rpb24gdG8gYWxsIHRoaW5raW5nIHNlY3Rpb25zCiAgICBtZXNzYWdlID0gUEFUVEVSTlNbInRoaW5raW5nIl0uc3ViKGNsZWFuX3RoaW5raW5nX3NlY3Rpb24sIG1lc3NhZ2UpCiAgICAKICAgICMgRXh0cmFjdCByZXN1bHQgY29udGVudCBmcm9tIGF0dGVtcHRfY29tcGxldGlvbgogICAgbWVzc2FnZSA9IFBBVFRFUk5TWyJhdHRlbXB0X2NvbXBsZXRpb24iXS5zdWIocidcMScsIG1lc3NhZ2UpCiAgICAKICAgICMgUmVtb3ZlIHRvb2wgdXNlcwogICAgZm9yIHRvb2xfbmFtZSwgcGF0dGVybiBpbiBQQVRURVJOU1sidG9vbF91c2VfcGF0dGVybnMiXS5pdGVtcygpOgogICAgICAgIGlmIHRvb2xfbmFtZSA9PSAiYXNrX2ZvbGxvd3VwX3F1ZXN0aW9uIjoKICAgICAgICAgICAgIyBLZWVwIGp1c3QgdGhlIHF1ZXN0aW9uIGZvciB0aGlzIHRvb2wKICAgICAgICAgICAgbWVzc2FnZSA9IHBhdHRlcm4uc3ViKHInXDEnLCBtZXNzYWdlKQogICAgICAgIGVsc2U6CiAgICAgICAgICAgICMgUmVtb3ZlIG90aGVyIHRvb2wgdXNlcyBjb21wbGV0ZWx5CiAgICAgICAgICAgIG1lc3NhZ2UgPSBwYXR0ZXJuLnN1YignJywgbWVzc2FnZSkKICAgIAogICAgIyBSZW1vdmUgUm9vLUNvZGUgc3BlY2lmaWMgcGF0dGVybnMKICAgIG1lc3NhZ2UgPSBQQVRURVJOU1sicm9vX3Rvb2xfdXNlIl0uc3ViKCcnLCBtZXNzYWdlKQogICAgbWVzc2FnZSA9IFBBVFRFUk5TWyJyb29fdG9vbF9yZXN1bHQiXS5zdWIoJycsIG1lc3NhZ2UpCiAgICBtZXNzYWdlID0gUEFUVEVSTlNbInJvb19pbWFnZV9yZWZlcmVuY2UiXS5zdWIoJycsIG1lc3NhZ2UpCiAgICAKICAgICMgUmVtb3ZlIGZpbGUgY29udGVudCBibG9ja3MKICAgIG1lc3NhZ2UgPSBQQVRURVJOU1siZmlsZV9jb250ZW50X3RhZyJdLnN1YignJywgbWVzc2FnZSkKICAgIAogICAgIyBSZW1vdmUgbGluZSBudW1iZXJzIGluIGNvZGUgYmxvY2tzCiAgICBtZXNzYWdlID0gUEFUVEVSTlNbImxpbmVfbnVtYmVycyJdLnN1YignJywgbWVzc2FnZSkKICAgIAogICAgIyBSZW1vdmUgc3lzdGVtIGVycm9yIG1lc3NhZ2VzCiAgICBtZXNzYWdlID0gUEFUVEVSTlNbInN5c3RlbV9lcnJvcl9tZXNzYWdlcyJdLnN1YignJywgbWVzc2FnZSkKICAgIAogICAgIyBSZW1vdmUgZmlsZSBvdXRwdXQgYmxvY2tzCiAgICBtZXNzYWdlID0gUEFUVEVSTlNbImZpbGVfb3V0cHV0X2Jsb2NrcyJdLnN1YignJywgbWVzc2FnZSkKICAgIAogICAgIyBSZW1vdmUgZmlsZSBwYXRoIHJlZmVyZW5jZXMKICAgIG1lc3NhZ2UgPSBQQVRURVJOU1siZmlsZV9wYXRoX3JlZmVyZW5jZXMiXS5zdWIoJycsIG1lc3NhZ2UpCiAgICAKICAgICMgQ2xlYW4gdXAgd2hpdGVzcGFjZQogICAgbWVzc2FnZSA9IHJlLnN1YihyJ1xuezMsfScsICdcblxuJywgbWVzc2FnZSkKICAgIG1lc3NhZ2UgPSByZS5zdWIocidbIFx0XStcbicsICdcbicsIG1lc3NhZ2UpCiAgICBtZXNzYWdlID0gcmUuc3ViKHInXG4rWyBcdF0rXG4rJywgJ1xuXG4nLCBtZXNzYWdlKQogICAgCiAgICByZXR1cm4gbWVzc2FnZS5zdHJpcCgpCgoKZGVmIHJlbW92ZV9kdXBsaWNhdGVzKGNvbnRlbnQ6IHN0cikgLT4gc3RyOgogICAgIiIiUmVtb3ZlIGR1cGxpY2F0ZSBwYXJhZ3JhcGhzIGFuZCBzZWN0aW9ucyBpbiBjb250ZW50LiIiIgogICAgIyBTcGxpdCBieSBwYXJhZ3JhcGgKICAgIHBhcmFncmFwaHMgPSByZS5zcGxpdChyJ1xuXG4rJywgY29udGVudCkKICAgIAogICAgIyBVc2UgYSBzZXQgdG8gdHJhY2sgc2VlbiBwYXJhZ3JhcGhzCiAgICBzZWVuID0gc2V0KCkKICAgIHVuaXF1ZV9wYXJhZ3JhcGhzID0gW10KICAgIAogICAgZm9yIHBhcmFncmFwaCBpbiBwYXJhZ3JhcGhzOgogICAgICAgICMgU2tpcCB2ZXJ5IHNob3J0IHBhcmFncmFwaHMgb3IgZW1wdHkgb25lcwogICAgICAgIGlmIGxlbihwYXJhZ3JhcGguc3RyaXAoKSkgPCAxMDoKICAgICAgICAgICAgdW5pcXVlX3BhcmFncmFwaHMuYXBwZW5kKHBhcmFncmFwaCkKICAgICAgICAgICAgY29udGludWUKICAgICAgICAgICAgCiAgICAgICAgIyBDcmVhdGUgYSBzaW1wbGlmaWVkIHZlcnNpb24gZm9yIGNvbXBhcmlzb24gKGxvd2VyY2FzZSwgbm8gc3BhY2VzKQogICAgICAgIHNpbXBsaWZpZWQgPSByZS5zdWIocidccysnLCAnJywgcGFyYWdyYXBoLmxvd2VyKCkpCiAgICAgICAgCiAgICAgICAgIyBDaGVjayBpZiB3ZSd2ZSBzZWVuIHNvbWV0aGluZyB2ZXJ5IHNpbWlsYXIKICAgICAgICBpZiBzaW1wbGlmaWVkIG5vdCBpbiBzZWVuOgogICAgICAgICAgICBzZWVuLmFkZChzaW1wbGlmaWVkKQogICAgICAgICAgICB1bmlxdWVfcGFyYWdyYXBocy5hcHBlbmQocGFyYWdyYXBoKQogICAgCiAgICByZXR1cm4gJ1xuXG4nLmpvaW4odW5pcXVlX3BhcmFncmFwaHMpCgoKZGVmIHNhdmVfY2xlYW5fY29udmVyc2F0aW9uKGNvbnZlcnNhdGlvbjogTGlzdFtUdXBsZVtzdHIsIHN0cl1dLCBvdXRwdXRfZmlsZTogc3RyLCBpbnB1dF9maWxlOiBzdHIpOgogICAgIiIiU2F2ZSB0aGUgY2xlYW5lZCBjb252ZXJzYXRpb24gdG8gYSBmaWxlLiIiIgogICAgd2l0aCBvcGVuKG91dHB1dF9maWxlLCAndycsIGVuY29kaW5nPSd1dGYtOCcpIGFzIGY6CiAgICAgICAgZm9yIGksIChzcGVha2VyLCBtZXNzYWdlKSBpbiBlbnVtZXJhdGUoY29udmVyc2F0aW9uKToKICAgICAgICAgICAgaWYgaSA+IDA6CiAgICAgICAgICAgICAgICBmLndyaXRlKCJcbi0tLVxuXG4iKQogICAgICAgICAgICBmLndyaXRlKGYiKip7c3BlYWtlcn06Kipcblxue21lc3NhZ2V9IikKICAgIAogICAgIyBDb3VudCB0b2tlbnMgaW4gb3JpZ2luYWwgYW5kIGNsZWFuZWQgZmlsZXMKICAgIG9yaWdpbmFsX3NpemUgPSBvcy5wYXRoLmdldHNpemUoaW5wdXRfZmlsZSkKICAgIGNsZWFuZWRfc2l6ZSA9IG9zLnBhdGguZ2V0c2l6ZShvdXRwdXRfZmlsZSkKICAgIHJlZHVjdGlvbiA9ICgob3JpZ2luYWxfc2l6ZSAtIGNsZWFuZWRfc2l6ZSkgLyBvcmlnaW5hbF9zaXplKSAqIDEwMAogICAgCiAgICByZXR1cm4gewogICAgICAgICJvcmlnaW5hbF9zaXplX2J5dGVzIjogb3JpZ2luYWxfc2l6ZSwKICAgICAgICAiY2xlYW5lZF9zaXplX2J5dGVzIjogY2xlYW5lZF9zaXplLAogICAgICAgICJyZWR1Y3Rpb25fcGVyY2VudGFnZSI6IHJvdW5kKHJlZHVjdGlvbiwgMikKICAgIH0KCgpkZWYgbWFpbigpOgogICAgIiIiTWFpbiBmdW5jdGlvbiB0byBwYXJzZSBhcmd1bWVudHMgYW5kIHJ1biB0aGUgc2NyaXB0LiIiIgogICAgaWYgbGVuKHN5cy5hcmd2KSA8IDI6CiAgICAgICAgcHJpbnQoIlVzYWdlOiBweXRob24gZXh0cmFjdF9jb252ZXJzYXRpb25fc2ltcGxlLnB5IGlucHV0X2ZpbGUgW291dHB1dF9maWxlXSIpCiAgICAgICAgcmV0dXJuCiAgICAKICAgIGlucHV0X2ZpbGUgPSBzeXMuYXJndlsxXQogICAgCiAgICAjIEdlbmVyYXRlIGRlZmF1bHQgb3V0cHV0IGZpbGVuYW1lIGlmIG5vdCBzcGVjaWZpZWQKICAgIGlmIGxlbihzeXMuYXJndikgPj0gMzoKICAgICAgICBvdXRwdXRfZmlsZSA9IHN5cy5hcmd2WzJdCiAgICBlbHNlOgogICAgICAgIGlucHV0X3BhdGggPSBQYXRoKGlucHV0X2ZpbGUpCiAgICAgICAgb3V0cHV0X2ZpbGUgPSBzdHIoaW5wdXRfcGF0aC53aXRoX25hbWUoZiJ7aW5wdXRfcGF0aC5zdGVtfV9jbGVhbntpbnB1dF9wYXRoLnN1ZmZpeH0iKSkKICAgIAogICAgIyBFeHRyYWN0IGFuZCBjbGVhbiBjb252ZXJzYXRpb24KICAgIGNvbnZlcnNhdGlvbiA9IGV4dHJhY3RfY29udmVyc2F0aW9uKGlucHV0X2ZpbGUpCiAgICAKICAgICMgQXBwbHkgZHVwbGljYXRlIHJlbW92YWwgdG8gZWFjaCBtZXNzYWdlCiAgICBjbGVhbmVkX2NvbnZlcnNhdGlvbiA9IFtdCiAgICBmb3Igc3BlYWtlciwgbWVzc2FnZSBpbiBjb252ZXJzYXRpb246CiAgICAgICAgY2xlYW5lZF9tZXNzYWdlID0gcmVtb3ZlX2R1cGxpY2F0ZXMobWVzc2FnZSkKICAgICAgICBjbGVhbmVkX2NvbnZlcnNhdGlvbi5hcHBlbmQoKHNwZWFrZXIsIGNsZWFuZWRfbWVzc2FnZSkpCiAgICAKICAgICMgU2F2ZSBjbGVhbmVkIGNvbnZlcnNhdGlvbgogICAgbWV0cmljcyA9IHNhdmVfY2xlYW5fY29udmVyc2F0aW9uKGNsZWFuZWRfY29udmVyc2F0aW9uLCBvdXRwdXRfZmlsZSwgaW5wdXRfZmlsZSkKICAgIAogICAgcHJpbnQoZiJDbGVhbmVkIGNvbnZlcnNhdGlvbiB3aXRoIHtsZW4oY2xlYW5lZF9jb252ZXJzYXRpb24pfSBtZXNzYWdlcyBzYXZlZCB0byB7b3V0cHV0X2ZpbGV9IikKICAgIHByaW50KGYiU2l6ZSByZWR1Y3Rpb246IHttZXRyaWNzWydvcmlnaW5hbF9zaXplX2J5dGVzJ106LH0gYnl0ZXMg4oaSIHttZXRyaWNzWydjbGVhbmVkX3NpemVfYnl0ZXMnXTosfSBieXRlcyAoe21ldHJpY3NbJ3JlZHVjdGlvbl9wZXJjZW50YWdlJ119JSkiKQoKCmlmIF9fbmFtZV9fID09ICJfX21haW5fXyI6CiAgICBtYWluKCk=",
"handoffs/0-system/scripts/2-create-milestone.js": "IyEvdXNyL2Jpbi9lbnYgbm9kZQovKioKICogTWlsZXN0b25lIENyZWF0aW9uIFNjcmlwdCAoTm9kZS5qcykKICogQ3JlYXRlcyBhIG5ldyBtaWxlc3RvbmUgZGlyZWN0b3J5IGFuZCBtb3ZlcyBoYW5kb2ZmIGZpbGVzCiAqIAogKiBVc2FnZToKICogICBub2RlIGNyZWF0ZS1taWxlc3RvbmUuanMgW21pbGVzdG9uZS1uYW1lXQogKi8KCmNvbnN0IGZzID0gcmVxdWlyZSgnZnMnKTsKY29uc3QgcGF0aCA9IHJlcXVpcmUoJ3BhdGgnKTsKY29uc3QgcmVhZGxpbmUgPSByZXF1aXJlKCdyZWFkbGluZScpOwoKLy8gQ3JlYXRlIHJlYWRsaW5lIGludGVyZmFjZSBmb3IgdXNlciBpbnB1dApjb25zdCBybCA9IHJlYWRsaW5lLmNyZWF0ZUludGVyZmFjZSh7CiAgaW5wdXQ6IHByb2Nlc3Muc3RkaW4sCiAgb3V0cHV0OiBwcm9jZXNzLnN0ZG91dAp9KTsKCi8qKgogKiBDcmVhdGVzIGEgbWlsZXN0b25lIGRpcmVjdG9yeSBhbmQgbW92ZXMgaGFuZG9mZiBmaWxlcwogKiBAcGFyYW0ge3N0cmluZ30gbWlsZXN0b25lTmFtZSAtIE5hbWUgZm9yIHRoZSBtaWxlc3RvbmUKICovCmFzeW5jIGZ1bmN0aW9uIGNyZWF0ZU1pbGVzdG9uZShtaWxlc3RvbmVOYW1lKSB7CiAgdHJ5IHsKICAgIC8vIEdldCB0aGUgbmV4dCBtaWxlc3RvbmUgbnVtYmVyCiAgICBjb25zdCBoYW5kb2Zmc0RpciA9ICdoYW5kb2Zmcyc7CiAgICAKICAgIC8vIENoZWNrIGlmIGhhbmRvZmZzIGRpcmVjdG9yeSBleGlzdHMKICAgIGlmICghZnMuZXhpc3RzU3luYyhoYW5kb2Zmc0RpcikpIHsKICAgICAgY29uc29sZS5lcnJvcihgRXJyb3I6IERpcmVjdG9yeSAnJHtoYW5kb2Zmc0Rpcn0nIG5vdCBmb3VuZGApOwogICAgICBwcm9jZXNzLmV4aXQoMSk7CiAgICB9CiAgICAKICAgIC8vIEZpbmQgbWlsZXN0b25lIGRpcmVjdG9yaWVzCiAgICBjb25zdCBkaXJzID0gZnMucmVhZGRpclN5bmMoaGFuZG9mZnNEaXIpCiAgICAgIC5maWx0ZXIoZCA9PiBmcy5zdGF0U3luYyhwYXRoLmpvaW4oaGFuZG9mZnNEaXIsIGQpKS5pc0RpcmVjdG9yeSgpICYmIC9eXGQrLS8udGVzdChkKSk7CiAgICAKICAgIC8vIERldGVybWluZSBuZXh0IG1pbGVzdG9uZSBudW1iZXIKICAgIGxldCBuZXh0TnVtID0gMTsKICAgIGlmIChkaXJzLmxlbmd0aCA+IDApIHsKICAgICAgLy8gRXh0cmFjdCBudW1iZXJzIGZyb20gZGlyZWN0b3J5IG5hbWVzIGFuZCBmaW5kIHRoZSBoaWdoZXN0CiAgICAgIGNvbnN0IG1heE51bSA9IE1hdGgubWF4KC4uLmRpcnMubWFwKGQgPT4gcGFyc2VJbnQoZC5tYXRjaCgvXihcZCspLS8pWzFdKSB8fCAwKSk7CiAgICAgIG5leHROdW0gPSBtYXhOdW0gKyAxOwogICAgfQogICAgCiAgICAvLyBJZiBtaWxlc3RvbmUgbmFtZSB3YXNuJ3QgcHJvdmlkZWQsIHByb21wdCBmb3IgaXQKICAgIGlmICghbWlsZXN0b25lTmFtZSkgewogICAgICBtaWxlc3RvbmVOYW1lID0gYXdhaXQgbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7CiAgICAgICAgcmwucXVlc3Rpb24oJ0VudGVyIG1pbGVzdG9uZSBuYW1lOiAnLCBhbnN3ZXIgPT4gcmVzb2x2ZShhbnN3ZXIpKTsKICAgICAgfSk7CiAgICB9CiAgICAKICAgIC8vIENyZWF0ZSBtaWxlc3RvbmUgZGlyZWN0b3J5CiAgICBjb25zdCBtaWxlc3RvbmVEaXIgPSBwYXRoLmpvaW4oaGFuZG9mZnNEaXIsIGAke25leHROdW19LSR7bWlsZXN0b25lTmFtZX1gKTsKICAgIGZzLm1rZGlyU3luYyhtaWxlc3RvbmVEaXIsIHsgcmVjdXJzaXZlOiB0cnVlIH0pOwogICAgY29uc29sZS5sb2coYENyZWF0ZWQgbWlsZXN0b25lIGRpcmVjdG9yeTogJHttaWxlc3RvbmVEaXJ9YCk7CiAgICAKICAgIC8vIEZpbmQgaGFuZG9mZiBmaWxlcwogICAgY29uc3QgaGFuZG9mZkZpbGVzID0gZnMucmVhZGRpclN5bmMoaGFuZG9mZnNEaXIpCiAgICAgIC5maWx0ZXIoZiA9PiAvXlsxLTldLipcLm1kJC8udGVzdChmKSAmJiBmcy5zdGF0U3luYyhwYXRoLmpvaW4oaGFuZG9mZnNEaXIsIGYpKS5pc0ZpbGUoKSk7CiAgICAKICAgIC8vIE1vdmUgaGFuZG9mZiBmaWxlcwogICAgbGV0IG1vdmVkQ291bnQgPSAwOwogICAgZm9yIChjb25zdCBmaWxlIG9mIGhhbmRvZmZGaWxlcykgewogICAgICBjb25zdCBzcmNQYXRoID0gcGF0aC5qb2luKGhhbmRvZmZzRGlyLCBmaWxlKTsKICAgICAgY29uc3QgZGVzdFBhdGggPSBwYXRoLmpvaW4obWlsZXN0b25lRGlyLCBmaWxlKTsKICAgICAgZnMucmVuYW1lU3luYyhzcmNQYXRoLCBkZXN0UGF0aCk7CiAgICAgIG1vdmVkQ291bnQrKzsKICAgIH0KICAgIAogICAgY29uc29sZS5sb2coYE1vdmVkICR7bW92ZWRDb3VudH0gaGFuZG9mZiBmaWxlcyB0byBtaWxlc3RvbmUgZGlyZWN0b3J5YCk7CiAgICBjb25zb2xlLmxvZyhgTWlsZXN0b25lICR7bmV4dE51bX0tJHttaWxlc3RvbmVOYW1lfSBjcmVhdGVkIHN1Y2Nlc3NmdWxseS5gKTsKICAgIGNvbnNvbGUubG9nKGBEb24ndCBmb3JnZXQgdG8gY3JlYXRlIDAtbWlsZXN0b25lLXN1bW1hcnkubWQgYW5kIDAtbGVzc29ucy1sZWFybmVkLm1kIGZpbGVzIGluIHRoZSBtaWxlc3RvbmUgZGlyZWN0b3J5LmApOwogICAgCiAgICBybC5jbG9zZSgpOwogIH0gY2F0Y2ggKGVycm9yKSB7CiAgICBjb25zb2xlLmVycm9yKGBFcnJvciBjcmVhdGluZyBtaWxlc3RvbmU6ICR7ZXJyb3IubWVzc2FnZX1gKTsKICAgIHJsLmNsb3NlKCk7CiAgICBwcm9jZXNzLmV4aXQoMSk7CiAgfQp9CgovLyBHZXQgbWlsZXN0b25lIG5hbWUgZnJvbSBjb21tYW5kIGxpbmUgYXJndW1lbnRzCmNvbnN0IG1pbGVzdG9uZU5hbWUgPSBwcm9jZXNzLmFyZ3ZbMl07CgovLyBDYWxsIHRoZSBmdW5jdGlvbgpjcmVhdGVNaWxlc3RvbmUobWlsZXN0b25lTmFtZSk7",
"handoffs/0-system/scripts/2-create-milestone.py": "IyEvdXNyL2Jpbi9lbnYgcHl0aG9uMwoiIiIKTWlsZXN0b25lIENyZWF0aW9uIFNjcmlwdCAoUHl0aG9uKQpDcmVhdGVzIGEgbmV3IG1pbGVzdG9uZSBkaXJlY3RvcnkgYW5kIG1vdmVzIGhhbmRvZmYgZmlsZXMKIiIiCgppbXBvcnQgb3MKaW1wb3J0IHJlCmltcG9ydCBzaHV0aWwKaW1wb3J0IHN5cwoKZGVmIGNyZWF0ZV9taWxlc3RvbmUobWlsZXN0b25lX25hbWU9Tm9uZSk6CiAgICAiIiJDcmVhdGUgYSBtaWxlc3RvbmUgZGlyZWN0b3J5IGFuZCBtb3ZlIGhhbmRvZmYgZmlsZXMgdG8gaXQuIiIiCiAgICAjIEdldCB0aGUgbmV4dCBtaWxlc3RvbmUgbnVtYmVyCiAgICBtaWxlc3RvbmVfZGlycyA9IFtkIGZvciBkIGluIG9zLmxpc3RkaXIoImhhbmRvZmZzIikgCiAgICAgICAgICAgICAgICAgICAgIGlmIG9zLnBhdGguaXNkaXIob3MucGF0aC5qb2luKCJoYW5kb2ZmcyIsIGQpKSAKICAgICAgICAgICAgICAgICAgICAgYW5kIHJlLm1hdGNoKHIiXGQrLSIsIGQpXQogICAgCiAgICBpZiBub3QgbWlsZXN0b25lX2RpcnM6CiAgICAgICAgbmV4dF9udW0gPSAxICAjIFN0YXJ0IHdpdGggMSBpZiBubyBtaWxlc3RvbmUgZGlyZWN0b3JpZXMgZXhpc3QKICAgIGVsc2U6CiAgICAgICAgIyBFeHRyYWN0IG51bWJlcnMgZnJvbSBkaXJlY3RvcnkgbmFtZXMgYW5kIGZpbmQgdGhlIGhpZ2hlc3QKICAgICAgICBtYXhfbnVtID0gbWF4KFtpbnQocmUubWF0Y2gociIoXGQrKS0iLCBkKS5ncm91cCgxKSkgZm9yIGQgaW4gbWlsZXN0b25lX2RpcnNdKQogICAgICAgIG5leHRfbnVtID0gbWF4X251bSArIDEKICAgIAogICAgIyBQcm9tcHQgZm9yIG1pbGVzdG9uZSBuYW1lIGlmIG5vdCBwcm92aWRlZAogICAgaWYgbWlsZXN0b25lX25hbWUgaXMgTm9uZToKICAgICAgICBtaWxlc3RvbmVfbmFtZSA9IGlucHV0KCJFbnRlciBtaWxlc3RvbmUgbmFtZTogIikKICAgIAogICAgIyBDcmVhdGUgbWlsZXN0b25lIGRpcmVjdG9yeQogICAgbWlsZXN0b25lX2RpciA9IGYiaGFuZG9mZnMve25leHRfbnVtfS17bWlsZXN0b25lX25hbWV9IgogICAgb3MubWFrZWRpcnMobWlsZXN0b25lX2RpciwgZXhpc3Rfb2s9VHJ1ZSkKICAgIHByaW50KGYiQ3JlYXRlZCBtaWxlc3RvbmUgZGlyZWN0b3J5OiB7bWlsZXN0b25lX2Rpcn0iKQogICAgCiAgICAjIE1vdmUgaGFuZG9mZiBmaWxlcwogICAgaGFuZG9mZl9maWxlcyA9IFtmIGZvciBmIGluIG9zLmxpc3RkaXIoImhhbmRvZmZzIikgCiAgICAgICAgICAgICAgICAgICAgIGlmIHJlLm1hdGNoKHIiWzEtOV0iLCBmKSBhbmQgZi5lbmRzd2l0aCgiLm1kIikgCiAgICAgICAgICAgICAgICAgICAgIGFuZCBvcy5wYXRoLmlzZmlsZShvcy5wYXRoLmpvaW4oImhhbmRvZmZzIiwgZikpXQogICAgCiAgICBmb3IgZmlsZSBpbiBoYW5kb2ZmX2ZpbGVzOgogICAgICAgIHNyYyA9IG9zLnBhdGguam9pbigiaGFuZG9mZnMiLCBmaWxlKQogICAgICAgIGRzdCA9IG9zLnBhdGguam9pbihtaWxlc3RvbmVfZGlyLCBmaWxlKQogICAgICAgIHNodXRpbC5tb3ZlKHNyYywgZHN0KQogICAgCiAgICBwcmludChmIk1vdmVkIHtsZW4oaGFuZG9mZl9maWxlcyl9IGhhbmRvZmYgZmlsZXMgdG8gbWlsZXN0b25lIGRpcmVjdG9yeSIpCiAgICBwcmludChmIk1pbGVzdG9uZSB7bmV4dF9udW19LXttaWxlc3RvbmVfbmFtZX0gY3JlYXRlZCBzdWNjZXNzZnVsbHkuIikKICAgIHByaW50KCJEb24ndCBmb3JnZXQgdG8gY3JlYXRlIDAtbWlsZXN0b25lLXN1bW1hcnkubWQgYW5kIDAtbGVzc29ucy1sZWFybmVkLm1kIGZpbGVzIGluIHRoZSBtaWxlc3RvbmUgZGlyZWN0b3J5LiIpCgppZiBfX25hbWVfXyA9PSAiX19tYWluX18iOgogICAgIyBHZXQgbWlsZXN0b25lIG5hbWUgZnJvbSBjb21tYW5kIGxpbmUgYXJndW1lbnQgaWYgcHJvdmlkZWQKICAgIGlmIGxlbihzeXMuYXJndikgPiAxOgogICAgICAgIGNyZWF0ZV9taWxlc3RvbmUoc3lzLmFyZ3ZbMV0pCiAgICBlbHNlOgogICAgICAgIGNyZWF0ZV9taWxlc3RvbmUoKQ==",
"handoffs/0-system/scripts/README.md": "IyBIYW5kb2ZmIFN5c3RlbSBTY3JpcHRzCgpUaGlzIGRpcmVjdG9yeSBjb250YWlucyBzY3JpcHRzIHRvIGF1dG9tYXRlIGNvbW1vbiB0YXNrcyBpbiB0aGUgSGFuZG9mZiBTeXN0ZW0uCgojIyBDb252ZXJzYXRpb24gRXh0cmFjdGlvbgoKIyMjIDEtZXh0cmFjdC1jb252ZXJzYXRpb24ucHkgJiYgMS1leHRyYWN0LWNvbnZlcnNhdGlvbi5qcyAKClByb2Nlc3NlcyBhbiBleHBvcnRlZCBjb252ZXJzYXRpb24gZmlsZSB0byBjcmVhdGUgYSBjbGVhbiB2ZXJzaW9uIGZvciBoYW5kb2ZmIGNyZWF0aW9uLiBUaGlzIHNjcmlwdCBjb21iaW5lcyBib3RoIFB5dGhvbiBhbmQgSmF2YVNjcmlwdCBhcHByb2FjaGVzIGZvciBtYXhpbXVtIGNvbXBhdGliaWxpdHkuIFRoZSAgcHl0aG9uIHNjcmlwdCB3b3JrcyBzbGlnaHRseSBiZXR0ZXIuIAoKYGBgYmFzaApub2RlIGV4dHJhY3QtY29udmVyc2F0aW9uLmpzIDxjb252ZXJzYXRpb25fZXhwb3J0X2ZpbGU+IFtoYW5kb2Zmc19kaXJdCmBgYAoKYGBgYmFzaApweXRob24gZXh0cmFjdC1jb252ZXJzYXRpb24ucHkgPGNvbnZlcnNhdGlvbl9leHBvcnRfZmlsZT4gW2hhbmRvZmZzX2Rpcl0KYGBgCgpUaGUgc2NyaXB0OgoxLiBEZXRlcm1pbmVzIHRoZSBuZXh0IGhhbmRvZmYgbnVtYmVyCjIuIE5hbWVzIHRoZSBvdXRwdXQgZmlsZSBgPE4+LWNoYXRfdHJhbnNjcmlwdC5tZGAgKGUuZy4sIGA0LWNoYXRfdHJhbnNjcmlwdC5tZGApCjMuIEZpcnN0IHRyaWVzIHRoZSBQeXRob24gZXh0cmFjdGlvbiBzY3JpcHQKNC4gRmFsbHMgYmFjayB0byB0aGUgSmF2YVNjcmlwdCBleHRyYWN0aW9uIHNjcmlwdCBpZiBQeXRob24gZmFpbHMKNS4gU2F2ZXMgdGhlIHJlc3VsdCBpbiB0aGUgaGFuZG9mZnMgZGlyZWN0b3J5CgpUaGlzIGVuc3VyZXMgdGhlIGNvbnZlcnNhdGlvbiBleHRyYWN0IGlzIGF2YWlsYWJsZSBmb3IgdGhlIGhhbmRvZmYgbWFuYWdlciB0byB1c2Ugd2hlbiBjcmVhdGluZyBoYW5kb2ZmIGRvY3VtZW50cy4KCiMjIE1pbGVzdG9uZSBTY3JpcHRzCgpUaGVzZSBzY3JpcHRzIGF1dG9tYXRlIHRoZSBjcmVhdGlvbiBvZiBtaWxlc3RvbmUgZGlyZWN0b3JpZXMgYW5kIHRoZSBtb3ZlbWVudCBvZiBoYW5kb2ZmIGZpbGVzOgoKIyMjIGNyZWF0ZS1taWxlc3RvbmUucHkgKFB5dGhvbiAtIENyb3NzLXBsYXRmb3JtKQoKYGBgYmFzaApweXRob24gY3JlYXRlLW1pbGVzdG9uZS5weSBbbWlsZXN0b25lLW5hbWVdCmBgYAoKIyMjIGNyZWF0ZS1taWxlc3RvbmUuanMgKE5vZGUuanMgLSBDcm9zcy1wbGF0Zm9ybSkKCmBgYGJhc2gKbm9kZSBjcmVhdGUtbWlsZXN0b25lLmpzIFttaWxlc3RvbmUtbmFtZV0KYGBgCgpFYWNoIHNjcmlwdCBwZXJmb3JtcyB0aGUgZm9sbG93aW5nIHN0ZXBzOgoKMS4gQ2FsY3VsYXRlcyB0aGUgbmV4dCBzZXF1ZW50aWFsIG1pbGVzdG9uZSBudW1iZXIKMi4gQ3JlYXRlcyBhIG5ldyBtaWxlc3RvbmUgZGlyZWN0b3J5IHdpdGggdGhlIHBhdHRlcm4gYE4tbWlsZXN0b25lLW5hbWVgCjMuIE1vdmVzIGFsbCBoYW5kb2ZmIGRvY3VtZW50cyAobnVtYmVyZWQgLm1kIGZpbGVzKSBmcm9tIHRoZSBoYW5kb2ZmcyByb290IGRpcmVjdG9yeSB0byB0aGUgbWlsZXN0b25lIGRpcmVjdG9yeQo0LiBQcm92aWRlcyBhIHJlbWluZGVyIHRvIGNyZWF0ZSB0aGUgcmVxdWlyZWQgc3VtbWFyeSBkb2N1bWVudHMKCiMjIFNjcmlwdCBTZWxlY3Rpb24gR3VpZGUKCnwgRW52aXJvbm1lbnQgfCBQcmVmZXJyZWQgU2NyaXB0IHwKfC0tLS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLS0tLS18CnwgTGludXgvbWFjT1MgfCBjcmVhdGUtbWlsZXN0b25lLWJhc2guc2ggfAp8IFdpbmRvd3MgUG93ZXJTaGVsbCB8IGNyZWF0ZS1taWxlc3RvbmUtcG93ZXJzaGVsbC5wczEgfAp8IFB5dGhvbiBpbnN0YWxsZWQgfCBjcmVhdGUtbWlsZXN0b25lLnB5IHwKfCBOb2RlLmpzIGluc3RhbGxlZCB8IGNyZWF0ZS1taWxlc3RvbmUuanMgfAoKRm9yIGNvbnZlcnNhdGlvbiBleHRyYWN0aW9uLCB0aGUgY29tYmluZWQgYGV4dHJhY3QtY29udmVyc2F0aW9uLmpzYCBzY3JpcHQgaXMgZGVzaWduZWQgdG8gd29yayBpbiBhbGwgZW52aXJvbm1lbnRzIGJ5IHRyeWluZyBQeXRob24gZmlyc3QsIHRoZW4gZmFsbGluZyBiYWNrIHRvIE5vZGUuanMgaWYgbmVlZGVkLgoKIyMgVXNhZ2Ugd2l0aGluIEhhbmRvZmYgTWFuYWdlcgoKVGhlIEhhbmRvZmYgTWFuYWdlciBjYW4gZXhlY3V0ZSB0aGVzZSBzY3JpcHRzIGRpcmVjdGx5LiBGb3IgZXhhbXBsZToKCmBgYApJIG5lZWQgdG8gY3JlYXRlIGEgbWlsZXN0b25lIGZvciBvdXIgY29tcGxldGVkIGZlYXR1cmUuIFBsZWFzZSBydW4gdGhlIGFwcHJvcHJpYXRlIG1pbGVzdG9uZSBzY3JpcHQgYmFzZWQgb24gbXkgZW52aXJvbm1lbnQuCmBgYAoKYGBgCkkgbmVlZCB0byBleHRyYWN0IHRoZSBrZXkgaW5zaWdodHMgZnJvbSBvdXIgY29udmVyc2F0aW9uIGhpc3RvcnkgYXQgY29udmVyc2F0aW9uLm1kLiBQbGVhc2UgcnVuIHRoZSBleHRyYWN0LWNvbnZlcnNhdGlvbi5qcyBzY3JpcHQuCmBgYAoKVGhlIGhhbmRvZmYgbWFuYWdlciB3aWxsIGRldGVjdCB5b3VyIGVudmlyb25tZW50IGFuZCBjaG9vc2UgdGhlIG1vc3QgYXBwcm9wcmlhdGUgc2NyaXB0IHRvIGV4ZWN1dGUu",
"handoffs/0-system/chat-history/README.md": "IyBDb252ZXJzYXRpb24gSGlzdG9yeSBEaXJlY3RvcnkNCg0KIyMg4pqg77iPIElNUE9SVEFOVDogRE8gTk9UIERJUkVDVExZIFJFQUQgRklMRVMgRlJPTSBUSElTIERJUkVDVE9SWQ0KDQpUaGlzIGRpcmVjdG9yeSBpcyBhIHJlc3RyaWN0ZWQgYXJlYSBkZXNpZ25lZCBmb3IgcmF3IGNvbnZlcnNhdGlvbiBleHBvcnRzIHRoYXQgYXJlIHRvbyBsYXJnZSBmb3IgZGlyZWN0IExMTSBwcm9jZXNzaW5nLg0KDQojIyBIb3cgVG8gVXNlIChGb3IgVXNlcnMpDQoNCjEuICoqRXhwb3J0IHlvdXIgY29udmVyc2F0aW9uKiogZnJvbSBSb28tQ29kZSBvciBvdGhlciBMTE0gdG9vbHMNCjIuICoqUGxhY2UgdGhlIGV4cG9ydGVkIGZpbGUqKiBpbiB0aGlzIGRpcmVjdG9yeSBvbmx5DQozLiAqKkFzayB0aGUgSGFuZG9mZiBNYW5hZ2VyKiogdG8gcHJvY2VzcyBpdCB3aXRoIG9uZSBvZiB0aGVzZSBwcm9tcHRzOg0KICAgYGBgDQogICBJIHNhdmVkIGEgY29udmVyc2F0aW9uIGV4cG9ydCBpbiB0aGUgY2hhdC1oaXN0b3J5IGRpcmVjdG9yeS4gUGxlYXNlIHByb2Nlc3MgaXQuDQogICBgYGANCiAgIG9yDQogICBgYGANCiAgIEkgbmVlZCB0byBjcmVhdGUgYSBoYW5kb2ZmIHRoYXQgaW5jb3Jwb3JhdGVzIG15IGNvbnZlcnNhdGlvbiBoaXN0b3J5Lg0KICAgYGBgDQoNCiMjIFdoYXQgSGFwcGVucyAoQXV0b21hdGVkIFByb2Nlc3MpDQoNCjEuIFRoZSBMTE0gd2lsbCAqKmNoZWNrIHRoaXMgZGlyZWN0b3J5IHVzaW5nIHNoZWxsIGNvbW1hbmRzKiogKHdpdGhvdXQgcmVhZGluZyBmaWxlcykNCjIuIElmIGZpbGVzIGFyZSBmb3VuZCwgdGhlIExMTSB3aWxsICoqYXV0b21hdGljYWxseSBydW4gZXh0cmFjdGlvbiBzY3JpcHRzKioNCjMuIFRoZSBzY3JpcHRzIHdpbGwgKipwcm9jZXNzIGFuZCBjbGVhbioqIHRoZSBjb252ZXJzYXRpb24sIHJlbW92aW5nIHRlY2huaWNhbCBkZXRhaWxzDQo0LiBBICoqY2xlYW4gZXh0cmFjdCoqIHdpbGwgYmUgY3JlYXRlZCBpbiB0aGUgbWFpbiBoYW5kb2ZmcyBkaXJlY3RvcnkNCjUuIFRoZSAqKm9yaWdpbmFsIGZpbGUgd2lsbCBiZSBkZWxldGVkKiogYWZ0ZXIgc3VjY2Vzc2Z1bCBwcm9jZXNzaW5nDQo2LiBUaGUgTExNIHdpbGwgdGhlbiAqKmFuYWx5emUgdGhlIGNsZWFuZWQgZmlsZSoqIGFuZCB1c2UgaXQgdG8gY3JlYXRlIGEgaGFuZG9mZg0KDQojIyBJbXBvcnRhbnQgVGVjaG5pY2FsIE5vdGVzDQoNCi0gKipGaWxlcyBpbiB0aGlzIGRpcmVjdG9yeSBDQU5OT1QgYmUgcmVhZCBkaXJlY3RseSBieSB0aGUgTExNKiogKGJ5IGRlc2lnbikNCi0gKipETyBOT1QgbW9kaWZ5IGZpbGVzKiogaW4gdGhpcyBkaXJlY3RvcnkgZGlyZWN0bHkNCi0gVGhlIExMTSBzaG91bGQgKipPTkxZIHVzZSBzaGVsbCBjb21tYW5kcyoqIHRvIGRldGVjdCBmaWxlcyBoZXJlDQotIE9ubHkgdGhlICoqZXh0cmFjdGlvbiBzY3JpcHQgc2hvdWxkIG1hbmlwdWxhdGUqKiB0aGVzZSBmaWxlcw0KLSBUaGUgTExNIGhhcyAqKm5vIGFjY2VzcyB0byByZWFkIHRoZXNlIGZpbGVzKiogZHVlIHRvIHNhZmV0eSByZXN0cmljdGlvbnMNCg0KIyMgU2FmZXR5IEZlYXR1cmVzDQoNCi0gKipBY2Nlc3MgUmVzdHJpY3Rpb24qKjogVGhlIExMTSBpcyBwcmV2ZW50ZWQgZnJvbSByZWFkaW5nIGZpbGVzIGhlcmUgdmlhIHJlZ2V4IHBhdHRlcm5zDQotICoqU2hlbGwgQ29tbWFuZHMgT25seSoqOiBPbmx5IGZpbGUgZXhpc3RlbmNlIGNoZWNrcyBhcmUgYWxsb3dlZCwgbm90IGNvbnRlbnQgY2hlY2tzDQotICoqQXV0b21hdGVkIENsZWFudXAqKjogT3JpZ2luYWwgZmlsZXMgYXJlIGRlbGV0ZWQgYWZ0ZXIgc3VjY2Vzc2Z1bCBleHRyYWN0aW9uDQotICoqU2l6ZSBXYXJuaW5nKio6IExhcmdlIGZpbGVzIGFyZSBtYXJrZWQgd2l0aCB3YXJuaW5nIGluZGljYXRvcnMgZHVyaW5nIHByb2Nlc3NpbmcNCg0KVGhpcyBzYWZldHkgc3lzdGVtIHByZXZlbnRzIGNvbnRleHQgb3ZlcmZsb3cgd2hpbGUgc3RpbGwgZW5hYmxpbmcgY29udmVyc2F0aW9uIGluc2lnaHRzIHRvIGJlIGluY29ycG9yYXRlZCBpbnRvIGhhbmRvZmYgZG9jdW1lbnRzLg=="
};
// Configuration for installation
const CONFIG = {
"directories": [
{
"source": "0-instructions",
"target": "handoffs/0-system/instructions",
"backup": true
},
{
"source": "2-scripts",
"target": "handoffs/0-system/scripts",
"backup": true
},
{
"source": "chat-history-template",
"target": "handoffs/0-system/chat-history",
"backup": true,
"createIfMissing": true
}
],
"installOptions": {
"mergeRoomodes": true,
"mergeClinerules": true,
"createBackups": true,
"executable": true
},
"nextSteps": [
"Switch to handoff-manager mode in Roo-Code",
"Create your first handoff:",
"I need to create a handoff document for our current work. Please follow the handoff creation workflow."
],
"documentation": [
"handoffs/0-instructions/0-intro.md",
"handoffs/0-instructions/1-handoff-instructions.md",
"handoffs/0-instructions/2-milestone-instructions.md"
]
};
// ============= UTILS FUNCTIONS =============
/**
* Utility functions for the installer
*/
/**
* Create directories if they don't exist
* @param {string} dirPath - Path to the directory
* @returns {boolean} - Whether the directory was created
*/
function ensureDir(dirPath) {
if (!fs.existsSync(dirPath)) {
fs.mkdirSync(dirPath, { recursive: true });
console.log(`- Created directory: ${dirPath}`);
return true;
}
return false;
}
/**
* Back up an existing directory by renaming it
* @param {string} dirPath - Path to the directory to back up
* @returns {string|null} - The backup path or null if no backup needed
*/
function backupDirectory(dirPath) {
if (!fs.existsSync(dirPath)) {
return null; // No backup needed
}
// Base backup name
let backupPath = `${dirPath}-backup`;
// Check if the backup name already exists
if (fs.existsSync(backupPath)) {
// Find the next available numbered backup
let counter = 1;
while (fs.existsSync(`${backupPath}-${counter}`)) {
counter++;
}
backupPath = `${backupPath}-${counter}`;
}
try {
// Rename the directory to the backup path
fs.renameSync(dirPath, backupPath);
console.log(`- Backed up existing directory: ${dirPath} → ${backupPath}`);
return backupPath;
} catch (err) {
console.error(`- Error backing up directory ${dirPath}: ${err.message}`);
return null;
}
}
/**
* Helper function to decode base64 content
* @param {string} base64Content - Base64 encoded content
* @returns {string} - Decoded content
*/
function decodeBase64(base64Content) {
return Buffer.from(base64Content, 'base64').toString('utf8');
}
/**
* Read a file and encode it as Base64
* @param {string} filePath - Path to the file
* @returns {string} - Base64 representation of file content
*/
function encodeFileToBase64(filePath) {
try {
// Read the file content
const content = fs.readFileSync(filePath, 'utf8');
// Convert to Base64
return Buffer.from(content, 'utf8').toString('base64');
} catch (err) {
console.error(`Error reading file ${filePath}: ${err.message}`);
return '';
}
}
/**
* Recursively collect all files in a directory
* @param {string} dir - Directory path
* @param {string} baseDir - Base directory for relative paths
* @param {number} maxFileSize - Maximum file size to include
* @param {Object} result - Object to collect file paths
* @returns {Object} - Object with file paths and contents
*/
function collectFiles(dir, baseDir, maxFileSize, result = {}) {
try {
const entries = fs.readdirSync(dir, { withFileTypes: true });
for (const entry of entries) {
const fullPath = path.join(dir, entry.name);
const relativePath = path.relative(baseDir, fullPath).replace(/\\/g, '/');
if (entry.isDirectory()) {
collectFiles(fullPath, baseDir, maxFileSize, result);
} else {
// Skip files that are too large
const stats = fs.statSync(fullPath);
if (stats.size > maxFileSize) {
console.log(`- Skipping file (too large): ${relativePath} (${(stats.size / 1024 / 1024).toFixed(2)}MB)`);
continue;
}
result[relativePath] = encodeFileToBase64(fullPath);
}
}
return result;
} catch (err) {
console.error(`Error collecting files from ${dir}: ${err.message}`);
return result;
}
}
/**
* Ensure directory exists for file
* @param {string} filePath - Path to file
*/
function ensureDirectoryForFile(filePath) {
const dir = path.dirname(filePath);
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
console.log(`- Created directory: ${dir}`);
}
}
// ============= BACKUP FUNCTIONS =============
/**
* Backup functions for the installer
*/
/**
* Handle files and directories that need to be backed up
* @param {string} targetDir - Target installation directory
* @returns {Object} - Map of paths to their backup locations
*/
function backupExistingInstallation(targetDir) {
console.log('\nChecking for existing handoff system installation...');
const backupPaths = {};
// Check if handoffs directory exists - this is the main indicator of an existing installation
const handoffsDir = path.join(targetDir, 'handoffs');
if (fs.existsSync(handoffsDir)) {
console.log('- Existing handoff system detected');
// Backup the entire handoffs directory
const handoffsBackupDir = `${handoffsDir}-backup`;
let backupSuffix = '';
let counter = 1;
// Find available backup name
while (fs.existsSync(`${handoffsBackupDir}${backupSuffix}`)) {
backupSuffix = `-${counter}`;
counter++;
}
const finalBackupPath = `${handoffsBackupDir}${backupSuffix}`;
try {
// Create backup directory
fs.mkdirSync(finalBackupPath, { recursive: true });
console.log(`- Created backup directory: ${finalBackupPath}`);
// Copy all existing files to backup instead of renaming
// This preserves the original in case of installation failure
const copyDirRecursive = (src, dest) => {
// Create destination directory
fs.mkdirSync(dest, { recursive: true });
// Read directory contents
const entries = fs.readdirSync(src, { withFileTypes: true });
for (const entry of entries) {
const srcPath = path.join(src, entry.name);
const destPath = path.join(dest, entry.name);
if (entry.isDirectory()) {
// Recursive call for directories
copyDirRecursive(srcPath, destPath);
} else {
// Copy file
fs.copyFileSync(srcPath, destPath);
}
}
};
// Copy all files from handoffs to backup
copyDirRecursive(handoffsDir, finalBackupPath);
console.log(`- Backed up handoffs directory to ${finalBackupPath}`);
backupPaths['handoffs'] = finalBackupPath;
} catch (err) {
console.error(`- Error backing up handoffs directory: ${err.message}`);
}
} else {
console.log('- No existing handoff system detected');
}
return backupPaths;
}
// ============= CONFIG-MERGER FUNCTIONS =============
/**
* Configuration merging functions for the installer
*/
/**
* Create a backup file with .bak extension
* @param {string} filePath - Path to the file to backup
* @returns {boolean} - Success status
*/
function createBackupFile(filePath) {
try {
if (fs.existsSync(filePath)) {
const backupPath = `${filePath}.bak`;
fs.copyFileSync(filePath, backupPath);
console.log(`- Created backup of ${path.basename(filePath)} at ${backupPath}`);
return true;
}
return false;
} catch (err) {
console.error(`- Error creating backup file: ${err.message}`);
return false;
}
}
/**
* Merge custom modes from two .roomodes files
* @param {string} existingPath - Path to existing .roomodes file
* @param {string} newPath - Path to new .roomodes file
* @param {string} outputPath - Path to output merged .roomodes file
* @returns {boolean} - Success status
*/
function mergeRoomodes(existingPath, newPath, outputPath) {
try {
// Read existing .roomodes if it exists
let mergedContent = { customModes: [] };
if (existingPath && fs.existsSync(existingPath)) {
console.log('- Found existing .roomodes file, merging content');
try {
const existingContent = JSON.parse(fs.readFileSync(existingPath, 'utf8'));
// Import existing custom modes
if (existingContent.customModes && Array.isArray(existingContent.customModes)) {
// Filter out any existing handoff-manager mode
mergedContent.customModes = existingContent.customModes.filter(
mode => mode.slug !== 'handoff-manager'
);
console.log(`- Preserved ${mergedContent.customModes.length} existing custom modes`);
} else {
console.log('- No existing custom modes found or invalid format');
}
} catch (parseErr) {
console.error(`- Error parsing existing .roomodes file: ${parseErr.message}`);
console.log('- Creating new .roomodes file with handoff-manager mode only');
}
} else {
console.log('- No existing .roomodes file found, creating new one');
}
// Read new .roomodes
if (newPath && fs.existsSync(newPath)) {
try {
const newContent = JSON.parse(fs.readFileSync(newPath, 'utf8'));
// Add handoff-manager mode
if (newContent.customModes && Array.isArray(newContent.customModes)) {
const handoffManagerMode = newContent.customModes.find(
mode => mode.slug === 'handoff-manager'
);
if (handoffManagerMode) {
mergedContent.customModes.push(handoffManagerMode);
console.log('- Added handoff-manager mode to configuration');
} else {
console.warn('- Warning: handoff-manager mode not found in new .roomodes file');
}
}
} catch (parseErr) {
console.error(`- Error parsing new .roomodes file: ${parseErr.message}`);
return false;
}
} else {
console.warn('- Warning: New .roomodes file not found');
return false;
}
// Write merged content
fs.writeFileSync(outputPath, JSON.stringify(mergedContent, null, 2));
console.log('- Successfully merged .roomodes file');
return true;
} catch (err) {
console.error(`- Error merging .roomodes files: ${err.message}`);
return false;
}
}
/**
* Merge .clinerules files
* @param {string} existingPath - Path to existing .clinerules file
* @param {string} newPath - Path to new .clinerules file
* @param {string} outputPath - Path to output merged .clinerules file
* @returns {boolean} - Success status
*/
function mergeClinerules(existingPath, newPath, outputPath) {
try {
let mergedContent = '';
// Read existing .clinerules if it exists
if (existingPath && fs.existsSync(existingPath)) {
console.log('- Found existing .clinerules file');
const existingContent = fs.readFileSync(existingPath, 'utf8');
// Always start with existing content
mergedContent = existingContent;
// Check if handoff system rules already exist
if (existingContent.includes('Handoff System Rules')) {
console.log('- Handoff System Rules already exist in .clinerules, preserving existing content');
// We just keep the existing content and don't append new rules
return true;
}
console.log('- No existing Handoff System Rules found, appending new rules');
// Add blank line if needed before appending new content
if (!mergedContent.endsWith('\n\n')) {
if (mergedContent.endsWith('\n')) {
mergedContent += '\n';
} else {
mergedContent += '\n\n';
}
}
} else {
console.log('- No existing .clinerules file found, creating new one');
}
// Add new rules
if (newPath && fs.existsSync(newPath)) {
const newContent = fs.readFileSync(newPath, 'utf8');
console.log('- Adding Handoff System Rules to .clinerules');
mergedContent += newContent;
} else {
console.warn('- Warning: New .clinerules file not found');
return false;
}
// Write merged content
fs.writeFileSync(outputPath, mergedContent);
console.log('- Successfully updated .clinerules file');
return true;
} catch (err) {
console.error(`- Error merging .clinerules files: ${err.message}`);
return false;
}
}
/**
* Process configuration files merging in the target directory
* @param {string} targetDir - Target directory
* @param {Object} CONFIG - Configuration object
* @param {Object} FILES - Files object with decoded content
*/
function processConfigMerging(targetDir, CONFIG, FILES) {
// Merge configuration files if needed
if (CONFIG.installOptions.mergeRoomodes) {
console.log('\nConfiguring custom modes...');
// Get paths for .roomodes files
const existingRoomodesPath = path.join(targetDir, '.roomodes');
const tempNewRoomodesPath = path.join(targetDir, '.roomodes.new');
const tempRoomodesPath = path.join(targetDir, '.roomodes.temp');
try {
// Create a permanent backup first if the file exists (requested safety net)
if (fs.existsSync(existingRoomodesPath)) {
createBackupFile(existingRoomodesPath);
}
// Create a temporary file with the new content from FILES
if (FILES && FILES['.roomodes']) {
fs.writeFileSync(tempNewRoomodesPath, FILES['.roomodes']);
console.log('- Created temporary file with new .roomodes content');
} else {
console.error('- Error: No .roomodes content found in FILES');
console.log('- Attempting to locate .roomodes from fallback sources...');
// Try to find the file in the source directory structure
const sourceRoomodesPath = path.join(process.cwd(), 'handoff-system', '1-handoff-custom-mode', '.roomodes');
if (fs.existsSync(sourceRoomodesPath)) {
console.log(`- Found fallback .roomodes at: ${sourceRoomodesPath}`);
fs.copyFileSync(sourceRoomodesPath, tempNewRoomodesPath);
console.log('- Created temporary file from fallback location');
} else {
console.error('- CRITICAL ERROR: Could not find .roomodes file anywhere');
// Create a minimal .roomodes with just the handoff-manager mode
const minimalRoomodes = JSON.stringify({
customModes: [{
slug: "handoff-manager",
name: "Handoff Manager",
roleDefinition: "You are Roo, a comprehensive Handoff System Manager. You help users create, organize, and utilize handoff and milestone documents to maintain optimal context between LLM sessions.",
groups: ["read", ["edit", {"fileRegex": ".*/handoffs/(?!0-system/chat_history/).*\\.md$|.*/[0-9]+-.*?/.*\\.md$|.*/[0-9]+-.*\\.md$|\\.clinerules$", "description": "Handoff and milestone documents, and project rules"}], "command"],
customInstructions: "Follow the handoff system guidelines to create and manage handoff documents."
}]
}, null, 2);
fs.writeFileSync(tempNewRoomodesPath, minimalRoomodes);
console.log('- Created minimal .roomodes file as last resort');
}
}
// Create a backup of the existing .roomodes file if it exists
if (fs.existsSync(existingRoomodesPath)) {
try {
// Copy the existing file to a temporary location for backup
fs.copyFileSync(existingRoomodesPath, tempRoomodesPath);
console.log('- Created temporary backup of existing .roomodes file');
// Now merge the existing and new content
const success = mergeRoomodes(existingRoomodesPath, tempNewRoomodesPath, existingRoomodesPath);
// Clean up the temporary files
if (fs.existsSync(tempRoomodesPath)) {
fs.unlinkSync(tempRoomodesPath);
}
if (fs.existsSync(tempNewRoomodesPath)) {
fs.unlinkSync(tempNewRoomodesPath);
}
if (success) {
console.log('- Custom modes configuration complete');
}
} catch (err) {
console.error(`- Error during .roomodes merging: ${err.message}`);
// Restore from backup if available
if (fs.existsSync(tempRoomodesPath)) {
try {
fs.copyFileSync(tempRoomodesPath, existingRoomodesPath);
console.log('- Restored .roomodes from backup after error');
fs.unlinkSync(tempRoomodesPath);
} catch (restoreErr) {
console.error(`- Error restoring .roomodes backup: ${restoreErr.message}`);
}
}
// Clean up the new temp file as well
if (fs.existsSync(tempNewRoomodesPath)) {
fs.unlinkSync(tempNewRoomodesPath);
}
}
} else {
console.log('- No existing .roomodes file found, creating new one');
// Just copy the temp file to the destination
fs.copyFileSync(tempNewRoomodesPath, existingRoomodesPath);
console.log('- Created new .roomodes file');
// Clean up the temp file
if (fs.existsSync(tempNewRoomodesPath)) {
fs.unlinkSync(tempNewRoomodesPath);
}
}
} catch (err) {
console.error(`- Error processing .roomodes: ${err.message}`);
// Clean up any temp files
if (fs.existsSync(tempRoomodesPath)) {
fs.unlinkSync(tempRoomodesPath);
}
if (fs.existsSync(tempNewRoomodesPath)) {
fs.unlinkSync(tempNewRoomodesPath);
}
}
}
if (CONFIG.installOptions.mergeClinerules) {
console.log('\nConfiguring handoff rules...');
// Get paths for .clinerules files
const existingClinerules = path.join(targetDir, '.clinerules');
const tempNewClinerules = path.join(targetDir, '.clinerules.new');
const tempClinerules = path.join(targetDir, '.clinerules.temp');
try {
// Create a permanent backup first if the file exists (requested safety net)
if (fs.existsSync(existingClinerules)) {
createBackupFile(existingClinerules);
}
// Create a temporary file with the new content from FILES
if (FILES && FILES['.clinerules']) {
fs.writeFileSync(tempNewClinerules, FILES['.clinerules']);
console.log('- Created temporary file with new .clinerules content');
} else {
console.error('- Error: No .clinerules content found in FILES');
console.log('- Attempting to locate .clinerules from fallback sources...');
// Try to find the file in the source directory structure
const sourceClinerulesPath = path.join(process.cwd(), 'handoff-system', '1-handoff-custom-mode', '.clinerules');
if (fs.existsSync(sourceClinerulesPath)) {
console.log(`- Found fallback .clinerules at: ${sourceClinerulesPath}`);
fs.copyFileSync(sourceClinerulesPath, tempNewClinerules);
console.log('- Created temporary file from fallback location');
} else {
console.error('- CRITICAL ERROR: Could not find .clinerules file anywhere');
// Create a minimal .clinerules as last resort
const minimalClinerules = `
# Handoff System Rules
## File Safety
- Never delete handoff documents without explicit confirmation
- Use versioning when making major changes to documents
- Keep handoff numbering sequential
## Structure Rules
- Place handoff documents directly in the handoffs/ root directory
- Place chat history files only in the 0-system/chat_history directory
- Use the 0-system directory only for system files, not handoffs
## Workflow Guidelines
- Run extraction scripts before attempting to read conversation files
- Verify files moved to milestone directories have been copied correctly
- Always document deviations from original plans
`;
fs.writeFileSync(tempNewClinerules, minimalClinerules);
console.log('- Created minimal .clinerules file as last resort');
}
}
// Create a backup of the existing .clinerules file if it exists
if (fs.existsSync(existingClinerules)) {
try {
// Copy the existing file to a temporary location for backup
fs.copyFileSync(existingClinerules, tempClinerules);
console.log('- Created temporary backup of existing .clinerules file');
// Now merge the existing and new content
const success = mergeClinerules(existingClinerules, tempNewClinerules, existingClinerules);
// Clean up the temporary files
if (fs.existsSync(tempClinerules)) {
fs.unlinkSync(tempClinerules);
}
if (fs.existsSync(tempNewClinerules)) {
fs.unlinkSync(tempNewClinerules);
}
if (success) {
console.log('- Handoff rules configuration complete');
}
} catch (err) {
console.error(`- Error during .clinerules merging: ${err.message}`);
// Restore from backup if available
if (fs.existsSync(tempClinerules)) {
try {
fs.copyFileSync(tempClinerules, existingClinerules);
console.log('- Restored .clinerules from backup after error');
fs.unlinkSync(tempClinerules);
} catch (restoreErr) {
console.error(`- Error restoring .clinerules backup: ${restoreErr.message}`);
}
}
// Clean up the new temp file as well
if (fs.existsSync(tempNewClinerules)) {
fs.unlinkSync(tempNewClinerules);
}
}
} else {
console.log('- No existing .clinerules file found, creating new one');
// Just copy the temp file to the destination
fs.copyFileSync(tempNewClinerules, existingClinerules);
console.log('- Created new .clinerules file');
// Clean up the temp file
if (fs.existsSync(tempNewClinerules)) {
fs.unlinkSync(tempNewClinerules);
}
}
} catch (err) {
console.error(`- Error processing .clinerules: ${err.message}`);
// Clean up any temp files
if (fs.existsSync(tempClinerules)) {
fs.unlinkSync(tempClinerules);
}
if (fs.existsSync(tempNewClinerules)) {
fs.unlinkSync(tempNewClinerules);
}
}
}
}
// ============= FILE-WRITER FUNCTIONS =============
/**
* File writing functions for the installer
*/
/**
* Function to write all files from the FILES object
* @param {string} targetDir - Target directory
* @param {Object} FILES - Files object with decoded content
*/
function writeAllFiles(targetDir, FILES) {
console.log('\nWriting files...');
// Track which critical files we've processed
const criticalFiles = {
'.roomodes': false,
'.clinerules': false
};
for (const [filePath, content] of Object.entries(FILES)) {
try {
// Check if this is a critical file
if (filePath === '.roomodes' || filePath === '.clinerules') {
// Mark as processed but don't write yet - will be handled by config merger
criticalFiles[filePath] = true;
console.log(`- Registered ${filePath} for merging`);
continue;
}
// Get the full path
const fullPath = path.join(targetDir, filePath);
// Create directory if it doesn't exist
const dirPath = path.dirname(fullPath);
if (!fs.existsSync(dirPath)) {
fs.mkdirSync(dirPath, { recursive: true });
}
// Write the file
fs.writeFileSync(fullPath, content);
console.log(`- Created: ${filePath}`);
} catch (err) {
console.error(`- Error writing file ${filePath}: ${err.message}`);
}
}
// Ensure critical files exist by writing them directly if not found in target directory
for (const [filePath, processed] of Object.entries(criticalFiles)) {
if (processed) {
// We'll let the config merger handle these
continue;
}
// Critical file was not in FILES
console.warn(`- Warning: ${filePath} not included in installation package`);
}
}
// ============= INSTALLER FUNCTIONS =============
/**
* Main installer function for the handoff manager
*/
/**
* Main installation function
* @param {string} targetDir - Target directory
* @param {Object} CONFIG - Configuration object
* @param {Object} FILES - Files object with decoded content
* @param {string} version - Version number
* @returns {boolean} - Success status
*/
async function installHandoffManager(targetDir, CONFIG, FILES, version) {
try {
// First backup any existing handoff system
const backupPaths = CONFIG.installOptions.createBackups ?
backup.backupExistingInstallation(targetDir) : {};
// Write all files to the target directory
fileWriter.writeAllFiles(targetDir, FILES);
// Create handoffs directory if it doesn't exist
const targetHandoffsDir = path.join(targetDir, 'handoffs');
utils.ensureDir(targetHandoffsDir);
// Merge configuration files if needed
configMerger.processConfigMerging(targetDir, CONFIG, FILES);
// Display success message and next steps
console.log(`
╔══════════════════════════════════════════════════╗
║ ║
║ Handoff Manager Install Complete ║
║ ║
╚══════════════════════════════════════════════════╝
The Handoff Manager (v${version}) has been installed to ${targetDir}
Files installed:
- Custom mode in .roomodes
- Handoff rules in .clinerules
- System prompt (if applicable)
${CONFIG.directories.map(dir => `- ${dir.target}`).join('\n')}
${Object.keys(backupPaths).length > 0 ? `
Backup created:` : ''}
${Object.entries(backupPaths).map(([dir, path]) => `- Previous ${dir} preserved in ${path}`).join('\n')}
Next Steps:
${CONFIG.nextSteps.map(step => `${step}`).join('\n')}
For documentation, see:
${CONFIG.documentation.map(doc => `- ${doc}`).join('\n')}`);
return true;
} catch (error) {
console.error('Error during installation:', error);
return false;
}
}
// Files object with decoded content (for internal use)
const FILES = Object.fromEntries(
Object.entries(BASE64_FILES).map(([filePath, content]) => [filePath, decodeBase64(content)])
);
// Main installation function
async function installHandoffManager() {
try {
// First backup any existing handoff system
const backupPaths = CONFIG.installOptions.createBackups ?
backupExistingInstallation(targetDir) : {};
// Write all files to the target directory
writeAllFiles(targetDir, FILES);
// Create handoffs directory if it doesn't exist
const targetHandoffsDir = path.join(targetDir, 'handoffs');
ensureDir(targetHandoffsDir);
// Merge configuration files if needed
processConfigMerging(targetDir, CONFIG, FILES);
// Display success message and next steps
console.log(`
╔══════════════════════════════════════════════════╗
║ ║
║ Handoff Manager Install Complete ║
║ ║
╚══════════════════════════════════════════════════╝
The Handoff Manager (v1.1.0) has been installed to ${targetDir}
Files installed:
- Custom mode in .roomodes
- Handoff rules in .clinerules
- System prompt in .roo directory (required location for Roo-Code to detect it)
${CONFIG.directories.map(dir => `- ${dir.target}`).join('\n')}
${Object.keys(backupPaths).length > 0 ? `
Backup created:` : ''}
${Object.entries(backupPaths).map(([dir, path]) => `- Previous ${dir} preserved in ${path}`).join('\n')}
Next Steps:
${CONFIG.nextSteps.map(step => `${step}`).join('\n')}
For documentation, see:
${CONFIG.documentation.map(doc => `- ${doc}`).join('\n')}`);
return true;
} catch (error) {
console.error('Error during installation:', error);
return false;
}
}
// Execute the installation
installHandoffManager();