@bongos/core 1.19.550 → 1.19.551
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 +57 -27
- package/.claude/skills/bug-triage/SKILL.md +191 -0
- package/clients/bongos-client/README.md +1 -1
- package/clients/bongos-client/bongos-client.global.js +2 -0
- package/clients/bongos-client/index.cjs +2 -0
- package/clients/bongos-client/index.d.ts +3 -0
- package/clients/bongos-client/index.mjs +2 -0
- package/docs/api/openapi.json +77 -2
- package/docs/api-reference.md +3 -2
- package/docs/file-map.md +1 -0
- package/docs/module-api-changelog.md +2 -0
- package/migrations/core_232_task_merge_provenance.sql +64 -0
- package/modules/dev-box/app/src/vendor/bongos-client.cjs +2 -0
- package/modules/government/catalog.js +1 -0
- package/modules/government/migrations/government_011_task_merge_metic.sql +38 -0
- package/modules/lifecycle/db-ship.js +147 -0
- package/modules/lifecycle/db.js +2 -0
- package/modules/lifecycle/routes/tasks.js +42 -0
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/scripts/gds/bug-triage.js +292 -0
- package/scripts/gds/triage.js +40 -21
- package/src/module-api.js +1 -1
- package/tests/abandon_task.mjs +17 -0
- package/tests/bug_triage.mjs +205 -0
- package/tests/task_merge.mjs +198 -0
package/.bongos-core.json
CHANGED
|
@@ -2,22 +2,22 @@
|
|
|
2
2
|
"artifact": "bongos-core",
|
|
3
3
|
"manifest_schema": 1,
|
|
4
4
|
"generator": "scripts/gds/package-core.js",
|
|
5
|
-
"core_version": "1.19.
|
|
6
|
-
"core_contract": "1.19.
|
|
7
|
-
"source_commit": "
|
|
5
|
+
"core_version": "1.19.551",
|
|
6
|
+
"core_contract": "1.19.551",
|
|
7
|
+
"source_commit": "de0b6c99753fd502f2356bcfb6bf338227445cc7",
|
|
8
8
|
"source_ref": "HEAD",
|
|
9
|
-
"built_at": "2026-09-
|
|
9
|
+
"built_at": "2026-09-04T20:39:18.276Z",
|
|
10
10
|
"redaction": {
|
|
11
11
|
"model": "docs-redacted+functional-verbatim",
|
|
12
|
-
"docs_redacted":
|
|
12
|
+
"docs_redacted": 442,
|
|
13
13
|
"agent_docs_stubbed": 24,
|
|
14
|
-
"functional_verbatim":
|
|
14
|
+
"functional_verbatim": 2018,
|
|
15
15
|
"rules": 3,
|
|
16
16
|
"gate_literals": 3,
|
|
17
17
|
"gate": "passed"
|
|
18
18
|
},
|
|
19
|
-
"file_count":
|
|
20
|
-
"tree_sha256": "
|
|
19
|
+
"file_count": 2484,
|
|
20
|
+
"tree_sha256": "38fea0008aa898d10d6e7388c30a7d422be81dcde8d201172848e551d72d361b",
|
|
21
21
|
"files": [
|
|
22
22
|
{
|
|
23
23
|
"path": ".claude/skills/blocker-review/SKILL.md",
|
|
@@ -29,6 +29,11 @@
|
|
|
29
29
|
"mode": "0000644",
|
|
30
30
|
"sha256": "90de8b32fb4dac69d6e5c781d78489c36c40f00c4b07f062c0650cff08052203"
|
|
31
31
|
},
|
|
32
|
+
{
|
|
33
|
+
"path": ".claude/skills/bug-triage/SKILL.md",
|
|
34
|
+
"mode": "0000644",
|
|
35
|
+
"sha256": "85481aea23304149520f1adcb7e2e8ab05b655c269dd2e38a6c04922013e9202"
|
|
36
|
+
},
|
|
32
37
|
{
|
|
33
38
|
"path": ".claude/skills/builder-backup/SKILL.md",
|
|
34
39
|
"mode": "0000644",
|
|
@@ -367,12 +372,12 @@
|
|
|
367
372
|
{
|
|
368
373
|
"path": "clients/bongos-client/README.md",
|
|
369
374
|
"mode": "0000644",
|
|
370
|
-
"sha256": "
|
|
375
|
+
"sha256": "262491824b5d7b6005c69d8190d50f450320f02dc1333dc7ae029616aff9f018"
|
|
371
376
|
},
|
|
372
377
|
{
|
|
373
378
|
"path": "clients/bongos-client/bongos-client.global.js",
|
|
374
379
|
"mode": "0000644",
|
|
375
|
-
"sha256": "
|
|
380
|
+
"sha256": "fd5d716ec3ba7fbdb9fdaee076ef89048424248139ef7d4ea51c3983866dea90"
|
|
376
381
|
},
|
|
377
382
|
{
|
|
378
383
|
"path": "clients/bongos-client/examples/hello-world.mjs",
|
|
@@ -382,17 +387,17 @@
|
|
|
382
387
|
{
|
|
383
388
|
"path": "clients/bongos-client/index.cjs",
|
|
384
389
|
"mode": "0000644",
|
|
385
|
-
"sha256": "
|
|
390
|
+
"sha256": "17753bb744e592f7d7871d33399536d9938b1b7d6c6249959bcbb4355688b557"
|
|
386
391
|
},
|
|
387
392
|
{
|
|
388
393
|
"path": "clients/bongos-client/index.d.ts",
|
|
389
394
|
"mode": "0000644",
|
|
390
|
-
"sha256": "
|
|
395
|
+
"sha256": "1b28c414b039d21ab8105d1687cf6d75cde078238ac84b920885772cd5e9bdbf"
|
|
391
396
|
},
|
|
392
397
|
{
|
|
393
398
|
"path": "clients/bongos-client/index.mjs",
|
|
394
399
|
"mode": "0000644",
|
|
395
|
-
"sha256": "
|
|
400
|
+
"sha256": "779dc3d8970036513a0f8da8e4846bd6c0d2d4714de38390b14ede249e75a3f6"
|
|
396
401
|
},
|
|
397
402
|
{
|
|
398
403
|
"path": "clients/bongos-client/package.json",
|
|
@@ -1767,12 +1772,12 @@
|
|
|
1767
1772
|
{
|
|
1768
1773
|
"path": "docs/api-reference.md",
|
|
1769
1774
|
"mode": "0000644",
|
|
1770
|
-
"sha256": "
|
|
1775
|
+
"sha256": "5ec1ca7cb551994a31d644eeebd77795955bac39e6389feaf6e6a5ec0217c911"
|
|
1771
1776
|
},
|
|
1772
1777
|
{
|
|
1773
1778
|
"path": "docs/api/openapi.json",
|
|
1774
1779
|
"mode": "0000644",
|
|
1775
|
-
"sha256": "
|
|
1780
|
+
"sha256": "40d863b7b46cc3691298f9e48c254cda3b7f4ab23bb008712a55e75764a69dd1"
|
|
1776
1781
|
},
|
|
1777
1782
|
{
|
|
1778
1783
|
"path": "docs/architecture.md",
|
|
@@ -2637,7 +2642,7 @@
|
|
|
2637
2642
|
{
|
|
2638
2643
|
"path": "docs/file-map.md",
|
|
2639
2644
|
"mode": "0000644",
|
|
2640
|
-
"sha256": "
|
|
2645
|
+
"sha256": "e7c193b1cca2fc3f59742e95f921fc65096a32fbbcfba16e4a3950448293a7ba"
|
|
2641
2646
|
},
|
|
2642
2647
|
{
|
|
2643
2648
|
"path": "docs/handoff-template.md",
|
|
@@ -2647,7 +2652,7 @@
|
|
|
2647
2652
|
{
|
|
2648
2653
|
"path": "docs/module-api-changelog.md",
|
|
2649
2654
|
"mode": "0000644",
|
|
2650
|
-
"sha256": "
|
|
2655
|
+
"sha256": "1389ff20919a19aef2fbff28102f596f0ca168c34bc4c4114cf557bbf52627a5"
|
|
2651
2656
|
},
|
|
2652
2657
|
{
|
|
2653
2658
|
"path": "docs/modules-contract.md",
|
|
@@ -3644,6 +3649,11 @@
|
|
|
3644
3649
|
"mode": "0000644",
|
|
3645
3650
|
"sha256": "8ae32be783a4ca41637f56626bd83375aa4ae0755e701a0c0170eada8d8303b8"
|
|
3646
3651
|
},
|
|
3652
|
+
{
|
|
3653
|
+
"path": "migrations/core_232_task_merge_provenance.sql",
|
|
3654
|
+
"mode": "0000644",
|
|
3655
|
+
"sha256": "5ed2ff8117e6650de621a1576062b27f2d6e84faf8860f9cb2aed45323a85aa6"
|
|
3656
|
+
},
|
|
3647
3657
|
{
|
|
3648
3658
|
"path": "modules/agents/lib/validate.js",
|
|
3649
3659
|
"mode": "0000644",
|
|
@@ -4042,7 +4052,7 @@
|
|
|
4042
4052
|
{
|
|
4043
4053
|
"path": "modules/dev-box/app/src/vendor/bongos-client.cjs",
|
|
4044
4054
|
"mode": "0000644",
|
|
4045
|
-
"sha256": "
|
|
4055
|
+
"sha256": "17753bb744e592f7d7871d33399536d9938b1b7d6c6249959bcbb4355688b557"
|
|
4046
4056
|
},
|
|
4047
4057
|
{
|
|
4048
4058
|
"path": "modules/dev-box/app/test/unit.mjs",
|
|
@@ -4282,7 +4292,7 @@
|
|
|
4282
4292
|
{
|
|
4283
4293
|
"path": "modules/government/catalog.js",
|
|
4284
4294
|
"mode": "0000644",
|
|
4285
|
-
"sha256": "
|
|
4295
|
+
"sha256": "57b29298fa5707d3a1d59e78612d2b039b1559d26b8a9116812d5c76e9c3af87"
|
|
4286
4296
|
},
|
|
4287
4297
|
{
|
|
4288
4298
|
"path": "modules/government/config.js",
|
|
@@ -4384,6 +4394,11 @@
|
|
|
4384
4394
|
"mode": "0000644",
|
|
4385
4395
|
"sha256": "2b729acbc94c933ff2558d59e3cb811e7725450f0d646f9d9bc89209c1340d0f"
|
|
4386
4396
|
},
|
|
4397
|
+
{
|
|
4398
|
+
"path": "modules/government/migrations/government_011_task_merge_metic.sql",
|
|
4399
|
+
"mode": "0000644",
|
|
4400
|
+
"sha256": "ccd2cd14103bae00957227d037d41f76adaaddc639bd09808f244b0bc514e702"
|
|
4401
|
+
},
|
|
4387
4402
|
{
|
|
4388
4403
|
"path": "modules/government/module.json",
|
|
4389
4404
|
"mode": "0000644",
|
|
@@ -5437,7 +5452,7 @@
|
|
|
5437
5452
|
{
|
|
5438
5453
|
"path": "modules/lifecycle/db-ship.js",
|
|
5439
5454
|
"mode": "0000644",
|
|
5440
|
-
"sha256": "
|
|
5455
|
+
"sha256": "e48d877a5951f02153c7384217421b2b04a3a1fed215b61ac41fc5b0b8355ded"
|
|
5441
5456
|
},
|
|
5442
5457
|
{
|
|
5443
5458
|
"path": "modules/lifecycle/db-tasks.js",
|
|
@@ -5452,7 +5467,7 @@
|
|
|
5452
5467
|
{
|
|
5453
5468
|
"path": "modules/lifecycle/db.js",
|
|
5454
5469
|
"mode": "0000644",
|
|
5455
|
-
"sha256": "
|
|
5470
|
+
"sha256": "df5de732d9484e1bcf801c657c78b618d1a0353a912cdb1ee4fdd2c9f121749c"
|
|
5456
5471
|
},
|
|
5457
5472
|
{
|
|
5458
5473
|
"path": "modules/lifecycle/dead-deps.js",
|
|
@@ -5682,7 +5697,7 @@
|
|
|
5682
5697
|
{
|
|
5683
5698
|
"path": "modules/lifecycle/routes/tasks.js",
|
|
5684
5699
|
"mode": "0000644",
|
|
5685
|
-
"sha256": "
|
|
5700
|
+
"sha256": "366cb9c60952539ab8a946f8cf757754163b6cd6764a6430777b4529c86c6a75"
|
|
5686
5701
|
},
|
|
5687
5702
|
{
|
|
5688
5703
|
"path": "modules/lifecycle/routes/versions.js",
|
|
@@ -7452,12 +7467,12 @@
|
|
|
7452
7467
|
{
|
|
7453
7468
|
"path": "package-lock.json",
|
|
7454
7469
|
"mode": "0000644",
|
|
7455
|
-
"sha256": "
|
|
7470
|
+
"sha256": "c71d59c13b87d9ffbd6c792eb56b26eb434704e855aed3afdfc58914dba02e29"
|
|
7456
7471
|
},
|
|
7457
7472
|
{
|
|
7458
7473
|
"path": "package.json",
|
|
7459
7474
|
"mode": "0000644",
|
|
7460
|
-
"sha256": "
|
|
7475
|
+
"sha256": "6a2c55e98a36d257177254a100569a14bec9b3720931caf9ef265971b81ba319"
|
|
7461
7476
|
},
|
|
7462
7477
|
{
|
|
7463
7478
|
"path": "public-docs/index.html",
|
|
@@ -7644,6 +7659,11 @@
|
|
|
7644
7659
|
"mode": "0000644",
|
|
7645
7660
|
"sha256": "afcebfb8e8e8f7041ee9cbfce1e9b8a46a299feb5e6e89ce4e00273135b268db"
|
|
7646
7661
|
},
|
|
7662
|
+
{
|
|
7663
|
+
"path": "scripts/gds/bug-triage.js",
|
|
7664
|
+
"mode": "0000644",
|
|
7665
|
+
"sha256": "70b8f34cd401395e828bcd7d2b1c3bf508d2f1e0918f998df034efb15b6783b8"
|
|
7666
|
+
},
|
|
7647
7667
|
{
|
|
7648
7668
|
"path": "scripts/gds/build-bongos.js",
|
|
7649
7669
|
"mode": "0000644",
|
|
@@ -8702,7 +8722,7 @@
|
|
|
8702
8722
|
{
|
|
8703
8723
|
"path": "scripts/gds/triage.js",
|
|
8704
8724
|
"mode": "0000644",
|
|
8705
|
-
"sha256": "
|
|
8725
|
+
"sha256": "dc494030979bf60de1d1423c68a07e36667e816d7e2a1652960cfbd17be4bfcc"
|
|
8706
8726
|
},
|
|
8707
8727
|
{
|
|
8708
8728
|
"path": "scripts/gds/turn-end-sound.js",
|
|
@@ -9147,7 +9167,7 @@
|
|
|
9147
9167
|
{
|
|
9148
9168
|
"path": "src/module-api.js",
|
|
9149
9169
|
"mode": "0000644",
|
|
9150
|
-
"sha256": "
|
|
9170
|
+
"sha256": "95e7b476152291d84e955bfd585e62c48c48d85dcab0ca8d73c4519af2997e8b"
|
|
9151
9171
|
},
|
|
9152
9172
|
{
|
|
9153
9173
|
"path": "src/module-loader/catalog.js",
|
|
@@ -9197,7 +9217,7 @@
|
|
|
9197
9217
|
{
|
|
9198
9218
|
"path": "tests/abandon_task.mjs",
|
|
9199
9219
|
"mode": "0000644",
|
|
9200
|
-
"sha256": "
|
|
9220
|
+
"sha256": "ccfb5d3e85fd6bd34acc78d510edf20d037d344eca58706f3e3130fa6dce611c"
|
|
9201
9221
|
},
|
|
9202
9222
|
{
|
|
9203
9223
|
"path": "tests/access_requests_invite.mjs",
|
|
@@ -9599,6 +9619,11 @@
|
|
|
9599
9619
|
"mode": "0000644",
|
|
9600
9620
|
"sha256": "b9303554061efaea510ef42d774ab9017ac7258cc0bc08f684abca7408b3fa86"
|
|
9601
9621
|
},
|
|
9622
|
+
{
|
|
9623
|
+
"path": "tests/bug_triage.mjs",
|
|
9624
|
+
"mode": "0000644",
|
|
9625
|
+
"sha256": "2bc6312ff72fffc04478d40adc60e57e031b52ed208adf1d88f78986e536623f"
|
|
9626
|
+
},
|
|
9602
9627
|
{
|
|
9603
9628
|
"path": "tests/build_info.mjs",
|
|
9604
9629
|
"mode": "0000644",
|
|
@@ -12214,6 +12239,11 @@
|
|
|
12214
12239
|
"mode": "0000644",
|
|
12215
12240
|
"sha256": "bc89502f571659477178d68047098cf6098030491ac5c5a82b46802474a48387"
|
|
12216
12241
|
},
|
|
12242
|
+
{
|
|
12243
|
+
"path": "tests/task_merge.mjs",
|
|
12244
|
+
"mode": "0000644",
|
|
12245
|
+
"sha256": "2a16f120729c641de65cccf79f1583e2d2e68b72bf10277310991c1787dde2bf"
|
|
12246
|
+
},
|
|
12217
12247
|
{
|
|
12218
12248
|
"path": "tests/task_ownership_gate.mjs",
|
|
12219
12249
|
"mode": "0000644",
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: bug-triage
|
|
3
|
+
description: >-
|
|
4
|
+
Daily walk through open kind=bug tasks, which land with no triage gate and
|
|
5
|
+
accumulate near-duplicates. Groups likely dups for one batch verdict, then
|
|
6
|
+
walks what's left: merge into a canonical task or won't-fix. Mirrors
|
|
7
|
+
/idea-triage. Triggers on "/bug-triage", "triage bugs", "walk the bug
|
|
8
|
+
queue", "dedupe bugs". Metic+ rank only (not Xenos/Thetes).
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
You are running the bug-triage session for Example. Open `kind=bug` tasks get
|
|
12
|
+
walked and verdicted, so near-duplicate reports don't sit forever as separate
|
|
13
|
+
claimable rows.
|
|
14
|
+
|
|
15
|
+
## Why this exists (task 1001478, idea 244)
|
|
16
|
+
|
|
17
|
+
Since task 1003071, a `#bugs` report routes straight to a `kind=bug` task at
|
|
18
|
+
filing time — no inbox stop, no gate. That is correct for getting a report
|
|
19
|
+
into the queue fast, but it means nothing ever folds two reports of the same
|
|
20
|
+
underlying bug together the way `/idea-triage` folds duplicate ideas. This
|
|
21
|
+
skill is that missing step, built on a **task-merge primitive** (`tasks`
|
|
22
|
+
gained `merged_into_task_id` + `triage_note` in `core_232`, mirroring
|
|
23
|
+
`idea_inbox`'s `merged_into_idea_id` from `core_195`) that did not exist
|
|
24
|
+
before this task.
|
|
25
|
+
|
|
26
|
+
**A merge is `abandoned` + a target, not a new status.** `tasks.status` has no
|
|
27
|
+
`'merged'` value — adding one would touch every place that already enumerates
|
|
28
|
+
task statuses (the claimable feed, dependency satisfaction, the diagrams
|
|
29
|
+
state machine) to answer a question `abandoned` already answers: this task is
|
|
30
|
+
retired, and by owner ruling its dependents are stranded, not waiting (see
|
|
31
|
+
`modules/lifecycle/CLAUDE.md`). `merged_into_task_id` carries the one thing
|
|
32
|
+
bare abandon can't: which task absorbed it. Read `modules/lifecycle/db-ship.js`
|
|
33
|
+
`mergeTask`'s header comment for the full guard list before touching this
|
|
34
|
+
surface.
|
|
35
|
+
|
|
36
|
+
## Rank gate — Metic+ only
|
|
37
|
+
|
|
38
|
+
**Gated to Metic+ (Metic, Archon); not Xenos or Thetes.** Merging or
|
|
39
|
+
won't-fixing a bug task reshapes the team's backlog the same way idea triage
|
|
40
|
+
does — `task.merge` and `task.abandon` are both floor-`metic` permissions
|
|
41
|
+
(`modules/government/catalog.js`). A sub-Metic can still **file** a bug (via
|
|
42
|
+
Discord `#bugs`, or `POST /tasks` if `task.create` allows it); they can't
|
|
43
|
+
verdict the queue.
|
|
44
|
+
|
|
45
|
+
**Enforce the gate at the very top of the session, before reading anything else:**
|
|
46
|
+
|
|
47
|
+
1. Call `GET /api/gds/me` and read `builder.rank`. Compare case-insensitively.
|
|
48
|
+
2. **If `rank` lowercases to `xenos` or `thetes`** → stop immediately. Tell the
|
|
49
|
+
builder: *"Bug triage is a Metic+ operation — merging or dismissing a bug
|
|
50
|
+
report reshapes the team's backlog. File new bugs via Discord `#bugs`;
|
|
51
|
+
ask an Archon to promote you if you need to triage them."* Do not list
|
|
52
|
+
open bugs, do not propose verdicts.
|
|
53
|
+
3. **If `rank` lowercases to `metic` or `archon`** → proceed below.
|
|
54
|
+
4. **If `rank` is absent** (pre-rank deployment) → treat the session as
|
|
55
|
+
available, the same pre-rank passthrough `/idea-triage` uses.
|
|
56
|
+
|
|
57
|
+
> Belt-and-braces: the server already rejects `POST /tasks/:id/merge` and
|
|
58
|
+
> `POST /tasks/:id/abandon` with `403 permission_forbidden` for a sub-Metic
|
|
59
|
+
> caller — this check just stops one early instead of after a wall of 403s.
|
|
60
|
+
|
|
61
|
+
## What this skill does
|
|
62
|
+
|
|
63
|
+
1. Lists open `kind=bug` tasks via `GET /api/gds/tasks?kind=bug&limit=1000`,
|
|
64
|
+
filtered to the still-open statuses (`backlog`, `ready`, `active`,
|
|
65
|
+
`blocked`, `completed`, `confirmed` — never `shipped` or `abandoned`,
|
|
66
|
+
the latter of which already includes merged-away duplicates).
|
|
67
|
+
2. **Batches near-duplicate bug tasks** into one verdict per cluster
|
|
68
|
+
(`node scripts/gds/bug-triage.js`'s reuse of `triage.js`'s `clusterRecords`
|
|
69
|
+
— the same union-find/Jaccard core `/idea-triage`'s `clusterIdeas` uses,
|
|
70
|
+
generalized in task 1001478 so the algorithm is written once). Partitioned
|
|
71
|
+
by `goal_id`, not `kind` — every row here is already `kind='bug'`, so a
|
|
72
|
+
kind gate would be a no-op; two bug reports in unrelated goals describing
|
|
73
|
+
similar-sounding symptoms are not the same triage decision.
|
|
74
|
+
3. For each remaining bug, prompts the user with: **merge** (this is the same
|
|
75
|
+
report as task N) or **won't-fix** (not a bug / already fixed / can't
|
|
76
|
+
reproduce — closes the report itself, folds into nothing).
|
|
77
|
+
4. Applies each verdict via `POST /api/gds/tasks/:id/merge` or
|
|
78
|
+
`POST /api/gds/tasks/:id/abandon`.
|
|
79
|
+
|
|
80
|
+
**No "promote" step, unlike `/idea-triage`.** A bug report is already a task —
|
|
81
|
+
there is no shape question (goal vs criterion vs task) to work out, because
|
|
82
|
+
`task-classifier.js`'s auto-routing already decided `kind=bug` at capture
|
|
83
|
+
time. The only two questions triage adds are "is this the same as an existing
|
|
84
|
+
report" and "should this report be closed at all".
|
|
85
|
+
|
|
86
|
+
## How to use
|
|
87
|
+
|
|
88
|
+
**Step 1 — fetch open bug tasks.**
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
node scripts/gds/api.js GET "/api/gds/tasks?kind=bug&limit=1000"
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Filter client-side to the open statuses above. If nothing remains, print "bug
|
|
95
|
+
queue empty — nothing to triage today" and stop.
|
|
96
|
+
|
|
97
|
+
For a human at a terminal, `node scripts/gds/bug-triage.js` runs the whole
|
|
98
|
+
walk interactively instead — batching, per-task prompts, and the summary all
|
|
99
|
+
in one command, same shape as `node scripts/gds/triage.js`.
|
|
100
|
+
|
|
101
|
+
**Step 1.5 — batch near-duplicate bug reports BEFORE walking individually.**
|
|
102
|
+
|
|
103
|
+
Run `clusterRecords` (`scripts/gds/triage.js`, pure, no I/O) with
|
|
104
|
+
`textOf: t => t.title + ' ' + t.description`, `kindOf: t => t.goal_id`,
|
|
105
|
+
`timeOf: t => new Date(t.created_at)`. For each cluster it returns, offer the
|
|
106
|
+
user ONE decision covering the whole group:
|
|
107
|
+
|
|
108
|
+
> Cluster of 3 likely duplicates: #501 "Login button does nothing on
|
|
109
|
+
> Safari", #517 "Safari: login unresponsive", #530 "Login broken in Safari".
|
|
110
|
+
> **Keep #501 and merge the rest, dismiss all as won't-fix, walk them
|
|
111
|
+
> individually, or skip?**
|
|
112
|
+
|
|
113
|
+
- **Keep #N** → merge every other member into #N (`POST /tasks/:id/merge
|
|
114
|
+
{"into_task_id": N}`), leaving #N itself open — it still gets the normal
|
|
115
|
+
Step 2 walk below, since "which report is the real one" and "should it stay
|
|
116
|
+
open" are different decisions.
|
|
117
|
+
- **Won't-fix all** → every member abandoned with one shared reason.
|
|
118
|
+
- **Individually** → ignore the grouping for this cluster; each member
|
|
119
|
+
returns to the normal walk.
|
|
120
|
+
- **Skip** → leave the whole cluster open; it clusters again next triage.
|
|
121
|
+
|
|
122
|
+
`node scripts/gds/bug-triage.js` already runs this pass automatically before
|
|
123
|
+
its interactive walk — a human running the deterministic walker gets it for
|
|
124
|
+
free with no flag.
|
|
125
|
+
|
|
126
|
+
**Step 2 — walk the list, task by task.**
|
|
127
|
+
|
|
128
|
+
Present each remaining bug with:
|
|
129
|
+
- id, status, title
|
|
130
|
+
- description (full)
|
|
131
|
+
- goal_id, created_at
|
|
132
|
+
|
|
133
|
+
Then ask the user (concise prompt — the owner may not be a software engineer,
|
|
134
|
+
CLAUDE.md §2's portable default; frame in product/outcome terms, not
|
|
135
|
+
implementation):
|
|
136
|
+
|
|
137
|
+
> Bug #N: "{title}". {one-sentence summary of the report}. **Is this a
|
|
138
|
+
> duplicate of an existing bug, should it be closed as won't-fix, or should
|
|
139
|
+
> it stay open?**
|
|
140
|
+
|
|
141
|
+
**Step 3 — apply the verdict.**
|
|
142
|
+
|
|
143
|
+
**Merge** → ask which existing task N is the canonical one, then fold this
|
|
144
|
+
report into it:
|
|
145
|
+
|
|
146
|
+
```
|
|
147
|
+
node scripts/gds/api.js POST /api/gds/tasks/<id>/merge --body '{"into_task_id":<N>,"reason":"same report as #N"}'
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
The server refuses a self-merge (`merge_self`), a shipped source
|
|
151
|
+
(`cannot_merge_shipped`), a task with an active claim
|
|
152
|
+
(`task_has_active_claim`), a target that doesn't exist
|
|
153
|
+
(`merge_target_not_found`), and a target that is itself merged elsewhere
|
|
154
|
+
(`merge_target_merged` — it names where the chain ends; retarget there
|
|
155
|
+
instead of re-merging).
|
|
156
|
+
|
|
157
|
+
**Won't-fix** → dismiss with a reason (not a bug / already fixed / cannot
|
|
158
|
+
reproduce):
|
|
159
|
+
|
|
160
|
+
```
|
|
161
|
+
node scripts/gds/api.js POST /api/gds/tasks/<id>/abandon --body '{"reason":"cannot reproduce on current build"}'
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
**Keep open** is implicit — leave the task un-patched by not calling either
|
|
165
|
+
route. It will surface again next triage.
|
|
166
|
+
|
|
167
|
+
**Step 4 — surface a summary.**
|
|
168
|
+
|
|
169
|
+
Report to the user:
|
|
170
|
+
- Total walked
|
|
171
|
+
- Merged (count + which task each folded into)
|
|
172
|
+
- Won't-fixed (count + ids)
|
|
173
|
+
- Skipped / left open (count — these surface again next session)
|
|
174
|
+
- Remaining open bug count
|
|
175
|
+
|
|
176
|
+
## Why we run this
|
|
177
|
+
|
|
178
|
+
The same reason `/idea-triage` runs daily: a queue nobody walks quietly fills
|
|
179
|
+
with near-duplicates that each cost a separate builder's attention to
|
|
180
|
+
discover independently. A fast pass with mostly "skip" verdicts beats
|
|
181
|
+
skipping the session entirely — the cadence is the discipline.
|
|
182
|
+
|
|
183
|
+
## Tone for the user
|
|
184
|
+
|
|
185
|
+
The owner is the prompter (CLAUDE.md §2's portable default). Frame merge/
|
|
186
|
+
won't-fix decisions in terms of what's actually broken for the end user, not
|
|
187
|
+
implementation: "these
|
|
188
|
+
are the same login failure reported twice" not "these share 71% word
|
|
189
|
+
overlap." Decide the mechanical merge target yourself; ask the human only
|
|
190
|
+
when two reports are genuinely ambiguous (different symptoms that might
|
|
191
|
+
share one root cause, say) rather than obviously the same.
|
|
@@ -5,7 +5,7 @@ A **generated**, zero-dependency typed client for the Bongos API — produced fr
|
|
|
5
5
|
by hand; it regenerates when the spec changes, so it can never drift from the routes.
|
|
6
6
|
|
|
7
7
|
- API version: **v1** (served at `/api/bongos/v1`)
|
|
8
|
-
-
|
|
8
|
+
- 356 operations across 55 resource groups
|
|
9
9
|
|
|
10
10
|
## Install
|
|
11
11
|
|
|
@@ -849,6 +849,8 @@ function createClient(opts = {}) {
|
|
|
849
849
|
deleteTasksIdDependenciesDepId: (args) => request("DELETE", "/tasks/{id}/dependencies/{depId}", { hasBody: false }, args),
|
|
850
850
|
// POST /tasks/{id}/grade — rank: any-builder — POST /tasks/:id/grade
|
|
851
851
|
postTasksIdGrade: (args) => request("POST", "/tasks/{id}/grade", { hasBody: true }, args),
|
|
852
|
+
// POST /tasks/{id}/merge — rank: metic+archon — POST /tasks/:id/merge
|
|
853
|
+
postTasksIdMerge: (args) => request("POST", "/tasks/{id}/merge", { hasBody: true }, args),
|
|
852
854
|
// POST /tasks/{id}/override-request — rank: any-builder — POST /tasks/:id/override-request
|
|
853
855
|
postTasksIdOverrideRequest: (args) => request("POST", "/tasks/{id}/override-request", { hasBody: true }, args),
|
|
854
856
|
// POST /tasks/{id}/promote — rank: metic+archon — POST /tasks/:id/promote
|
|
@@ -848,6 +848,8 @@ function createClient(opts = {}) {
|
|
|
848
848
|
deleteTasksIdDependenciesDepId: (args) => request("DELETE", "/tasks/{id}/dependencies/{depId}", { hasBody: false }, args),
|
|
849
849
|
// POST /tasks/{id}/grade — rank: any-builder — POST /tasks/:id/grade
|
|
850
850
|
postTasksIdGrade: (args) => request("POST", "/tasks/{id}/grade", { hasBody: true }, args),
|
|
851
|
+
// POST /tasks/{id}/merge — rank: metic+archon — POST /tasks/:id/merge
|
|
852
|
+
postTasksIdMerge: (args) => request("POST", "/tasks/{id}/merge", { hasBody: true }, args),
|
|
851
853
|
// POST /tasks/{id}/override-request — rank: any-builder — POST /tasks/:id/override-request
|
|
852
854
|
postTasksIdOverrideRequest: (args) => request("POST", "/tasks/{id}/override-request", { hasBody: true }, args),
|
|
853
855
|
// POST /tasks/{id}/promote — rank: metic+archon — POST /tasks/:id/promote
|
|
@@ -371,6 +371,7 @@ export interface PostTasksIdDemoteResponse { ok: boolean }
|
|
|
371
371
|
export interface PostTasksIdDependenciesRequest { depends_on_task_ids?: unknown[]; depends_on_task_id?: StringifiableId }
|
|
372
372
|
export interface PostTasksIdDependenciesResponse { ok: boolean; added: unknown; dependencies: unknown }
|
|
373
373
|
export interface PostTasksIdGradeRequest { subagent_output?: unknown; signals?: Record<string, unknown>; committed_files?: string[]; diff_hash?: string }
|
|
374
|
+
export interface PostTasksIdMergeRequest { into_task_id: number; reason?: string }
|
|
374
375
|
export interface PostTasksIdOverrideRequestRequest { rationale: string }
|
|
375
376
|
export interface PostTasksIdOverrideRequestResponse { ok: boolean; request: unknown }
|
|
376
377
|
export interface PostTasksIdPublishBranchRequest { branch: string; head_sha: string; bundle_b64: string; value_summary?: string }
|
|
@@ -1172,6 +1173,8 @@ export interface BongosClient {
|
|
|
1172
1173
|
deleteTasksIdDependenciesDepId(args?: RequestArgs): Promise<DeleteTasksIdDependenciesDepIdResponse>;
|
|
1173
1174
|
/** POST /tasks/{id}/grade — rank: any-builder */
|
|
1174
1175
|
postTasksIdGrade(args?: RequestArgs & { body?: PostTasksIdGradeRequest }): Promise<ApiResponse>;
|
|
1176
|
+
/** POST /tasks/{id}/merge — rank: metic+archon */
|
|
1177
|
+
postTasksIdMerge(args: RequestArgs & { body: PostTasksIdMergeRequest }): Promise<ApiResponse>;
|
|
1175
1178
|
/** POST /tasks/{id}/override-request — rank: any-builder */
|
|
1176
1179
|
postTasksIdOverrideRequest(args: RequestArgs & { body: PostTasksIdOverrideRequestRequest }): Promise<PostTasksIdOverrideRequestResponse>;
|
|
1177
1180
|
/** POST /tasks/{id}/promote — rank: metic+archon */
|
|
@@ -845,6 +845,8 @@ export function createClient(opts = {}) {
|
|
|
845
845
|
deleteTasksIdDependenciesDepId: (args) => request("DELETE", "/tasks/{id}/dependencies/{depId}", { hasBody: false }, args),
|
|
846
846
|
// POST /tasks/{id}/grade — rank: any-builder — POST /tasks/:id/grade
|
|
847
847
|
postTasksIdGrade: (args) => request("POST", "/tasks/{id}/grade", { hasBody: true }, args),
|
|
848
|
+
// POST /tasks/{id}/merge — rank: metic+archon — POST /tasks/:id/merge
|
|
849
|
+
postTasksIdMerge: (args) => request("POST", "/tasks/{id}/merge", { hasBody: true }, args),
|
|
848
850
|
// POST /tasks/{id}/override-request — rank: any-builder — POST /tasks/:id/override-request
|
|
849
851
|
postTasksIdOverrideRequest: (args) => request("POST", "/tasks/{id}/override-request", { hasBody: true }, args),
|
|
850
852
|
// POST /tasks/{id}/promote — rank: metic+archon — POST /tasks/:id/promote
|
package/docs/api/openapi.json
CHANGED
|
@@ -15213,6 +15213,65 @@
|
|
|
15213
15213
|
]
|
|
15214
15214
|
}
|
|
15215
15215
|
},
|
|
15216
|
+
"/tasks/{id}/merge": {
|
|
15217
|
+
"post": {
|
|
15218
|
+
"operationId": "post_tasks_id_merge",
|
|
15219
|
+
"tags": [
|
|
15220
|
+
"tasks"
|
|
15221
|
+
],
|
|
15222
|
+
"summary": "POST /tasks/:id/merge",
|
|
15223
|
+
"description": "POST /tasks/:id/merge — mark a duplicate task merged into its canonical one (task 1001478 — the /bug-triage counterpart to idea_inbox's merge verdict). Implemented as `abandonTask` plus a target (db.mergeTask, db-ship.js) rather than a new `tasks.status` value — see that function's header for why. Refuses a self-merge, a shipped task, a task with an active claim, a target that doesn't exist, and a target that is itself merged elsewhere (no chains); idempotent when re-merging into the SAME target already recorded. rank: metic+archon — same floor as task.abandon, which this reuses under the hood; a Metic who may retire a task may also say which task it duplicates.\n\n**Rank:** `metic+archon` — Metic or Archon rank (review/triage powers).\n\n**Permissions:** `task.merge` (all required).",
|
|
15224
|
+
"x-rank": "metic+archon",
|
|
15225
|
+
"x-source": "modules/lifecycle/routes/tasks.js",
|
|
15226
|
+
"x-permissions": [
|
|
15227
|
+
"task.merge"
|
|
15228
|
+
],
|
|
15229
|
+
"parameters": [
|
|
15230
|
+
{
|
|
15231
|
+
"name": "id",
|
|
15232
|
+
"in": "path",
|
|
15233
|
+
"required": true,
|
|
15234
|
+
"schema": {
|
|
15235
|
+
"type": "string"
|
|
15236
|
+
},
|
|
15237
|
+
"description": "Path parameter `id`."
|
|
15238
|
+
}
|
|
15239
|
+
],
|
|
15240
|
+
"requestBody": {
|
|
15241
|
+
"required": true,
|
|
15242
|
+
"content": {
|
|
15243
|
+
"application/json": {
|
|
15244
|
+
"schema": {
|
|
15245
|
+
"$ref": "#/components/schemas/PostTasksIdMergeRequest"
|
|
15246
|
+
}
|
|
15247
|
+
}
|
|
15248
|
+
},
|
|
15249
|
+
"x-validated": true
|
|
15250
|
+
},
|
|
15251
|
+
"responses": {
|
|
15252
|
+
"200": {
|
|
15253
|
+
"description": "Success."
|
|
15254
|
+
},
|
|
15255
|
+
"400": {
|
|
15256
|
+
"$ref": "#/components/responses/ValidationFailed"
|
|
15257
|
+
},
|
|
15258
|
+
"401": {
|
|
15259
|
+
"$ref": "#/components/responses/Unauthorized"
|
|
15260
|
+
},
|
|
15261
|
+
"403": {
|
|
15262
|
+
"$ref": "#/components/responses/Forbidden"
|
|
15263
|
+
},
|
|
15264
|
+
"404": {
|
|
15265
|
+
"$ref": "#/components/responses/NotFound"
|
|
15266
|
+
}
|
|
15267
|
+
},
|
|
15268
|
+
"security": [
|
|
15269
|
+
{
|
|
15270
|
+
"builderSession": []
|
|
15271
|
+
}
|
|
15272
|
+
]
|
|
15273
|
+
}
|
|
15274
|
+
},
|
|
15216
15275
|
"/tasks/{id}/override-request": {
|
|
15217
15276
|
"post": {
|
|
15218
15277
|
"operationId": "post_tasks_id_override_request",
|
|
@@ -21790,6 +21849,22 @@
|
|
|
21790
21849
|
},
|
|
21791
21850
|
"additionalProperties": false
|
|
21792
21851
|
},
|
|
21852
|
+
"PostTasksIdMergeRequest": {
|
|
21853
|
+
"type": "object",
|
|
21854
|
+
"properties": {
|
|
21855
|
+
"into_task_id": {
|
|
21856
|
+
"type": "integer",
|
|
21857
|
+
"minimum": 1
|
|
21858
|
+
},
|
|
21859
|
+
"reason": {
|
|
21860
|
+
"type": "string"
|
|
21861
|
+
}
|
|
21862
|
+
},
|
|
21863
|
+
"required": [
|
|
21864
|
+
"into_task_id"
|
|
21865
|
+
],
|
|
21866
|
+
"additionalProperties": false
|
|
21867
|
+
},
|
|
21793
21868
|
"PostTasksIdOverrideRequestRequest": {
|
|
21794
21869
|
"type": "object",
|
|
21795
21870
|
"properties": {
|
|
@@ -22384,8 +22459,8 @@
|
|
|
22384
22459
|
"description": "A required dependency/feature is not configured or is temporarily down."
|
|
22385
22460
|
}
|
|
22386
22461
|
},
|
|
22387
|
-
"x-endpoint-count":
|
|
22388
|
-
"x-schema-count":
|
|
22462
|
+
"x-endpoint-count": 356,
|
|
22463
|
+
"x-schema-count": 391,
|
|
22389
22464
|
"x-undocumented-bodies": 9,
|
|
22390
22465
|
"x-response-schemas": 265,
|
|
22391
22466
|
"x-generated-by": "scripts/gds/gen-api-docs.js"
|
package/docs/api-reference.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# Bongos API reference
|
|
4
4
|
|
|
5
|
-
> **Generated from the live route files** — the route file is authoritative.
|
|
5
|
+
> **Generated from the live route files** — the route file is authoritative. 356 endpoints across 58 route files.
|
|
6
6
|
> Machine-readable spec: [`docs/api/openapi.json`](api/openapi.json) (OpenAPI 3.1). Rendered docs site: **`/docs`** (e.g. `cloudbongos.com/docs`).
|
|
7
7
|
|
|
8
8
|
Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/<redacted>.md)): `public` < `any-builder` < `metic+archon` < `archon`.
|
|
@@ -581,7 +581,7 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/<redacted>
|
|
|
581
581
|
|---|---|---|---|---|
|
|
582
582
|
| GET | `/api/bongos/task-visuals/:name` | `public` | — | the WIDEST path this route can take, declared honestly. |
|
|
583
583
|
|
|
584
|
-
## `tasks` (
|
|
584
|
+
## `tasks` (32)
|
|
585
585
|
|
|
586
586
|
| Method | Path | Rank | Body | Description |
|
|
587
587
|
|---|---|---|---|---|
|
|
@@ -601,6 +601,7 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/<redacted>
|
|
|
601
601
|
| PUT | `/api/bongos/tasks/:id/dependencies` | `metic+archon` | `depends_on_task_ids` | PUT /tasks/:id/dependencies — replace the full dep set. |
|
|
602
602
|
| DELETE | `/api/bongos/tasks/:id/dependencies/:depId` | `metic+archon` | — | DELETE /tasks/:id/dependencies/:depId — removes the edge. |
|
|
603
603
|
| POST | `/api/bongos/tasks/:id/grade` | `any-builder` | `subagent_output`, `signals`, `committed_files`, `diff_hash` | GDS-V3 task V3.R18 (task 209). |
|
|
604
|
+
| POST | `/api/bongos/tasks/:id/merge` | `metic+archon` | `into_task_id`, `reason` | POST /tasks/:id/merge — mark a duplicate task merged into its canonical one (task 1001478 — the /bug-triage counterpart to idea_inbox's m… |
|
|
604
605
|
| POST | `/api/bongos/tasks/:id/override-request` | `any-builder` | `rationale` | POST /tasks/:id/override-request — V3.R74 (task 293). |
|
|
605
606
|
| POST | `/api/bongos/tasks/:id/promote` | `metic+archon` | — | backlog→ready promotion; scope mutation; ADR 0090 (was archon). |
|
|
606
607
|
| POST | `/api/bongos/tasks/:id/publish-branch` | `any-builder` | `branch`, `head_sha`, `bundle_b64`, `value_summary` | |
|
package/docs/file-map.md
CHANGED
|
@@ -375,6 +375,7 @@ tests/
|
|
|
375
375
|
.claude/skills/
|
|
376
376
|
├── blocker-review/SKILL.md ← /blocker-review — daily review of open GDS blockers (resolve / escalate / note); Metic+
|
|
377
377
|
├── blocker-solve/SKILL.md ← /blocker-solve N — drive ONE blocker to done: do the doable parts, hand back owner-only steps, verify, auto-resolve (auto-promotes waiters); Metic+
|
|
378
|
+
├── bug-triage/SKILL.md ← /bug-triage — daily walk through open kind=bug tasks (batch-cluster near-dups, merge / won't-fix); the idea-triage counterpart built on the new tasks.merge primitive (task 1001478); Metic+
|
|
378
379
|
├── builder-backup/SKILL.md ← /builder-backup — check DB backup status or trigger a fresh local dump before risky changes (migrations, destructive SQL); no SSH required
|
|
379
380
|
├── builder-box/SKILL.md ← /builder-box — show the builder their own dev box (state, IP/host, cost, SSH keys) and help them (re)connect
|
|
380
381
|
├── builder-claim/SKILL.md ← /builder-claim N — atomic claim; prints the claim-time context pack + discipline playbook routing
|
|
@@ -1549,5 +1549,7 @@ is load-bearing: the script throws rather than guess if it is missing, and
|
|
|
1549
1549
|
landed since 1.19.548 with no explicit bump. run 33906859934. (task 1002620)
|
|
1550
1550
|
1.19.550 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
1551
1551
|
landed since 1.19.549 with no explicit bump. run 33907331050. (task 1002620)
|
|
1552
|
+
1.19.551 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
1553
|
+
landed since 1.19.550 with no explicit bump. run 33917261720. (task 1002620)
|
|
1552
1554
|
---------------------------------------------------------------------------
|
|
1553
1555
|
```
|