@bongos/core 1.19.818 → 1.19.820
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/.bongos-core.json +85 -35
- package/.claude/skills/strand-fix/SKILL.md +11 -2
- package/.gitattributes +9 -0
- package/clients/bongos-client/index.d.ts +1 -1
- package/docs/api/openapi.json +4 -2
- package/docs/copy-inventory.md +23 -18
- package/docs/copy-registry.json +76 -31
- package/docs/module-api-changelog.md +4 -0
- package/docs/recipes/gds-db-backup.md +46 -0
- package/migrations/core_246_session_type.sql +49 -0
- package/modules/discord/bug-attachments.js +36 -1
- package/modules/hall-ui/public/sessions.css +19 -0
- package/modules/hall-ui/public/sessions.html +16 -1
- package/modules/hall-ui/public/sessions.js +135 -6
- package/modules/sessions/db.js +92 -6
- package/modules/sessions/routes/sessions.js +18 -1
- package/modules/sessions/session-type.js +132 -0
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/scripts/gds/backfill-session-types.js +87 -0
- package/scripts/gds/bug-attachment-audit.js +143 -0
- package/scripts/gds/capture.js +19 -0
- package/scripts/gds/db-backup-nightly.sh +37 -1
- package/scripts/gds/fitness.js +12 -1
- package/scripts/gds/home-isolation-guard.js +126 -0
- package/scripts/gds/ship-merge.js +5 -1
- package/scripts/gds/ship-regen.js +29 -0
- package/scripts/gds/skill-preflight.js +28 -4
- package/src/module-api.js +1 -1
- package/tests/bug_attachment_audit.mjs +122 -0
- package/tests/cli_package.mjs +18 -2
- package/tests/cli_surface.mjs +31 -2
- package/tests/hall_roster_world.mjs +10 -5
- package/tests/home_isolation_guard.mjs +95 -0
- package/tests/module_api_lazy.mjs +32 -1
- package/tests/routine_capture_kind.mjs +147 -0
- package/tests/session_type.mjs +215 -0
- package/tests/ship_regen_copy_inventory.mjs +69 -0
- package/tests/skill_preflight.mjs +45 -0
package/docs/copy-registry.json
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
"generator": "scripts/gds/copy-inventory.js",
|
|
4
4
|
"goal": 1000074,
|
|
5
5
|
"counts": {
|
|
6
|
-
"strings":
|
|
7
|
-
"unique_ids":
|
|
8
|
-
"certain":
|
|
6
|
+
"strings": 1868,
|
|
7
|
+
"unique_ids": 1622,
|
|
8
|
+
"certain": 1868,
|
|
9
9
|
"heuristic": 0,
|
|
10
10
|
"duplicate_ids": 170
|
|
11
11
|
},
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"builders-hall": {
|
|
14
14
|
"at": "modules/hall-ui/public",
|
|
15
15
|
"files": 86,
|
|
16
|
-
"strings":
|
|
16
|
+
"strings": 1378
|
|
17
17
|
},
|
|
18
18
|
"status-dashboard": {
|
|
19
19
|
"at": "modules/status-ui/public",
|
|
@@ -730,8 +730,8 @@
|
|
|
730
730
|
"text": "Could not load sessions.",
|
|
731
731
|
"occurrences": 2,
|
|
732
732
|
"at": [
|
|
733
|
-
"modules/hall-ui/public/sessions.js:
|
|
734
|
-
"modules/hall-ui/public/sessions.js:
|
|
733
|
+
"modules/hall-ui/public/sessions.js:399",
|
|
734
|
+
"modules/hall-ui/public/sessions.js:437"
|
|
735
735
|
]
|
|
736
736
|
},
|
|
737
737
|
{
|
|
@@ -1480,8 +1480,8 @@
|
|
|
1480
1480
|
"text": "The session log could not be loaded. Try again.",
|
|
1481
1481
|
"occurrences": 2,
|
|
1482
1482
|
"at": [
|
|
1483
|
-
"modules/hall-ui/public/sessions.js:
|
|
1484
|
-
"modules/hall-ui/public/sessions.js:
|
|
1483
|
+
"modules/hall-ui/public/sessions.js:398",
|
|
1484
|
+
"modules/hall-ui/public/sessions.js:450"
|
|
1485
1485
|
]
|
|
1486
1486
|
},
|
|
1487
1487
|
{
|
|
@@ -2491,6 +2491,15 @@
|
|
|
2491
2491
|
"origin": "html-text",
|
|
2492
2492
|
"confidence": "certain"
|
|
2493
2493
|
},
|
|
2494
|
+
{
|
|
2495
|
+
"id": "e08d410571e9",
|
|
2496
|
+
"surface": "builders-hall",
|
|
2497
|
+
"text": "All kinds",
|
|
2498
|
+
"file": "modules/hall-ui/public/sessions.js",
|
|
2499
|
+
"line": 286,
|
|
2500
|
+
"origin": "js-markup",
|
|
2501
|
+
"confidence": "certain"
|
|
2502
|
+
},
|
|
2494
2503
|
{
|
|
2495
2504
|
"id": "9c34bccb06ef",
|
|
2496
2505
|
"surface": "builders-hall",
|
|
@@ -3954,7 +3963,7 @@
|
|
|
3954
3963
|
"surface": "builders-hall",
|
|
3955
3964
|
"text": "Could not load sessions.",
|
|
3956
3965
|
"file": "modules/hall-ui/public/sessions.js",
|
|
3957
|
-
"line":
|
|
3966
|
+
"line": 399,
|
|
3958
3967
|
"origin": "js-notice",
|
|
3959
3968
|
"confidence": "certain"
|
|
3960
3969
|
},
|
|
@@ -3963,7 +3972,7 @@
|
|
|
3963
3972
|
"surface": "builders-hall",
|
|
3964
3973
|
"text": "Could not load sessions.",
|
|
3965
3974
|
"file": "modules/hall-ui/public/sessions.js",
|
|
3966
|
-
"line":
|
|
3975
|
+
"line": 437,
|
|
3967
3976
|
"origin": "js-notice",
|
|
3968
3977
|
"confidence": "certain"
|
|
3969
3978
|
},
|
|
@@ -4395,7 +4404,7 @@
|
|
|
4395
4404
|
"surface": "builders-hall",
|
|
4396
4405
|
"text": "Could not verify your access. Try again.",
|
|
4397
4406
|
"file": "modules/hall-ui/public/sessions.js",
|
|
4398
|
-
"line":
|
|
4407
|
+
"line": 436,
|
|
4399
4408
|
"origin": "js-text-assign",
|
|
4400
4409
|
"confidence": "certain"
|
|
4401
4410
|
},
|
|
@@ -5119,6 +5128,15 @@
|
|
|
5119
5128
|
"origin": "js-text-assign",
|
|
5120
5129
|
"confidence": "certain"
|
|
5121
5130
|
},
|
|
5131
|
+
{
|
|
5132
|
+
"id": "e8dd9a8f3a7e",
|
|
5133
|
+
"surface": "builders-hall",
|
|
5134
|
+
"text": "Filter sessions by kind",
|
|
5135
|
+
"file": "modules/hall-ui/public/sessions.html",
|
|
5136
|
+
"line": 67,
|
|
5137
|
+
"origin": "html-attr:aria-label",
|
|
5138
|
+
"confidence": "certain"
|
|
5139
|
+
},
|
|
5122
5140
|
{
|
|
5123
5141
|
"id": "1def0e7c716e",
|
|
5124
5142
|
"surface": "builders-hall",
|
|
@@ -5700,7 +5718,7 @@
|
|
|
5700
5718
|
"surface": "builders-hall",
|
|
5701
5719
|
"text": "How the session read to this builder, scored against their own interaction profile. Advisory — it gates nothing.",
|
|
5702
5720
|
"file": "modules/hall-ui/public/sessions.html",
|
|
5703
|
-
"line":
|
|
5721
|
+
"line": 78,
|
|
5704
5722
|
"origin": "html-attr:title",
|
|
5705
5723
|
"confidence": "certain"
|
|
5706
5724
|
},
|
|
@@ -6735,7 +6753,7 @@
|
|
|
6735
6753
|
"surface": "builders-hall",
|
|
6736
6754
|
"text": "Most recent first. Each load of this page is itself recorded in the audit log.",
|
|
6737
6755
|
"file": "modules/hall-ui/public/sessions.js",
|
|
6738
|
-
"line":
|
|
6756
|
+
"line": 340,
|
|
6739
6757
|
"origin": "js-text-assign",
|
|
6740
6758
|
"confidence": "certain"
|
|
6741
6759
|
},
|
|
@@ -7104,7 +7122,7 @@
|
|
|
7104
7122
|
"surface": "builders-hall",
|
|
7105
7123
|
"text": "No sessions recorded yet. They land here as builders ship and end sessions.",
|
|
7106
7124
|
"file": "modules/hall-ui/public/sessions.js",
|
|
7107
|
-
"line":
|
|
7125
|
+
"line": 146,
|
|
7108
7126
|
"origin": "js-markup",
|
|
7109
7127
|
"confidence": "certain"
|
|
7110
7128
|
},
|
|
@@ -7162,6 +7180,15 @@
|
|
|
7162
7180
|
"origin": "js-markup",
|
|
7163
7181
|
"confidence": "certain"
|
|
7164
7182
|
},
|
|
7183
|
+
{
|
|
7184
|
+
"id": "086665af6208",
|
|
7185
|
+
"surface": "builders-hall",
|
|
7186
|
+
"text": "No {…} sessions recorded. Choose another kind to widen the ledger.",
|
|
7187
|
+
"file": "modules/hall-ui/public/sessions.js",
|
|
7188
|
+
"line": 145,
|
|
7189
|
+
"origin": "js-markup",
|
|
7190
|
+
"confidence": "certain"
|
|
7191
|
+
},
|
|
7165
7192
|
{
|
|
7166
7193
|
"id": "1967d2176f2e",
|
|
7167
7194
|
"surface": "builders-hall",
|
|
@@ -7230,7 +7257,7 @@
|
|
|
7230
7257
|
"surface": "builders-hall",
|
|
7231
7258
|
"text": "Not scored — this builder’s own profile waived every signal, or the session predates this measure.",
|
|
7232
7259
|
"file": "modules/hall-ui/public/sessions.js",
|
|
7233
|
-
"line":
|
|
7260
|
+
"line": 100,
|
|
7234
7261
|
"origin": "js-markup",
|
|
7235
7262
|
"confidence": "certain"
|
|
7236
7263
|
},
|
|
@@ -7261,6 +7288,15 @@
|
|
|
7261
7288
|
"origin": "js-markup",
|
|
7262
7289
|
"confidence": "certain"
|
|
7263
7290
|
},
|
|
7291
|
+
{
|
|
7292
|
+
"id": "20bb29015a84",
|
|
7293
|
+
"surface": "builders-hall",
|
|
7294
|
+
"text": "Not yet classified.",
|
|
7295
|
+
"file": "modules/hall-ui/public/sessions.js",
|
|
7296
|
+
"line": 72,
|
|
7297
|
+
"origin": "js-markup",
|
|
7298
|
+
"confidence": "certain"
|
|
7299
|
+
},
|
|
7264
7300
|
{
|
|
7265
7301
|
"id": "571b9b22dbda",
|
|
7266
7302
|
"surface": "builders-hall",
|
|
@@ -7869,7 +7905,7 @@
|
|
|
7869
7905
|
"surface": "builders-hall",
|
|
7870
7906
|
"text": "Plain speech",
|
|
7871
7907
|
"file": "modules/hall-ui/public/sessions.html",
|
|
7872
|
-
"line":
|
|
7908
|
+
"line": 78,
|
|
7873
7909
|
"origin": "html-text",
|
|
7874
7910
|
"confidence": "certain"
|
|
7875
7911
|
},
|
|
@@ -10209,7 +10245,7 @@
|
|
|
10209
10245
|
"surface": "builders-hall",
|
|
10210
10246
|
"text": "The session log could not be loaded. Try again.",
|
|
10211
10247
|
"file": "modules/hall-ui/public/sessions.js",
|
|
10212
|
-
"line":
|
|
10248
|
+
"line": 398,
|
|
10213
10249
|
"origin": "js-text-assign",
|
|
10214
10250
|
"confidence": "certain"
|
|
10215
10251
|
},
|
|
@@ -10218,7 +10254,7 @@
|
|
|
10218
10254
|
"surface": "builders-hall",
|
|
10219
10255
|
"text": "The session log could not be loaded. Try again.",
|
|
10220
10256
|
"file": "modules/hall-ui/public/sessions.js",
|
|
10221
|
-
"line":
|
|
10257
|
+
"line": 450,
|
|
10222
10258
|
"origin": "js-text-assign",
|
|
10223
10259
|
"confidence": "certain"
|
|
10224
10260
|
},
|
|
@@ -10731,7 +10767,7 @@
|
|
|
10731
10767
|
"surface": "builders-hall",
|
|
10732
10768
|
"text": "Tool errors",
|
|
10733
10769
|
"file": "modules/hall-ui/public/sessions.html",
|
|
10734
|
-
"line":
|
|
10770
|
+
"line": 76,
|
|
10735
10771
|
"origin": "html-text",
|
|
10736
10772
|
"confidence": "certain"
|
|
10737
10773
|
},
|
|
@@ -11068,6 +11104,15 @@
|
|
|
11068
11104
|
"origin": "html-attr:placeholder",
|
|
11069
11105
|
"confidence": "certain"
|
|
11070
11106
|
},
|
|
11107
|
+
{
|
|
11108
|
+
"id": "e179870922a3",
|
|
11109
|
+
"surface": "builders-hall",
|
|
11110
|
+
"text": "What the session did, derived from its own transcript: whether it wrote files, used tools, and how many prompts a person actually sent.",
|
|
11111
|
+
"file": "modules/hall-ui/public/sessions.html",
|
|
11112
|
+
"line": 74,
|
|
11113
|
+
"origin": "html-attr:title",
|
|
11114
|
+
"confidence": "certain"
|
|
11115
|
+
},
|
|
11071
11116
|
{
|
|
11072
11117
|
"id": "5f2b989bbf6a",
|
|
11073
11118
|
"surface": "builders-hall",
|
|
@@ -13395,7 +13440,7 @@
|
|
|
13395
13440
|
"surface": "builders-hall",
|
|
13396
13441
|
"text": "{…} and up",
|
|
13397
13442
|
"file": "modules/hall-ui/public/sessions.js",
|
|
13398
|
-
"line":
|
|
13443
|
+
"line": 187,
|
|
13399
13444
|
"origin": "js-text-assign",
|
|
13400
13445
|
"confidence": "certain"
|
|
13401
13446
|
},
|
|
@@ -13404,7 +13449,7 @@
|
|
|
13404
13449
|
"surface": "builders-hall",
|
|
13405
13450
|
"text": "{…} and up.",
|
|
13406
13451
|
"file": "modules/hall-ui/public/sessions.js",
|
|
13407
|
-
"line":
|
|
13452
|
+
"line": 185,
|
|
13408
13453
|
"origin": "js-text-assign",
|
|
13409
13454
|
"confidence": "certain"
|
|
13410
13455
|
},
|
|
@@ -13579,15 +13624,6 @@
|
|
|
13579
13624
|
"origin": "js-markup",
|
|
13580
13625
|
"confidence": "certain"
|
|
13581
13626
|
},
|
|
13582
|
-
{
|
|
13583
|
-
"id": "3d76dce19c4a",
|
|
13584
|
-
"surface": "builders-hall",
|
|
13585
|
-
"text": "{…} session{…} across {…} builder{…}.",
|
|
13586
|
-
"file": "modules/hall-ui/public/sessions.js",
|
|
13587
|
-
"line": 226,
|
|
13588
|
-
"origin": "js-text-assign",
|
|
13589
|
-
"confidence": "certain"
|
|
13590
|
-
},
|
|
13591
13627
|
{
|
|
13592
13628
|
"id": "e08fa22622f0",
|
|
13593
13629
|
"surface": "builders-hall",
|
|
@@ -13629,7 +13665,7 @@
|
|
|
13629
13665
|
"surface": "builders-hall",
|
|
13630
13666
|
"text": "{…} tokens",
|
|
13631
13667
|
"file": "modules/hall-ui/public/sessions.js",
|
|
13632
|
-
"line":
|
|
13668
|
+
"line": 170,
|
|
13633
13669
|
"origin": "js-markup",
|
|
13634
13670
|
"confidence": "certain"
|
|
13635
13671
|
},
|
|
@@ -13840,6 +13876,15 @@
|
|
|
13840
13876
|
"origin": "js-markup",
|
|
13841
13877
|
"confidence": "certain"
|
|
13842
13878
|
},
|
|
13879
|
+
{
|
|
13880
|
+
"id": "97e27ab169ae",
|
|
13881
|
+
"surface": "builders-hall",
|
|
13882
|
+
"text": "{…}{…} session{…} across {…} builder{…}.",
|
|
13883
|
+
"file": "modules/hall-ui/public/sessions.js",
|
|
13884
|
+
"line": 338,
|
|
13885
|
+
"origin": "js-text-assign",
|
|
13886
|
+
"confidence": "certain"
|
|
13887
|
+
},
|
|
13843
13888
|
{
|
|
13844
13889
|
"id": "3d74668f69e5",
|
|
13845
13890
|
"surface": "builders-hall",
|
|
@@ -2110,5 +2110,9 @@ is load-bearing: the script throws rather than guess if it is missing, and
|
|
|
2110
2110
|
landed since 1.19.816 with no explicit bump. run 35200401779. (task 1002620)
|
|
2111
2111
|
1.19.818 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
2112
2112
|
landed since 1.19.817 with no explicit bump. run 35201213516. (task 1002620)
|
|
2113
|
+
1.19.819 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
2114
|
+
landed since 1.19.818 with no explicit bump. run 35206448426. (task 1002620)
|
|
2115
|
+
1.19.820 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
2116
|
+
landed since 1.19.819 with no explicit bump. run 35209838815. (task 1002620)
|
|
2113
2117
|
---------------------------------------------------------------------------
|
|
2114
2118
|
```
|
|
@@ -242,6 +242,52 @@ curl -s https://example.com/api/gds/healthz
|
|
|
242
242
|
curl -s https://example.com/api/gds/public/progress | jq '.progress[0]'
|
|
243
243
|
```
|
|
244
244
|
|
|
245
|
+
## Bug attachments — the state that is not in the database (task 1003918)
|
|
246
|
+
|
|
247
|
+
The nightly dump is not the whole of this instance. Re-hosted `#bugs` screenshots
|
|
248
|
+
live on disk under `var/bug-attachments`, outside Postgres and outside git, and they
|
|
249
|
+
are the one artefact here that **cannot be regenerated**: the Discord CDN URL each was
|
|
250
|
+
copied from is signed and expires in about a day, so our copy *is* the image.
|
|
251
|
+
|
|
252
|
+
Nothing backed them up until this task. All five this instance had ever stored were
|
|
253
|
+
lost in the 2026-07-05 droplet move (ADR 0126) — `pg_dump` carried the database and
|
|
254
|
+
nothing carried `var/` — and the loss surfaced two months later, when somebody opened
|
|
255
|
+
an old bug task and saw a broken image.
|
|
256
|
+
|
|
257
|
+
Two things changed, and one thing is still on you:
|
|
258
|
+
|
|
259
|
+
1. **The nightly job archives them.** `db-backup-nightly.sh` now writes
|
|
260
|
+
`<db>-attachments-<TS>.tar.gz` beside the dump, same timestamp and same retention,
|
|
261
|
+
so a restore drill that picks a date gets the database and the images that go with
|
|
262
|
+
it. Best-effort: a missing or empty attachments dir is the ordinary case on a fresh
|
|
263
|
+
instance and never fails a night of database backup.
|
|
264
|
+
|
|
265
|
+
2. **The default store follows the instance, not the package.** It resolves against the
|
|
266
|
+
instance root, so an instance running a vendored core no longer keeps these files
|
|
267
|
+
inside `node_modules/@bongos/core/var`, where every core reinstall would wipe them.
|
|
268
|
+
|
|
269
|
+
3. **On a box where the instance root is itself impermanent, set `BUG_ATTACHMENTS_DIR`**
|
|
270
|
+
to a persistent path (e.g. `/srv/<instance>/bug-attachments`) in the service
|
|
271
|
+
environment, and make sure that path is on the volume your backups actually cover.
|
|
272
|
+
The override wins over everything above.
|
|
273
|
+
|
|
274
|
+
### Checking
|
|
275
|
+
|
|
276
|
+
```bash
|
|
277
|
+
node scripts/gds/bug-attachment-audit.js
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
Reads every bug task's description, extracts the attachment links it promises a reader,
|
|
281
|
+
and asks the disk whether it can keep them. Exits 1 when any are missing and names the
|
|
282
|
+
task each broken image sits in. `--json` for a machine, `--line` for a one-line probe
|
|
283
|
+
that never blocks a session.
|
|
284
|
+
|
|
285
|
+
A missing file cannot be re-fetched. Restore it from an attachments archive:
|
|
286
|
+
|
|
287
|
+
```bash
|
|
288
|
+
tar -xzf /var/backups/gds/<db>-attachments-<TS>.tar.gz -C "$BUG_ATTACHMENTS_DIR"
|
|
289
|
+
```
|
|
290
|
+
|
|
245
291
|
## Limits — what this recipe does NOT cover
|
|
246
292
|
|
|
247
293
|
1. **Whole-droplet loss window is ~1 week, not zero.** The weekly offsite copy ([#415](https://example.com/builders#/task/415), above) closes the catastrophic-loss gap, but it runs weekly — so in the worst case (droplet dies right before the weekly run) you lose up to ~7 days of writes that made it into the local daily dumps but not yet offsite. Acceptable for the Bongos DB's shape; tighten the offsite cadence to daily if that ever stops being true.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
-- core_246_session_type.sql — WHAT EACH SESSION WAS (task 1003975, idea 1001033).
|
|
2
|
+
--
|
|
3
|
+
-- The session ledger could say whether a session shipped a task and nothing else,
|
|
4
|
+
-- so the 54% of the corpus with an empty task_ids read as an undifferentiated
|
|
5
|
+
-- column of dashes. This column holds the verdict of modules/sessions/session-type.js
|
|
6
|
+
-- — a pure, deterministic read of the digest the session already uploaded (its
|
|
7
|
+
-- prompt count and which tools it called), computed once at upload rather than on
|
|
8
|
+
-- every query, because the write-tool signal lives in the `detail` jsonb and
|
|
9
|
+
-- scanning it per request would put a jsonb walk on the ledger's hot path.
|
|
10
|
+
--
|
|
11
|
+
-- WHY IT IS HERE AND NOT IN modules/sessions/migrations/. The sessions module's
|
|
12
|
+
-- own CLAUDE.md says a new session migration belongs in the module — but that
|
|
13
|
+
-- holds only for a table the module OWNS. `session_records` predates the module
|
|
14
|
+
-- system and lives in core, and ADR 0083 §Decision #5 (enforced by fitness.js,
|
|
15
|
+
-- "module migrations additive + namespaced") lets a module migration touch only
|
|
16
|
+
-- its own `sessions_`-prefixed tables. A module migration adding this column was
|
|
17
|
+
-- written first and the gate refused it, correctly. The rule wins; the module doc
|
|
18
|
+
-- has been narrowed to say so.
|
|
19
|
+
--
|
|
20
|
+
-- NULLABLE ON PURPOSE, and there is no DEFAULT. Three reasons:
|
|
21
|
+
-- * Every row that predates this migration is legitimately unclassified until
|
|
22
|
+
-- the backfill (scripts/gds/backfill-session-types.js) runs. A DEFAULT would
|
|
23
|
+
-- assert a type for 4,595 rows nobody measured.
|
|
24
|
+
-- * The upload path fills it, but an older CLI posting the current body shape
|
|
25
|
+
-- must keep working — the column is derived server-side from what the body
|
|
26
|
+
-- already carries, never sent by the client, so no pinned core is broken.
|
|
27
|
+
-- * NULL is distinguishable from 'unknown'. NULL means "not yet classified";
|
|
28
|
+
-- 'unknown' means "classified, and the digest did not decide". Collapsing the
|
|
29
|
+
-- two would make the backfill's own progress unreadable.
|
|
30
|
+
--
|
|
31
|
+
-- NO CHECK CONSTRAINT against the type list. The closed set lives in
|
|
32
|
+
-- session-type.js, which the route filter and the ledger both validate against;
|
|
33
|
+
-- duplicating it here would give the vocabulary a second home that a deploy can
|
|
34
|
+
-- leave behind. The values are written by one function, never by a client.
|
|
35
|
+
|
|
36
|
+
ALTER TABLE session_records
|
|
37
|
+
ADD COLUMN IF NOT EXISTS session_type text;
|
|
38
|
+
|
|
39
|
+
COMMENT ON COLUMN session_records.session_type IS
|
|
40
|
+
'Derived shape of the session (build / automated / exploration / conversation / unknown) '
|
|
41
|
+
'from modules/sessions/session-type.js. NULL = not yet classified, which is not the same '
|
|
42
|
+
'as ''unknown''. Never client-supplied.';
|
|
43
|
+
|
|
44
|
+
-- Partial index: the ledger filters BY a type, never FOR the unclassified, so the
|
|
45
|
+
-- NULL rows are dead weight in the index. Drops with the backlog as the backfill
|
|
46
|
+
-- runs, which is the opposite of what a full index would do.
|
|
47
|
+
CREATE INDEX IF NOT EXISTS idx_session_records_type
|
|
48
|
+
ON session_records (session_type, uploaded_at DESC)
|
|
49
|
+
WHERE session_type IS NOT NULL;
|
|
@@ -50,8 +50,43 @@ const NAME_RE = /^bug-[a-z0-9]{1,40}-[0-9a-f]{16}\.(png|jpg|gif|webp)$/;
|
|
|
50
50
|
// Where re-hosted images live. Outside the git tree (a `var/` dir) so a deploy's
|
|
51
51
|
// `git reset --hard` / pull never wipes them; gitignored. Env override for tests
|
|
52
52
|
// / non-default layouts.
|
|
53
|
+
//
|
|
54
|
+
// RESOLVED AGAINST THE INSTANCE ROOT, not this file (task 1003918). The default
|
|
55
|
+
// used to be __dirname/../../var, which is the repo root in a single checkout and
|
|
56
|
+
// `node_modules/@bongos/core/var` on an instance running a vendored core — where
|
|
57
|
+
// every core reinstall wipes it. That is the task 1002237 shape, and these files
|
|
58
|
+
// are the one thing here that cannot be regenerated: a Discord CDN URL expires in
|
|
59
|
+
// about a day, so our copy IS the image. All five attachments this instance ever
|
|
60
|
+
// stored are already gone (the 2026-07-05 droplet move carried the database and
|
|
61
|
+
// not var/), which is what this default is meant to stop happening again.
|
|
62
|
+
//
|
|
63
|
+
// BUG_ATTACHMENTS_DIR still wins, and on a box where the instance root is itself
|
|
64
|
+
// impermanent that override is the answer — the standup recipe says so.
|
|
65
|
+
// The instance root is resolved ONCE. resolveInstanceRoot() reads an optional
|
|
66
|
+
// bongos.config.json on every call, and this runs per served attachment — a sync
|
|
67
|
+
// file read per image request, where the old code did a path.join. The root cannot
|
|
68
|
+
// move under a running process, so caching it costs nothing and keeps the serve
|
|
69
|
+
// path as cheap as it was. The env override is still read every call, so a test
|
|
70
|
+
// (or an operator) can still change it without restarting.
|
|
71
|
+
let instanceRootCache;
|
|
72
|
+
function attachmentsRoot() {
|
|
73
|
+
if (instanceRootCache === undefined) {
|
|
74
|
+
try {
|
|
75
|
+
// Through the published doorway (ADR 0083), like every other core read here.
|
|
76
|
+
instanceRootCache = require('../../src/module-api').resolveInstanceRoot();
|
|
77
|
+
} catch (e) {
|
|
78
|
+
// Never let a storage-path lookup take down the bot: fall back to the historical
|
|
79
|
+
// location, which is correct in a single checkout and is where any existing
|
|
80
|
+
// files already are.
|
|
81
|
+
instanceRootCache = path.join(__dirname, '..', '..');
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return instanceRootCache;
|
|
85
|
+
}
|
|
86
|
+
|
|
53
87
|
function attachmentsDir() {
|
|
54
|
-
|
|
88
|
+
if (process.env.BUG_ATTACHMENTS_DIR) return process.env.BUG_ATTACHMENTS_DIR;
|
|
89
|
+
return path.join(attachmentsRoot(), 'var', 'bug-attachments');
|
|
55
90
|
}
|
|
56
91
|
|
|
57
92
|
// PURE — is this a well-formed, bot-generated attachment name?
|
|
@@ -17,3 +17,22 @@
|
|
|
17
17
|
/* The task ids: chips that are doors (the family's a.fact-chip hover). */
|
|
18
18
|
.ledger-tasks { display: inline-flex; flex-wrap: wrap; gap: 6px; }
|
|
19
19
|
.ledger-tasks .fact-chip { text-decoration: none; }
|
|
20
|
+
/* task 1003975 — the kind filter row. Right-aligned above the ledger so it sits
|
|
21
|
+
over the column it acts on without stealing the lede's line; it reuses the
|
|
22
|
+
pager's .pager__perpage label+select so the page has ONE control grammar. */
|
|
23
|
+
.ledger-filters { display: flex; justify-content: flex-end; margin: 0 0 var(--sp-sm); }
|
|
24
|
+
/* The control itself: the same label+select proportions as the pager's per-page
|
|
25
|
+
picker, so the page reads as one grammar — but its OWN class, because the
|
|
26
|
+
hall_audit guard treats any .pager* markup outside the kit as a second pager,
|
|
27
|
+
and borrowing that family is exactly how one starts. */
|
|
28
|
+
.ledger-filter {
|
|
29
|
+
display: inline-flex; align-items: center; gap: 6px;
|
|
30
|
+
font-size: 12px; color: var(--ink-faint);
|
|
31
|
+
}
|
|
32
|
+
.ledger-filter select { height: 30px; padding: 2px 8px; font-size: 13px; }
|
|
33
|
+
/* The kind cell: a quiet fact, not a chip. The ledger already spends its colour
|
|
34
|
+
on the two warnings (tool errors, plain speech), and a third coloured token
|
|
35
|
+
per row would make the warnings stop reading as warnings. Deliberately NO
|
|
36
|
+
white-space: nowrap — task 1003470 removed the blanket nowrap that broke this
|
|
37
|
+
table on a phone, and "Automated run" is short enough to wrap harmlessly. */
|
|
38
|
+
.ledger-kind { color: var(--ink-soft); }
|
|
@@ -54,10 +54,25 @@
|
|
|
54
54
|
<section class="scroll" id="sessions-scroll" aria-labelledby="sessions-h" hidden>
|
|
55
55
|
<h2 id="sessions-h" class="scroll__h">Recorded sessions</h2>
|
|
56
56
|
<p class="scroll__lede">Most recent first. Each row is one recorded work session; every id on it opens its record.</p>
|
|
57
|
+
<!-- task 1003975: the ledger's first filter. It LOOKS like the pager's
|
|
58
|
+
per-page control on purpose (one control grammar per page) but wears
|
|
59
|
+
its own class — the hall_audit guard reads `class="pager…"` as a
|
|
60
|
+
hand-rolled pager, and it is right to: borrowing that family is how a
|
|
61
|
+
second pager implementation starts. Its options are filled from the
|
|
62
|
+
server's vocabulary in sessions.js, never hardcoded here, where they
|
|
63
|
+
would drift from what the route accepts. -->
|
|
64
|
+
<div class="ledger-filters">
|
|
65
|
+
<label class="ledger-filter">
|
|
66
|
+
<span>Kind</span>
|
|
67
|
+
<select id="session-type-filter" aria-label="Filter sessions by kind"></select>
|
|
68
|
+
</label>
|
|
69
|
+
</div>
|
|
57
70
|
<table class="ledger" id="sessions-table">
|
|
58
71
|
<thead>
|
|
59
72
|
<tr>
|
|
60
|
-
<th>Session</th><th>Builder</th
|
|
73
|
+
<th>Session</th><th>Builder</th>
|
|
74
|
+
<th title="What the session did, derived from its own transcript: whether it wrote files, used tools, and how many prompts a person actually sent.">Kind</th>
|
|
75
|
+
<th>Tasks</th>
|
|
61
76
|
<th class="ledger__num">Earned</th><th class="ledger__num">Turns</th><th class="ledger__num">Tokens</th><th class="ledger__num">Tool errors</th>
|
|
62
77
|
<th class="ledger__num">Duration</th>
|
|
63
78
|
<th class="ledger__num" title="How the session read to this builder, scored against their own interaction profile. Advisory — it gates nothing.">Plain speech</th>
|