@spooky-sync/core 0.0.1-canary.239 → 0.0.1-canary.240

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/coverage/lcov-report/base.css +224 -0
  2. package/coverage/lcov-report/block-navigation.js +87 -0
  3. package/coverage/lcov-report/favicon.png +0 -0
  4. package/coverage/lcov-report/index.html +476 -0
  5. package/coverage/lcov-report/prettify.css +1 -0
  6. package/coverage/lcov-report/prettify.js +2 -0
  7. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  8. package/coverage/lcov-report/sorter.js +210 -0
  9. package/coverage/lcov-report/src/boot/auth-flip.saga.ts.html +271 -0
  10. package/coverage/lcov-report/src/boot/boot.saga.ts.html +469 -0
  11. package/coverage/lcov-report/src/boot/bucket-switch.saga.ts.html +430 -0
  12. package/coverage/lcov-report/src/boot/index.html +161 -0
  13. package/coverage/lcov-report/src/boot/preload.saga.ts.html +178 -0
  14. package/coverage/lcov-report/src/client/bucket-handle.ts.html +766 -0
  15. package/coverage/lcov-report/src/client/index.html +161 -0
  16. package/coverage/lcov-report/src/client/router.ts.html +367 -0
  17. package/coverage/lcov-report/src/client/runtime.ts.html +940 -0
  18. package/coverage/lcov-report/src/client/sp00ky-client.ts.html +1531 -0
  19. package/coverage/lcov-report/src/events/index.html +116 -0
  20. package/coverage/lcov-report/src/events/index.ts.html +877 -0
  21. package/coverage/lcov-report/src/index.html +146 -0
  22. package/coverage/lcov-report/src/index.ts.html +202 -0
  23. package/coverage/lcov-report/src/kernel/constants.ts.html +247 -0
  24. package/coverage/lcov-report/src/kernel/effects.ts.html +562 -0
  25. package/coverage/lcov-report/src/kernel/events.ts.html +250 -0
  26. package/coverage/lcov-report/src/kernel/index.html +176 -0
  27. package/coverage/lcov-report/src/kernel/interpreter.ts.html +514 -0
  28. package/coverage/lcov-report/src/kernel/saga.ts.html +304 -0
  29. package/coverage/lcov-report/src/modules/app-release/index.html +116 -0
  30. package/coverage/lcov-report/src/modules/app-release/index.ts.html +712 -0
  31. package/coverage/lcov-report/src/modules/auth/events/index.html +116 -0
  32. package/coverage/lcov-report/src/modules/auth/events/index.ts.html +142 -0
  33. package/coverage/lcov-report/src/modules/auth/index.html +116 -0
  34. package/coverage/lcov-report/src/modules/auth/index.ts.html +1225 -0
  35. package/coverage/lcov-report/src/modules/crdt/crdt-field.ts.html +967 -0
  36. package/coverage/lcov-report/src/modules/crdt/index.html +146 -0
  37. package/coverage/lcov-report/src/modules/crdt/index.ts.html +1474 -0
  38. package/coverage/lcov-report/src/modules/crdt/loro-loader.ts.html +160 -0
  39. package/coverage/lcov-report/src/modules/devtools/flags.ts.html +1132 -0
  40. package/coverage/lcov-report/src/modules/devtools/index.html +161 -0
  41. package/coverage/lcov-report/src/modules/devtools/index.ts.html +2413 -0
  42. package/coverage/lcov-report/src/modules/devtools/storage-info.ts.html +589 -0
  43. package/coverage/lcov-report/src/modules/devtools/versions.ts.html +415 -0
  44. package/coverage/lcov-report/src/modules/feature-flag/index.html +116 -0
  45. package/coverage/lcov-report/src/modules/feature-flag/index.ts.html +1033 -0
  46. package/coverage/lcov-report/src/modules/index.html +116 -0
  47. package/coverage/lcov-report/src/modules/ref-tables.ts.html +349 -0
  48. package/coverage/lcov-report/src/mutation/index.html +191 -0
  49. package/coverage/lcov-report/src/mutation/jobs.ts.html +208 -0
  50. package/coverage/lcov-report/src/mutation/mutation-id.ts.html +190 -0
  51. package/coverage/lcov-report/src/mutation/push.saga.ts.html +730 -0
  52. package/coverage/lcov-report/src/mutation/rows.ts.html +1216 -0
  53. package/coverage/lcov-report/src/mutation/tray.saga.ts.html +229 -0
  54. package/coverage/lcov-report/src/mutation/write.saga.ts.html +583 -0
  55. package/coverage/lcov-report/src/otel/index.html +116 -0
  56. package/coverage/lcov-report/src/otel/index.ts.html +466 -0
  57. package/coverage/lcov-report/src/query/env.ts.html +253 -0
  58. package/coverage/lcov-report/src/query/fetch.saga.ts.html +412 -0
  59. package/coverage/lcov-report/src/query/hash.ts.html +139 -0
  60. package/coverage/lcov-report/src/query/index.html +281 -0
  61. package/coverage/lcov-report/src/query/lifecycle.saga.ts.html +388 -0
  62. package/coverage/lcov-report/src/query/materialize.saga.ts.html +310 -0
  63. package/coverage/lcov-report/src/query/materialize.ts.html +217 -0
  64. package/coverage/lcov-report/src/query/membership.saga.ts.html +709 -0
  65. package/coverage/lcov-report/src/query/membership.ts.html +559 -0
  66. package/coverage/lcov-report/src/query/register.saga.ts.html +655 -0
  67. package/coverage/lcov-report/src/query/render-set.ts.html +265 -0
  68. package/coverage/lcov-report/src/query/sql.ts.html +322 -0
  69. package/coverage/lcov-report/src/query/window-query.ts.html +670 -0
  70. package/coverage/lcov-report/src/services/blobs/blob-cache.ts.html +1894 -0
  71. package/coverage/lcov-report/src/services/blobs/blob-manifest.ts.html +766 -0
  72. package/coverage/lcov-report/src/services/blobs/blob-store.ts.html +1162 -0
  73. package/coverage/lcov-report/src/services/blobs/index.html +161 -0
  74. package/coverage/lcov-report/src/services/blobs/index.ts.html +295 -0
  75. package/coverage/lcov-report/src/services/database/cache-engine.ts.html +664 -0
  76. package/coverage/lcov-report/src/services/database/connection-supervisor.ts.html +1330 -0
  77. package/coverage/lcov-report/src/services/database/database.ts.html +658 -0
  78. package/coverage/lcov-report/src/services/database/engine-factory.ts.html +184 -0
  79. package/coverage/lcov-report/src/services/database/errors.ts.html +187 -0
  80. package/coverage/lcov-report/src/services/database/events/index.html +116 -0
  81. package/coverage/lcov-report/src/services/database/events/index.ts.html +184 -0
  82. package/coverage/lcov-report/src/services/database/index.html +386 -0
  83. package/coverage/lcov-report/src/services/database/index.ts.html +121 -0
  84. package/coverage/lcov-report/src/services/database/local-migrator.ts.html +703 -0
  85. package/coverage/lcov-report/src/services/database/local.ts.html +1633 -0
  86. package/coverage/lcov-report/src/services/database/plan-render.ts.html +409 -0
  87. package/coverage/lcov-report/src/services/database/relation-resolver.ts.html +682 -0
  88. package/coverage/lcov-report/src/services/database/remote.ts.html +1036 -0
  89. package/coverage/lcov-report/src/services/database/sqlite-cache-engine.ts.html +4132 -0
  90. package/coverage/lcov-report/src/services/database/sqlite-lock-verify.ts.html +220 -0
  91. package/coverage/lcov-report/src/services/database/sqlite-open.ts.html +577 -0
  92. package/coverage/lcov-report/src/services/database/sqlite-plan-sql.ts.html +499 -0
  93. package/coverage/lcov-report/src/services/database/sqlite-select.ts.html +478 -0
  94. package/coverage/lcov-report/src/services/database/sqlite-transport.ts.html +757 -0
  95. package/coverage/lcov-report/src/services/database/surql-translate.ts.html +1333 -0
  96. package/coverage/lcov-report/src/services/database/surreal-cache-engine.ts.html +568 -0
  97. package/coverage/lcov-report/src/services/logger/index.html +116 -0
  98. package/coverage/lcov-report/src/services/logger/index.ts.html +154 -0
  99. package/coverage/lcov-report/src/services/persistence/index.html +146 -0
  100. package/coverage/lcov-report/src/services/persistence/localstorage.ts.html +163 -0
  101. package/coverage/lcov-report/src/services/persistence/resilient.ts.html +208 -0
  102. package/coverage/lcov-report/src/services/persistence/surrealdb.ts.html +271 -0
  103. package/coverage/lcov-report/src/services/stream-processor/index.html +146 -0
  104. package/coverage/lcov-report/src/services/stream-processor/index.ts.html +3313 -0
  105. package/coverage/lcov-report/src/services/stream-processor/permissions.ts.html +244 -0
  106. package/coverage/lcov-report/src/services/stream-processor/wasm-types.ts.html +346 -0
  107. package/coverage/lcov-report/src/services/tabs/broker-client.ts.html +934 -0
  108. package/coverage/lcov-report/src/services/tabs/coordinator.ts.html +1984 -0
  109. package/coverage/lcov-report/src/services/tabs/index.html +191 -0
  110. package/coverage/lcov-report/src/services/tabs/leader-locks.ts.html +310 -0
  111. package/coverage/lcov-report/src/services/tabs/protocol.ts.html +871 -0
  112. package/coverage/lcov-report/src/services/tabs/support.ts.html +193 -0
  113. package/coverage/lcov-report/src/services/tabs/tabs-broker-worker.ts.html +2005 -0
  114. package/coverage/lcov-report/src/sp00ky.ts.html +100 -0
  115. package/coverage/lcov-report/src/state/client-state.ts.html +637 -0
  116. package/coverage/lcov-report/src/state/index.html +161 -0
  117. package/coverage/lcov-report/src/state/lifecycle.ts.html +343 -0
  118. package/coverage/lcov-report/src/state/reducers.ts.html +1471 -0
  119. package/coverage/lcov-report/src/state/selectors.ts.html +637 -0
  120. package/coverage/lcov-report/src/sync/connection.saga.ts.html +343 -0
  121. package/coverage/lcov-report/src/sync/index.html +176 -0
  122. package/coverage/lcov-report/src/sync/live.saga.ts.html +232 -0
  123. package/coverage/lcov-report/src/sync/policy.ts.html +1606 -0
  124. package/coverage/lcov-report/src/sync/poll.saga.ts.html +193 -0
  125. package/coverage/lcov-report/src/sync/tabs.saga.ts.html +361 -0
  126. package/coverage/lcov-report/src/types.ts.html +2419 -0
  127. package/coverage/lcov-report/src/utils/blurhash.ts.html +355 -0
  128. package/coverage/lcov-report/src/utils/error-classification.ts.html +244 -0
  129. package/coverage/lcov-report/src/utils/index.html +191 -0
  130. package/coverage/lcov-report/src/utils/index.ts.html +820 -0
  131. package/coverage/lcov-report/src/utils/parser.ts.html +313 -0
  132. package/coverage/lcov-report/src/utils/semver.ts.html +175 -0
  133. package/coverage/lcov-report/src/utils/surql.ts.html +667 -0
  134. package/coverage/lcov.info +19079 -0
  135. package/dist/index.js +3 -3
  136. package/dist/sqlite-open.js +20 -1
  137. package/package.json +3 -3
  138. package/src/services/database/relation-resolver.test.ts +55 -1
  139. package/src/services/database/relation-resolver.ts +0 -0
