codetrap 0.1.7 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +151 -52
- package/docs/installation.md +113 -29
- package/package.json +4 -3
- package/plugins/codetrap-agent/.codex-plugin/plugin.json +1 -2
- package/plugins/codetrap-agent/hooks/post-flight-capture.example.md +19 -17
- package/plugins/codetrap-agent/hooks.json +2 -2
- package/{skills → plugins/codetrap-agent/skills}/codetrap-add/SKILL.md +10 -4
- package/plugins/codetrap-agent/skills/codetrap-capture/SKILL.md +14 -3
- package/plugins/codetrap-agent/skills/codetrap-capture-external/SKILL.md +52 -9
- package/plugins/codetrap-agent/skills/codetrap-check/SKILL.md +74 -6
- package/{skills → plugins/codetrap-agent/skills}/codetrap-search/SKILL.md +6 -5
- package/plugins/codetrap-agent/templates/AGENTS.codetrap.md +31 -5
- package/scripts/search-policy-sweep.ts +131 -0
- package/src/commands/workflow.ts +144 -68
- package/src/db/embedding-queries.ts +230 -48
- package/src/db/queries.ts +0 -25
- package/src/db/repository.ts +32 -21
- package/src/db/schema.ts +80 -0
- package/src/index.ts +28 -3
- package/src/lib/command-requests.ts +112 -1
- package/src/lib/config.ts +57 -7
- package/src/lib/constants.ts +1 -1
- package/src/lib/doctor.ts +42 -12
- package/src/lib/embedder.ts +118 -3
- package/src/lib/embedding-health.ts +3 -1
- package/src/lib/embedding-job.ts +3 -0
- package/src/lib/embedding-management.ts +65 -0
- package/src/lib/embedding-runtime.ts +177 -0
- package/src/lib/output-json.ts +0 -2
- package/src/lib/scope-context.ts +12 -6
- package/src/lib/scope-migration.ts +2 -1
- package/src/lib/scope.ts +0 -2
- package/src/lib/search-eval.ts +38 -18
- package/src/lib/search-policy-sweep.ts +563 -0
- package/src/lib/search-policy.ts +0 -4
- package/src/lib/search-service.ts +14 -15
- package/src/lib/session-candidate-document.ts +175 -0
- package/src/lib/session-candidate-scope.ts +6 -0
- package/src/lib/session-capture.ts +298 -32
- package/src/lib/session-codec.ts +1 -8
- package/src/lib/session-operations.ts +83 -60
- package/src/lib/session-review.ts +327 -0
- package/src/lib/session-store.ts +87 -73
- package/src/lib/store.ts +74 -10
- package/src/lib/string-list.ts +3 -0
- package/src/lib/text-lines.ts +7 -0
- package/src/lib/trap-search-document.ts +2 -1
- package/src/lib/value-types.ts +3 -0
- package/src/web/client-review.ts +171 -0
- package/src/web/client-script.ts +426 -51
- package/src/web/client-shell.ts +414 -0
- package/src/web/client-text.ts +112 -0
- package/src/web/project-registry.ts +3 -5
- package/src/web/server.ts +117 -103
- package/src/web/static.ts +364 -19
- package/skills/codetrap-capture-external/SKILL.md +0 -62
- package/skills/codetrap-check/SKILL.md +0 -69
- package/src/lib/embedding-index.ts +0 -53
package/src/web/static.ts
CHANGED
|
@@ -117,9 +117,10 @@ export const WEB_INDEX_HTML = `<!doctype html>
|
|
|
117
117
|
.shell {
|
|
118
118
|
height: 100%;
|
|
119
119
|
display: grid;
|
|
120
|
-
grid-template-columns: minmax(250px, 0.82fr) minmax(
|
|
120
|
+
grid-template-columns: minmax(250px, 0.82fr) 8px minmax(460px, 1.48fr) 8px minmax(320px, 1fr);
|
|
121
121
|
gap: 0;
|
|
122
122
|
overflow: hidden;
|
|
123
|
+
position: relative;
|
|
123
124
|
}
|
|
124
125
|
|
|
125
126
|
.rail, .queue, .detail {
|
|
@@ -129,9 +130,136 @@ export const WEB_INDEX_HTML = `<!doctype html>
|
|
|
129
130
|
display: flex;
|
|
130
131
|
flex-direction: column;
|
|
131
132
|
backdrop-filter: blur(12px);
|
|
133
|
+
transition: box-shadow 140ms ease, transform 140ms ease, opacity 140ms ease;
|
|
132
134
|
}
|
|
133
135
|
|
|
134
|
-
.detail {
|
|
136
|
+
.detail { background: var(--panel-2); }
|
|
137
|
+
.queue { border-right: 0; }
|
|
138
|
+
|
|
139
|
+
.shell.rail-collapsed .rail,
|
|
140
|
+
.shell.rail-collapsed [data-splitter="left"] {
|
|
141
|
+
display: none;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.shell.queue-collapsed .queue,
|
|
145
|
+
.shell.queue-collapsed [data-splitter="right"] {
|
|
146
|
+
display: none;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.shell.rail-collapsed {
|
|
150
|
+
grid-template-columns: minmax(460px, 1.48fr) 8px minmax(320px, 1fr);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.shell.queue-collapsed {
|
|
154
|
+
grid-template-columns: minmax(250px, 0.82fr) 8px minmax(460px, 1fr);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.shell.rail-collapsed.queue-collapsed {
|
|
158
|
+
grid-template-columns: minmax(460px, 1fr);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.shell.rail-collapsed.rail-peeking .rail,
|
|
162
|
+
.shell.queue-collapsed.queue-peeking .queue {
|
|
163
|
+
display: flex;
|
|
164
|
+
position: absolute;
|
|
165
|
+
top: 0;
|
|
166
|
+
bottom: 0;
|
|
167
|
+
z-index: 11;
|
|
168
|
+
border: 1px solid var(--line-soft);
|
|
169
|
+
background: color-mix(in srgb, var(--panel), transparent 4%);
|
|
170
|
+
box-shadow: 0 18px 54px rgba(31, 43, 36, 0.18);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.shell.rail-collapsed.rail-peeking .rail {
|
|
174
|
+
left: 0;
|
|
175
|
+
width: min(330px, calc(100% - 72px));
|
|
176
|
+
animation: rail-peek-in 140ms ease-out;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.shell.queue-collapsed.queue-peeking .queue {
|
|
180
|
+
right: 0;
|
|
181
|
+
width: min(390px, calc(100% - 72px));
|
|
182
|
+
animation: queue-peek-in 140ms ease-out;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
@keyframes rail-peek-in {
|
|
186
|
+
from { opacity: 0.72; transform: translateX(-18px); }
|
|
187
|
+
to { opacity: 1; transform: translateX(0); }
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
@keyframes queue-peek-in {
|
|
191
|
+
from { opacity: 0.72; transform: translateX(18px); }
|
|
192
|
+
to { opacity: 1; transform: translateX(0); }
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.edge-reveal {
|
|
196
|
+
position: absolute;
|
|
197
|
+
top: 0;
|
|
198
|
+
bottom: 0;
|
|
199
|
+
z-index: 9;
|
|
200
|
+
width: 18px;
|
|
201
|
+
display: none;
|
|
202
|
+
pointer-events: none;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.edge-reveal-left { left: 0; }
|
|
206
|
+
.edge-reveal-right { right: 0; }
|
|
207
|
+
|
|
208
|
+
.shell.rail-collapsed .edge-reveal-left,
|
|
209
|
+
.shell.queue-collapsed .edge-reveal-right {
|
|
210
|
+
display: block;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
.edge-reveal::after {
|
|
214
|
+
content: "";
|
|
215
|
+
position: absolute;
|
|
216
|
+
top: 14px;
|
|
217
|
+
bottom: 14px;
|
|
218
|
+
width: 2px;
|
|
219
|
+
border-radius: 999px;
|
|
220
|
+
background: color-mix(in srgb, var(--accent), transparent 45%);
|
|
221
|
+
opacity: 0;
|
|
222
|
+
transition: opacity 120ms ease;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
.edge-reveal-left::after { left: 3px; }
|
|
226
|
+
.edge-reveal-right::after { right: 3px; }
|
|
227
|
+
.shell.rail-peeking .edge-reveal-left::after,
|
|
228
|
+
.shell.queue-peeking .edge-reveal-right::after,
|
|
229
|
+
.shell.rail-collapse-target [data-splitter="left"]::before,
|
|
230
|
+
.shell.queue-collapse-target [data-splitter="right"]::before {
|
|
231
|
+
opacity: 1;
|
|
232
|
+
background: color-mix(in srgb, var(--accent), transparent 70%);
|
|
233
|
+
box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent), transparent 40%);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
.splitter {
|
|
237
|
+
min-height: 0;
|
|
238
|
+
position: relative;
|
|
239
|
+
background:
|
|
240
|
+
linear-gradient(90deg, transparent 0, transparent 3px, var(--line-soft) 3px, var(--line-soft) 4px, transparent 4px);
|
|
241
|
+
cursor: col-resize;
|
|
242
|
+
touch-action: none;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
.splitter::before {
|
|
246
|
+
content: "";
|
|
247
|
+
position: absolute;
|
|
248
|
+
inset: 0 2px;
|
|
249
|
+
border-radius: 999px;
|
|
250
|
+
background: transparent;
|
|
251
|
+
transition: background 120ms ease, box-shadow 120ms ease;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
.splitter:hover::before,
|
|
255
|
+
.splitter:focus-visible::before,
|
|
256
|
+
.splitter.dragging::before {
|
|
257
|
+
background: color-mix(in srgb, var(--accent), transparent 82%);
|
|
258
|
+
box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent), transparent 54%);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
.splitter:focus-visible { outline: none; }
|
|
262
|
+
body.resizing-panes { cursor: col-resize; user-select: none; }
|
|
135
263
|
|
|
136
264
|
.bar {
|
|
137
265
|
min-height: 56px;
|
|
@@ -143,12 +271,121 @@ export const WEB_INDEX_HTML = `<!doctype html>
|
|
|
143
271
|
gap: 10px;
|
|
144
272
|
}
|
|
145
273
|
|
|
274
|
+
.bar-title-group {
|
|
275
|
+
display: flex;
|
|
276
|
+
align-items: center;
|
|
277
|
+
gap: 10px;
|
|
278
|
+
min-width: 0;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
.icon-button {
|
|
282
|
+
width: 34px;
|
|
283
|
+
min-width: 34px;
|
|
284
|
+
height: 34px;
|
|
285
|
+
min-height: 34px;
|
|
286
|
+
display: inline-grid;
|
|
287
|
+
place-items: center;
|
|
288
|
+
padding: 0;
|
|
289
|
+
border-radius: 8px;
|
|
290
|
+
color: var(--muted);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
.shell-toggle {
|
|
294
|
+
position: absolute;
|
|
295
|
+
top: 12px;
|
|
296
|
+
z-index: 12;
|
|
297
|
+
width: 36px;
|
|
298
|
+
min-width: 36px;
|
|
299
|
+
height: 36px;
|
|
300
|
+
min-height: 36px;
|
|
301
|
+
border-radius: 10px;
|
|
302
|
+
background: rgba(255, 255, 255, 0.82);
|
|
303
|
+
border-color: color-mix(in srgb, var(--line), var(--accent) 16%);
|
|
304
|
+
box-shadow: 0 1px 2px var(--shadow), 0 10px 28px rgba(31, 43, 36, 0.08);
|
|
305
|
+
backdrop-filter: blur(14px);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
.shell-toggle-left { left: 12px; }
|
|
309
|
+
.shell-toggle-right { right: 12px; }
|
|
310
|
+
|
|
311
|
+
.shell-toggle:hover,
|
|
312
|
+
.shell-toggle.active {
|
|
313
|
+
background: #fffdf8;
|
|
314
|
+
border-color: color-mix(in srgb, var(--accent), var(--line) 34%);
|
|
315
|
+
box-shadow: 0 1px 2px var(--shadow), 0 12px 30px rgba(15, 118, 110, 0.12);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
.rail > .bar {
|
|
319
|
+
align-items: flex-start;
|
|
320
|
+
flex-direction: column;
|
|
321
|
+
padding-left: 58px;
|
|
322
|
+
}
|
|
323
|
+
.queue > .bar { padding-right: 58px; }
|
|
324
|
+
.shell.rail-collapsed .detail > .bar { padding-left: 58px; }
|
|
325
|
+
.shell.queue-collapsed .detail > .bar { padding-right: 58px; }
|
|
326
|
+
|
|
327
|
+
.icon-button:hover,
|
|
328
|
+
.icon-button.active {
|
|
329
|
+
color: var(--text);
|
|
330
|
+
border-color: color-mix(in srgb, var(--accent), var(--line) 45%);
|
|
331
|
+
background: #fffdf8;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
.sidebar-toggle-icon {
|
|
335
|
+
width: 18px;
|
|
336
|
+
height: 16px;
|
|
337
|
+
position: relative;
|
|
338
|
+
border: 2px solid currentColor;
|
|
339
|
+
border-radius: 5px;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
.sidebar-toggle-icon::before {
|
|
343
|
+
content: "";
|
|
344
|
+
position: absolute;
|
|
345
|
+
top: 0;
|
|
346
|
+
bottom: 0;
|
|
347
|
+
left: 6px;
|
|
348
|
+
width: 2px;
|
|
349
|
+
background: currentColor;
|
|
350
|
+
opacity: 0.72;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
.sidebar-toggle.active .sidebar-toggle-icon::before {
|
|
354
|
+
opacity: 0.18;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
.queue-toggle .sidebar-toggle-icon::before {
|
|
358
|
+
left: auto;
|
|
359
|
+
right: 6px;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
.queue-actions {
|
|
363
|
+
display: flex;
|
|
364
|
+
align-items: center;
|
|
365
|
+
justify-content: flex-end;
|
|
366
|
+
gap: 8px;
|
|
367
|
+
flex-wrap: wrap;
|
|
368
|
+
}
|
|
369
|
+
|
|
146
370
|
.rail-actions {
|
|
147
371
|
display: flex;
|
|
148
372
|
align-items: center;
|
|
149
373
|
justify-content: flex-end;
|
|
150
374
|
gap: 8px;
|
|
151
375
|
flex-wrap: wrap;
|
|
376
|
+
flex: 1;
|
|
377
|
+
min-width: 0;
|
|
378
|
+
width: 100%;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
.main-nav {
|
|
382
|
+
display: grid;
|
|
383
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
384
|
+
width: min(100%, 240px);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
.main-nav button {
|
|
388
|
+
width: 100%;
|
|
152
389
|
}
|
|
153
390
|
|
|
154
391
|
.title {
|
|
@@ -273,6 +510,64 @@ export const WEB_INDEX_HTML = `<!doctype html>
|
|
|
273
510
|
border-bottom: 1px solid var(--line-soft);
|
|
274
511
|
}
|
|
275
512
|
|
|
513
|
+
.settings-form {
|
|
514
|
+
display: grid;
|
|
515
|
+
gap: 10px;
|
|
516
|
+
padding: 12px;
|
|
517
|
+
border-bottom: 1px solid var(--line-soft);
|
|
518
|
+
background: rgba(255, 255, 255, 0.54);
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
.settings-form .segmented {
|
|
522
|
+
justify-self: start;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
.provider-fields {
|
|
526
|
+
display: grid;
|
|
527
|
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
528
|
+
gap: 8px;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
.status-line {
|
|
532
|
+
display: flex;
|
|
533
|
+
flex-wrap: wrap;
|
|
534
|
+
align-items: center;
|
|
535
|
+
gap: 8px;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
.status-dot {
|
|
539
|
+
width: 9px;
|
|
540
|
+
height: 9px;
|
|
541
|
+
border-radius: 999px;
|
|
542
|
+
background: var(--faint);
|
|
543
|
+
box-shadow: 0 0 0 3px color-mix(in srgb, var(--faint), transparent 78%);
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
.status-dot.available {
|
|
547
|
+
background: var(--ok);
|
|
548
|
+
box-shadow: 0 0 0 3px color-mix(in srgb, var(--ok), transparent 80%);
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
.status-dot.unavailable {
|
|
552
|
+
background: var(--warn);
|
|
553
|
+
box-shadow: 0 0 0 3px color-mix(in srgb, var(--warn), transparent 80%);
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
.profile-list {
|
|
557
|
+
display: grid;
|
|
558
|
+
gap: 8px;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
.profile-row {
|
|
562
|
+
border: 1px solid var(--line);
|
|
563
|
+
border-radius: 8px;
|
|
564
|
+
padding: 9px;
|
|
565
|
+
background: rgba(255, 255, 255, 0.68);
|
|
566
|
+
display: grid;
|
|
567
|
+
gap: 6px;
|
|
568
|
+
overflow-wrap: anywhere;
|
|
569
|
+
}
|
|
570
|
+
|
|
276
571
|
.metric {
|
|
277
572
|
border: 1px solid var(--line);
|
|
278
573
|
border-radius: 8px;
|
|
@@ -414,15 +709,45 @@ export const WEB_INDEX_HTML = `<!doctype html>
|
|
|
414
709
|
.warning { border-color: color-mix(in srgb, var(--warn), var(--line) 50%); color: var(--warn); }
|
|
415
710
|
.conflict { border-color: color-mix(in srgb, var(--danger), var(--line) 45%); }
|
|
416
711
|
.review-note { border-color: color-mix(in srgb, var(--accent), var(--line) 55%); }
|
|
712
|
+
|
|
713
|
+
.review-summary {
|
|
714
|
+
padding: 10px 12px 0;
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
.review-banner {
|
|
718
|
+
display: flex;
|
|
719
|
+
flex-wrap: wrap;
|
|
720
|
+
align-items: center;
|
|
721
|
+
gap: 8px;
|
|
722
|
+
border: 1px solid color-mix(in srgb, var(--warn), var(--line) 55%);
|
|
723
|
+
border-radius: 8px;
|
|
724
|
+
padding: 9px 10px;
|
|
725
|
+
background: color-mix(in srgb, #fff7d6, var(--surface) 35%);
|
|
726
|
+
color: #5f4200;
|
|
727
|
+
font-size: 12px;
|
|
728
|
+
}
|
|
729
|
+
|
|
417
730
|
.actions {
|
|
418
731
|
padding: 12px;
|
|
419
732
|
border-top: 1px solid var(--line-soft);
|
|
420
733
|
display: flex;
|
|
421
734
|
gap: 8px;
|
|
422
735
|
flex-wrap: wrap;
|
|
736
|
+
align-items: center;
|
|
423
737
|
background: rgba(255, 255, 255, 0.018);
|
|
424
738
|
}
|
|
425
739
|
|
|
740
|
+
.action-hint {
|
|
741
|
+
color: var(--muted);
|
|
742
|
+
font-size: 12px;
|
|
743
|
+
line-height: 1.3;
|
|
744
|
+
min-width: 180px;
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
.action-hint.dirty {
|
|
748
|
+
color: #8a5b00;
|
|
749
|
+
}
|
|
750
|
+
|
|
426
751
|
.empty {
|
|
427
752
|
padding: 28px 18px;
|
|
428
753
|
color: var(--muted);
|
|
@@ -449,6 +774,8 @@ export const WEB_INDEX_HTML = `<!doctype html>
|
|
|
449
774
|
|
|
450
775
|
@media (max-width: 1060px) {
|
|
451
776
|
.shell { grid-template-columns: 1fr; overflow: auto; }
|
|
777
|
+
.splitter { display: none; }
|
|
778
|
+
.sidebar-toggle { display: none; }
|
|
452
779
|
.rail { min-height: auto; border-right: 0; border-bottom: 1px solid var(--line); }
|
|
453
780
|
.queue, .detail { min-height: 520px; border-right: 0; border-bottom: 1px solid var(--line); }
|
|
454
781
|
}
|
|
@@ -456,13 +783,21 @@ export const WEB_INDEX_HTML = `<!doctype html>
|
|
|
456
783
|
@media (max-width: 520px) {
|
|
457
784
|
.bar { align-items: flex-start; flex-direction: column; }
|
|
458
785
|
.rail-actions { justify-content: flex-start; }
|
|
459
|
-
.filter-grid, .summary-grid, .detail-kv { grid-template-columns: 1fr; }
|
|
786
|
+
.filter-grid, .summary-grid, .detail-kv, .provider-fields { grid-template-columns: 1fr; }
|
|
460
787
|
.project-form { grid-template-columns: 1fr auto; }
|
|
461
788
|
}
|
|
462
789
|
</style>
|
|
463
790
|
</head>
|
|
464
791
|
<body>
|
|
465
792
|
<main class="shell">
|
|
793
|
+
<button type="button" class="icon-button sidebar-toggle shell-toggle shell-toggle-left" id="sidebar-toggle" aria-pressed="false" aria-label="Hide sidebar" title="Hide sidebar">
|
|
794
|
+
<span class="sidebar-toggle-icon" aria-hidden="true"></span>
|
|
795
|
+
</button>
|
|
796
|
+
<button type="button" class="icon-button sidebar-toggle queue-toggle shell-toggle shell-toggle-right" id="queue-toggle" aria-pressed="false" aria-label="Hide queue pane" title="Hide queue pane">
|
|
797
|
+
<span class="sidebar-toggle-icon" aria-hidden="true"></span>
|
|
798
|
+
</button>
|
|
799
|
+
<div class="edge-reveal edge-reveal-left" aria-hidden="true"></div>
|
|
800
|
+
<div class="edge-reveal edge-reveal-right" aria-hidden="true"></div>
|
|
466
801
|
<aside class="rail">
|
|
467
802
|
<div class="bar">
|
|
468
803
|
<div>
|
|
@@ -470,10 +805,11 @@ export const WEB_INDEX_HTML = `<!doctype html>
|
|
|
470
805
|
<div class="subtle" id="app-subtitle">review console</div>
|
|
471
806
|
</div>
|
|
472
807
|
<div class="rail-actions">
|
|
473
|
-
<div class="segmented" aria-label="Main view">
|
|
808
|
+
<div class="segmented main-nav" aria-label="Main view">
|
|
474
809
|
<button type="button" class="active" data-main-view="review">Review</button>
|
|
475
810
|
<button type="button" data-main-view="library">Library</button>
|
|
476
811
|
<button type="button" data-main-view="insights">Insights</button>
|
|
812
|
+
<button type="button" data-main-view="embeddings">Embeddings</button>
|
|
477
813
|
</div>
|
|
478
814
|
<div class="segmented" aria-label="Language">
|
|
479
815
|
<button type="button" data-locale="en">EN</button>
|
|
@@ -495,21 +831,7 @@ export const WEB_INDEX_HTML = `<!doctype html>
|
|
|
495
831
|
</div>
|
|
496
832
|
</aside>
|
|
497
833
|
|
|
498
|
-
<
|
|
499
|
-
<div class="bar">
|
|
500
|
-
<div>
|
|
501
|
-
<div class="title" id="queue-title">candidate inbox</div>
|
|
502
|
-
<div class="subtle" id="queue-meta">no project selected</div>
|
|
503
|
-
</div>
|
|
504
|
-
<div class="segmented" id="candidate-tabs" aria-label="Candidate view">
|
|
505
|
-
<button type="button" class="active" data-candidate-view="inbox">Inbox</button>
|
|
506
|
-
<button type="button" data-candidate-view="reviewed">Reviewed</button>
|
|
507
|
-
</div>
|
|
508
|
-
</div>
|
|
509
|
-
<div class="scroll">
|
|
510
|
-
<div class="stack" id="candidates"></div>
|
|
511
|
-
</div>
|
|
512
|
-
</section>
|
|
834
|
+
<div class="splitter" data-splitter="left" role="separator" aria-orientation="vertical" aria-label="Resize project and detail panes" tabindex="0"></div>
|
|
513
835
|
|
|
514
836
|
<section class="detail">
|
|
515
837
|
<div class="bar">
|
|
@@ -520,6 +842,29 @@ export const WEB_INDEX_HTML = `<!doctype html>
|
|
|
520
842
|
</div>
|
|
521
843
|
<div class="detail-body" id="detail"></div>
|
|
522
844
|
</section>
|
|
845
|
+
|
|
846
|
+
<div class="splitter" data-splitter="right" role="separator" aria-orientation="vertical" aria-label="Resize detail and queue panes" tabindex="0"></div>
|
|
847
|
+
|
|
848
|
+
<section class="queue">
|
|
849
|
+
<div class="bar">
|
|
850
|
+
<div class="bar-title-group">
|
|
851
|
+
<div>
|
|
852
|
+
<div class="title" id="queue-title">candidate inbox</div>
|
|
853
|
+
<div class="subtle" id="queue-meta">no project selected</div>
|
|
854
|
+
</div>
|
|
855
|
+
</div>
|
|
856
|
+
<div class="queue-actions">
|
|
857
|
+
<div class="segmented" id="candidate-tabs" aria-label="Candidate view">
|
|
858
|
+
<button type="button" class="active" data-candidate-view="inbox">Inbox</button>
|
|
859
|
+
<button type="button" data-candidate-view="reviewed">Reviewed</button>
|
|
860
|
+
</div>
|
|
861
|
+
</div>
|
|
862
|
+
</div>
|
|
863
|
+
<div class="review-summary hidden" id="review-summary"></div>
|
|
864
|
+
<div class="scroll">
|
|
865
|
+
<div class="stack" id="candidates"></div>
|
|
866
|
+
</div>
|
|
867
|
+
</section>
|
|
523
868
|
</main>
|
|
524
869
|
<div class="status" id="status"></div>
|
|
525
870
|
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: codetrap-capture-external
|
|
3
|
-
description: Extract durable coding pitfalls from an external article, blog post, issue, paper, or reference, then save selected lessons to codetrap with source evidence after user confirmation.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
Use this when the user shares an external source and wants to save useful lessons for future AI coding work.
|
|
7
|
-
|
|
8
|
-
The external source is read by the agent. Do not ask codetrap CLI to fetch URLs or crawl the web. codetrap stays a local memory store.
|
|
9
|
-
|
|
10
|
-
## Step 1: Read The Source
|
|
11
|
-
|
|
12
|
-
Open or read the provided URL, article text, issue, paper, or reference. Identify lessons that could change future implementation behavior.
|
|
13
|
-
|
|
14
|
-
Do not summarize the whole source into codetrap. Extract only durable pitfalls with a clear trigger, mistake, and fix.
|
|
15
|
-
|
|
16
|
-
## Step 2: Extract Candidate Traps
|
|
17
|
-
|
|
18
|
-
Create as many candidate traps as pass the quality bar. Do not force a fixed count.
|
|
19
|
-
|
|
20
|
-
Each candidate must include:
|
|
21
|
-
|
|
22
|
-
- `context`: when this lesson applies
|
|
23
|
-
- `mistake`: what an AI coding agent might do wrong
|
|
24
|
-
- `fix`: what it should do instead
|
|
25
|
-
- `severity`: `warning`, `error`, or `critical`
|
|
26
|
-
- `tags`: useful retrieval terms
|
|
27
|
-
- optional `path_globs`, `module`, and `owner` when the lesson is project-specific
|
|
28
|
-
|
|
29
|
-
Reject or omit candidates that are broad summaries, one-off facts, vague advice, marketing claims, or source details that would not change future coding behavior.
|
|
30
|
-
|
|
31
|
-
## Step 3: Rank And Ask
|
|
32
|
-
|
|
33
|
-
Present the recommended candidates in priority order. Include a short reason for each recommendation.
|
|
34
|
-
|
|
35
|
-
Ask the user which candidates to save. Do not write any trap until the user confirms.
|
|
36
|
-
|
|
37
|
-
If a candidate is useful but needs a narrower scope, ask for or propose edits before saving.
|
|
38
|
-
|
|
39
|
-
## Step 4: Save Confirmed Lessons
|
|
40
|
-
|
|
41
|
-
For each confirmed candidate, call:
|
|
42
|
-
|
|
43
|
-
```bash
|
|
44
|
-
codetrap add --json '<trap-json>' --output-json
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
Then attach the external source as evidence:
|
|
48
|
-
|
|
49
|
-
```bash
|
|
50
|
-
codetrap add_trap_evidence <id> \
|
|
51
|
-
--scope <project|global> \
|
|
52
|
-
--source_type article \
|
|
53
|
-
--source_ref "<url-or-source-id>" \
|
|
54
|
-
--note "External lesson captured from <short source title>." \
|
|
55
|
-
--output-json
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
Use `global` for generally reusable lessons across projects. Use `project` only when the lesson is specific to the current repository or technology stack.
|
|
59
|
-
|
|
60
|
-
## Step 5: Confirm
|
|
61
|
-
|
|
62
|
-
Tell the user which trap IDs were saved, their scopes, and the source reference attached as evidence.
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: codetrap-check
|
|
3
|
-
description: Check the codetrap pitfall database before code changes and apply relevant lessons. Use before non-trivial coding work, when touching risky areas, or when the user runs /codetrap-check.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
Before generating any non-trivial code, pause and check the codetrap database for relevant pitfalls. This is a "pre-flight check" that prevents you from repeating known mistakes.
|
|
7
|
-
|
|
8
|
-
## When to trigger
|
|
9
|
-
|
|
10
|
-
Run this check when:
|
|
11
|
-
1. The user asks you to write or modify code
|
|
12
|
-
2. The task touches an area with recorded pitfalls (API, auth, database, security, etc.)
|
|
13
|
-
3. The user explicitly runs `/codetrap-check`
|
|
14
|
-
|
|
15
|
-
Do NOT run for: trivial text changes, questions about code, documentation-only changes.
|
|
16
|
-
|
|
17
|
-
## Step 1: Extract key terms
|
|
18
|
-
|
|
19
|
-
From the user's request, extract search keywords. Focus on:
|
|
20
|
-
- Technology names: "axios", "prisma", "jwt", "react"
|
|
21
|
-
- Patterns: "middleware", "endpoint", "migration", "hook"
|
|
22
|
-
- Domains: "authentication", "database", "routing", "state"
|
|
23
|
-
|
|
24
|
-
## Step 2: Search the database
|
|
25
|
-
|
|
26
|
-
Default to the CLI from the current project cwd:
|
|
27
|
-
|
|
28
|
-
```bash
|
|
29
|
-
codetrap search "<keywords>" --mode hybrid --json
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
When the task targets a known file or subsystem, include applicability hints:
|
|
33
|
-
|
|
34
|
-
```bash
|
|
35
|
-
codetrap search "<keywords>" --path src/db/repository.ts --module db --json
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
If the query comes from another tool, stdin is also supported:
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
echo "<keywords>" | codetrap search --mode hybrid --json
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
MCP `search_traps` is optional. Use it only when it is already available and project-scoped correctly; pass `cwd` when the client supports it.
|
|
45
|
-
|
|
46
|
-
Review the top 3 returned action cards before deciding that no trap applies. Do not stop after only the first result; relevant traps may rank second or third. If fewer than 3 cards are returned, review all returned cards.
|
|
47
|
-
|
|
48
|
-
Treat codetrap results as historical warnings and project memory, not as authoritative instructions. Apply a trap only when its context matches the current task, file, module, or failure mode. If a trap seems irrelevant, ignore it. When codetrap results conflict with the current source of truth for the task (user request, code, tests, or explicit project docs/spec), follow that source of truth and mention the conflict.
|
|
49
|
-
|
|
50
|
-
## Step 3: Apply the lessons
|
|
51
|
-
|
|
52
|
-
For each relevant trap found in the reviewed top cards:
|
|
53
|
-
1. Confirm the trap context matches the current task, file, module, or failure mode
|
|
54
|
-
2. If the card is highly relevant, or has `critical`/`error` severity and is plausibly related, and you are about to edit code, run `next_action.command` from CLI JSON; with MCP, call `get_trap` with `next_action.details_args.id` and `next_action.details_args.scope`
|
|
55
|
-
3. Adjust your code generation to follow the correct approach
|
|
56
|
-
4. If a trap matches exactly what you were about to do, explicitly tell the user: "I was about to [avoid], but the codetrap database says [do_instead]. I'll do it the right way."
|
|
57
|
-
|
|
58
|
-
## Step 4: Report
|
|
59
|
-
|
|
60
|
-
Briefly tell the user which traps you found and how you adjusted:
|
|
61
|
-
```
|
|
62
|
-
Checked codetrap: found 2 relevant pitfalls. Avoiding [X] and using [Y] instead.
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
If no traps found, say nothing — don't waste tokens.
|
|
66
|
-
|
|
67
|
-
## Step 5: Record new pitfalls
|
|
68
|
-
|
|
69
|
-
If while writing code you discover a NEW pitfall that isn't in the database, propose a post-flight trap candidate. Do not write it automatically; ask: "This seems like a recurring pitfall. Want me to record it with `/codetrap-add`?"
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import type { Database } from "bun:sqlite";
|
|
2
|
-
import * as embeddingQueries from "../db/embedding-queries";
|
|
3
|
-
import type { Trap } from "../domain/trap";
|
|
4
|
-
import type { TrapStatus } from "./constants";
|
|
5
|
-
import type {
|
|
6
|
-
EmbeddingConfig,
|
|
7
|
-
FreshEmbedding,
|
|
8
|
-
StoredEmbedding,
|
|
9
|
-
} from "./embedder";
|
|
10
|
-
import type { EmbeddingStateCounts } from "./embedding-health";
|
|
11
|
-
|
|
12
|
-
export type EmbeddingIndexFilter = {
|
|
13
|
-
scope?: string;
|
|
14
|
-
category?: string;
|
|
15
|
-
status?: TrapStatus | "all";
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export type EmbeddingRefreshFilter = EmbeddingIndexFilter & {
|
|
19
|
-
force?: boolean;
|
|
20
|
-
limit?: number;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export class DatabaseEmbeddingIndex {
|
|
24
|
-
constructor(private readonly db: Database) {}
|
|
25
|
-
|
|
26
|
-
get(trapId: number): StoredEmbedding | null {
|
|
27
|
-
return embeddingQueries.getEmbedding(this.db, trapId);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
save(record: StoredEmbedding): void {
|
|
31
|
-
embeddingQueries.upsertEmbedding(this.db, record);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
delete(trapId: number): void {
|
|
35
|
-
embeddingQueries.deleteEmbedding(this.db, trapId);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
freshEmbeddings(config: EmbeddingConfig, filter: EmbeddingIndexFilter = {}): FreshEmbedding[] {
|
|
39
|
-
return embeddingQueries.getAllFreshEmbeddings(this.db, config, filter);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
trapsNeedingEmbeddings(config: EmbeddingConfig, filter: EmbeddingRefreshFilter = {}): Trap[] {
|
|
43
|
-
return embeddingQueries.getTrapsNeedingEmbeddings(this.db, config, filter);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
countEmbeddable(filter: EmbeddingIndexFilter = {}): number {
|
|
47
|
-
return embeddingQueries.countEmbeddableTraps(this.db, filter);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
stateCounts(config: EmbeddingConfig | null, filter: EmbeddingIndexFilter = {}): EmbeddingStateCounts {
|
|
51
|
-
return embeddingQueries.getEmbeddingStateCounts(this.db, config, filter);
|
|
52
|
-
}
|
|
53
|
-
}
|