@@ -0,0 +1,2413 @@
1
+
2
+ <!doctype html>
3
+ <html lang="en">
4
+
5
+ <head>
6
+ <title>Code coverage report for src/modules/devtools/index.ts</title>
7
+ <meta charset="utf-8" />
8
+ <link rel="stylesheet" href="../../../prettify.css" />
9
+ <link rel="stylesheet" href="../../../base.css" />
10
+ <link rel="shortcut icon" type="image/x-icon" href="../../../favicon.png" />
11
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
12
+ <style type='text/css'>
13
+ .coverage-summary .sorter {
14
+ background-image: url(../../../sort-arrow-sprite.png);
15
+ }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <div class='wrapper'>
21
+ <div class='pad1'>
22
+ <h1><a href="../../../index.html">All files</a> / <a href="index.html">src/modules/devtools</a> index.ts</h1>
23
+ <div class='clearfix'>
24
+
25
+ <div class='fl pad1y space-right2'>
26
+ <span class="strong">61.78% </span>
27
+ <span class="quiet">Statements</span>
28
+ <span class='fraction'>333/539</span>
29
+ </div>
30
+
31
+
32
+ <div class='fl pad1y space-right2'>
33
+ <span class="strong">69.52% </span>
34
+ <span class="quiet">Branches</span>
35
+ <span class='fraction'>73/105</span>
36
+ </div>
37
+
38
+
39
+ <div class='fl pad1y space-right2'>
40
+ <span class="strong">55% </span>
41
+ <span class="quiet">Functions</span>
42
+ <span class='fraction'>22/40</span>
43
+ </div>
44
+
45
+
46
+ <div class='fl pad1y space-right2'>
47
+ <span class="strong">61.78% </span>
48
+ <span class="quiet">Lines</span>
49
+ <span class='fraction'>333/539</span>
50
+ </div>
51
+
52
+
53
+ </div>
54
+ <p class="quiet">
55
+ Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
56
+ </p>
57
+ <template id="filterTemplate">
58
+ <div class="quiet">
59
+ Filter:
60
+ <input type="search" id="fileSearch">
61
+ </div>
62
+ </template>
63
+ </div>
64
+ <div class='status-line medium'></div>
65
+ <pre><table class="coverage">
66
+ <tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
67
+ <a name='L2'></a><a href='#L2'>2</a>
68
+ <a name='L3'></a><a href='#L3'>3</a>
69
+ <a name='L4'></a><a href='#L4'>4</a>
70
+ <a name='L5'></a><a href='#L5'>5</a>
71
+ <a name='L6'></a><a href='#L6'>6</a>
72
+ <a name='L7'></a><a href='#L7'>7</a>
73
+ <a name='L8'></a><a href='#L8'>8</a>
74
+ <a name='L9'></a><a href='#L9'>9</a>
75
+ <a name='L10'></a><a href='#L10'>10</a>
76
+ <a name='L11'></a><a href='#L11'>11</a>
77
+ <a name='L12'></a><a href='#L12'>12</a>
78
+ <a name='L13'></a><a href='#L13'>13</a>
79
+ <a name='L14'></a><a href='#L14'>14</a>
80
+ <a name='L15'></a><a href='#L15'>15</a>
81
+ <a name='L16'></a><a href='#L16'>16</a>
82
+ <a name='L17'></a><a href='#L17'>17</a>
83
+ <a name='L18'></a><a href='#L18'>18</a>
84
+ <a name='L19'></a><a href='#L19'>19</a>
85
+ <a name='L20'></a><a href='#L20'>20</a>
86
+ <a name='L21'></a><a href='#L21'>21</a>
87
+ <a name='L22'></a><a href='#L22'>22</a>
88
+ <a name='L23'></a><a href='#L23'>23</a>
89
+ <a name='L24'></a><a href='#L24'>24</a>
90
+ <a name='L25'></a><a href='#L25'>25</a>
91
+ <a name='L26'></a><a href='#L26'>26</a>
92
+ <a name='L27'></a><a href='#L27'>27</a>
93
+ <a name='L28'></a><a href='#L28'>28</a>
94
+ <a name='L29'></a><a href='#L29'>29</a>
95
+ <a name='L30'></a><a href='#L30'>30</a>
96
+ <a name='L31'></a><a href='#L31'>31</a>
97
+ <a name='L32'></a><a href='#L32'>32</a>
98
+ <a name='L33'></a><a href='#L33'>33</a>
99
+ <a name='L34'></a><a href='#L34'>34</a>
100
+ <a name='L35'></a><a href='#L35'>35</a>
101
+ <a name='L36'></a><a href='#L36'>36</a>
102
+ <a name='L37'></a><a href='#L37'>37</a>
103
+ <a name='L38'></a><a href='#L38'>38</a>
104
+ <a name='L39'></a><a href='#L39'>39</a>
105
+ <a name='L40'></a><a href='#L40'>40</a>
106
+ <a name='L41'></a><a href='#L41'>41</a>
107
+ <a name='L42'></a><a href='#L42'>42</a>
108
+ <a name='L43'></a><a href='#L43'>43</a>
109
+ <a name='L44'></a><a href='#L44'>44</a>
110
+ <a name='L45'></a><a href='#L45'>45</a>
111
+ <a name='L46'></a><a href='#L46'>46</a>
112
+ <a name='L47'></a><a href='#L47'>47</a>
113
+ <a name='L48'></a><a href='#L48'>48</a>
114
+ <a name='L49'></a><a href='#L49'>49</a>
115
+ <a name='L50'></a><a href='#L50'>50</a>
116
+ <a name='L51'></a><a href='#L51'>51</a>
117
+ <a name='L52'></a><a href='#L52'>52</a>
118
+ <a name='L53'></a><a href='#L53'>53</a>
119
+ <a name='L54'></a><a href='#L54'>54</a>
120
+ <a name='L55'></a><a href='#L55'>55</a>
121
+ <a name='L56'></a><a href='#L56'>56</a>
122
+ <a name='L57'></a><a href='#L57'>57</a>
123
+ <a name='L58'></a><a href='#L58'>58</a>
124
+ <a name='L59'></a><a href='#L59'>59</a>
125
+ <a name='L60'></a><a href='#L60'>60</a>
126
+ <a name='L61'></a><a href='#L61'>61</a>
127
+ <a name='L62'></a><a href='#L62'>62</a>
128
+ <a name='L63'></a><a href='#L63'>63</a>
129
+ <a name='L64'></a><a href='#L64'>64</a>
130
+ <a name='L65'></a><a href='#L65'>65</a>
131
+ <a name='L66'></a><a href='#L66'>66</a>
132
+ <a name='L67'></a><a href='#L67'>67</a>
133
+ <a name='L68'></a><a href='#L68'>68</a>
134
+ <a name='L69'></a><a href='#L69'>69</a>
135
+ <a name='L70'></a><a href='#L70'>70</a>
136
+ <a name='L71'></a><a href='#L71'>71</a>
137
+ <a name='L72'></a><a href='#L72'>72</a>
138
+ <a name='L73'></a><a href='#L73'>73</a>
139
+ <a name='L74'></a><a href='#L74'>74</a>
140
+ <a name='L75'></a><a href='#L75'>75</a>
141
+ <a name='L76'></a><a href='#L76'>76</a>
142
+ <a name='L77'></a><a href='#L77'>77</a>
143
+ <a name='L78'></a><a href='#L78'>78</a>
144
+ <a name='L79'></a><a href='#L79'>79</a>
145
+ <a name='L80'></a><a href='#L80'>80</a>
146
+ <a name='L81'></a><a href='#L81'>81</a>
147
+ <a name='L82'></a><a href='#L82'>82</a>
148
+ <a name='L83'></a><a href='#L83'>83</a>
149
+ <a name='L84'></a><a href='#L84'>84</a>
150
+ <a name='L85'></a><a href='#L85'>85</a>
151
+ <a name='L86'></a><a href='#L86'>86</a>
152
+ <a name='L87'></a><a href='#L87'>87</a>
153
+ <a name='L88'></a><a href='#L88'>88</a>
154
+ <a name='L89'></a><a href='#L89'>89</a>
155
+ <a name='L90'></a><a href='#L90'>90</a>
156
+ <a name='L91'></a><a href='#L91'>91</a>
157
+ <a name='L92'></a><a href='#L92'>92</a>
158
+ <a name='L93'></a><a href='#L93'>93</a>
159
+ <a name='L94'></a><a href='#L94'>94</a>
160
+ <a name='L95'></a><a href='#L95'>95</a>
161
+ <a name='L96'></a><a href='#L96'>96</a>
162
+ <a name='L97'></a><a href='#L97'>97</a>
163
+ <a name='L98'></a><a href='#L98'>98</a>
164
+ <a name='L99'></a><a href='#L99'>99</a>
165
+ <a name='L100'></a><a href='#L100'>100</a>
166
+ <a name='L101'></a><a href='#L101'>101</a>
167
+ <a name='L102'></a><a href='#L102'>102</a>
168
+ <a name='L103'></a><a href='#L103'>103</a>
169
+ <a name='L104'></a><a href='#L104'>104</a>
170
+ <a name='L105'></a><a href='#L105'>105</a>
171
+ <a name='L106'></a><a href='#L106'>106</a>
172
+ <a name='L107'></a><a href='#L107'>107</a>
173
+ <a name='L108'></a><a href='#L108'>108</a>
174
+ <a name='L109'></a><a href='#L109'>109</a>
175
+ <a name='L110'></a><a href='#L110'>110</a>
176
+ <a name='L111'></a><a href='#L111'>111</a>
177
+ <a name='L112'></a><a href='#L112'>112</a>
178
+ <a name='L113'></a><a href='#L113'>113</a>
179
+ <a name='L114'></a><a href='#L114'>114</a>
180
+ <a name='L115'></a><a href='#L115'>115</a>
181
+ <a name='L116'></a><a href='#L116'>116</a>
182
+ <a name='L117'></a><a href='#L117'>117</a>
183
+ <a name='L118'></a><a href='#L118'>118</a>
184
+ <a name='L119'></a><a href='#L119'>119</a>
185
+ <a name='L120'></a><a href='#L120'>120</a>
186
+ <a name='L121'></a><a href='#L121'>121</a>
187
+ <a name='L122'></a><a href='#L122'>122</a>
188
+ <a name='L123'></a><a href='#L123'>123</a>
189
+ <a name='L124'></a><a href='#L124'>124</a>
190
+ <a name='L125'></a><a href='#L125'>125</a>
191
+ <a name='L126'></a><a href='#L126'>126</a>
192
+ <a name='L127'></a><a href='#L127'>127</a>
193
+ <a name='L128'></a><a href='#L128'>128</a>
194
+ <a name='L129'></a><a href='#L129'>129</a>
195
+ <a name='L130'></a><a href='#L130'>130</a>
196
+ <a name='L131'></a><a href='#L131'>131</a>
197
+ <a name='L132'></a><a href='#L132'>132</a>
198
+ <a name='L133'></a><a href='#L133'>133</a>
199
+ <a name='L134'></a><a href='#L134'>134</a>
200
+ <a name='L135'></a><a href='#L135'>135</a>
201
+ <a name='L136'></a><a href='#L136'>136</a>
202
+ <a name='L137'></a><a href='#L137'>137</a>
203
+ <a name='L138'></a><a href='#L138'>138</a>
204
+ <a name='L139'></a><a href='#L139'>139</a>
205
+ <a name='L140'></a><a href='#L140'>140</a>
206
+ <a name='L141'></a><a href='#L141'>141</a>
207
+ <a name='L142'></a><a href='#L142'>142</a>
208
+ <a name='L143'></a><a href='#L143'>143</a>
209
+ <a name='L144'></a><a href='#L144'>144</a>
210
+ <a name='L145'></a><a href='#L145'>145</a>
211
+ <a name='L146'></a><a href='#L146'>146</a>
212
+ <a name='L147'></a><a href='#L147'>147</a>
213
+ <a name='L148'></a><a href='#L148'>148</a>
214
+ <a name='L149'></a><a href='#L149'>149</a>
215
+ <a name='L150'></a><a href='#L150'>150</a>
216
+ <a name='L151'></a><a href='#L151'>151</a>
217
+ <a name='L152'></a><a href='#L152'>152</a>
218
+ <a name='L153'></a><a href='#L153'>153</a>
219
+ <a name='L154'></a><a href='#L154'>154</a>
220
+ <a name='L155'></a><a href='#L155'>155</a>
221
+ <a name='L156'></a><a href='#L156'>156</a>
222
+ <a name='L157'></a><a href='#L157'>157</a>
223
+ <a name='L158'></a><a href='#L158'>158</a>
224
+ <a name='L159'></a><a href='#L159'>159</a>
225
+ <a name='L160'></a><a href='#L160'>160</a>
226
+ <a name='L161'></a><a href='#L161'>161</a>
227
+ <a name='L162'></a><a href='#L162'>162</a>
228
+ <a name='L163'></a><a href='#L163'>163</a>
229
+ <a name='L164'></a><a href='#L164'>164</a>
230
+ <a name='L165'></a><a href='#L165'>165</a>
231
+ <a name='L166'></a><a href='#L166'>166</a>
232
+ <a name='L167'></a><a href='#L167'>167</a>
233
+ <a name='L168'></a><a href='#L168'>168</a>
234
+ <a name='L169'></a><a href='#L169'>169</a>
235
+ <a name='L170'></a><a href='#L170'>170</a>
236
+ <a name='L171'></a><a href='#L171'>171</a>
237
+ <a name='L172'></a><a href='#L172'>172</a>
238
+ <a name='L173'></a><a href='#L173'>173</a>
239
+ <a name='L174'></a><a href='#L174'>174</a>
240
+ <a name='L175'></a><a href='#L175'>175</a>
241
+ <a name='L176'></a><a href='#L176'>176</a>
242
+ <a name='L177'></a><a href='#L177'>177</a>
243
+ <a name='L178'></a><a href='#L178'>178</a>
244
+ <a name='L179'></a><a href='#L179'>179</a>
245
+ <a name='L180'></a><a href='#L180'>180</a>
246
+ <a name='L181'></a><a href='#L181'>181</a>
247
+ <a name='L182'></a><a href='#L182'>182</a>
248
+ <a name='L183'></a><a href='#L183'>183</a>
249
+ <a name='L184'></a><a href='#L184'>184</a>
250
+ <a name='L185'></a><a href='#L185'>185</a>
251
+ <a name='L186'></a><a href='#L186'>186</a>
252
+ <a name='L187'></a><a href='#L187'>187</a>
253
+ <a name='L188'></a><a href='#L188'>188</a>
254
+ <a name='L189'></a><a href='#L189'>189</a>
255
+ <a name='L190'></a><a href='#L190'>190</a>
256
+ <a name='L191'></a><a href='#L191'>191</a>
257
+ <a name='L192'></a><a href='#L192'>192</a>
258
+ <a name='L193'></a><a href='#L193'>193</a>
259
+ <a name='L194'></a><a href='#L194'>194</a>
260
+ <a name='L195'></a><a href='#L195'>195</a>
261
+ <a name='L196'></a><a href='#L196'>196</a>
262
+ <a name='L197'></a><a href='#L197'>197</a>
263
+ <a name='L198'></a><a href='#L198'>198</a>
264
+ <a name='L199'></a><a href='#L199'>199</a>
265
+ <a name='L200'></a><a href='#L200'>200</a>
266
+ <a name='L201'></a><a href='#L201'>201</a>
267
+ <a name='L202'></a><a href='#L202'>202</a>
268
+ <a name='L203'></a><a href='#L203'>203</a>
269
+ <a name='L204'></a><a href='#L204'>204</a>
270
+ <a name='L205'></a><a href='#L205'>205</a>
271
+ <a name='L206'></a><a href='#L206'>206</a>
272
+ <a name='L207'></a><a href='#L207'>207</a>
273
+ <a name='L208'></a><a href='#L208'>208</a>
274
+ <a name='L209'></a><a href='#L209'>209</a>
275
+ <a name='L210'></a><a href='#L210'>210</a>
276
+ <a name='L211'></a><a href='#L211'>211</a>
277
+ <a name='L212'></a><a href='#L212'>212</a>
278
+ <a name='L213'></a><a href='#L213'>213</a>
279
+ <a name='L214'></a><a href='#L214'>214</a>
280
+ <a name='L215'></a><a href='#L215'>215</a>
281
+ <a name='L216'></a><a href='#L216'>216</a>
282
+ <a name='L217'></a><a href='#L217'>217</a>
283
+ <a name='L218'></a><a href='#L218'>218</a>
284
+ <a name='L219'></a><a href='#L219'>219</a>
285
+ <a name='L220'></a><a href='#L220'>220</a>
286
+ <a name='L221'></a><a href='#L221'>221</a>
287
+ <a name='L222'></a><a href='#L222'>222</a>
288
+ <a name='L223'></a><a href='#L223'>223</a>
289
+ <a name='L224'></a><a href='#L224'>224</a>
290
+ <a name='L225'></a><a href='#L225'>225</a>
291
+ <a name='L226'></a><a href='#L226'>226</a>
292
+ <a name='L227'></a><a href='#L227'>227</a>
293
+ <a name='L228'></a><a href='#L228'>228</a>
294
+ <a name='L229'></a><a href='#L229'>229</a>
295
+ <a name='L230'></a><a href='#L230'>230</a>
296
+ <a name='L231'></a><a href='#L231'>231</a>
297
+ <a name='L232'></a><a href='#L232'>232</a>
298
+ <a name='L233'></a><a href='#L233'>233</a>
299
+ <a name='L234'></a><a href='#L234'>234</a>
300
+ <a name='L235'></a><a href='#L235'>235</a>
301
+ <a name='L236'></a><a href='#L236'>236</a>
302
+ <a name='L237'></a><a href='#L237'>237</a>
303
+ <a name='L238'></a><a href='#L238'>238</a>
304
+ <a name='L239'></a><a href='#L239'>239</a>
305
+ <a name='L240'></a><a href='#L240'>240</a>
306
+ <a name='L241'></a><a href='#L241'>241</a>
307
+ <a name='L242'></a><a href='#L242'>242</a>
308
+ <a name='L243'></a><a href='#L243'>243</a>
309
+ <a name='L244'></a><a href='#L244'>244</a>
310
+ <a name='L245'></a><a href='#L245'>245</a>
311
+ <a name='L246'></a><a href='#L246'>246</a>
312
+ <a name='L247'></a><a href='#L247'>247</a>
313
+ <a name='L248'></a><a href='#L248'>248</a>
314
+ <a name='L249'></a><a href='#L249'>249</a>
315
+ <a name='L250'></a><a href='#L250'>250</a>
316
+ <a name='L251'></a><a href='#L251'>251</a>
317
+ <a name='L252'></a><a href='#L252'>252</a>
318
+ <a name='L253'></a><a href='#L253'>253</a>
319
+ <a name='L254'></a><a href='#L254'>254</a>
320
+ <a name='L255'></a><a href='#L255'>255</a>
321
+ <a name='L256'></a><a href='#L256'>256</a>
322
+ <a name='L257'></a><a href='#L257'>257</a>
323
+ <a name='L258'></a><a href='#L258'>258</a>
324
+ <a name='L259'></a><a href='#L259'>259</a>
325
+ <a name='L260'></a><a href='#L260'>260</a>
326
+ <a name='L261'></a><a href='#L261'>261</a>
327
+ <a name='L262'></a><a href='#L262'>262</a>
328
+ <a name='L263'></a><a href='#L263'>263</a>
329
+ <a name='L264'></a><a href='#L264'>264</a>
330
+ <a name='L265'></a><a href='#L265'>265</a>
331
+ <a name='L266'></a><a href='#L266'>266</a>
332
+ <a name='L267'></a><a href='#L267'>267</a>
333
+ <a name='L268'></a><a href='#L268'>268</a>
334
+ <a name='L269'></a><a href='#L269'>269</a>
335
+ <a name='L270'></a><a href='#L270'>270</a>
336
+ <a name='L271'></a><a href='#L271'>271</a>
337
+ <a name='L272'></a><a href='#L272'>272</a>
338
+ <a name='L273'></a><a href='#L273'>273</a>
339
+ <a name='L274'></a><a href='#L274'>274</a>
340
+ <a name='L275'></a><a href='#L275'>275</a>
341
+ <a name='L276'></a><a href='#L276'>276</a>
342
+ <a name='L277'></a><a href='#L277'>277</a>
343
+ <a name='L278'></a><a href='#L278'>278</a>
344
+ <a name='L279'></a><a href='#L279'>279</a>
345
+ <a name='L280'></a><a href='#L280'>280</a>
346
+ <a name='L281'></a><a href='#L281'>281</a>
347
+ <a name='L282'></a><a href='#L282'>282</a>
348
+ <a name='L283'></a><a href='#L283'>283</a>
349
+ <a name='L284'></a><a href='#L284'>284</a>
350
+ <a name='L285'></a><a href='#L285'>285</a>
351
+ <a name='L286'></a><a href='#L286'>286</a>
352
+ <a name='L287'></a><a href='#L287'>287</a>
353
+ <a name='L288'></a><a href='#L288'>288</a>
354
+ <a name='L289'></a><a href='#L289'>289</a>
355
+ <a name='L290'></a><a href='#L290'>290</a>
356
+ <a name='L291'></a><a href='#L291'>291</a>
357
+ <a name='L292'></a><a href='#L292'>292</a>
358
+ <a name='L293'></a><a href='#L293'>293</a>
359
+ <a name='L294'></a><a href='#L294'>294</a>
360
+ <a name='L295'></a><a href='#L295'>295</a>
361
+ <a name='L296'></a><a href='#L296'>296</a>
362
+ <a name='L297'></a><a href='#L297'>297</a>
363
+ <a name='L298'></a><a href='#L298'>298</a>
364
+ <a name='L299'></a><a href='#L299'>299</a>
365
+ <a name='L300'></a><a href='#L300'>300</a>
366
+ <a name='L301'></a><a href='#L301'>301</a>
367
+ <a name='L302'></a><a href='#L302'>302</a>
368
+ <a name='L303'></a><a href='#L303'>303</a>
369
+ <a name='L304'></a><a href='#L304'>304</a>
370
+ <a name='L305'></a><a href='#L305'>305</a>
371
+ <a name='L306'></a><a href='#L306'>306</a>
372
+ <a name='L307'></a><a href='#L307'>307</a>
373
+ <a name='L308'></a><a href='#L308'>308</a>
374
+ <a name='L309'></a><a href='#L309'>309</a>
375
+ <a name='L310'></a><a href='#L310'>310</a>
376
+ <a name='L311'></a><a href='#L311'>311</a>
377
+ <a name='L312'></a><a href='#L312'>312</a>
378
+ <a name='L313'></a><a href='#L313'>313</a>
379
+ <a name='L314'></a><a href='#L314'>314</a>
380
+ <a name='L315'></a><a href='#L315'>315</a>
381
+ <a name='L316'></a><a href='#L316'>316</a>
382
+ <a name='L317'></a><a href='#L317'>317</a>
383
+ <a name='L318'></a><a href='#L318'>318</a>
384
+ <a name='L319'></a><a href='#L319'>319</a>
385
+ <a name='L320'></a><a href='#L320'>320</a>
386
+ <a name='L321'></a><a href='#L321'>321</a>
387
+ <a name='L322'></a><a href='#L322'>322</a>
388
+ <a name='L323'></a><a href='#L323'>323</a>
389
+ <a name='L324'></a><a href='#L324'>324</a>
390
+ <a name='L325'></a><a href='#L325'>325</a>
391
+ <a name='L326'></a><a href='#L326'>326</a>
392
+ <a name='L327'></a><a href='#L327'>327</a>
393
+ <a name='L328'></a><a href='#L328'>328</a>
394
+ <a name='L329'></a><a href='#L329'>329</a>
395
+ <a name='L330'></a><a href='#L330'>330</a>
396
+ <a name='L331'></a><a href='#L331'>331</a>
397
+ <a name='L332'></a><a href='#L332'>332</a>
398
+ <a name='L333'></a><a href='#L333'>333</a>
399
+ <a name='L334'></a><a href='#L334'>334</a>
400
+ <a name='L335'></a><a href='#L335'>335</a>
401
+ <a name='L336'></a><a href='#L336'>336</a>
402
+ <a name='L337'></a><a href='#L337'>337</a>
403
+ <a name='L338'></a><a href='#L338'>338</a>
404
+ <a name='L339'></a><a href='#L339'>339</a>
405
+ <a name='L340'></a><a href='#L340'>340</a>
406
+ <a name='L341'></a><a href='#L341'>341</a>
407
+ <a name='L342'></a><a href='#L342'>342</a>
408
+ <a name='L343'></a><a href='#L343'>343</a>
409
+ <a name='L344'></a><a href='#L344'>344</a>
410
+ <a name='L345'></a><a href='#L345'>345</a>
411
+ <a name='L346'></a><a href='#L346'>346</a>
412
+ <a name='L347'></a><a href='#L347'>347</a>
413
+ <a name='L348'></a><a href='#L348'>348</a>
414
+ <a name='L349'></a><a href='#L349'>349</a>
415
+ <a name='L350'></a><a href='#L350'>350</a>
416
+ <a name='L351'></a><a href='#L351'>351</a>
417
+ <a name='L352'></a><a href='#L352'>352</a>
418
+ <a name='L353'></a><a href='#L353'>353</a>
419
+ <a name='L354'></a><a href='#L354'>354</a>
420
+ <a name='L355'></a><a href='#L355'>355</a>
421
+ <a name='L356'></a><a href='#L356'>356</a>
422
+ <a name='L357'></a><a href='#L357'>357</a>
423
+ <a name='L358'></a><a href='#L358'>358</a>
424
+ <a name='L359'></a><a href='#L359'>359</a>
425
+ <a name='L360'></a><a href='#L360'>360</a>
426
+ <a name='L361'></a><a href='#L361'>361</a>
427
+ <a name='L362'></a><a href='#L362'>362</a>
428
+ <a name='L363'></a><a href='#L363'>363</a>
429
+ <a name='L364'></a><a href='#L364'>364</a>
430
+ <a name='L365'></a><a href='#L365'>365</a>
431
+ <a name='L366'></a><a href='#L366'>366</a>
432
+ <a name='L367'></a><a href='#L367'>367</a>
433
+ <a name='L368'></a><a href='#L368'>368</a>
434
+ <a name='L369'></a><a href='#L369'>369</a>
435
+ <a name='L370'></a><a href='#L370'>370</a>
436
+ <a name='L371'></a><a href='#L371'>371</a>
437
+ <a name='L372'></a><a href='#L372'>372</a>
438
+ <a name='L373'></a><a href='#L373'>373</a>
439
+ <a name='L374'></a><a href='#L374'>374</a>
440
+ <a name='L375'></a><a href='#L375'>375</a>
441
+ <a name='L376'></a><a href='#L376'>376</a>
442
+ <a name='L377'></a><a href='#L377'>377</a>
443
+ <a name='L378'></a><a href='#L378'>378</a>
444
+ <a name='L379'></a><a href='#L379'>379</a>
445
+ <a name='L380'></a><a href='#L380'>380</a>
446
+ <a name='L381'></a><a href='#L381'>381</a>
447
+ <a name='L382'></a><a href='#L382'>382</a>
448
+ <a name='L383'></a><a href='#L383'>383</a>
449
+ <a name='L384'></a><a href='#L384'>384</a>
450
+ <a name='L385'></a><a href='#L385'>385</a>
451
+ <a name='L386'></a><a href='#L386'>386</a>
452
+ <a name='L387'></a><a href='#L387'>387</a>
453
+ <a name='L388'></a><a href='#L388'>388</a>
454
+ <a name='L389'></a><a href='#L389'>389</a>
455
+ <a name='L390'></a><a href='#L390'>390</a>
456
+ <a name='L391'></a><a href='#L391'>391</a>
457
+ <a name='L392'></a><a href='#L392'>392</a>
458
+ <a name='L393'></a><a href='#L393'>393</a>
459
+ <a name='L394'></a><a href='#L394'>394</a>
460
+ <a name='L395'></a><a href='#L395'>395</a>
461
+ <a name='L396'></a><a href='#L396'>396</a>
462
+ <a name='L397'></a><a href='#L397'>397</a>
463
+ <a name='L398'></a><a href='#L398'>398</a>
464
+ <a name='L399'></a><a href='#L399'>399</a>
465
+ <a name='L400'></a><a href='#L400'>400</a>
466
+ <a name='L401'></a><a href='#L401'>401</a>
467
+ <a name='L402'></a><a href='#L402'>402</a>
468
+ <a name='L403'></a><a href='#L403'>403</a>
469
+ <a name='L404'></a><a href='#L404'>404</a>
470
+ <a name='L405'></a><a href='#L405'>405</a>
471
+ <a name='L406'></a><a href='#L406'>406</a>
472
+ <a name='L407'></a><a href='#L407'>407</a>
473
+ <a name='L408'></a><a href='#L408'>408</a>
474
+ <a name='L409'></a><a href='#L409'>409</a>
475
+ <a name='L410'></a><a href='#L410'>410</a>
476
+ <a name='L411'></a><a href='#L411'>411</a>
477
+ <a name='L412'></a><a href='#L412'>412</a>
478
+ <a name='L413'></a><a href='#L413'>413</a>
479
+ <a name='L414'></a><a href='#L414'>414</a>
480
+ <a name='L415'></a><a href='#L415'>415</a>
481
+ <a name='L416'></a><a href='#L416'>416</a>
482
+ <a name='L417'></a><a href='#L417'>417</a>
483
+ <a name='L418'></a><a href='#L418'>418</a>
484
+ <a name='L419'></a><a href='#L419'>419</a>
485
+ <a name='L420'></a><a href='#L420'>420</a>
486
+ <a name='L421'></a><a href='#L421'>421</a>
487
+ <a name='L422'></a><a href='#L422'>422</a>
488
+ <a name='L423'></a><a href='#L423'>423</a>
489
+ <a name='L424'></a><a href='#L424'>424</a>
490
+ <a name='L425'></a><a href='#L425'>425</a>
491
+ <a name='L426'></a><a href='#L426'>426</a>
492
+ <a name='L427'></a><a href='#L427'>427</a>
493
+ <a name='L428'></a><a href='#L428'>428</a>
494
+ <a name='L429'></a><a href='#L429'>429</a>
495
+ <a name='L430'></a><a href='#L430'>430</a>
496
+ <a name='L431'></a><a href='#L431'>431</a>
497
+ <a name='L432'></a><a href='#L432'>432</a>
498
+ <a name='L433'></a><a href='#L433'>433</a>
499
+ <a name='L434'></a><a href='#L434'>434</a>
500
+ <a name='L435'></a><a href='#L435'>435</a>
501
+ <a name='L436'></a><a href='#L436'>436</a>
502
+ <a name='L437'></a><a href='#L437'>437</a>
503
+ <a name='L438'></a><a href='#L438'>438</a>
504
+ <a name='L439'></a><a href='#L439'>439</a>
505
+ <a name='L440'></a><a href='#L440'>440</a>
506
+ <a name='L441'></a><a href='#L441'>441</a>
507
+ <a name='L442'></a><a href='#L442'>442</a>
508
+ <a name='L443'></a><a href='#L443'>443</a>
509
+ <a name='L444'></a><a href='#L444'>444</a>
510
+ <a name='L445'></a><a href='#L445'>445</a>
511
+ <a name='L446'></a><a href='#L446'>446</a>
512
+ <a name='L447'></a><a href='#L447'>447</a>
513
+ <a name='L448'></a><a href='#L448'>448</a>
514
+ <a name='L449'></a><a href='#L449'>449</a>
515
+ <a name='L450'></a><a href='#L450'>450</a>
516
+ <a name='L451'></a><a href='#L451'>451</a>
517
+ <a name='L452'></a><a href='#L452'>452</a>
518
+ <a name='L453'></a><a href='#L453'>453</a>
519
+ <a name='L454'></a><a href='#L454'>454</a>
520
+ <a name='L455'></a><a href='#L455'>455</a>
521
+ <a name='L456'></a><a href='#L456'>456</a>
522
+ <a name='L457'></a><a href='#L457'>457</a>
523
+ <a name='L458'></a><a href='#L458'>458</a>
524
+ <a name='L459'></a><a href='#L459'>459</a>
525
+ <a name='L460'></a><a href='#L460'>460</a>
526
+ <a name='L461'></a><a href='#L461'>461</a>
527
+ <a name='L462'></a><a href='#L462'>462</a>
528
+ <a name='L463'></a><a href='#L463'>463</a>
529
+ <a name='L464'></a><a href='#L464'>464</a>
530
+ <a name='L465'></a><a href='#L465'>465</a>
531
+ <a name='L466'></a><a href='#L466'>466</a>
532
+ <a name='L467'></a><a href='#L467'>467</a>
533
+ <a name='L468'></a><a href='#L468'>468</a>
534
+ <a name='L469'></a><a href='#L469'>469</a>
535
+ <a name='L470'></a><a href='#L470'>470</a>
536
+ <a name='L471'></a><a href='#L471'>471</a>
537
+ <a name='L472'></a><a href='#L472'>472</a>
538
+ <a name='L473'></a><a href='#L473'>473</a>
539
+ <a name='L474'></a><a href='#L474'>474</a>
540
+ <a name='L475'></a><a href='#L475'>475</a>
541
+ <a name='L476'></a><a href='#L476'>476</a>
542
+ <a name='L477'></a><a href='#L477'>477</a>
543
+ <a name='L478'></a><a href='#L478'>478</a>
544
+ <a name='L479'></a><a href='#L479'>479</a>
545
+ <a name='L480'></a><a href='#L480'>480</a>
546
+ <a name='L481'></a><a href='#L481'>481</a>
547
+ <a name='L482'></a><a href='#L482'>482</a>
548
+ <a name='L483'></a><a href='#L483'>483</a>
549
+ <a name='L484'></a><a href='#L484'>484</a>
550
+ <a name='L485'></a><a href='#L485'>485</a>
551
+ <a name='L486'></a><a href='#L486'>486</a>
552
+ <a name='L487'></a><a href='#L487'>487</a>
553
+ <a name='L488'></a><a href='#L488'>488</a>
554
+ <a name='L489'></a><a href='#L489'>489</a>
555
+ <a name='L490'></a><a href='#L490'>490</a>
556
+ <a name='L491'></a><a href='#L491'>491</a>
557
+ <a name='L492'></a><a href='#L492'>492</a>
558
+ <a name='L493'></a><a href='#L493'>493</a>
559
+ <a name='L494'></a><a href='#L494'>494</a>
560
+ <a name='L495'></a><a href='#L495'>495</a>
561
+ <a name='L496'></a><a href='#L496'>496</a>
562
+ <a name='L497'></a><a href='#L497'>497</a>
563
+ <a name='L498'></a><a href='#L498'>498</a>
564
+ <a name='L499'></a><a href='#L499'>499</a>
565
+ <a name='L500'></a><a href='#L500'>500</a>
566
+ <a name='L501'></a><a href='#L501'>501</a>
567
+ <a name='L502'></a><a href='#L502'>502</a>
568
+ <a name='L503'></a><a href='#L503'>503</a>
569
+ <a name='L504'></a><a href='#L504'>504</a>
570
+ <a name='L505'></a><a href='#L505'>505</a>
571
+ <a name='L506'></a><a href='#L506'>506</a>
572
+ <a name='L507'></a><a href='#L507'>507</a>
573
+ <a name='L508'></a><a href='#L508'>508</a>
574
+ <a name='L509'></a><a href='#L509'>509</a>
575
+ <a name='L510'></a><a href='#L510'>510</a>
576
+ <a name='L511'></a><a href='#L511'>511</a>
577
+ <a name='L512'></a><a href='#L512'>512</a>
578
+ <a name='L513'></a><a href='#L513'>513</a>
579
+ <a name='L514'></a><a href='#L514'>514</a>
580
+ <a name='L515'></a><a href='#L515'>515</a>
581
+ <a name='L516'></a><a href='#L516'>516</a>
582
+ <a name='L517'></a><a href='#L517'>517</a>
583
+ <a name='L518'></a><a href='#L518'>518</a>
584
+ <a name='L519'></a><a href='#L519'>519</a>
585
+ <a name='L520'></a><a href='#L520'>520</a>
586
+ <a name='L521'></a><a href='#L521'>521</a>
587
+ <a name='L522'></a><a href='#L522'>522</a>
588
+ <a name='L523'></a><a href='#L523'>523</a>
589
+ <a name='L524'></a><a href='#L524'>524</a>
590
+ <a name='L525'></a><a href='#L525'>525</a>
591
+ <a name='L526'></a><a href='#L526'>526</a>
592
+ <a name='L527'></a><a href='#L527'>527</a>
593
+ <a name='L528'></a><a href='#L528'>528</a>
594
+ <a name='L529'></a><a href='#L529'>529</a>
595
+ <a name='L530'></a><a href='#L530'>530</a>
596
+ <a name='L531'></a><a href='#L531'>531</a>
597
+ <a name='L532'></a><a href='#L532'>532</a>
598
+ <a name='L533'></a><a href='#L533'>533</a>
599
+ <a name='L534'></a><a href='#L534'>534</a>
600
+ <a name='L535'></a><a href='#L535'>535</a>
601
+ <a name='L536'></a><a href='#L536'>536</a>
602
+ <a name='L537'></a><a href='#L537'>537</a>
603
+ <a name='L538'></a><a href='#L538'>538</a>
604
+ <a name='L539'></a><a href='#L539'>539</a>
605
+ <a name='L540'></a><a href='#L540'>540</a>
606
+ <a name='L541'></a><a href='#L541'>541</a>
607
+ <a name='L542'></a><a href='#L542'>542</a>
608
+ <a name='L543'></a><a href='#L543'>543</a>
609
+ <a name='L544'></a><a href='#L544'>544</a>
610
+ <a name='L545'></a><a href='#L545'>545</a>
611
+ <a name='L546'></a><a href='#L546'>546</a>
612
+ <a name='L547'></a><a href='#L547'>547</a>
613
+ <a name='L548'></a><a href='#L548'>548</a>
614
+ <a name='L549'></a><a href='#L549'>549</a>
615
+ <a name='L550'></a><a href='#L550'>550</a>
616
+ <a name='L551'></a><a href='#L551'>551</a>
617
+ <a name='L552'></a><a href='#L552'>552</a>
618
+ <a name='L553'></a><a href='#L553'>553</a>
619
+ <a name='L554'></a><a href='#L554'>554</a>
620
+ <a name='L555'></a><a href='#L555'>555</a>
621
+ <a name='L556'></a><a href='#L556'>556</a>
622
+ <a name='L557'></a><a href='#L557'>557</a>
623
+ <a name='L558'></a><a href='#L558'>558</a>
624
+ <a name='L559'></a><a href='#L559'>559</a>
625
+ <a name='L560'></a><a href='#L560'>560</a>
626
+ <a name='L561'></a><a href='#L561'>561</a>
627
+ <a name='L562'></a><a href='#L562'>562</a>
628
+ <a name='L563'></a><a href='#L563'>563</a>
629
+ <a name='L564'></a><a href='#L564'>564</a>
630
+ <a name='L565'></a><a href='#L565'>565</a>
631
+ <a name='L566'></a><a href='#L566'>566</a>
632
+ <a name='L567'></a><a href='#L567'>567</a>
633
+ <a name='L568'></a><a href='#L568'>568</a>
634
+ <a name='L569'></a><a href='#L569'>569</a>
635
+ <a name='L570'></a><a href='#L570'>570</a>
636
+ <a name='L571'></a><a href='#L571'>571</a>
637
+ <a name='L572'></a><a href='#L572'>572</a>
638
+ <a name='L573'></a><a href='#L573'>573</a>
639
+ <a name='L574'></a><a href='#L574'>574</a>
640
+ <a name='L575'></a><a href='#L575'>575</a>
641
+ <a name='L576'></a><a href='#L576'>576</a>
642
+ <a name='L577'></a><a href='#L577'>577</a>
643
+ <a name='L578'></a><a href='#L578'>578</a>
644
+ <a name='L579'></a><a href='#L579'>579</a>
645
+ <a name='L580'></a><a href='#L580'>580</a>
646
+ <a name='L581'></a><a href='#L581'>581</a>
647
+ <a name='L582'></a><a href='#L582'>582</a>
648
+ <a name='L583'></a><a href='#L583'>583</a>
649
+ <a name='L584'></a><a href='#L584'>584</a>
650
+ <a name='L585'></a><a href='#L585'>585</a>
651
+ <a name='L586'></a><a href='#L586'>586</a>
652
+ <a name='L587'></a><a href='#L587'>587</a>
653
+ <a name='L588'></a><a href='#L588'>588</a>
654
+ <a name='L589'></a><a href='#L589'>589</a>
655
+ <a name='L590'></a><a href='#L590'>590</a>
656
+ <a name='L591'></a><a href='#L591'>591</a>
657
+ <a name='L592'></a><a href='#L592'>592</a>
658
+ <a name='L593'></a><a href='#L593'>593</a>
659
+ <a name='L594'></a><a href='#L594'>594</a>
660
+ <a name='L595'></a><a href='#L595'>595</a>
661
+ <a name='L596'></a><a href='#L596'>596</a>
662
+ <a name='L597'></a><a href='#L597'>597</a>
663
+ <a name='L598'></a><a href='#L598'>598</a>
664
+ <a name='L599'></a><a href='#L599'>599</a>
665
+ <a name='L600'></a><a href='#L600'>600</a>
666
+ <a name='L601'></a><a href='#L601'>601</a>
667
+ <a name='L602'></a><a href='#L602'>602</a>
668
+ <a name='L603'></a><a href='#L603'>603</a>
669
+ <a name='L604'></a><a href='#L604'>604</a>
670
+ <a name='L605'></a><a href='#L605'>605</a>
671
+ <a name='L606'></a><a href='#L606'>606</a>
672
+ <a name='L607'></a><a href='#L607'>607</a>
673
+ <a name='L608'></a><a href='#L608'>608</a>
674
+ <a name='L609'></a><a href='#L609'>609</a>
675
+ <a name='L610'></a><a href='#L610'>610</a>
676
+ <a name='L611'></a><a href='#L611'>611</a>
677
+ <a name='L612'></a><a href='#L612'>612</a>
678
+ <a name='L613'></a><a href='#L613'>613</a>
679
+ <a name='L614'></a><a href='#L614'>614</a>
680
+ <a name='L615'></a><a href='#L615'>615</a>
681
+ <a name='L616'></a><a href='#L616'>616</a>
682
+ <a name='L617'></a><a href='#L617'>617</a>
683
+ <a name='L618'></a><a href='#L618'>618</a>
684
+ <a name='L619'></a><a href='#L619'>619</a>
685
+ <a name='L620'></a><a href='#L620'>620</a>
686
+ <a name='L621'></a><a href='#L621'>621</a>
687
+ <a name='L622'></a><a href='#L622'>622</a>
688
+ <a name='L623'></a><a href='#L623'>623</a>
689
+ <a name='L624'></a><a href='#L624'>624</a>
690
+ <a name='L625'></a><a href='#L625'>625</a>
691
+ <a name='L626'></a><a href='#L626'>626</a>
692
+ <a name='L627'></a><a href='#L627'>627</a>
693
+ <a name='L628'></a><a href='#L628'>628</a>
694
+ <a name='L629'></a><a href='#L629'>629</a>
695
+ <a name='L630'></a><a href='#L630'>630</a>
696
+ <a name='L631'></a><a href='#L631'>631</a>
697
+ <a name='L632'></a><a href='#L632'>632</a>
698
+ <a name='L633'></a><a href='#L633'>633</a>
699
+ <a name='L634'></a><a href='#L634'>634</a>
700
+ <a name='L635'></a><a href='#L635'>635</a>
701
+ <a name='L636'></a><a href='#L636'>636</a>
702
+ <a name='L637'></a><a href='#L637'>637</a>
703
+ <a name='L638'></a><a href='#L638'>638</a>
704
+ <a name='L639'></a><a href='#L639'>639</a>
705
+ <a name='L640'></a><a href='#L640'>640</a>
706
+ <a name='L641'></a><a href='#L641'>641</a>
707
+ <a name='L642'></a><a href='#L642'>642</a>
708
+ <a name='L643'></a><a href='#L643'>643</a>
709
+ <a name='L644'></a><a href='#L644'>644</a>
710
+ <a name='L645'></a><a href='#L645'>645</a>
711
+ <a name='L646'></a><a href='#L646'>646</a>
712
+ <a name='L647'></a><a href='#L647'>647</a>
713
+ <a name='L648'></a><a href='#L648'>648</a>
714
+ <a name='L649'></a><a href='#L649'>649</a>
715
+ <a name='L650'></a><a href='#L650'>650</a>
716
+ <a name='L651'></a><a href='#L651'>651</a>
717
+ <a name='L652'></a><a href='#L652'>652</a>
718
+ <a name='L653'></a><a href='#L653'>653</a>
719
+ <a name='L654'></a><a href='#L654'>654</a>
720
+ <a name='L655'></a><a href='#L655'>655</a>
721
+ <a name='L656'></a><a href='#L656'>656</a>
722
+ <a name='L657'></a><a href='#L657'>657</a>
723
+ <a name='L658'></a><a href='#L658'>658</a>
724
+ <a name='L659'></a><a href='#L659'>659</a>
725
+ <a name='L660'></a><a href='#L660'>660</a>
726
+ <a name='L661'></a><a href='#L661'>661</a>
727
+ <a name='L662'></a><a href='#L662'>662</a>
728
+ <a name='L663'></a><a href='#L663'>663</a>
729
+ <a name='L664'></a><a href='#L664'>664</a>
730
+ <a name='L665'></a><a href='#L665'>665</a>
731
+ <a name='L666'></a><a href='#L666'>666</a>
732
+ <a name='L667'></a><a href='#L667'>667</a>
733
+ <a name='L668'></a><a href='#L668'>668</a>
734
+ <a name='L669'></a><a href='#L669'>669</a>
735
+ <a name='L670'></a><a href='#L670'>670</a>
736
+ <a name='L671'></a><a href='#L671'>671</a>
737
+ <a name='L672'></a><a href='#L672'>672</a>
738
+ <a name='L673'></a><a href='#L673'>673</a>
739
+ <a name='L674'></a><a href='#L674'>674</a>
740
+ <a name='L675'></a><a href='#L675'>675</a>
741
+ <a name='L676'></a><a href='#L676'>676</a>
742
+ <a name='L677'></a><a href='#L677'>677</a>
743
+ <a name='L678'></a><a href='#L678'>678</a>
744
+ <a name='L679'></a><a href='#L679'>679</a>
745
+ <a name='L680'></a><a href='#L680'>680</a>
746
+ <a name='L681'></a><a href='#L681'>681</a>
747
+ <a name='L682'></a><a href='#L682'>682</a>
748
+ <a name='L683'></a><a href='#L683'>683</a>
749
+ <a name='L684'></a><a href='#L684'>684</a>
750
+ <a name='L685'></a><a href='#L685'>685</a>
751
+ <a name='L686'></a><a href='#L686'>686</a>
752
+ <a name='L687'></a><a href='#L687'>687</a>
753
+ <a name='L688'></a><a href='#L688'>688</a>
754
+ <a name='L689'></a><a href='#L689'>689</a>
755
+ <a name='L690'></a><a href='#L690'>690</a>
756
+ <a name='L691'></a><a href='#L691'>691</a>
757
+ <a name='L692'></a><a href='#L692'>692</a>
758
+ <a name='L693'></a><a href='#L693'>693</a>
759
+ <a name='L694'></a><a href='#L694'>694</a>
760
+ <a name='L695'></a><a href='#L695'>695</a>
761
+ <a name='L696'></a><a href='#L696'>696</a>
762
+ <a name='L697'></a><a href='#L697'>697</a>
763
+ <a name='L698'></a><a href='#L698'>698</a>
764
+ <a name='L699'></a><a href='#L699'>699</a>
765
+ <a name='L700'></a><a href='#L700'>700</a>
766
+ <a name='L701'></a><a href='#L701'>701</a>
767
+ <a name='L702'></a><a href='#L702'>702</a>
768
+ <a name='L703'></a><a href='#L703'>703</a>
769
+ <a name='L704'></a><a href='#L704'>704</a>
770
+ <a name='L705'></a><a href='#L705'>705</a>
771
+ <a name='L706'></a><a href='#L706'>706</a>
772
+ <a name='L707'></a><a href='#L707'>707</a>
773
+ <a name='L708'></a><a href='#L708'>708</a>
774
+ <a name='L709'></a><a href='#L709'>709</a>
775
+ <a name='L710'></a><a href='#L710'>710</a>
776
+ <a name='L711'></a><a href='#L711'>711</a>
777
+ <a name='L712'></a><a href='#L712'>712</a>
778
+ <a name='L713'></a><a href='#L713'>713</a>
779
+ <a name='L714'></a><a href='#L714'>714</a>
780
+ <a name='L715'></a><a href='#L715'>715</a>
781
+ <a name='L716'></a><a href='#L716'>716</a>
782
+ <a name='L717'></a><a href='#L717'>717</a>
783
+ <a name='L718'></a><a href='#L718'>718</a>
784
+ <a name='L719'></a><a href='#L719'>719</a>
785
+ <a name='L720'></a><a href='#L720'>720</a>
786
+ <a name='L721'></a><a href='#L721'>721</a>
787
+ <a name='L722'></a><a href='#L722'>722</a>
788
+ <a name='L723'></a><a href='#L723'>723</a>
789
+ <a name='L724'></a><a href='#L724'>724</a>
790
+ <a name='L725'></a><a href='#L725'>725</a>
791
+ <a name='L726'></a><a href='#L726'>726</a>
792
+ <a name='L727'></a><a href='#L727'>727</a>
793
+ <a name='L728'></a><a href='#L728'>728</a>
794
+ <a name='L729'></a><a href='#L729'>729</a>
795
+ <a name='L730'></a><a href='#L730'>730</a>
796
+ <a name='L731'></a><a href='#L731'>731</a>
797
+ <a name='L732'></a><a href='#L732'>732</a>
798
+ <a name='L733'></a><a href='#L733'>733</a>
799
+ <a name='L734'></a><a href='#L734'>734</a>
800
+ <a name='L735'></a><a href='#L735'>735</a>
801
+ <a name='L736'></a><a href='#L736'>736</a>
802
+ <a name='L737'></a><a href='#L737'>737</a>
803
+ <a name='L738'></a><a href='#L738'>738</a>
804
+ <a name='L739'></a><a href='#L739'>739</a>
805
+ <a name='L740'></a><a href='#L740'>740</a>
806
+ <a name='L741'></a><a href='#L741'>741</a>
807
+ <a name='L742'></a><a href='#L742'>742</a>
808
+ <a name='L743'></a><a href='#L743'>743</a>
809
+ <a name='L744'></a><a href='#L744'>744</a>
810
+ <a name='L745'></a><a href='#L745'>745</a>
811
+ <a name='L746'></a><a href='#L746'>746</a>
812
+ <a name='L747'></a><a href='#L747'>747</a>
813
+ <a name='L748'></a><a href='#L748'>748</a>
814
+ <a name='L749'></a><a href='#L749'>749</a>
815
+ <a name='L750'></a><a href='#L750'>750</a>
816
+ <a name='L751'></a><a href='#L751'>751</a>
817
+ <a name='L752'></a><a href='#L752'>752</a>
818
+ <a name='L753'></a><a href='#L753'>753</a>
819
+ <a name='L754'></a><a href='#L754'>754</a>
820
+ <a name='L755'></a><a href='#L755'>755</a>
821
+ <a name='L756'></a><a href='#L756'>756</a>
822
+ <a name='L757'></a><a href='#L757'>757</a>
823
+ <a name='L758'></a><a href='#L758'>758</a>
824
+ <a name='L759'></a><a href='#L759'>759</a>
825
+ <a name='L760'></a><a href='#L760'>760</a>
826
+ <a name='L761'></a><a href='#L761'>761</a>
827
+ <a name='L762'></a><a href='#L762'>762</a>
828
+ <a name='L763'></a><a href='#L763'>763</a>
829
+ <a name='L764'></a><a href='#L764'>764</a>
830
+ <a name='L765'></a><a href='#L765'>765</a>
831
+ <a name='L766'></a><a href='#L766'>766</a>
832
+ <a name='L767'></a><a href='#L767'>767</a>
833
+ <a name='L768'></a><a href='#L768'>768</a>
834
+ <a name='L769'></a><a href='#L769'>769</a>
835
+ <a name='L770'></a><a href='#L770'>770</a>
836
+ <a name='L771'></a><a href='#L771'>771</a>
837
+ <a name='L772'></a><a href='#L772'>772</a>
838
+ <a name='L773'></a><a href='#L773'>773</a>
839
+ <a name='L774'></a><a href='#L774'>774</a>
840
+ <a name='L775'></a><a href='#L775'>775</a>
841
+ <a name='L776'></a><a href='#L776'>776</a>
842
+ <a name='L777'></a><a href='#L777'>777</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</span>
843
+ <span class="cline-any cline-neutral">&nbsp;</span>
844
+ <span class="cline-any cline-neutral">&nbsp;</span>
845
+ <span class="cline-any cline-neutral">&nbsp;</span>
846
+ <span class="cline-any cline-neutral">&nbsp;</span>
847
+ <span class="cline-any cline-neutral">&nbsp;</span>
848
+ <span class="cline-any cline-neutral">&nbsp;</span>
849
+ <span class="cline-any cline-neutral">&nbsp;</span>
850
+ <span class="cline-any cline-neutral">&nbsp;</span>
851
+ <span class="cline-any cline-neutral">&nbsp;</span>
852
+ <span class="cline-any cline-neutral">&nbsp;</span>
853
+ <span class="cline-any cline-neutral">&nbsp;</span>
854
+ <span class="cline-any cline-neutral">&nbsp;</span>
855
+ <span class="cline-any cline-neutral">&nbsp;</span>
856
+ <span class="cline-any cline-neutral">&nbsp;</span>
857
+ <span class="cline-any cline-neutral">&nbsp;</span>
858
+ <span class="cline-any cline-neutral">&nbsp;</span>
859
+ <span class="cline-any cline-neutral">&nbsp;</span>
860
+ <span class="cline-any cline-neutral">&nbsp;</span>
861
+ <span class="cline-any cline-neutral">&nbsp;</span>
862
+ <span class="cline-any cline-neutral">&nbsp;</span>
863
+ <span class="cline-any cline-neutral">&nbsp;</span>
864
+ <span class="cline-any cline-neutral">&nbsp;</span>
865
+ <span class="cline-any cline-neutral">&nbsp;</span>
866
+ <span class="cline-any cline-neutral">&nbsp;</span>
867
+ <span class="cline-any cline-neutral">&nbsp;</span>
868
+ <span class="cline-any cline-neutral">&nbsp;</span>
869
+ <span class="cline-any cline-neutral">&nbsp;</span>
870
+ <span class="cline-any cline-neutral">&nbsp;</span>
871
+ <span class="cline-any cline-neutral">&nbsp;</span>
872
+ <span class="cline-any cline-neutral">&nbsp;</span>
873
+ <span class="cline-any cline-neutral">&nbsp;</span>
874
+ <span class="cline-any cline-yes">1x</span>
875
+ <span class="cline-any cline-yes">1x</span>
876
+ <span class="cline-any cline-yes">1x</span>
877
+ <span class="cline-any cline-yes">1x</span>
878
+ <span class="cline-any cline-yes">1x</span>
879
+ <span class="cline-any cline-yes">1x</span>
880
+ <span class="cline-any cline-neutral">&nbsp;</span>
881
+ <span class="cline-any cline-neutral">&nbsp;</span>
882
+ <span class="cline-any cline-neutral">&nbsp;</span>
883
+ <span class="cline-any cline-neutral">&nbsp;</span>
884
+ <span class="cline-any cline-neutral">&nbsp;</span>
885
+ <span class="cline-any cline-neutral">&nbsp;</span>
886
+ <span class="cline-any cline-neutral">&nbsp;</span>
887
+ <span class="cline-any cline-neutral">&nbsp;</span>
888
+ <span class="cline-any cline-yes">1x</span>
889
+ <span class="cline-any cline-yes">23x</span>
890
+ <span class="cline-any cline-yes">23x</span>
891
+ <span class="cline-any cline-neutral">&nbsp;</span>
892
+ <span class="cline-any cline-yes">23x</span>
893
+ <span class="cline-any cline-neutral">&nbsp;</span>
894
+ <span class="cline-any cline-neutral">&nbsp;</span>
895
+ <span class="cline-any cline-yes">23x</span>
896
+ <span class="cline-any cline-neutral">&nbsp;</span>
897
+ <span class="cline-any cline-neutral">&nbsp;</span>
898
+ <span class="cline-any cline-neutral">&nbsp;</span>
899
+ <span class="cline-any cline-neutral">&nbsp;</span>
900
+ <span class="cline-any cline-neutral">&nbsp;</span>
901
+ <span class="cline-any cline-yes">23x</span>
902
+ <span class="cline-any cline-neutral">&nbsp;</span>
903
+ <span class="cline-any cline-neutral">&nbsp;</span>
904
+ <span class="cline-any cline-neutral">&nbsp;</span>
905
+ <span class="cline-any cline-neutral">&nbsp;</span>
906
+ <span class="cline-any cline-neutral">&nbsp;</span>
907
+ <span class="cline-any cline-neutral">&nbsp;</span>
908
+ <span class="cline-any cline-neutral">&nbsp;</span>
909
+ <span class="cline-any cline-neutral">&nbsp;</span>
910
+ <span class="cline-any cline-neutral">&nbsp;</span>
911
+ <span class="cline-any cline-yes">23x</span>
912
+ <span class="cline-any cline-yes">23x</span>
913
+ <span class="cline-any cline-yes">23x</span>
914
+ <span class="cline-any cline-neutral">&nbsp;</span>
915
+ <span class="cline-any cline-yes">23x</span>
916
+ <span class="cline-any cline-neutral">&nbsp;</span>
917
+ <span class="cline-any cline-yes">23x</span>
918
+ <span class="cline-any cline-neutral">&nbsp;</span>
919
+ <span class="cline-any cline-neutral">&nbsp;</span>
920
+ <span class="cline-any cline-neutral">&nbsp;</span>
921
+ <span class="cline-any cline-yes">23x</span>
922
+ <span class="cline-any cline-neutral">&nbsp;</span>
923
+ <span class="cline-any cline-yes">23x</span>
924
+ <span class="cline-any cline-yes">1x</span>
925
+ <span class="cline-any cline-yes">1x</span>
926
+ <span class="cline-any cline-neutral">&nbsp;</span>
927
+ <span class="cline-any cline-neutral">&nbsp;</span>
928
+ <span class="cline-any cline-yes">23x</span>
929
+ <span class="cline-any cline-neutral">&nbsp;</span>
930
+ <span class="cline-any cline-yes">23x</span>
931
+ <span class="cline-any cline-yes">8x</span>
932
+ <span class="cline-any cline-yes">8x</span>
933
+ <span class="cline-any cline-neutral">&nbsp;</span>
934
+ <span class="cline-any cline-neutral">&nbsp;</span>
935
+ <span class="cline-any cline-neutral">&nbsp;</span>
936
+ <span class="cline-any cline-neutral">&nbsp;</span>
937
+ <span class="cline-any cline-yes">23x</span>
938
+ <span class="cline-any cline-yes">23x</span>
939
+ <span class="cline-any cline-yes">23x</span>
940
+ <span class="cline-any cline-neutral">&nbsp;</span>
941
+ <span class="cline-any cline-neutral">&nbsp;</span>
942
+ <span class="cline-any cline-neutral">&nbsp;</span>
943
+ <span class="cline-any cline-neutral">&nbsp;</span>
944
+ <span class="cline-any cline-yes">23x</span>
945
+ <span class="cline-any cline-yes">23x</span>
946
+ <span class="cline-any cline-neutral">&nbsp;</span>
947
+ <span class="cline-any cline-yes">23x</span>
948
+ <span class="cline-any cline-yes">19x</span>
949
+ <span class="cline-any cline-yes">19x</span>
950
+ <span class="cline-any cline-yes">19x</span>
951
+ <span class="cline-any cline-yes">19x</span>
952
+ <span class="cline-any cline-yes">19x</span>
953
+ <span class="cline-any cline-yes">19x</span>
954
+ <span class="cline-any cline-yes">19x</span>
955
+ <span class="cline-any cline-yes">19x</span>
956
+ <span class="cline-any cline-yes">19x</span>
957
+ <span class="cline-any cline-yes">19x</span>
958
+ <span class="cline-any cline-yes">19x</span>
959
+ <span class="cline-any cline-yes">19x</span>
960
+ <span class="cline-any cline-no">&nbsp;</span>
961
+ <span class="cline-any cline-no">&nbsp;</span>
962
+ <span class="cline-any cline-no">&nbsp;</span>
963
+ <span class="cline-any cline-no">&nbsp;</span>
964
+ <span class="cline-any cline-yes">19x</span>
965
+ <span class="cline-any cline-yes">19x</span>
966
+ <span class="cline-any cline-neutral">&nbsp;</span>
967
+ <span class="cline-any cline-yes">19x</span>
968
+ <span class="cline-any cline-neutral">&nbsp;</span>
969
+ <span class="cline-any cline-neutral">&nbsp;</span>
970
+ <span class="cline-any cline-neutral">&nbsp;</span>
971
+ <span class="cline-any cline-neutral">&nbsp;</span>
972
+ <span class="cline-any cline-yes">19x</span>
973
+ <span class="cline-any cline-yes">11x</span>
974
+ <span class="cline-any cline-yes">11x</span>
975
+ <span class="cline-any cline-yes">11x</span>
976
+ <span class="cline-any cline-yes">11x</span>
977
+ <span class="cline-any cline-yes">11x</span>
978
+ <span class="cline-any cline-yes">11x</span>
979
+ <span class="cline-any cline-yes">11x</span>
980
+ <span class="cline-any cline-yes">11x</span>
981
+ <span class="cline-any cline-no">&nbsp;</span>
982
+ <span class="cline-any cline-no">&nbsp;</span>
983
+ <span class="cline-any cline-yes">11x</span>
984
+ <span class="cline-any cline-yes">11x</span>
985
+ <span class="cline-any cline-neutral">&nbsp;</span>
986
+ <span class="cline-any cline-neutral">&nbsp;</span>
987
+ <span class="cline-any cline-neutral">&nbsp;</span>
988
+ <span class="cline-any cline-neutral">&nbsp;</span>
989
+ <span class="cline-any cline-neutral">&nbsp;</span>
990
+ <span class="cline-any cline-neutral">&nbsp;</span>
991
+ <span class="cline-any cline-yes">19x</span>
992
+ <span class="cline-any cline-no">&nbsp;</span>
993
+ <span class="cline-any cline-no">&nbsp;</span>
994
+ <span class="cline-any cline-no">&nbsp;</span>
995
+ <span class="cline-any cline-no">&nbsp;</span>
996
+ <span class="cline-any cline-no">&nbsp;</span>
997
+ <span class="cline-any cline-yes">19x</span>
998
+ <span class="cline-any cline-neutral">&nbsp;</span>
999
+ <span class="cline-any cline-neutral">&nbsp;</span>
1000
+ <span class="cline-any cline-neutral">&nbsp;</span>
1001
+ <span class="cline-any cline-neutral">&nbsp;</span>
1002
+ <span class="cline-any cline-yes">19x</span>
1003
+ <span class="cline-any cline-neutral">&nbsp;</span>
1004
+ <span class="cline-any cline-neutral">&nbsp;</span>
1005
+ <span class="cline-any cline-yes">19x</span>
1006
+ <span class="cline-any cline-neutral">&nbsp;</span>
1007
+ <span class="cline-any cline-yes">19x</span>
1008
+ <span class="cline-any cline-yes">19x</span>
1009
+ <span class="cline-any cline-neutral">&nbsp;</span>
1010
+ <span class="cline-any cline-neutral">&nbsp;</span>
1011
+ <span class="cline-any cline-neutral">&nbsp;</span>
1012
+ <span class="cline-any cline-neutral">&nbsp;</span>
1013
+ <span class="cline-any cline-neutral">&nbsp;</span>
1014
+ <span class="cline-any cline-neutral">&nbsp;</span>
1015
+ <span class="cline-any cline-yes">23x</span>
1016
+ <span class="cline-any cline-yes">19x</span>
1017
+ <span class="cline-any cline-neutral">&nbsp;</span>
1018
+ <span class="cline-any cline-yes">19x</span>
1019
+ <span class="cline-any cline-yes">19x</span>
1020
+ <span class="cline-any cline-yes">19x</span>
1021
+ <span class="cline-any cline-yes">19x</span>
1022
+ <span class="cline-any cline-yes">19x</span>
1023
+ <span class="cline-any cline-yes">19x</span>
1024
+ <span class="cline-any cline-no">&nbsp;</span>
1025
+ <span class="cline-any cline-no">&nbsp;</span>
1026
+ <span class="cline-any cline-no">&nbsp;</span>
1027
+ <span class="cline-any cline-no">&nbsp;</span>
1028
+ <span class="cline-any cline-no">&nbsp;</span>
1029
+ <span class="cline-any cline-no">&nbsp;</span>
1030
+ <span class="cline-any cline-yes">19x</span>
1031
+ <span class="cline-any cline-yes">19x</span>
1032
+ <span class="cline-any cline-neutral">&nbsp;</span>
1033
+ <span class="cline-any cline-neutral">&nbsp;</span>
1034
+ <span class="cline-any cline-yes">23x</span>
1035
+ <span class="cline-any cline-yes">24x</span>
1036
+ <span class="cline-any cline-yes">24x</span>
1037
+ <span class="cline-any cline-neutral">&nbsp;</span>
1038
+ <span class="cline-any cline-yes">24x</span>
1039
+ <span class="cline-any cline-yes">24x</span>
1040
+ <span class="cline-any cline-yes">24x</span>
1041
+ <span class="cline-any cline-yes">24x</span>
1042
+ <span class="cline-any cline-yes">24x</span>
1043
+ <span class="cline-any cline-no">&nbsp;</span>
1044
+ <span class="cline-any cline-yes">24x</span>
1045
+ <span class="cline-any cline-yes">24x</span>
1046
+ <span class="cline-any cline-yes">24x</span>
1047
+ <span class="cline-any cline-yes">24x</span>
1048
+ <span class="cline-any cline-yes">24x</span>
1049
+ <span class="cline-any cline-yes">24x</span>
1050
+ <span class="cline-any cline-yes">24x</span>
1051
+ <span class="cline-any cline-neutral">&nbsp;</span>
1052
+ <span class="cline-any cline-neutral">&nbsp;</span>
1053
+ <span class="cline-any cline-yes">24x</span>
1054
+ <span class="cline-any cline-yes">24x</span>
1055
+ <span class="cline-any cline-yes">24x</span>
1056
+ <span class="cline-any cline-neutral">&nbsp;</span>
1057
+ <span class="cline-any cline-neutral">&nbsp;</span>
1058
+ <span class="cline-any cline-yes">24x</span>
1059
+ <span class="cline-any cline-yes">24x</span>
1060
+ <span class="cline-any cline-yes">24x</span>
1061
+ <span class="cline-any cline-yes">24x</span>
1062
+ <span class="cline-any cline-yes">24x</span>
1063
+ <span class="cline-any cline-yes">24x</span>
1064
+ <span class="cline-any cline-neutral">&nbsp;</span>
1065
+ <span class="cline-any cline-neutral">&nbsp;</span>
1066
+ <span class="cline-any cline-neutral">&nbsp;</span>
1067
+ <span class="cline-any cline-neutral">&nbsp;</span>
1068
+ <span class="cline-any cline-neutral">&nbsp;</span>
1069
+ <span class="cline-any cline-yes">24x</span>
1070
+ <span class="cline-any cline-yes">24x</span>
1071
+ <span class="cline-any cline-yes">24x</span>
1072
+ <span class="cline-any cline-yes">24x</span>
1073
+ <span class="cline-any cline-yes">24x</span>
1074
+ <span class="cline-any cline-yes">24x</span>
1075
+ <span class="cline-any cline-yes">23x</span>
1076
+ <span class="cline-any cline-neutral">&nbsp;</span>
1077
+ <span class="cline-any cline-neutral">&nbsp;</span>
1078
+ <span class="cline-any cline-neutral">&nbsp;</span>
1079
+ <span class="cline-any cline-yes">24x</span>
1080
+ <span class="cline-any cline-yes">24x</span>
1081
+ <span class="cline-any cline-yes">24x</span>
1082
+ <span class="cline-any cline-yes">24x</span>
1083
+ <span class="cline-any cline-neutral">&nbsp;</span>
1084
+ <span class="cline-any cline-neutral">&nbsp;</span>
1085
+ <span class="cline-any cline-neutral">&nbsp;</span>
1086
+ <span class="cline-any cline-yes">24x</span>
1087
+ <span class="cline-any cline-yes">24x</span>
1088
+ <span class="cline-any cline-yes">24x</span>
1089
+ <span class="cline-any cline-yes">24x</span>
1090
+ <span class="cline-any cline-yes">24x</span>
1091
+ <span class="cline-any cline-neutral">&nbsp;</span>
1092
+ <span class="cline-any cline-yes">23x</span>
1093
+ <span class="cline-any cline-no">&nbsp;</span>
1094
+ <span class="cline-any cline-no">&nbsp;</span>
1095
+ <span class="cline-any cline-no">&nbsp;</span>
1096
+ <span class="cline-any cline-no">&nbsp;</span>
1097
+ <span class="cline-any cline-no">&nbsp;</span>
1098
+ <span class="cline-any cline-neutral">&nbsp;</span>
1099
+ <span class="cline-any cline-no">&nbsp;</span>
1100
+ <span class="cline-any cline-no">&nbsp;</span>
1101
+ <span class="cline-any cline-no">&nbsp;</span>
1102
+ <span class="cline-any cline-no">&nbsp;</span>
1103
+ <span class="cline-any cline-no">&nbsp;</span>
1104
+ <span class="cline-any cline-no">&nbsp;</span>
1105
+ <span class="cline-any cline-no">&nbsp;</span>
1106
+ <span class="cline-any cline-neutral">&nbsp;</span>
1107
+ <span class="cline-any cline-yes">23x</span>
1108
+ <span class="cline-any cline-yes">1x</span>
1109
+ <span class="cline-any cline-yes">1x</span>
1110
+ <span class="cline-any cline-yes">1x</span>
1111
+ <span class="cline-any cline-yes">1x</span>
1112
+ <span class="cline-any cline-yes">1x</span>
1113
+ <span class="cline-any cline-yes">1x</span>
1114
+ <span class="cline-any cline-yes">1x</span>
1115
+ <span class="cline-any cline-yes">1x</span>
1116
+ <span class="cline-any cline-neutral">&nbsp;</span>
1117
+ <span class="cline-any cline-yes">1x</span>
1118
+ <span class="cline-any cline-yes">1x</span>
1119
+ <span class="cline-any cline-yes">1x</span>
1120
+ <span class="cline-any cline-yes">1x</span>
1121
+ <span class="cline-any cline-yes">1x</span>
1122
+ <span class="cline-any cline-yes">1x</span>
1123
+ <span class="cline-any cline-neutral">&nbsp;</span>
1124
+ <span class="cline-any cline-yes">23x</span>
1125
+ <span class="cline-any cline-neutral">&nbsp;</span>
1126
+ <span class="cline-any cline-yes">14x</span>
1127
+ <span class="cline-any cline-yes">13x</span>
1128
+ <span class="cline-any cline-yes">13x</span>
1129
+ <span class="cline-any cline-yes">13x</span>
1130
+ <span class="cline-any cline-yes">13x</span>
1131
+ <span class="cline-any cline-neutral">&nbsp;</span>
1132
+ <span class="cline-any cline-neutral">&nbsp;</span>
1133
+ <span class="cline-any cline-yes">13x</span>
1134
+ <span class="cline-any cline-yes">13x</span>
1135
+ <span class="cline-any cline-yes">13x</span>
1136
+ <span class="cline-any cline-yes">14x</span>
1137
+ <span class="cline-any cline-yes">14x</span>
1138
+ <span class="cline-any cline-yes">14x</span>
1139
+ <span class="cline-any cline-yes">14x</span>
1140
+ <span class="cline-any cline-yes">14x</span>
1141
+ <span class="cline-any cline-yes">14x</span>
1142
+ <span class="cline-any cline-yes">14x</span>
1143
+ <span class="cline-any cline-yes">14x</span>
1144
+ <span class="cline-any cline-neutral">&nbsp;</span>
1145
+ <span class="cline-any cline-yes">23x</span>
1146
+ <span class="cline-any cline-yes">5x</span>
1147
+ <span class="cline-any cline-yes">5x</span>
1148
+ <span class="cline-any cline-yes">5x</span>
1149
+ <span class="cline-any cline-yes">5x</span>
1150
+ <span class="cline-any cline-yes">5x</span>
1151
+ <span class="cline-any cline-neutral">&nbsp;</span>
1152
+ <span class="cline-any cline-neutral">&nbsp;</span>
1153
+ <span class="cline-any cline-yes">5x</span>
1154
+ <span class="cline-any cline-yes">5x</span>
1155
+ <span class="cline-any cline-yes">5x</span>
1156
+ <span class="cline-any cline-yes">5x</span>
1157
+ <span class="cline-any cline-yes">5x</span>
1158
+ <span class="cline-any cline-yes">5x</span>
1159
+ <span class="cline-any cline-yes">5x</span>
1160
+ <span class="cline-any cline-neutral">&nbsp;</span>
1161
+ <span class="cline-any cline-yes">23x</span>
1162
+ <span class="cline-any cline-yes">25x</span>
1163
+ <span class="cline-any cline-yes">25x</span>
1164
+ <span class="cline-any cline-yes">25x</span>
1165
+ <span class="cline-any cline-yes">289x</span>
1166
+ <span class="cline-any cline-yes">289x</span>
1167
+ <span class="cline-any cline-yes">289x</span>
1168
+ <span class="cline-any cline-yes">289x</span>
1169
+ <span class="cline-any cline-yes">25x</span>
1170
+ <span class="cline-any cline-yes">25x</span>
1171
+ <span class="cline-any cline-neutral">&nbsp;</span>
1172
+ <span class="cline-any cline-yes">23x</span>
1173
+ <span class="cline-any cline-yes">412x</span>
1174
+ <span class="cline-any cline-yes">412x</span>
1175
+ <span class="cline-any cline-yes">412x</span>
1176
+ <span class="cline-any cline-neutral">&nbsp;</span>
1177
+ <span class="cline-any cline-yes">23x</span>
1178
+ <span class="cline-any cline-neutral">&nbsp;</span>
1179
+ <span class="cline-any cline-yes">431x</span>
1180
+ <span class="cline-any cline-yes">419x</span>
1181
+ <span class="cline-any cline-yes">419x</span>
1182
+ <span class="cline-any cline-yes">419x</span>
1183
+ <span class="cline-any cline-yes">419x</span>
1184
+ <span class="cline-any cline-yes">419x</span>
1185
+ <span class="cline-any cline-yes">419x</span>
1186
+ <span class="cline-any cline-yes">419x</span>
1187
+ <span class="cline-any cline-yes">431x</span>
1188
+ <span class="cline-any cline-neutral">&nbsp;</span>
1189
+ <span class="cline-any cline-neutral">&nbsp;</span>
1190
+ <span class="cline-any cline-yes">23x</span>
1191
+ <span class="cline-any cline-yes">12x</span>
1192
+ <span class="cline-any cline-no">&nbsp;</span>
1193
+ <span class="cline-any cline-yes">12x</span>
1194
+ <span class="cline-any cline-no">&nbsp;</span>
1195
+ <span class="cline-any cline-no">&nbsp;</span>
1196
+ <span class="cline-any cline-yes">12x</span>
1197
+ <span class="cline-any cline-neutral">&nbsp;</span>
1198
+ <span class="cline-any cline-neutral">&nbsp;</span>
1199
+ <span class="cline-any cline-neutral">&nbsp;</span>
1200
+ <span class="cline-any cline-neutral">&nbsp;</span>
1201
+ <span class="cline-any cline-neutral">&nbsp;</span>
1202
+ <span class="cline-any cline-neutral">&nbsp;</span>
1203
+ <span class="cline-any cline-yes">23x</span>
1204
+ <span class="cline-any cline-yes">13x</span>
1205
+ <span class="cline-any cline-yes">12x</span>
1206
+ <span class="cline-any cline-yes">12x</span>
1207
+ <span class="cline-any cline-yes">12x</span>
1208
+ <span class="cline-any cline-yes">12x</span>
1209
+ <span class="cline-any cline-yes">12x</span>
1210
+ <span class="cline-any cline-yes">12x</span>
1211
+ <span class="cline-any cline-yes">12x</span>
1212
+ <span class="cline-any cline-yes">12x</span>
1213
+ <span class="cline-any cline-yes">12x</span>
1214
+ <span class="cline-any cline-neutral">&nbsp;</span>
1215
+ <span class="cline-any cline-neutral">&nbsp;</span>
1216
+ <span class="cline-any cline-no">&nbsp;</span>
1217
+ <span class="cline-any cline-no">&nbsp;</span>
1218
+ <span class="cline-any cline-no">&nbsp;</span>
1219
+ <span class="cline-any cline-no">&nbsp;</span>
1220
+ <span class="cline-any cline-no">&nbsp;</span>
1221
+ <span class="cline-any cline-no">&nbsp;</span>
1222
+ <span class="cline-any cline-no">&nbsp;</span>
1223
+ <span class="cline-any cline-yes">12x</span>
1224
+ <span class="cline-any cline-yes">12x</span>
1225
+ <span class="cline-any cline-neutral">&nbsp;</span>
1226
+ <span class="cline-any cline-yes">12x</span>
1227
+ <span class="cline-any cline-yes">12x</span>
1228
+ <span class="cline-any cline-yes">12x</span>
1229
+ <span class="cline-any cline-yes">12x</span>
1230
+ <span class="cline-any cline-yes">13x</span>
1231
+ <span class="cline-any cline-neutral">&nbsp;</span>
1232
+ <span class="cline-any cline-yes">23x</span>
1233
+ <span class="cline-any cline-neutral">&nbsp;</span>
1234
+ <span class="cline-any cline-neutral">&nbsp;</span>
1235
+ <span class="cline-any cline-neutral">&nbsp;</span>
1236
+ <span class="cline-any cline-neutral">&nbsp;</span>
1237
+ <span class="cline-any cline-yes">24x</span>
1238
+ <span class="cline-any cline-yes">24x</span>
1239
+ <span class="cline-any cline-yes">24x</span>
1240
+ <span class="cline-any cline-yes">24x</span>
1241
+ <span class="cline-any cline-yes">24x</span>
1242
+ <span class="cline-any cline-yes">24x</span>
1243
+ <span class="cline-any cline-yes">24x</span>
1244
+ <span class="cline-any cline-yes">24x</span>
1245
+ <span class="cline-any cline-yes">24x</span>
1246
+ <span class="cline-any cline-yes">24x</span>
1247
+ <span class="cline-any cline-yes">24x</span>
1248
+ <span class="cline-any cline-yes">24x</span>
1249
+ <span class="cline-any cline-yes">24x</span>
1250
+ <span class="cline-any cline-yes">24x</span>
1251
+ <span class="cline-any cline-yes">24x</span>
1252
+ <span class="cline-any cline-yes">24x</span>
1253
+ <span class="cline-any cline-yes">24x</span>
1254
+ <span class="cline-any cline-yes">24x</span>
1255
+ <span class="cline-any cline-yes">24x</span>
1256
+ <span class="cline-any cline-neutral">&nbsp;</span>
1257
+ <span class="cline-any cline-neutral">&nbsp;</span>
1258
+ <span class="cline-any cline-yes">24x</span>
1259
+ <span class="cline-any cline-no">&nbsp;</span>
1260
+ <span class="cline-any cline-yes">24x</span>
1261
+ <span class="cline-any cline-yes">24x</span>
1262
+ <span class="cline-any cline-neutral">&nbsp;</span>
1263
+ <span class="cline-any cline-neutral">&nbsp;</span>
1264
+ <span class="cline-any cline-neutral">&nbsp;</span>
1265
+ <span class="cline-any cline-yes">24x</span>
1266
+ <span class="cline-any cline-neutral">&nbsp;</span>
1267
+ <span class="cline-any cline-neutral">&nbsp;</span>
1268
+ <span class="cline-any cline-yes">24x</span>
1269
+ <span class="cline-any cline-neutral">&nbsp;</span>
1270
+ <span class="cline-any cline-yes">24x</span>
1271
+ <span class="cline-any cline-yes">24x</span>
1272
+ <span class="cline-any cline-yes">24x</span>
1273
+ <span class="cline-any cline-yes">24x</span>
1274
+ <span class="cline-any cline-neutral">&nbsp;</span>
1275
+ <span class="cline-any cline-neutral">&nbsp;</span>
1276
+ <span class="cline-any cline-neutral">&nbsp;</span>
1277
+ <span class="cline-any cline-neutral">&nbsp;</span>
1278
+ <span class="cline-any cline-neutral">&nbsp;</span>
1279
+ <span class="cline-any cline-neutral">&nbsp;</span>
1280
+ <span class="cline-any cline-neutral">&nbsp;</span>
1281
+ <span class="cline-any cline-yes">23x</span>
1282
+ <span class="cline-any cline-no">&nbsp;</span>
1283
+ <span class="cline-any cline-neutral">&nbsp;</span>
1284
+ <span class="cline-any cline-no">&nbsp;</span>
1285
+ <span class="cline-any cline-no">&nbsp;</span>
1286
+ <span class="cline-any cline-no">&nbsp;</span>
1287
+ <span class="cline-any cline-no">&nbsp;</span>
1288
+ <span class="cline-any cline-no">&nbsp;</span>
1289
+ <span class="cline-any cline-no">&nbsp;</span>
1290
+ <span class="cline-any cline-no">&nbsp;</span>
1291
+ <span class="cline-any cline-no">&nbsp;</span>
1292
+ <span class="cline-any cline-no">&nbsp;</span>
1293
+ <span class="cline-any cline-no">&nbsp;</span>
1294
+ <span class="cline-any cline-no">&nbsp;</span>
1295
+ <span class="cline-any cline-no">&nbsp;</span>
1296
+ <span class="cline-any cline-neutral">&nbsp;</span>
1297
+ <span class="cline-any cline-no">&nbsp;</span>
1298
+ <span class="cline-any cline-no">&nbsp;</span>
1299
+ <span class="cline-any cline-no">&nbsp;</span>
1300
+ <span class="cline-any cline-no">&nbsp;</span>
1301
+ <span class="cline-any cline-no">&nbsp;</span>
1302
+ <span class="cline-any cline-neutral">&nbsp;</span>
1303
+ <span class="cline-any cline-no">&nbsp;</span>
1304
+ <span class="cline-any cline-no">&nbsp;</span>
1305
+ <span class="cline-any cline-no">&nbsp;</span>
1306
+ <span class="cline-any cline-no">&nbsp;</span>
1307
+ <span class="cline-any cline-no">&nbsp;</span>
1308
+ <span class="cline-any cline-no">&nbsp;</span>
1309
+ <span class="cline-any cline-no">&nbsp;</span>
1310
+ <span class="cline-any cline-no">&nbsp;</span>
1311
+ <span class="cline-any cline-no">&nbsp;</span>
1312
+ <span class="cline-any cline-neutral">&nbsp;</span>
1313
+ <span class="cline-any cline-no">&nbsp;</span>
1314
+ <span class="cline-any cline-neutral">&nbsp;</span>
1315
+ <span class="cline-any cline-no">&nbsp;</span>
1316
+ <span class="cline-any cline-no">&nbsp;</span>
1317
+ <span class="cline-any cline-no">&nbsp;</span>
1318
+ <span class="cline-any cline-no">&nbsp;</span>
1319
+ <span class="cline-any cline-no">&nbsp;</span>
1320
+ <span class="cline-any cline-no">&nbsp;</span>
1321
+ <span class="cline-any cline-no">&nbsp;</span>
1322
+ <span class="cline-any cline-no">&nbsp;</span>
1323
+ <span class="cline-any cline-neutral">&nbsp;</span>
1324
+ <span class="cline-any cline-no">&nbsp;</span>
1325
+ <span class="cline-any cline-no">&nbsp;</span>
1326
+ <span class="cline-any cline-no">&nbsp;</span>
1327
+ <span class="cline-any cline-no">&nbsp;</span>
1328
+ <span class="cline-any cline-neutral">&nbsp;</span>
1329
+ <span class="cline-any cline-no">&nbsp;</span>
1330
+ <span class="cline-any cline-no">&nbsp;</span>
1331
+ <span class="cline-any cline-no">&nbsp;</span>
1332
+ <span class="cline-any cline-no">&nbsp;</span>
1333
+ <span class="cline-any cline-no">&nbsp;</span>
1334
+ <span class="cline-any cline-no">&nbsp;</span>
1335
+ <span class="cline-any cline-no">&nbsp;</span>
1336
+ <span class="cline-any cline-no">&nbsp;</span>
1337
+ <span class="cline-any cline-neutral">&nbsp;</span>
1338
+ <span class="cline-any cline-no">&nbsp;</span>
1339
+ <span class="cline-any cline-no">&nbsp;</span>
1340
+ <span class="cline-any cline-neutral">&nbsp;</span>
1341
+ <span class="cline-any cline-neutral">&nbsp;</span>
1342
+ <span class="cline-any cline-yes">23x</span>
1343
+ <span class="cline-any cline-no">&nbsp;</span>
1344
+ <span class="cline-any cline-no">&nbsp;</span>
1345
+ <span class="cline-any cline-no">&nbsp;</span>
1346
+ <span class="cline-any cline-no">&nbsp;</span>
1347
+ <span class="cline-any cline-no">&nbsp;</span>
1348
+ <span class="cline-any cline-no">&nbsp;</span>
1349
+ <span class="cline-any cline-no">&nbsp;</span>
1350
+ <span class="cline-any cline-neutral">&nbsp;</span>
1351
+ <span class="cline-any cline-neutral">&nbsp;</span>
1352
+ <span class="cline-any cline-neutral">&nbsp;</span>
1353
+ <span class="cline-any cline-neutral">&nbsp;</span>
1354
+ <span class="cline-any cline-neutral">&nbsp;</span>
1355
+ <span class="cline-any cline-neutral">&nbsp;</span>
1356
+ <span class="cline-any cline-neutral">&nbsp;</span>
1357
+ <span class="cline-any cline-neutral">&nbsp;</span>
1358
+ <span class="cline-any cline-yes">23x</span>
1359
+ <span class="cline-any cline-neutral">&nbsp;</span>
1360
+ <span class="cline-any cline-yes">461x</span>
1361
+ <span class="cline-any cline-yes">440x</span>
1362
+ <span class="cline-any cline-neutral">&nbsp;</span>
1363
+ <span class="cline-any cline-yes">440x</span>
1364
+ <span class="cline-any cline-neutral">&nbsp;</span>
1365
+ <span class="cline-any cline-neutral">&nbsp;</span>
1366
+ <span class="cline-any cline-neutral">&nbsp;</span>
1367
+ <span class="cline-any cline-neutral">&nbsp;</span>
1368
+ <span class="cline-any cline-neutral">&nbsp;</span>
1369
+ <span class="cline-any cline-yes">27x</span>
1370
+ <span class="cline-any cline-yes">27x</span>
1371
+ <span class="cline-any cline-yes">27x</span>
1372
+ <span class="cline-any cline-yes">23x</span>
1373
+ <span class="cline-any cline-neutral">&nbsp;</span>
1374
+ <span class="cline-any cline-yes">23x</span>
1375
+ <span class="cline-any cline-yes">27x</span>
1376
+ <span class="cline-any cline-yes">461x</span>
1377
+ <span class="cline-any cline-neutral">&nbsp;</span>
1378
+ <span class="cline-any cline-yes">23x</span>
1379
+ <span class="cline-any cline-yes">22x</span>
1380
+ <span class="cline-any cline-yes">22x</span>
1381
+ <span class="cline-any cline-yes">22x</span>
1382
+ <span class="cline-any cline-yes">22x</span>
1383
+ <span class="cline-any cline-yes">22x</span>
1384
+ <span class="cline-any cline-yes">22x</span>
1385
+ <span class="cline-any cline-yes">22x</span>
1386
+ <span class="cline-any cline-yes">22x</span>
1387
+ <span class="cline-any cline-yes">22x</span>
1388
+ <span class="cline-any cline-yes">22x</span>
1389
+ <span class="cline-any cline-neutral">&nbsp;</span>
1390
+ <span class="cline-any cline-yes">23x</span>
1391
+ <span class="cline-any cline-yes">4097x</span>
1392
+ <span class="cline-any cline-no">&nbsp;</span>
1393
+ <span class="cline-any cline-no">&nbsp;</span>
1394
+ <span class="cline-any cline-neutral">&nbsp;</span>
1395
+ <span class="cline-any cline-yes">4097x</span>
1396
+ <span class="cline-any cline-yes">48x</span>
1397
+ <span class="cline-any cline-yes">48x</span>
1398
+ <span class="cline-any cline-neutral">&nbsp;</span>
1399
+ <span class="cline-any cline-yes">4097x</span>
1400
+ <span class="cline-any cline-no">&nbsp;</span>
1401
+ <span class="cline-any cline-no">&nbsp;</span>
1402
+ <span class="cline-any cline-neutral">&nbsp;</span>
1403
+ <span class="cline-any cline-yes">4097x</span>
1404
+ <span class="cline-any cline-yes">126x</span>
1405
+ <span class="cline-any cline-yes">1x</span>
1406
+ <span class="cline-any cline-yes">1x</span>
1407
+ <span class="cline-any cline-yes">125x</span>
1408
+ <span class="cline-any cline-yes">125x</span>
1409
+ <span class="cline-any cline-yes">125x</span>
1410
+ <span class="cline-any cline-neutral">&nbsp;</span>
1411
+ <span class="cline-any cline-yes">4097x</span>
1412
+ <span class="cline-any cline-no">&nbsp;</span>
1413
+ <span class="cline-any cline-no">&nbsp;</span>
1414
+ <span class="cline-any cline-neutral">&nbsp;</span>
1415
+ <span class="cline-any cline-yes">4097x</span>
1416
+ <span class="cline-any cline-no">&nbsp;</span>
1417
+ <span class="cline-any cline-no">&nbsp;</span>
1418
+ <span class="cline-any cline-neutral">&nbsp;</span>
1419
+ <span class="cline-any cline-yes">4097x</span>
1420
+ <span class="cline-any cline-yes">1563x</span>
1421
+ <span class="cline-any cline-no">&nbsp;</span>
1422
+ <span class="cline-any cline-no">&nbsp;</span>
1423
+ <span class="cline-any cline-yes">1563x</span>
1424
+ <span class="cline-any cline-neutral">&nbsp;</span>
1425
+ <span class="cline-any cline-yes">1563x</span>
1426
+ <span class="cline-any cline-yes">1563x</span>
1427
+ <span class="cline-any cline-yes">3107x</span>
1428
+ <span class="cline-any cline-neutral">&nbsp;</span>
1429
+ <span class="cline-any cline-neutral">&nbsp;</span>
1430
+ <span class="cline-any cline-neutral">&nbsp;</span>
1431
+ <span class="cline-any cline-yes">3107x</span>
1432
+ <span class="cline-any cline-yes">3005x</span>
1433
+ <span class="cline-any cline-yes">3005x</span>
1434
+ <span class="cline-any cline-yes">3107x</span>
1435
+ <span class="cline-any cline-yes">1563x</span>
1436
+ <span class="cline-any cline-yes">1563x</span>
1437
+ <span class="cline-any cline-neutral">&nbsp;</span>
1438
+ <span class="cline-any cline-yes">2360x</span>
1439
+ <span class="cline-any cline-yes">4097x</span>
1440
+ <span class="cline-any cline-neutral">&nbsp;</span>
1441
+ <span class="cline-any cline-neutral">&nbsp;</span>
1442
+ <span class="cline-any cline-neutral">&nbsp;</span>
1443
+ <span class="cline-any cline-neutral">&nbsp;</span>
1444
+ <span class="cline-any cline-neutral">&nbsp;</span>
1445
+ <span class="cline-any cline-neutral">&nbsp;</span>
1446
+ <span class="cline-any cline-yes">23x</span>
1447
+ <span class="cline-any cline-yes">8x</span>
1448
+ <span class="cline-any cline-yes">8x</span>
1449
+ <span class="cline-any cline-neutral">&nbsp;</span>
1450
+ <span class="cline-any cline-yes">23x</span>
1451
+ <span class="cline-any cline-yes">19x</span>
1452
+ <span class="cline-any cline-yes">11x</span>
1453
+ <span class="cline-any cline-yes">11x</span>
1454
+ <span class="cline-any cline-yes">11x</span>
1455
+ <span class="cline-any cline-neutral">&nbsp;</span>
1456
+ <span class="cline-any cline-neutral">&nbsp;</span>
1457
+ <span class="cline-any cline-neutral">&nbsp;</span>
1458
+ <span class="cline-any cline-yes">11x</span>
1459
+ <span class="cline-any cline-yes">2x</span>
1460
+ <span class="cline-any cline-yes">2x</span>
1461
+ <span class="cline-any cline-yes">2x</span>
1462
+ <span class="cline-any cline-yes">1x</span>
1463
+ <span class="cline-any cline-yes">1x</span>
1464
+ <span class="cline-any cline-yes">1x</span>
1465
+ <span class="cline-any cline-yes">1x</span>
1466
+ <span class="cline-any cline-yes">1x</span>
1467
+ <span class="cline-any cline-yes">1x</span>
1468
+ <span class="cline-any cline-yes">2x</span>
1469
+ <span class="cline-any cline-neutral">&nbsp;</span>
1470
+ <span class="cline-any cline-neutral">&nbsp;</span>
1471
+ <span class="cline-any cline-neutral">&nbsp;</span>
1472
+ <span class="cline-any cline-neutral">&nbsp;</span>
1473
+ <span class="cline-any cline-neutral">&nbsp;</span>
1474
+ <span class="cline-any cline-yes">11x</span>
1475
+ <span class="cline-any cline-yes">11x</span>
1476
+ <span class="cline-any cline-no">&nbsp;</span>
1477
+ <span class="cline-any cline-yes">11x</span>
1478
+ <span class="cline-any cline-no">&nbsp;</span>
1479
+ <span class="cline-any cline-yes">11x</span>
1480
+ <span class="cline-any cline-no">&nbsp;</span>
1481
+ <span class="cline-any cline-yes">11x</span>
1482
+ <span class="cline-any cline-yes">11x</span>
1483
+ <span class="cline-any cline-no">&nbsp;</span>
1484
+ <span class="cline-any cline-no">&nbsp;</span>
1485
+ <span class="cline-any cline-no">&nbsp;</span>
1486
+ <span class="cline-any cline-yes">11x</span>
1487
+ <span class="cline-any cline-yes">11x</span>
1488
+ <span class="cline-any cline-yes">11x</span>
1489
+ <span class="cline-any cline-yes">11x</span>
1490
+ <span class="cline-any cline-no">&nbsp;</span>
1491
+ <span class="cline-any cline-neutral">&nbsp;</span>
1492
+ <span class="cline-any cline-neutral">&nbsp;</span>
1493
+ <span class="cline-any cline-neutral">&nbsp;</span>
1494
+ <span class="cline-any cline-no">&nbsp;</span>
1495
+ <span class="cline-any cline-neutral">&nbsp;</span>
1496
+ <span class="cline-any cline-no">&nbsp;</span>
1497
+ <span class="cline-any cline-neutral">&nbsp;</span>
1498
+ <span class="cline-any cline-no">&nbsp;</span>
1499
+ <span class="cline-any cline-no">&nbsp;</span>
1500
+ <span class="cline-any cline-no">&nbsp;</span>
1501
+ <span class="cline-any cline-neutral">&nbsp;</span>
1502
+ <span class="cline-any cline-no">&nbsp;</span>
1503
+ <span class="cline-any cline-no">&nbsp;</span>
1504
+ <span class="cline-any cline-no">&nbsp;</span>
1505
+ <span class="cline-any cline-no">&nbsp;</span>
1506
+ <span class="cline-any cline-no">&nbsp;</span>
1507
+ <span class="cline-any cline-no">&nbsp;</span>
1508
+ <span class="cline-any cline-no">&nbsp;</span>
1509
+ <span class="cline-any cline-neutral">&nbsp;</span>
1510
+ <span class="cline-any cline-no">&nbsp;</span>
1511
+ <span class="cline-any cline-no">&nbsp;</span>
1512
+ <span class="cline-any cline-neutral">&nbsp;</span>
1513
+ <span class="cline-any cline-no">&nbsp;</span>
1514
+ <span class="cline-any cline-no">&nbsp;</span>
1515
+ <span class="cline-any cline-no">&nbsp;</span>
1516
+ <span class="cline-any cline-neutral">&nbsp;</span>
1517
+ <span class="cline-any cline-no">&nbsp;</span>
1518
+ <span class="cline-any cline-no">&nbsp;</span>
1519
+ <span class="cline-any cline-neutral">&nbsp;</span>
1520
+ <span class="cline-any cline-no">&nbsp;</span>
1521
+ <span class="cline-any cline-no">&nbsp;</span>
1522
+ <span class="cline-any cline-no">&nbsp;</span>
1523
+ <span class="cline-any cline-no">&nbsp;</span>
1524
+ <span class="cline-any cline-no">&nbsp;</span>
1525
+ <span class="cline-any cline-no">&nbsp;</span>
1526
+ <span class="cline-any cline-no">&nbsp;</span>
1527
+ <span class="cline-any cline-no">&nbsp;</span>
1528
+ <span class="cline-any cline-no">&nbsp;</span>
1529
+ <span class="cline-any cline-yes">11x</span>
1530
+ <span class="cline-any cline-no">&nbsp;</span>
1531
+ <span class="cline-any cline-no">&nbsp;</span>
1532
+ <span class="cline-any cline-no">&nbsp;</span>
1533
+ <span class="cline-any cline-no">&nbsp;</span>
1534
+ <span class="cline-any cline-no">&nbsp;</span>
1535
+ <span class="cline-any cline-no">&nbsp;</span>
1536
+ <span class="cline-any cline-no">&nbsp;</span>
1537
+ <span class="cline-any cline-no">&nbsp;</span>
1538
+ <span class="cline-any cline-no">&nbsp;</span>
1539
+ <span class="cline-any cline-no">&nbsp;</span>
1540
+ <span class="cline-any cline-no">&nbsp;</span>
1541
+ <span class="cline-any cline-yes">11x</span>
1542
+ <span class="cline-any cline-no">&nbsp;</span>
1543
+ <span class="cline-any cline-no">&nbsp;</span>
1544
+ <span class="cline-any cline-no">&nbsp;</span>
1545
+ <span class="cline-any cline-no">&nbsp;</span>
1546
+ <span class="cline-any cline-no">&nbsp;</span>
1547
+ <span class="cline-any cline-no">&nbsp;</span>
1548
+ <span class="cline-any cline-no">&nbsp;</span>
1549
+ <span class="cline-any cline-yes">11x</span>
1550
+ <span class="cline-any cline-no">&nbsp;</span>
1551
+ <span class="cline-any cline-no">&nbsp;</span>
1552
+ <span class="cline-any cline-no">&nbsp;</span>
1553
+ <span class="cline-any cline-no">&nbsp;</span>
1554
+ <span class="cline-any cline-no">&nbsp;</span>
1555
+ <span class="cline-any cline-no">&nbsp;</span>
1556
+ <span class="cline-any cline-neutral">&nbsp;</span>
1557
+ <span class="cline-any cline-no">&nbsp;</span>
1558
+ <span class="cline-any cline-no">&nbsp;</span>
1559
+ <span class="cline-any cline-no">&nbsp;</span>
1560
+ <span class="cline-any cline-neutral">&nbsp;</span>
1561
+ <span class="cline-any cline-no">&nbsp;</span>
1562
+ <span class="cline-any cline-no">&nbsp;</span>
1563
+ <span class="cline-any cline-no">&nbsp;</span>
1564
+ <span class="cline-any cline-no">&nbsp;</span>
1565
+ <span class="cline-any cline-no">&nbsp;</span>
1566
+ <span class="cline-any cline-no">&nbsp;</span>
1567
+ <span class="cline-any cline-no">&nbsp;</span>
1568
+ <span class="cline-any cline-no">&nbsp;</span>
1569
+ <span class="cline-any cline-no">&nbsp;</span>
1570
+ <span class="cline-any cline-no">&nbsp;</span>
1571
+ <span class="cline-any cline-neutral">&nbsp;</span>
1572
+ <span class="cline-any cline-neutral">&nbsp;</span>
1573
+ <span class="cline-any cline-no">&nbsp;</span>
1574
+ <span class="cline-any cline-no">&nbsp;</span>
1575
+ <span class="cline-any cline-no">&nbsp;</span>
1576
+ <span class="cline-any cline-neutral">&nbsp;</span>
1577
+ <span class="cline-any cline-no">&nbsp;</span>
1578
+ <span class="cline-any cline-no">&nbsp;</span>
1579
+ <span class="cline-any cline-no">&nbsp;</span>
1580
+ <span class="cline-any cline-no">&nbsp;</span>
1581
+ <span class="cline-any cline-no">&nbsp;</span>
1582
+ <span class="cline-any cline-no">&nbsp;</span>
1583
+ <span class="cline-any cline-no">&nbsp;</span>
1584
+ <span class="cline-any cline-no">&nbsp;</span>
1585
+ <span class="cline-any cline-neutral">&nbsp;</span>
1586
+ <span class="cline-any cline-no">&nbsp;</span>
1587
+ <span class="cline-any cline-no">&nbsp;</span>
1588
+ <span class="cline-any cline-no">&nbsp;</span>
1589
+ <span class="cline-any cline-no">&nbsp;</span>
1590
+ <span class="cline-any cline-no">&nbsp;</span>
1591
+ <span class="cline-any cline-no">&nbsp;</span>
1592
+ <span class="cline-any cline-no">&nbsp;</span>
1593
+ <span class="cline-any cline-no">&nbsp;</span>
1594
+ <span class="cline-any cline-no">&nbsp;</span>
1595
+ <span class="cline-any cline-no">&nbsp;</span>
1596
+ <span class="cline-any cline-neutral">&nbsp;</span>
1597
+ <span class="cline-any cline-no">&nbsp;</span>
1598
+ <span class="cline-any cline-no">&nbsp;</span>
1599
+ <span class="cline-any cline-no">&nbsp;</span>
1600
+ <span class="cline-any cline-no">&nbsp;</span>
1601
+ <span class="cline-any cline-no">&nbsp;</span>
1602
+ <span class="cline-any cline-yes">11x</span>
1603
+ <span class="cline-any cline-neutral">&nbsp;</span>
1604
+ <span class="cline-any cline-yes">11x</span>
1605
+ <span class="cline-any cline-yes">11x</span>
1606
+ <span class="cline-any cline-yes">11x</span>
1607
+ <span class="cline-any cline-yes">11x</span>
1608
+ <span class="cline-any cline-yes">11x</span>
1609
+ <span class="cline-any cline-yes">11x</span>
1610
+ <span class="cline-any cline-yes">11x</span>
1611
+ <span class="cline-any cline-yes">11x</span>
1612
+ <span class="cline-any cline-neutral">&nbsp;</span>
1613
+ <span class="cline-any cline-neutral">&nbsp;</span>
1614
+ <span class="cline-any cline-yes">11x</span>
1615
+ <span class="cline-any cline-yes">11x</span>
1616
+ <span class="cline-any cline-yes">19x</span>
1617
+ <span class="cline-any cline-yes">23x</span>
1618
+ <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import type { LocalStore, RemoteDatabaseService } from '../../services/database/index';
1619
+ import type { Logger } from '../../services/logger/index';
1620
+ import type { SchemaStructure } from '@spooky-sync/query-builder';
1621
+ import { RecordId } from 'surrealdb';
1622
+ import type { StreamUpdate, StreamUpdateReceiver } from '../../services/stream-processor/index';
1623
+ import { encodeRecordId } from '../../utils/index';
1624
+ &nbsp;
1625
+ // DevTools interfaces (matching extension expectations)
1626
+ export interface DevToolsEvent {
1627
+ id: number;
1628
+ timestamp: number;
1629
+ eventType: string;
1630
+ payload: any;
1631
+ }
1632
+ &nbsp;
1633
+ import type { QueryState, QueryTimings } from '../../types';
1634
+ import type { AuthService } from '../auth/index';
1635
+ import { AuthEventTypes } from '../auth/events/index';
1636
+ import {
1637
+ type BackendInfo,
1638
+ emptyBackendInfo,
1639
+ parseBackendInfo,
1640
+ UNAVAILABLE,
1641
+ } from './versions';
1642
+ import { walkOpfs, type BlobCacheInfo, type SharedTabsInfo, type StorageInfo } from './storage-info';
1643
+ import { FlagsAdminService, type LocalOverrideStore } from './flags';
1644
+ &nbsp;
1645
+ // Real bundled frontend versions, injected at build time by tsdown's
1646
+ // version-define plugin (see tsdown.config.ts). The `typeof` guard keeps these
1647
+ // from throwing a ReferenceError when a downstream app bundles core from source
1648
+ // (where the plugin never runs); in that case they fall back to 'unknown' and
1649
+ // DevTools simply reports an unknown frontend version instead of crashing.
1650
+ const CORE_VERSION =
1651
+ typeof __SP00KY_CORE_VERSION__ !== <span class="branch-0 cbranch-no" title="branch not covered" >'undefined' ? __SP00KY_CORE_VERSION__ : '</span>unknown';
1652
+ const WASM_VERSION =
1653
+ typeof __SP00KY_WASM_VERSION__ !== <span class="branch-0 cbranch-no" title="branch not covered" >'undefined' ? __SP00KY_WASM_VERSION__ : '</span>unknown';
1654
+ const SURREAL_VERSION =
1655
+ typeof __SP00KY_SURREAL_VERSION__ !== <span class="branch-0 cbranch-no" title="branch not covered" >'undefined' ? __SP00KY_SURREAL_VERSION__ : '</span>unknown';
1656
+ &nbsp;
1657
+ /** What DevTools reads about live queries; the runtime derives it from state. */
1658
+ export interface DevToolsQuerySource {
1659
+ getActiveQueries(): QueryState[];
1660
+ getQueryById(id: RecordId&lt;string&gt;): QueryState | undefined;
1661
+ phaseTimings(q: QueryState): QueryTimings;
1662
+ }
1663
+ &nbsp;
1664
+ export class DevToolsService implements StreamUpdateReceiver {
1665
+ private eventsHistory: DevToolsEvent[] = [];
1666
+ private eventIdCounter = 0;
1667
+ // Real bundled frontend version (injected at build time via tsdown `define`).
1668
+ private version = CORE_VERSION;
1669
+ // Backend stack info (versions + per-entity status), read via the
1670
+ // `fn::spooky::info()` SurrealQL function; empty/'unavailable' until resolved.
1671
+ private backendInfo: BackendInfo = emptyBackendInfo();
1672
+ // Dormant until a devtools consumer (extension panel or MCP) handshakes via
1673
+ // `SP00KY_DEVTOOLS_CONNECT`. While false, `notifyDevTools()`/`addEvent()` do no
1674
+ // work, so prod pays zero serialization/postMessage cost for an unwatched panel.
1675
+ // `window.__00__.getState()` stays live regardless, so the panel's first paint
1676
+ // (the on-demand GET_STATE pull) still works before the push channel turns on.
1677
+ private enabled = false;
1678
+ &nbsp;
1679
+ // A state push serializes EVERY active query's full record set (see
1680
+ // `getActiveQueries`) and postMessage clones it again, so its cost scales with
1681
+ // the whole client dataset — and it is triggered per event, including one per
1682
+ // local DB query (`DATABASE_LOCAL_QUERY` → `logEvent`). Unthrottled, a single
1683
+ // page load's few hundred local queries turn a handful of MB of rows into GBs
1684
+ // of short-lived large-object garbage and OOM the renderer (V8
1685
+ // "young object promotion failed"). Coalesce instead: push immediately when
1686
+ // idle, then at most once per window, always serializing the LATEST state.
1687
+ private static readonly NOTIFY_MIN_INTERVAL_MS = 250;
1688
+ private notifyTimer: ReturnType&lt;typeof setTimeout&gt; | null = null;
1689
+ private lastNotifyAt = 0;
1690
+ /** How many ids a pushed state carries per view; the rest is on demand. */
1691
+ private static readonly STATE_IDS_CAP = 200;
1692
+ /** devtools numeric hash -&gt; the query's `_00_query` id, for on-demand rows. */
1693
+ private hashToQuery = new Map&lt;number, unknown&gt;();
1694
+ &nbsp;
1695
+ /** Shared-tabs snapshot for the panel, wired by Sp00kyClient whenever the
1696
+ * feature was REQUESTED (so an inactive/degraded tab still reports why). */
1697
+ private tabsInfoProvider: (() =&gt; SharedTabsInfo | null) | null = null;
1698
+ &nbsp;
1699
+ setTabsInfoProvider(provider: () =&gt; SharedTabsInfo | null): void {
1700
+ this.tabsInfoProvider = provider;
1701
+ }
1702
+ &nbsp;
1703
+ /** Blob cache counters for the panel, wired by Sp00kyClient. */
1704
+ private blobInfoProvider: (() =&gt; BlobCacheInfo) | null = null;
1705
+ &nbsp;
1706
+ setBlobInfoProvider(provider: () =&gt; BlobCacheInfo): void {
1707
+ this.blobInfoProvider = provider;
1708
+ }
1709
+ &nbsp;
1710
+ // Full local table list (incl. internal `_00_*`), enumerated from the local DB
1711
+ // via our own reliable `service.query` — the DevTools panel's page-eval query
1712
+ // bridge is unreliable under load, so the panel relies on this instead.
1713
+ private localTables: string[] = [];
1714
+ private localTablesFetching = false;
1715
+ private localTablesAt = 0;
1716
+ &nbsp;
1717
+ // Feature flag admin, backing the panel's Access tab. The local-override
1718
+ // store is injected later (`setFeatureFlagOverrides`) because the
1719
+ // FeatureFlagModule is built after this service.
1720
+ private featureOverrides: LocalOverrideStore | null = null;
1721
+ private readonly flagsAdmin: FlagsAdminService;
1722
+ &nbsp;
1723
+ constructor(
1724
+ private databaseService: LocalStore,
1725
+ private remoteDatabaseService: RemoteDatabaseService,
1726
+ private logger: Logger,
1727
+ private schema: SchemaStructure,
1728
+ private authService: AuthService&lt;SchemaStructure&gt;,
1729
+ private dataManager?: DevToolsQuerySource
1730
+ ) {
1731
+ this.flagsAdmin = new FlagsAdminService({
1732
+ remote: this.remoteDatabaseService,
1733
+ local: this.databaseService,
1734
+ logger: this.logger,
1735
+ currentUserId: <span class="fstat-no" title="function not covered" >() =&gt; {</span>
1736
+ <span class="cstat-no" title="statement not covered" > const id = this.authService.currentUser?.id;</span>
1737
+ <span class="cstat-no" title="statement not covered" > if (!id) return null;</span>
1738
+ <span class="cstat-no" title="statement not covered" > return id instanceof RecordId ? encodeRecordId(id) : String(id);</span>
1739
+ <span class="cstat-no" title="statement not covered" > },</span>
1740
+ overrides: <span class="fstat-no" title="function not covered" >() =&gt; this.featureOverrides,</span>
1741
+ });
1742
+ &nbsp;
1743
+ this.exposeToWindow();
1744
+ &nbsp;
1745
+ // Stay dormant until a devtools consumer announces itself. The extension's
1746
+ // page-script posts this once it detects `window.__00__`; the panel can also
1747
+ // disconnect to return us to dormant. Until then we skip all serialization.
1748
+ if (typeof window !== 'undefined') {
1749
+ window.addEventListener('message', (e) =&gt; {
1750
+ if (e.source !== window) <span class="branch-0 cbranch-no" title="branch not covered" >return;</span>
1751
+ const type = (e.data as { type?: string } | undefined)?.type;
1752
+ if (type === 'SP00KY_DEVTOOLS_CONNECT') {
1753
+ this.enabled = true;
1754
+ this.refreshLocalTables();
1755
+ this.notifyDevTools();
1756
+ <span class="branch-0 cbranch-no" title="branch not covered" > } else if (type === 'SP00KY_DEVTOOLS_DISCONNECT') {</span>
1757
+ <span class="cstat-no" title="statement not covered" > this.enabled = false;</span>
1758
+ <span class="cstat-no" title="statement not covered" > }</span>
1759
+ });
1760
+ }
1761
+ &nbsp;
1762
+ // Subscribe to auth events. The initial fire-and-forget version fetch (below)
1763
+ // races the remote connection; on the free plan the remote DB (SurrealDB
1764
+ // Cloud) has no guest access, so `fn::spooky::info()` is only callable once
1765
+ // signed in. Re-fetch when auth resolves — until the versions actually land —
1766
+ // instead of leaving them 'unavailable' forever.
1767
+ this.authService.eventSystem.subscribe(AuthEventTypes.AuthStateChanged, () =&gt; {
1768
+ <span class="cstat-no" title="statement not covered" > if (this.authService.isAuthenticated &amp;&amp; this.backendInfo.versions.ssp === UNAVAILABLE) {</span>
1769
+ <span class="cstat-no" title="statement not covered" > void this.refreshBackendVersions();</span>
1770
+ <span class="cstat-no" title="statement not covered" > } else {</span>
1771
+ <span class="cstat-no" title="statement not covered" > this.notifyDevTools();</span>
1772
+ <span class="cstat-no" title="statement not covered" > }</span>
1773
+ });
1774
+ &nbsp;
1775
+ // Push state when the local store reports its durability (the open happens
1776
+ // during connect, typically before a panel attaches, so this mostly matters
1777
+ // for a later bucket switch that loses OPFS).
1778
+ this.databaseService.<span class="branch-0 cbranch-no" title="branch not covered" >subscribeToStorageHealth?.(() =&gt; this.notifyDevTools());</span>
1779
+ &nbsp;
1780
+ // Fire-and-forget backend version discovery; re-push state when it lands.
1781
+ void this.refreshBackendVersions();
1782
+ &nbsp;
1783
+ this.logger.debug({ Category: 'sp00ky-client::DevToolsService::init' }, 'Service initialized');
1784
+ }
1785
+ &nbsp;
1786
+ /**
1787
+ * Re-read backend stack info via the `fn::spooky::info()` SurrealQL function
1788
+ * over the open remote connection (no HTTP/CORS), then notify the panel.
1789
+ * Never throws: on failure the info stays empty/'unavailable'.
1790
+ */
1791
+ private async refreshBackendVersions(): Promise&lt;void&gt; {
1792
+ try {
1793
+ // `RETURN fn::spooky::info()` → one statement result: the /info entity array.
1794
+ const result = await this.remoteDatabaseService.query&lt;unknown[]&gt;(
1795
+ 'RETURN fn::spooky::info()'
1796
+ );
1797
+ const first = Array.isArray(result) ? result[0<span class="branch-0 cbranch-no" title="branch not covered" >] : result;</span>
1798
+ this.backendInfo = parseBackendInfo(first);
1799
+ <span class="branch-0 cbranch-no" title="branch not covered" > } catch (err) {</span>
1800
+ <span class="cstat-no" title="statement not covered" > this.logger.debug(</span>
1801
+ <span class="cstat-no" title="statement not covered" > { err, Category: 'sp00ky-client::DevToolsService::versions' },</span>
1802
+ <span class="cstat-no" title="statement not covered" > 'fn::spooky::info() unavailable; backend versions stay unavailable'</span>
1803
+ <span class="cstat-no" title="statement not covered" > );</span>
1804
+ <span class="cstat-no" title="statement not covered" > this.backendInfo = emptyBackendInfo();</span>
1805
+ <span class="cstat-no" title="statement not covered" > }</span>
1806
+ this.notifyDevTools();
1807
+ }
1808
+ &nbsp;
1809
+ // Get active queries directly from DataManager (single source of truth)
1810
+ private getActiveQueries(): Map&lt;number, any&gt; {
1811
+ const result = new Map&lt;number, any&gt;();
1812
+ if (!this.dataManager) <span class="branch-0 cbranch-no" title="branch not covered" >return result;</span>
1813
+ &nbsp;
1814
+ const queries = this.dataManager.getActiveQueries();
1815
+ queries.forEach((q) =&gt; {
1816
+ const queryHash = this.hashString(encodeRecordId(q.config.id));
1817
+ const createdAt =
1818
+ q.config.lastActiveAt instanceof <span class="branch-0 cbranch-no" title="branch not covered" >Date</span>
1819
+ <span class="cstat-no" title="statement not covered" > ? q.config.lastActiveAt.getTime()</span>
1820
+ : new Date(q.config.lastActiveAt || Date.now()).getTime();
1821
+ this.hashToQuery.set(queryHash, q.config.id);
1822
+ const localArray = q.config.localArray ?? [];
1823
+ const remoteArray = q.config.remoteArray ?? [];
1824
+ result.set(queryHash, {
1825
+ queryHash,
1826
+ status: 'active',
1827
+ // Runtime fetch status, distinct from the `status: 'active'`
1828
+ // registration flag above. `fetchStatus` is 'idle' | 'fetching'.
1829
+ fetchStatus: q.status,
1830
+ isFetching: q.status === 'fetching',
1831
+ createdAt,
1832
+ // Real last-update time; before the first update it equals createdAt.
1833
+ // (Previously Date.now(), which reset the column on every state push.)
1834
+ lastUpdate: q.lastUpdatedAt ?? createdAt,
1835
+ updateCount: q.updateCount,
1836
+ ttl: q.config.ttl,
1837
+ query: q.config.surql,
1838
+ variables: q.config.<span class="branch-0 cbranch-no" title="branch not covered" >params || {},</span>
1839
+ dataSize: q.records?.<span class="branch-0 cbranch-no" title="branch not covered" >length || 0,</span>
1840
+ // Counts and (capped) ids only. The rows themselves used to ride along
1841
+ // here: every push then deep-cloned every view's records twice
1842
+ // (serialize + postMessage), on a 4k-row client dataset up to four
1843
+ // times a second, from inside the ingest call stack. The panel pulls
1844
+ // rows on demand through `getQueryRows` instead.
1845
+ localCount: localArray.length,
1846
+ remoteCount: remoteArray.length,
1847
+ localIds: localArray.slice(0, DevToolsService.STATE_IDS_CAP).map(([id]) =&gt; id),
1848
+ remoteIds: remoteArray.slice(0, DevToolsService.STATE_IDS_CAP).map(([id]) =&gt; id),
1849
+ idsTruncated:
1850
+ localArray.length &gt; DevToolsService.STATE_IDS_CAP ||
1851
+ remoteArray.length &gt; DevToolsService.STATE_IDS_CAP,
1852
+ // Membership state, so "why is this list empty" is answerable from
1853
+ // the panel: is the server's set known, has a non-empty one been seen
1854
+ // this session, how many empty reads were ignored.
1855
+ membershipKnown: q.config.membershipKnown === true,
1856
+ authoritative: q.config.membershipKnown === true,
1857
+ viewLost: q.viewLost === true,
1858
+ serverState: q.serverState ?? null,
1859
+ // Detailed per-phase processing-time breakdown (SSP sub-phases, local/
1860
+ // remote record fetch, frontend reconcile, registration). Flows to both
1861
+ // the DevTools panel and the MCP (which returns activeQueries verbatim).
1862
+ timings: this.dataManager!.phaseTimings(q),
1863
+ });
1864
+ });
1865
+ return result;
1866
+ }
1867
+ &nbsp;
1868
+ public <span class="fstat-no" title="function not covered" >onQueryInitialized(payload: any) {</span>
1869
+ <span class="cstat-no" title="statement not covered" > this.logger.debug(</span>
1870
+ <span class="cstat-no" title="statement not covered" > { payload, Category: 'sp00ky-client::DevToolsService::onQueryInitialized' },</span>
1871
+ <span class="cstat-no" title="statement not covered" > 'QueryInitialized'</span>
1872
+ <span class="cstat-no" title="statement not covered" > );</span>
1873
+ <span class="cstat-no" title="statement not covered" > const queryHash = this.hashString(payload.queryId.toString());</span>
1874
+ &nbsp;
1875
+ <span class="cstat-no" title="statement not covered" > this.addEvent('QUERY_REQUEST_INIT', {</span>
1876
+ <span class="cstat-no" title="statement not covered" > queryHash,</span>
1877
+ <span class="cstat-no" title="statement not covered" > query: payload.sql,</span>
1878
+ <span class="cstat-no" title="statement not covered" > variables: {},</span>
1879
+ <span class="cstat-no" title="statement not covered" > });</span>
1880
+ <span class="cstat-no" title="statement not covered" > this.notifyDevTools();</span>
1881
+ <span class="cstat-no" title="statement not covered" > }</span>
1882
+ &nbsp;
1883
+ public onQueryUpdated(payload: any) {
1884
+ this.logger.debug(
1885
+ {
1886
+ id: payload.queryId?.toString(),
1887
+ Category: 'sp00ky-client::DevToolsService::onQueryUpdated',
1888
+ },
1889
+ 'QueryUpdated'
1890
+ );
1891
+ const queryHash = this.hashString(payload.queryId.toString());
1892
+ &nbsp;
1893
+ this.addEvent('QUERY_UPDATED', {
1894
+ queryHash,
1895
+ recordCount: Array.isArray(payload.records) ? payload.records.<span class="branch-0 cbranch-no" title="branch not covered" >length : 0,</span>
1896
+ });
1897
+ this.notifyDevTools();
1898
+ }
1899
+ &nbsp;
1900
+ public onStreamUpdate(update: StreamUpdate) {
1901
+ // A synthetic re-materialize is not an ingest (DataModule.scheduleRematerialize).
1902
+ if (update.synthetic) return;
1903
+ this.logger.debug(
1904
+ { queryHash: update.queryHash, Category: 'sp00ky-client::DevToolsService::onStreamUpdate' },
1905
+ 'StreamUpdate'
1906
+ );
1907
+ // Counts and timings, not the `localArray` itself: that is one [id, version]
1908
+ // pair per row of the view, serialized on every single update.
1909
+ this.addEvent('STREAM_UPDATE', {
1910
+ queryHash: update.queryHash,
1911
+ op: update.op,
1912
+ localCount: update.localArray?.<span class="branch-0 cbranch-no" title="branch not covered" >length ?? 0,</span>
1913
+ materializationTimeMs: update.materializationTimeMs,
1914
+ storeApplyMs: update.storeApplyMs,
1915
+ circuitStepMs: update.circuitStepMs,
1916
+ transformMs: update.transformMs,
1917
+ });
1918
+ this.notifyDevTools();
1919
+ }
1920
+ &nbsp;
1921
+ public onMutation(payload: any[]) {
1922
+ const payloads = payload;
1923
+ payloads.forEach((p) =&gt; {
1924
+ this.addEvent('MUTATION_REQUEST_EXECUTION', {
1925
+ mutation: {
1926
+ type: p.<span class="branch-0 cbranch-no" title="branch not covered" >type ?? 'create',</span>
1927
+ // Field names only; a payload body (a PGN, a document) is not
1928
+ // something to clone on every write.
1929
+ fields: 'data' in p &amp;&amp; p.data &amp;&amp; typeof p.data === 'object' ? Object.keys(p.data) : [],
1930
+ selector: encodeRecordId(p.record_id),
1931
+ },
1932
+ });
1933
+ });
1934
+ this.notifyDevTools();
1935
+ }
1936
+ &nbsp;
1937
+ private hashString(str: string): number {
1938
+ let hash = 0;
1939
+ if (str.length === 0) <span class="branch-0 cbranch-no" title="branch not covered" >return hash;</span>
1940
+ for (let i = 0; i &lt; str.length; i++) {
1941
+ const char = str.charCodeAt(i);
1942
+ hash = (hash &lt;&lt; 5) - hash + char;
1943
+ hash = hash &amp; hash; // Convert to 32bit integer
1944
+ }
1945
+ return hash;
1946
+ }
1947
+ &nbsp;
1948
+ public logEvent(eventType: string, payload: any) {
1949
+ this.addEvent(eventType, payload);
1950
+ this.notifyDevTools();
1951
+ }
1952
+ &nbsp;
1953
+ private addEvent(eventType: string, payload: any) {
1954
+ // No consumer attached → skip recording (and the recursive serialize it does).
1955
+ if (!this.enabled) return;
1956
+ this.eventsHistory.push({
1957
+ id: this.eventIdCounter++,
1958
+ timestamp: Date.now(),
1959
+ eventType,
1960
+ payload: this.serializeForDevTools(payload),
1961
+ });
1962
+ if (this.eventsHistory.length &gt; 100) this.eventsHistory.shift();
1963
+ }
1964
+ &nbsp;
1965
+ /** Unwrap a SurrealDB `INFO FOR DB` result to its `{ tables, ... }` object. */
1966
+ private unwrapInfo(res: any): any {
1967
+ if (!Array.isArray(res) || !res[0]) return <span class="branch-0 cbranch-no" title="branch not covered" >null;</span>
1968
+ <span class="cstat-no" title="statement not covered" > const first = res[0];</span>
1969
+ if (first &amp;&amp; typeof first === <span class="branch-0 cbranch-no" title="branch not covered" >'object' &amp;&amp; 'result' in first) <span class="branch-0 cbranch-no" title="branch not covered" >r</span>eturn first.result;</span>
1970
+ <span class="cstat-no" title="statement not covered" > if (Array.isArray(first)) return first[0];</span>
1971
+ <span class="cstat-no" title="statement not covered" > return first;</span>
1972
+ }
1973
+ &nbsp;
1974
+ /**
1975
+ * Refresh the cached full local-table list from `INFO FOR DB`. Fire-and-forget
1976
+ * and throttled — called from getState() so the panel gets every table
1977
+ * (including internal `_00_*`) without running its own (flaky) queries.
1978
+ */
1979
+ private refreshLocalTables(): void {
1980
+ if (this.localTablesFetching) return;
1981
+ const now = Date.now();
1982
+ if (now - this.localTablesAt &lt; 30_000) <span class="branch-0 cbranch-no" title="branch not covered" >return;</span>
1983
+ this.localTablesFetching = true;
1984
+ void this.databaseService
1985
+ .query&lt;any&gt;('INFO FOR DB')
1986
+ .then((res) =&gt; {
1987
+ const info = this.unwrapInfo(res);
1988
+ this.localTablesAt = Date.now();
1989
+ if (<span class="branch-0 cbranch-no" title="branch not covered" >info &amp;&amp; info.tables) <span class="branch-0 cbranch-no" title="branch not covered" >{</span></span>
1990
+ // The circuit snapshot table holds a BLOB, not JSON rows; the
1991
+ // explorer cannot render it and has nothing to show for it.
1992
+ <span class="cstat-no" title="statement not covered" > const names = Object.keys(info.tables).filter((n) =&gt; n !== '_00_circuit_snapshot');</span>
1993
+ <span class="cstat-no" title="statement not covered" > const changed =</span>
1994
+ <span class="cstat-no" title="statement not covered" > names.length !== this.localTables.length ||</span>
1995
+ <span class="cstat-no" title="statement not covered" > names.some((n, i) =&gt; n !== this.localTables[i]);</span>
1996
+ <span class="cstat-no" title="statement not covered" > this.localTables = names;</span>
1997
+ <span class="cstat-no" title="statement not covered" > if (changed) this.notifyDevTools();</span>
1998
+ <span class="cstat-no" title="statement not covered" > }</span>
1999
+ })
2000
+ .catch(() =&gt; {
2001
+ // Ignore — fall back to the declared app schema below.
2002
+ })
2003
+ .finally(() =&gt; {
2004
+ this.localTablesFetching = false;
2005
+ });
2006
+ }
2007
+ &nbsp;
2008
+ private getState(opts: { refreshTables?: boolean } = {}) {
2009
+ // The local-table list (`INFO FOR DB`, a local round trip) is refreshed on
2010
+ // an explicit pull only, never by the push path: pushes follow every sync
2011
+ // event, and a local query per push competed with the app's own writes for
2012
+ // the single local op queue.
2013
+ if (opts.refreshTables) this.refreshLocalTables();
2014
+ return this.serializeForDevTools({
2015
+ eventsHistory: [...this.eventsHistory],
2016
+ activeQueries: Object.fromEntries(this.getActiveQueries()),
2017
+ auth: {
2018
+ authenticated: this.authService.isAuthenticated,
2019
+ userId: this.authService.<span class="branch-0 cbranch-no" title="branch not covered" >currentUser?.id,</span>
2020
+ },
2021
+ version: this.version,
2022
+ versions: {
2023
+ frontend: {
2024
+ core: CORE_VERSION,
2025
+ wasm: WASM_VERSION,
2026
+ surrealdb: SURREAL_VERSION,
2027
+ },
2028
+ backend: this.backendInfo.versions,
2029
+ entities: this.backendInfo.entities,
2030
+ },
2031
+ database: {
2032
+ // Prefer the live local-table list (includes internal `_00_*`); fall
2033
+ // back to the declared app schema until the first enumeration lands.
2034
+ tables: this.localTables.<span class="branch-0 cbranch-no" title="branch not covered" >length</span>
2035
+ <span class="cstat-no" title="statement not covered" > ? this.localTables</span>
2036
+ : this.schema.tables.map((t) =&gt; t.name),
2037
+ tableData: {},
2038
+ // Which backend answers "Local". The Database explorer labels its source
2039
+ // picker with it and explains translation failures against `sqlite`,
2040
+ // whose SurrealQL vocabulary is a bounded subset.
2041
+ engine: this.databaseService.engineKind ?? 'custom',
2042
+ // Durability of the local store. `fallback: true` means persistence was
2043
+ // requested but the dataset is actually sitting in RAM.
2044
+ storage: this.databaseService.<span class="branch-0 cbranch-no" title="branch not covered" >storageHealth ?? { status: 'unknown', fallback: false },</span>
2045
+ // Shared-tabs role state (null when the feature is off / fell back).
2046
+ tabs: this.<span class="branch-0 cbranch-no" title="branch not covered" >tabsInfoProvider?.() ?? n</span>ull,
2047
+ },
2048
+ });
2049
+ }
2050
+ &nbsp;
2051
+ /**
2052
+ * Full storage diagnostics for the DevTools Storage tab. Every section is
2053
+ * gathered independently and failures land in that section's `error` field,
2054
+ * so one broken source (a mid-switch worker, a browser without OPFS) never
2055
+ * blanks the whole panel.
2056
+ */
2057
+ <span class="fstat-no" title="function not covered" > public async getStorageInfo(opts?: { tableCounts?: boolean }): Promise&lt;StorageInfo&gt; {</span>
2058
+ <span class="cstat-no" title="statement not covered" > const nav = typeof navigator !== 'undefined' ? navigator : undefined;</span>
2059
+ &nbsp;
2060
+ <span class="cstat-no" title="statement not covered" > const info: StorageInfo = {</span>
2061
+ <span class="cstat-no" title="statement not covered" > at: Date.now(),</span>
2062
+ <span class="cstat-no" title="statement not covered" > engine: {</span>
2063
+ <span class="cstat-no" title="statement not covered" > kind: this.databaseService.engineKind ?? 'custom',</span>
2064
+ <span class="cstat-no" title="statement not covered" > store: this.databaseService.getConfig()?.store ?? 'memory',</span>
2065
+ <span class="cstat-no" title="statement not covered" > bucketId: this.databaseService.currentBucketId,</span>
2066
+ <span class="cstat-no" title="statement not covered" > },</span>
2067
+ <span class="cstat-no" title="statement not covered" > health: this.databaseService.storageHealth ?? { status: 'unknown', fallback: false },</span>
2068
+ <span class="cstat-no" title="statement not covered" > tabs: this.tabsInfoProvider?.() ?? null,</span>
2069
+ <span class="cstat-no" title="statement not covered" > browser: {},</span>
2070
+ <span class="cstat-no" title="statement not covered" > opfs: { supported: false, entries: [], totalBytes: 0, truncated: false },</span>
2071
+ <span class="cstat-no" title="statement not covered" > };</span>
2072
+ &nbsp;
2073
+ <span class="cstat-no" title="statement not covered" > try {</span>
2074
+ <span class="cstat-no" title="statement not covered" > if (nav?.storage?.estimate) {</span>
2075
+ <span class="cstat-no" title="statement not covered" > const est = await nav.storage.estimate();</span>
2076
+ <span class="cstat-no" title="statement not covered" > info.browser.usage = est.usage;</span>
2077
+ <span class="cstat-no" title="statement not covered" > info.browser.quota = est.quota;</span>
2078
+ // Chrome-only per-storage-system breakdown; absent elsewhere.
2079
+ <span class="cstat-no" title="statement not covered" > const details = (est as any).usageDetails;</span>
2080
+ <span class="cstat-no" title="statement not covered" > if (details &amp;&amp; typeof details === 'object') info.browser.usageDetails = details;</span>
2081
+ <span class="cstat-no" title="statement not covered" > }</span>
2082
+ <span class="cstat-no" title="statement not covered" > if (nav?.storage?.persisted) {</span>
2083
+ <span class="cstat-no" title="statement not covered" > info.browser.persisted = await nav.storage.persisted();</span>
2084
+ <span class="cstat-no" title="statement not covered" > }</span>
2085
+ <span class="cstat-no" title="statement not covered" > } catch (e) {</span>
2086
+ <span class="cstat-no" title="statement not covered" > info.browser.error = e instanceof Error ? e.message : String(e);</span>
2087
+ <span class="cstat-no" title="statement not covered" > }</span>
2088
+ &nbsp;
2089
+ <span class="cstat-no" title="statement not covered" > info.opfs = await walkOpfs();</span>
2090
+ &nbsp;
2091
+ <span class="cstat-no" title="statement not covered" > try {</span>
2092
+ <span class="cstat-no" title="statement not covered" > info.blobs = this.blobInfoProvider?.();</span>
2093
+ <span class="cstat-no" title="statement not covered" > } catch (e) {</span>
2094
+ <span class="cstat-no" title="statement not covered" > this.logger.warn(</span>
2095
+ <span class="cstat-no" title="statement not covered" > { err: e, Category: 'sp00ky-client::DevToolsService::getStorageInfo' },</span>
2096
+ <span class="cstat-no" title="statement not covered" > 'Blob cache diagnostics failed'</span>
2097
+ <span class="cstat-no" title="statement not covered" > );</span>
2098
+ <span class="cstat-no" title="statement not covered" > }</span>
2099
+ &nbsp;
2100
+ <span class="cstat-no" title="statement not covered" > const stats = (globalThis as any).__sqliteStats;</span>
2101
+ <span class="cstat-no" title="statement not covered" > if (stats &amp;&amp; typeof stats === 'object') {</span>
2102
+ <span class="cstat-no" title="statement not covered" > info.sqliteStats = { ...stats, byType: { ...(stats.byType ?? {}) } };</span>
2103
+ <span class="cstat-no" title="statement not covered" > }</span>
2104
+ &nbsp;
2105
+ <span class="cstat-no" title="statement not covered" > try {</span>
2106
+ <span class="cstat-no" title="statement not covered" > info.engineDiagnostics = await this.databaseService.getStorageDiagnostics?.(opts);</span>
2107
+ <span class="cstat-no" title="statement not covered" > } catch (e) {</span>
2108
+ <span class="cstat-no" title="statement not covered" > this.logger.warn(</span>
2109
+ <span class="cstat-no" title="statement not covered" > { err: e, Category: 'sp00ky-client::DevToolsService::getStorageInfo' },</span>
2110
+ <span class="cstat-no" title="statement not covered" > 'Engine storage diagnostics failed'</span>
2111
+ <span class="cstat-no" title="statement not covered" > );</span>
2112
+ <span class="cstat-no" title="statement not covered" > }</span>
2113
+ &nbsp;
2114
+ <span class="cstat-no" title="statement not covered" > return this.serializeForDevTools(info);</span>
2115
+ <span class="cstat-no" title="statement not covered" > }</span>
2116
+ &nbsp;
2117
+ /** Ask the browser to exempt this origin's storage from eviction. */
2118
+ <span class="fstat-no" title="function not covered" > public async requestPersistentStorage(): Promise&lt;{ granted: boolean }&gt; {</span>
2119
+ <span class="cstat-no" title="statement not covered" > try {</span>
2120
+ <span class="cstat-no" title="statement not covered" > const granted = (await navigator.storage?.persist?.()) ?? false;</span>
2121
+ <span class="cstat-no" title="statement not covered" > return { granted };</span>
2122
+ <span class="cstat-no" title="statement not covered" > } catch {</span>
2123
+ <span class="cstat-no" title="statement not covered" > return { granted: false };</span>
2124
+ <span class="cstat-no" title="statement not covered" > }</span>
2125
+ <span class="cstat-no" title="statement not covered" > }</span>
2126
+ &nbsp;
2127
+ /**
2128
+ * Request a state push. Coalesced (see {@link NOTIFY_MIN_INTERVAL_MS}): the
2129
+ * first call after an idle period pushes straight away so the panel stays
2130
+ * responsive, and any calls during the window collapse into ONE trailing push
2131
+ * that serializes the state as of the flush, not as of the request. Callers
2132
+ * stay fire-and-forget.
2133
+ */
2134
+ private notifyDevTools() {
2135
+ // No consumer attached → no getState() serialization, no postMessage broadcast.
2136
+ if (!this.enabled) return;
2137
+ if (typeof window === 'undefined') <span class="branch-0 cbranch-no" title="branch not covered" >return;</span>
2138
+ // A trailing push is already queued; it will carry this change too.
2139
+ if (this.notifyTimer !== null) return;
2140
+ &nbsp;
2141
+ // Always a macrotask, never inline: this is called from inside the ingest
2142
+ // and mutation call stacks (onStreamUpdate / onMutation), i.e. inside the
2143
+ // `await db.create(...)` the app is waiting on. A push that serializes the
2144
+ // state right there charged every write for the panel's refresh.
2145
+ const waited = Date.now() - this.lastNotifyAt;
2146
+ const delay = Math.max(0, DevToolsService.NOTIFY_MIN_INTERVAL_MS - waited);
2147
+ this.notifyTimer = setTimeout(() =&gt; {
2148
+ this.notifyTimer = null;
2149
+ // Still gated on `enabled`: the panel may have disconnected while queued.
2150
+ if (this.enabled) this.flushNotify();
2151
+ }, delay);
2152
+ }
2153
+ &nbsp;
2154
+ private flushNotify() {
2155
+ this.lastNotifyAt = Date.now();
2156
+ window.postMessage(
2157
+ {
2158
+ type: 'SP00KY_STATE_CHANGED',
2159
+ source: 'sp00ky-devtools-page',
2160
+ state: this.getState(),
2161
+ },
2162
+ '*'
2163
+ );
2164
+ }
2165
+ &nbsp;
2166
+ private serializeForDevTools(data: any, seen = new WeakSet&lt;object&gt;()): any {
2167
+ if (data === undefined) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
2168
+ <span class="cstat-no" title="statement not covered" > return 'undefined';</span>
2169
+ <span class="cstat-no" title="statement not covered" > }</span>
2170
+ &nbsp;
2171
+ if (data === null) {
2172
+ return null;
2173
+ }
2174
+ &nbsp;
2175
+ if (data instanceof RecordId) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
2176
+ <span class="cstat-no" title="statement not covered" > return data.toString();</span>
2177
+ <span class="cstat-no" title="statement not covered" > }</span>
2178
+ &nbsp;
2179
+ if (Array.isArray(data)) {
2180
+ if (seen.has(data)) {
2181
+ return '[Circular Array]';
2182
+ }
2183
+ seen.add(data);
2184
+ return data.map((item) =&gt; this.serializeForDevTools(item, seen));
2185
+ }
2186
+ &nbsp;
2187
+ if (typeof data === 'bigint') <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
2188
+ <span class="cstat-no" title="statement not covered" > return data.toString();</span>
2189
+ <span class="cstat-no" title="statement not covered" > }</span>
2190
+ &nbsp;
2191
+ if (data instanceof Date) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
2192
+ <span class="cstat-no" title="statement not covered" > return data.toISOString();</span>
2193
+ <span class="cstat-no" title="statement not covered" > }</span>
2194
+ &nbsp;
2195
+ if (typeof data === 'object') {
2196
+ if (seen.has(data)) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
2197
+ <span class="cstat-no" title="statement not covered" > return '[Circular Object]';</span>
2198
+ <span class="cstat-no" title="statement not covered" > }</span>
2199
+ seen.add(data);
2200
+ &nbsp;
2201
+ const result: Record&lt;string, any&gt; = {};
2202
+ for (const key in data) {
2203
+ if (Object.prototype.hasOwnProperty.call(data, key)) {
2204
+ // Skip absent optional fields: recursing them would emit the STRING
2205
+ // 'undefined' (the top-level mapping below), which panels then have
2206
+ // to filter back out (see 3d84fe8a).
2207
+ if (data[key] === undefined) continue;
2208
+ result[key] = this.serializeForDevTools(data[key], seen);
2209
+ }
2210
+ }
2211
+ return result;
2212
+ }
2213
+ &nbsp;
2214
+ return data;
2215
+ }
2216
+ &nbsp;
2217
+ /**
2218
+ * Hand the FeatureFlagModule to the Access tab so it can read and write local
2219
+ * overrides. Called from `Sp00kyClient` once both are constructed; until then
2220
+ * the override methods are no-ops that report an empty map.
2221
+ */
2222
+ public setFeatureFlagOverrides(store: LocalOverrideStore): void {
2223
+ this.featureOverrides = store;
2224
+ }
2225
+ &nbsp;
2226
+ private exposeToWindow() {
2227
+ if (typeof window !== 'undefined') {
2228
+ (window as any).__00__ = {
2229
+ version: this.version,
2230
+ getState: () =&gt; this.getState({ refreshTables: true }),
2231
+ // The rows of ONE view, on demand. The pushed state carries counts and
2232
+ // capped ids only (see getActiveQueries); the panel's Data tab and the
2233
+ // MCP fetch the rows here when somebody actually looks at them.
2234
+ getQueryRows: (queryHash: number) =&gt; {
2235
+ const id = this.hashToQuery.get(Number(queryHash));
2236
+ const q = id !== undefined ? this.dataManager?.getQueryById(id as any) : undefined;
2237
+ if (!q) return null;
2238
+ return this.serializeForDevTools({
2239
+ queryHash: Number(queryHash),
2240
+ data: q.records,
2241
+ localArray: q.config.localArray,
2242
+ remoteArray: q.config.remoteArray,
2243
+ });
2244
+ },
2245
+ // ---- Feature flags (Access tab) --------------------------------
2246
+ // Remote reads/writes are admin-gated by SurrealDB, not here: a
2247
+ // non-admin gets an empty flag list, and the `fn::feature::*` calls
2248
+ // are denied outright. The override methods are purely local and
2249
+ // work signed out.
2250
+ getFlags: <span class="fstat-no" title="function not covered" >() =&gt; this.flagsAdmin.getFlags(),</span>
2251
+ setFlagEnabled: <span class="fstat-no" title="function not covered" >(key: string, enabled: boolean) =&gt;</span>
2252
+ <span class="cstat-no" title="statement not covered" > this.flagsAdmin.setFlagEnabled(key, enabled),</span>
2253
+ setFlagUserVariant: <span class="fstat-no" title="function not covered" >(key: string, variant: string, remove: boolean, userId?: string) =&gt;</span>
2254
+ <span class="cstat-no" title="statement not covered" > this.flagsAdmin.setFlagUserVariant(key, variant, remove, userId),</span>
2255
+ setLocalFlagOverride: <span class="fstat-no" title="function not covered" >(key: string, variant: string | null, payload?: unknown) =&gt;</span>
2256
+ <span class="cstat-no" title="statement not covered" > this.flagsAdmin.setLocalFlagOverride(key, variant, payload),</span>
2257
+ clearLocalFlagOverrides: <span class="fstat-no" title="function not covered" >() =&gt; this.flagsAdmin.clearLocalFlagOverrides(),</span>
2258
+ clearHistory: <span class="fstat-no" title="function not covered" >() =&gt; {</span>
2259
+ <span class="cstat-no" title="statement not covered" > this.eventsHistory = [];</span>
2260
+ <span class="cstat-no" title="statement not covered" > this.notifyDevTools();</span>
2261
+ <span class="cstat-no" title="statement not covered" > },</span>
2262
+ refreshVersions: <span class="fstat-no" title="function not covered" >() =&gt; this.refreshBackendVersions(),</span>
2263
+ getStorageInfo: <span class="fstat-no" title="function not covered" >(opts?: { tableCounts?: boolean }) =&gt; this.getStorageInfo(opts),</span>
2264
+ requestPersistentStorage: <span class="fstat-no" title="function not covered" >() =&gt; this.requestPersistentStorage(),</span>
2265
+ getTableData: <span class="fstat-no" title="function not covered" >async (tableName: string) =&gt; {</span>
2266
+ <span class="cstat-no" title="statement not covered" > try {</span>
2267
+ // Returns the first statement result as T.
2268
+ // SurrealDB query returns [Result1, Result2...].
2269
+ // We want the records from the first result.
2270
+ <span class="cstat-no" title="statement not covered" > const result = await this.databaseService.query&lt;any&gt;(`SELECT * FROM ${tableName}`);</span>
2271
+ &nbsp;
2272
+ <span class="cstat-no" title="statement not covered" > let records: any[] = [];</span>
2273
+ &nbsp;
2274
+ <span class="cstat-no" title="statement not covered" > if (Array.isArray(result) &amp;&amp; result.length &gt; 0) {</span>
2275
+ <span class="cstat-no" title="statement not covered" > const first = result[0];</span>
2276
+ <span class="cstat-no" title="statement not covered" > if (Array.isArray(first)) {</span>
2277
+ // Legacy or flattened format: [[records]]
2278
+ <span class="cstat-no" title="statement not covered" > records = first;</span>
2279
+ <span class="cstat-no" title="statement not covered" > } else if (</span>
2280
+ <span class="cstat-no" title="statement not covered" > first &amp;&amp;</span>
2281
+ <span class="cstat-no" title="statement not covered" > typeof first === 'object' &amp;&amp;</span>
2282
+ <span class="cstat-no" title="statement not covered" > 'result' in first &amp;&amp;</span>
2283
+ <span class="cstat-no" title="statement not covered" > 'status' in first</span>
2284
+ <span class="cstat-no" title="statement not covered" > ) {</span>
2285
+ // SurrealDB 2.0 format: [{ result: [...records], status: 'OK', ... }]
2286
+ <span class="cstat-no" title="statement not covered" > records = Array.isArray(first.result) ? first.result : [];</span>
2287
+ <span class="cstat-no" title="statement not covered" > } else {</span>
2288
+ // Fallback: assume result is the array of records itself
2289
+ <span class="cstat-no" title="statement not covered" > records = result;</span>
2290
+ <span class="cstat-no" title="statement not covered" > }</span>
2291
+ <span class="cstat-no" title="statement not covered" > } else if (Array.isArray(result)) {</span>
2292
+ // Empty array
2293
+ <span class="cstat-no" title="statement not covered" > records = [];</span>
2294
+ <span class="cstat-no" title="statement not covered" > }</span>
2295
+ &nbsp;
2296
+ <span class="cstat-no" title="statement not covered" > return this.serializeForDevTools(records) || [];</span>
2297
+ <span class="cstat-no" title="statement not covered" > } catch (e) {</span>
2298
+ <span class="cstat-no" title="statement not covered" > this.logger.error(</span>
2299
+ <span class="cstat-no" title="statement not covered" > { err: e, Category: 'sp00ky-client::DevToolsService::exposeToWindow' },</span>
2300
+ <span class="cstat-no" title="statement not covered" > 'Failed to get table data'</span>
2301
+ <span class="cstat-no" title="statement not covered" > );</span>
2302
+ <span class="cstat-no" title="statement not covered" > return [];</span>
2303
+ <span class="cstat-no" title="statement not covered" > }</span>
2304
+ <span class="cstat-no" title="statement not covered" > },</span>
2305
+ updateTableRow: <span class="fstat-no" title="function not covered" >async (</span>
2306
+ <span class="cstat-no" title="statement not covered" > tableName: string,</span>
2307
+ <span class="cstat-no" title="statement not covered" > recordId: string,</span>
2308
+ <span class="cstat-no" title="statement not covered" > updates: Record&lt;string, unknown&gt;</span>
2309
+ <span class="cstat-no" title="statement not covered" > ) =&gt; {</span>
2310
+ <span class="cstat-no" title="statement not covered" > try {</span>
2311
+ <span class="cstat-no" title="statement not covered" > await this.databaseService.query(`UPDATE ${recordId} MERGE $updates`, { updates });</span>
2312
+ <span class="cstat-no" title="statement not covered" > return { success: true };</span>
2313
+ <span class="cstat-no" title="statement not covered" > } catch (e: any) {</span>
2314
+ <span class="cstat-no" title="statement not covered" > return { success: false, error: e.message };</span>
2315
+ <span class="cstat-no" title="statement not covered" > }</span>
2316
+ <span class="cstat-no" title="statement not covered" > },</span>
2317
+ deleteTableRow: <span class="fstat-no" title="function not covered" >async (tableName: string, recordId: string) =&gt; {</span>
2318
+ <span class="cstat-no" title="statement not covered" > try {</span>
2319
+ <span class="cstat-no" title="statement not covered" > await this.databaseService.query(`DELETE ${recordId}`);</span>
2320
+ <span class="cstat-no" title="statement not covered" > return { success: true };</span>
2321
+ <span class="cstat-no" title="statement not covered" > } catch (e: any) {</span>
2322
+ <span class="cstat-no" title="statement not covered" > return { success: false, error: e.message };</span>
2323
+ <span class="cstat-no" title="statement not covered" > }</span>
2324
+ <span class="cstat-no" title="statement not covered" > },</span>
2325
+ runQuery: <span class="fstat-no" title="function not covered" >async (query: string, target: 'local' | 'remote' = 'local') =&gt; {</span>
2326
+ <span class="cstat-no" title="statement not covered" > try {</span>
2327
+ <span class="cstat-no" title="statement not covered" > this.logger.debug(</span>
2328
+ <span class="cstat-no" title="statement not covered" > { query, target, Category: 'sp00ky-client::DevToolsService::runQuery' },</span>
2329
+ <span class="cstat-no" title="statement not covered" > 'Running query (START)'</span>
2330
+ <span class="cstat-no" title="statement not covered" > );</span>
2331
+ <span class="cstat-no" title="statement not covered" > const service = target === 'remote' ? this.remoteDatabaseService : this.databaseService;</span>
2332
+ &nbsp;
2333
+ <span class="cstat-no" title="statement not covered" > const startTime = Date.now();</span>
2334
+ <span class="cstat-no" title="statement not covered" > const result = await service.query&lt;any&gt;(query);</span>
2335
+ <span class="cstat-no" title="statement not covered" > const queryTime = Date.now() - startTime;</span>
2336
+ &nbsp;
2337
+ <span class="cstat-no" title="statement not covered" > this.logger.debug(</span>
2338
+ <span class="cstat-no" title="statement not covered" > {</span>
2339
+ <span class="cstat-no" title="statement not covered" > query,</span>
2340
+ <span class="cstat-no" title="statement not covered" > time: queryTime,</span>
2341
+ <span class="cstat-no" title="statement not covered" > resultType: typeof result,</span>
2342
+ <span class="cstat-no" title="statement not covered" > isArray: Array.isArray(result),</span>
2343
+ <span class="cstat-no" title="statement not covered" > Category: 'sp00ky-client::DevToolsService::runQuery',</span>
2344
+ <span class="cstat-no" title="statement not covered" > },</span>
2345
+ <span class="cstat-no" title="statement not covered" > 'Database returned result'</span>
2346
+ <span class="cstat-no" title="statement not covered" > );</span>
2347
+ &nbsp;
2348
+ // Serialize the result for DevTools
2349
+ <span class="cstat-no" title="statement not covered" > const serializeStart = Date.now();</span>
2350
+ <span class="cstat-no" title="statement not covered" > const serialized = this.serializeForDevTools(result);</span>
2351
+ <span class="cstat-no" title="statement not covered" > const serializeTime = Date.now() - serializeStart;</span>
2352
+ &nbsp;
2353
+ <span class="cstat-no" title="statement not covered" > this.logger.debug(</span>
2354
+ <span class="cstat-no" title="statement not covered" > {</span>
2355
+ <span class="cstat-no" title="statement not covered" > serializeTime,</span>
2356
+ <span class="cstat-no" title="statement not covered" > serializedLength: JSON.stringify(serialized).length,</span>
2357
+ <span class="cstat-no" title="statement not covered" > Category: 'sp00ky-client::DevToolsService::runQuery',</span>
2358
+ <span class="cstat-no" title="statement not covered" > },</span>
2359
+ <span class="cstat-no" title="statement not covered" > 'Serialization complete'</span>
2360
+ <span class="cstat-no" title="statement not covered" > );</span>
2361
+ &nbsp;
2362
+ <span class="cstat-no" title="statement not covered" > return {</span>
2363
+ <span class="cstat-no" title="statement not covered" > success: true,</span>
2364
+ <span class="cstat-no" title="statement not covered" > data: serialized,</span>
2365
+ <span class="cstat-no" title="statement not covered" > target,</span>
2366
+ <span class="cstat-no" title="statement not covered" > };</span>
2367
+ <span class="cstat-no" title="statement not covered" > } catch (e: any) {</span>
2368
+ <span class="cstat-no" title="statement not covered" > this.logger.error(</span>
2369
+ <span class="cstat-no" title="statement not covered" > { err: e, query, target, Category: 'sp00ky-client::DevToolsService::runQuery' },</span>
2370
+ <span class="cstat-no" title="statement not covered" > 'Query execution failed'</span>
2371
+ <span class="cstat-no" title="statement not covered" > );</span>
2372
+ // Ensure we always return a string for error
2373
+ <span class="cstat-no" title="statement not covered" > const errorMessage =</span>
2374
+ <span class="cstat-no" title="statement not covered" > e instanceof Error ? e.message : typeof e === 'string' ? e : JSON.stringify(e);</span>
2375
+ <span class="cstat-no" title="statement not covered" > return { success: false, error: errorMessage || 'Unknown occurred' };</span>
2376
+ <span class="cstat-no" title="statement not covered" > }</span>
2377
+ <span class="cstat-no" title="statement not covered" > },</span>
2378
+ };
2379
+ &nbsp;
2380
+ window.postMessage(
2381
+ {
2382
+ type: 'SP00KY_DETECTED',
2383
+ source: 'sp00ky-devtools-page',
2384
+ data: { version: this.version, detected: true },
2385
+ },
2386
+ '*'
2387
+ );
2388
+ &nbsp;
2389
+ // Dispatch custom event so the devtools page-script can detect late initialization
2390
+ window.dispatchEvent(new CustomEvent('sp00ky:init'));
2391
+ }
2392
+ }
2393
+ }
2394
+ &nbsp;</pre></td></tr></table></pre>
2395
+
2396
+ <div class='push'></div><!-- for sticky footer -->
2397
+ </div><!-- /wrapper -->
2398
+ <div class='footer quiet pad2 space-top1 center small'>
2399
+ Code coverage generated by
2400
+ <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
2401
+ at 2026-09-09T09:49:51.780Z
2402
+ </div>
2403
+ <script src="../../../prettify.js"></script>
2404
+ <script>
2405
+ window.onload = function () {
2406
+ prettyPrint();
2407
+ };
2408
+ </script>
2409
+ <script src="../../../sorter.js"></script>
2410
+ <script src="../../../block-navigation.js"></script>
2411
+ </body>
2412
+ </html>
2413
+