@bongos/core 1.19.275 → 1.19.277
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 +37 -27
- package/.claude/skills/builder-sequence/SKILL.md +16 -1
- 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 +55 -3
- package/docs/api-reference.md +3 -2
- package/docs/copy-inventory.md +6 -4
- package/docs/copy-registry.json +23 -5
- package/modules/dev-box/app/src/vendor/bongos-client.cjs +2 -0
- package/modules/hall-ui/public/goal-inbox.js +81 -3
- package/modules/ideas/inbox.js +119 -12
- package/modules/ideas/migrations/ideas_004_lineage_route_index.sql +37 -0
- package/modules/ideas/routes/inbox.js +44 -0
- package/modules/ideas/routing.js +111 -0
- package/modules/lifecycle/ship-card.js +71 -2
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/src/module-api.js +5 -1
- package/tests/idea_routing.mjs +288 -1
- package/tests/session_boundary_handoff.mjs +184 -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.277",
|
|
6
|
+
"core_contract": "1.19.277",
|
|
7
|
+
"source_commit": "35b30c3a1c2a68136a144277b48bb750148995a4",
|
|
8
8
|
"source_ref": "HEAD",
|
|
9
|
-
"built_at": "2026-08-
|
|
9
|
+
"built_at": "2026-08-21T16:28:45.099Z",
|
|
10
10
|
"redaction": {
|
|
11
11
|
"model": "docs-redacted+functional-verbatim",
|
|
12
12
|
"docs_redacted": 318,
|
|
13
13
|
"agent_docs_stubbed": 22,
|
|
14
|
-
"functional_verbatim":
|
|
14
|
+
"functional_verbatim": 1376,
|
|
15
15
|
"rules": 3,
|
|
16
16
|
"gate_literals": 3,
|
|
17
17
|
"gate": "passed"
|
|
18
18
|
},
|
|
19
|
-
"file_count":
|
|
20
|
-
"tree_sha256": "
|
|
19
|
+
"file_count": 1716,
|
|
20
|
+
"tree_sha256": "42012dded2c6108d84ebdea4781e6cf78523e2f6c93cf2eebbc16e032b8a33b2",
|
|
21
21
|
"files": [
|
|
22
22
|
{
|
|
23
23
|
"path": ".claude/skills/blocker-review/SKILL.md",
|
|
@@ -87,7 +87,7 @@
|
|
|
87
87
|
{
|
|
88
88
|
"path": ".claude/skills/builder-sequence/SKILL.md",
|
|
89
89
|
"mode": "0000644",
|
|
90
|
-
"sha256": "
|
|
90
|
+
"sha256": "838648912f0f058c58c42d943282346e2c35a90aea507b0ec136e9b0fbda50b0"
|
|
91
91
|
},
|
|
92
92
|
{
|
|
93
93
|
"path": ".claude/skills/builder-setup/SKILL.md",
|
|
@@ -347,12 +347,12 @@
|
|
|
347
347
|
{
|
|
348
348
|
"path": "clients/bongos-client/README.md",
|
|
349
349
|
"mode": "0000644",
|
|
350
|
-
"sha256": "
|
|
350
|
+
"sha256": "28ea93104b710162845534c03881affa2ebfa5e9e622c195ef5332fb919762c4"
|
|
351
351
|
},
|
|
352
352
|
{
|
|
353
353
|
"path": "clients/bongos-client/bongos-client.global.js",
|
|
354
354
|
"mode": "0000644",
|
|
355
|
-
"sha256": "
|
|
355
|
+
"sha256": "8b6c0691763e21272008f0cb5c24e40d7bc65b297d81e4d1c1b2f58d5f1ab657"
|
|
356
356
|
},
|
|
357
357
|
{
|
|
358
358
|
"path": "clients/bongos-client/examples/hello-world.mjs",
|
|
@@ -362,17 +362,17 @@
|
|
|
362
362
|
{
|
|
363
363
|
"path": "clients/bongos-client/index.cjs",
|
|
364
364
|
"mode": "0000644",
|
|
365
|
-
"sha256": "
|
|
365
|
+
"sha256": "3b7b24b5ced8eead07e1d758e4c1b59321b0fb0f2108aefefd0e4b73bb7cc78b"
|
|
366
366
|
},
|
|
367
367
|
{
|
|
368
368
|
"path": "clients/bongos-client/index.d.ts",
|
|
369
369
|
"mode": "0000644",
|
|
370
|
-
"sha256": "
|
|
370
|
+
"sha256": "183d88c492aae87e1a06a1cb69ba5227db6b023057676637025fee0a77bddd88"
|
|
371
371
|
},
|
|
372
372
|
{
|
|
373
373
|
"path": "clients/bongos-client/index.mjs",
|
|
374
374
|
"mode": "0000644",
|
|
375
|
-
"sha256": "
|
|
375
|
+
"sha256": "0348faad8b08aefdc42d7bdff79a97a94f547f824c3ec37ed7642cde357a6950"
|
|
376
376
|
},
|
|
377
377
|
{
|
|
378
378
|
"path": "clients/bongos-client/package.json",
|
|
@@ -1397,12 +1397,12 @@
|
|
|
1397
1397
|
{
|
|
1398
1398
|
"path": "docs/api-reference.md",
|
|
1399
1399
|
"mode": "0000644",
|
|
1400
|
-
"sha256": "
|
|
1400
|
+
"sha256": "1f499b7f98aba5e51d30f7e3a76c00a3c1b535fe676eb03a31f1eb559d9a0f13"
|
|
1401
1401
|
},
|
|
1402
1402
|
{
|
|
1403
1403
|
"path": "docs/api/openapi.json",
|
|
1404
1404
|
"mode": "0000644",
|
|
1405
|
-
"sha256": "
|
|
1405
|
+
"sha256": "7fa333bb7864fa72672b463f5c53ae9340bd5ecad808bbfe193e835e57ae3e8d"
|
|
1406
1406
|
},
|
|
1407
1407
|
{
|
|
1408
1408
|
"path": "docs/architecture.md",
|
|
@@ -1427,12 +1427,12 @@
|
|
|
1427
1427
|
{
|
|
1428
1428
|
"path": "docs/copy-inventory.md",
|
|
1429
1429
|
"mode": "0000644",
|
|
1430
|
-
"sha256": "
|
|
1430
|
+
"sha256": "5d38acb7694c5e60631e0ba4ad00f9ce79fd7b761434e6c55de9b1034b62722e"
|
|
1431
1431
|
},
|
|
1432
1432
|
{
|
|
1433
1433
|
"path": "docs/copy-registry.json",
|
|
1434
1434
|
"mode": "0000644",
|
|
1435
|
-
"sha256": "
|
|
1435
|
+
"sha256": "6d4123b12211e88f62337fb4f76743459af1af9629a1e6215676fdcc19a2f71f"
|
|
1436
1436
|
},
|
|
1437
1437
|
{
|
|
1438
1438
|
"path": "docs/design-contract.md",
|
|
@@ -2787,7 +2787,7 @@
|
|
|
2787
2787
|
{
|
|
2788
2788
|
"path": "modules/dev-box/app/src/vendor/bongos-client.cjs",
|
|
2789
2789
|
"mode": "0000644",
|
|
2790
|
-
"sha256": "
|
|
2790
|
+
"sha256": "3b7b24b5ced8eead07e1d758e4c1b59321b0fb0f2108aefefd0e4b73bb7cc78b"
|
|
2791
2791
|
},
|
|
2792
2792
|
{
|
|
2793
2793
|
"path": "modules/dev-box/app/test/unit.mjs",
|
|
@@ -3377,7 +3377,7 @@
|
|
|
3377
3377
|
{
|
|
3378
3378
|
"path": "modules/hall-ui/public/goal-inbox.js",
|
|
3379
3379
|
"mode": "0000644",
|
|
3380
|
-
"sha256": "
|
|
3380
|
+
"sha256": "ede756a5c11c8c6a9eca4c841f2110a5e05293b0fbd6d34a5c90a05dc02943c4"
|
|
3381
3381
|
},
|
|
3382
3382
|
{
|
|
3383
3383
|
"path": "modules/hall-ui/public/goals-page.js",
|
|
@@ -3682,7 +3682,7 @@
|
|
|
3682
3682
|
{
|
|
3683
3683
|
"path": "modules/ideas/inbox.js",
|
|
3684
3684
|
"mode": "0000644",
|
|
3685
|
-
"sha256": "
|
|
3685
|
+
"sha256": "379a6e51a8865dcf52061d858e7e2f3b572f16bc04473aba163e52cadcaf1873"
|
|
3686
3686
|
},
|
|
3687
3687
|
{
|
|
3688
3688
|
"path": "modules/ideas/migrations/ideas_001_grades.sql",
|
|
@@ -3699,6 +3699,11 @@
|
|
|
3699
3699
|
"mode": "0000644",
|
|
3700
3700
|
"sha256": "8edeeb0bbf5bac57111008357fc287f8dc14e6907d7bc218264c40633778b9c3"
|
|
3701
3701
|
},
|
|
3702
|
+
{
|
|
3703
|
+
"path": "modules/ideas/migrations/ideas_004_lineage_route_index.sql",
|
|
3704
|
+
"mode": "0000644",
|
|
3705
|
+
"sha256": "eb1393f0ee8dccc57efcfe0acd0fdac7857389b74e0cb734042bb4293768b8e8"
|
|
3706
|
+
},
|
|
3702
3707
|
{
|
|
3703
3708
|
"path": "modules/ideas/module.json",
|
|
3704
3709
|
"mode": "0000644",
|
|
@@ -3712,12 +3717,12 @@
|
|
|
3712
3717
|
{
|
|
3713
3718
|
"path": "modules/ideas/routes/inbox.js",
|
|
3714
3719
|
"mode": "0000644",
|
|
3715
|
-
"sha256": "
|
|
3720
|
+
"sha256": "9c7027f70daba8cb956ab540567972afcec96900ce8d7f7793647bc58c13abdd"
|
|
3716
3721
|
},
|
|
3717
3722
|
{
|
|
3718
3723
|
"path": "modules/ideas/routing.js",
|
|
3719
3724
|
"mode": "0000644",
|
|
3720
|
-
"sha256": "
|
|
3725
|
+
"sha256": "2ca0adb68b0fd44a65b9637c177848648ecd20ecd8ef67e65527c17b7a46414d"
|
|
3721
3726
|
},
|
|
3722
3727
|
{
|
|
3723
3728
|
"path": "modules/ideas/templates.js",
|
|
@@ -3867,7 +3872,7 @@
|
|
|
3867
3872
|
{
|
|
3868
3873
|
"path": "modules/lifecycle/ship-card.js",
|
|
3869
3874
|
"mode": "0000644",
|
|
3870
|
-
"sha256": "
|
|
3875
|
+
"sha256": "c08ee0e89f67a2db7ea049353a12bdd6e5d97c6a7ec9039d19bdd797f66c112e"
|
|
3871
3876
|
},
|
|
3872
3877
|
{
|
|
3873
3878
|
"path": "modules/lifecycle/ship-preflight.js",
|
|
@@ -4482,12 +4487,12 @@
|
|
|
4482
4487
|
{
|
|
4483
4488
|
"path": "package-lock.json",
|
|
4484
4489
|
"mode": "0000644",
|
|
4485
|
-
"sha256": "
|
|
4490
|
+
"sha256": "296343fcb5f99b8dc4fb410e8b7c983d8c27da94bb23a64ffae6e246b87634d1"
|
|
4486
4491
|
},
|
|
4487
4492
|
{
|
|
4488
4493
|
"path": "package.json",
|
|
4489
4494
|
"mode": "0000644",
|
|
4490
|
-
"sha256": "
|
|
4495
|
+
"sha256": "0fa3267232afe7bfab282670e735d0cdd313d21614128c7666a10368f302ae2e"
|
|
4491
4496
|
},
|
|
4492
4497
|
{
|
|
4493
4498
|
"path": "public-docs/index.html",
|
|
@@ -6132,7 +6137,7 @@
|
|
|
6132
6137
|
{
|
|
6133
6138
|
"path": "src/module-api.js",
|
|
6134
6139
|
"mode": "0000644",
|
|
6135
|
-
"sha256": "
|
|
6140
|
+
"sha256": "3068c942e43140df9169a36c39acb9b3daffb182d2a7f33e89180b3926abfd37"
|
|
6136
6141
|
},
|
|
6137
6142
|
{
|
|
6138
6143
|
"path": "src/module-loader/catalog.js",
|
|
@@ -7417,7 +7422,7 @@
|
|
|
7417
7422
|
{
|
|
7418
7423
|
"path": "tests/idea_routing.mjs",
|
|
7419
7424
|
"mode": "0000644",
|
|
7420
|
-
"sha256": "
|
|
7425
|
+
"sha256": "7bea2d388fad9a6b186c4712d6921a554f1d24c70dcae5760b381782149068e7"
|
|
7421
7426
|
},
|
|
7422
7427
|
{
|
|
7423
7428
|
"path": "tests/idea_task_lineage.mjs",
|
|
@@ -8189,6 +8194,11 @@
|
|
|
8189
8194
|
"mode": "0000644",
|
|
8190
8195
|
"sha256": "e76a3baf5fb2cdee08ffe8d80c55630b5ab4f708046f3c63c07c480926ccda31"
|
|
8191
8196
|
},
|
|
8197
|
+
{
|
|
8198
|
+
"path": "tests/session_boundary_handoff.mjs",
|
|
8199
|
+
"mode": "0000644",
|
|
8200
|
+
"sha256": "8789eb59b2c3984500b4b2eb24d1e812e0ce6c970fc6fc940c06a6daf2613ec2"
|
|
8201
|
+
},
|
|
8192
8202
|
{
|
|
8193
8203
|
"path": "tests/session_caps.mjs",
|
|
8194
8204
|
"mode": "0000644",
|
|
@@ -35,7 +35,20 @@ This skill owns the **loop and the halt discipline**. It does not re-derive how
|
|
|
35
35
|
|
|
36
36
|
5. **Ship it** — `/builder-ship`. The task must reach `shipped`, not stall at `completed` or `confirmed`. A ship that does not land has not unblocked anything, so the chain cannot advance; treat it as a halt (see `ship_failed` below).
|
|
37
37
|
|
|
38
|
-
6. **
|
|
38
|
+
6. **Hand the chain off before the next link — the chain gets slower otherwise.** This is the step that makes a long run stay fast, and it is easy to skip because nothing breaks without it.
|
|
39
|
+
|
|
40
|
+
Every turn re-reads the whole conversation, so a chain worked in one window pays more per turn the further down it goes. Measured on a three-task run (2026-08-21): 11.3M cached tokens on the first task, 36.1M on the second, 78.1M on the third. The third task was not twice the work of the second — it re-processed twice the context.
|
|
41
|
+
|
|
42
|
+
A shipped task is the moment almost all of that context turns into dead weight: superseded diffs, resolved test failures, closed grade rounds. **The chain's state is already durable** — dependencies and claims live in the GDS, and `--next` re-derives the plan from them — so a fresh window loses nothing that matters.
|
|
43
|
+
|
|
44
|
+
So, when the ship card shows a **heavy session** (it says so itself: `⚠ heavy session (NNM cached) — run /session-handoff…`), or when you have landed **three or more links** in one window:
|
|
45
|
+
|
|
46
|
+
- Run `/session-handoff`, scoped to the REMAINDER of the chain — the next task id, the chain's tail, and any decision from the links already landed that the rest depends on. Do not summarise the finished work in detail; it is shipped, and the GDS is its record.
|
|
47
|
+
- Hand the user that prompt and say plainly that the chain continues in a fresh session. Then **stop.** Do not claim the next task in this window.
|
|
48
|
+
|
|
49
|
+
`/session-handoff` composes text and changes nothing, so this is safe at any point — and it cannot be automated away: a hook cannot clear a conversation, which is exactly why this step is the runner's job.
|
|
50
|
+
|
|
51
|
+
7. **Otherwise, go back to step 2.** The ship you just landed is what promotes the next task to `ready`.
|
|
39
52
|
|
|
40
53
|
Between passes, report progress in one line — which task landed, what is next, how much of the chain remains. The user is following a long run; they should never have to ask where it is.
|
|
41
54
|
|
|
@@ -73,6 +86,8 @@ node scripts/gds/sequence.js --check <task-id>
|
|
|
73
86
|
|
|
74
87
|
## What NOT to do
|
|
75
88
|
|
|
89
|
+
- **Do not run a long chain to exhaustion in one window** to avoid the handoff in step 6. It feels like progress and it is the single biggest reason a long run drags: the last link can cost several times the first for identical work. Handing off is not an interruption of the chain; it is how the chain stays cheap.
|
|
90
|
+
|
|
76
91
|
- **Do not skip a halted task and continue down the chain.** The owner chose stop-and-report precisely so a blocked predecessor does not silently strand its dependents.
|
|
77
92
|
- **Do not batch-claim.** See "The one rule".
|
|
78
93
|
- **Do not widen a task's `touches[]`** to make the chain flow. File a new task instead (`node scripts/gds/capture.js`).
|
|
@@ -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
|
+
- 290 operations across 47 resource groups
|
|
9
9
|
|
|
10
10
|
## Install
|
|
11
11
|
|
|
@@ -401,6 +401,8 @@ function createClient(opts = {}) {
|
|
|
401
401
|
postInboxIdRatify: (args) => request("POST", "/inbox/{id}/ratify", { hasBody: true }, args),
|
|
402
402
|
// POST /inbox/{id}/resubmit — rank: any-builder — POST /inbox/:id/resubmit
|
|
403
403
|
postInboxIdResubmit: (args) => request("POST", "/inbox/{id}/resubmit", { hasBody: true }, args),
|
|
404
|
+
// GET /inbox/awaiting-nod — rank: metic+archon — GET /inbox/awaiting-nod
|
|
405
|
+
getInboxAwaitingNod: (args) => request("GET", "/inbox/awaiting-nod", { hasBody: false }, args),
|
|
404
406
|
},
|
|
405
407
|
"instance": {
|
|
406
408
|
// GET /instance — rank: public — GET /instance
|
|
@@ -400,6 +400,8 @@ function createClient(opts = {}) {
|
|
|
400
400
|
postInboxIdRatify: (args) => request("POST", "/inbox/{id}/ratify", { hasBody: true }, args),
|
|
401
401
|
// POST /inbox/{id}/resubmit — rank: any-builder — POST /inbox/:id/resubmit
|
|
402
402
|
postInboxIdResubmit: (args) => request("POST", "/inbox/{id}/resubmit", { hasBody: true }, args),
|
|
403
|
+
// GET /inbox/awaiting-nod — rank: metic+archon — GET /inbox/awaiting-nod
|
|
404
|
+
getInboxAwaitingNod: (args) => request("GET", "/inbox/awaiting-nod", { hasBody: false }, args),
|
|
403
405
|
},
|
|
404
406
|
"instance": {
|
|
405
407
|
// GET /instance — rank: public — GET /instance
|
|
@@ -47,6 +47,7 @@ export interface GetGovernmentPermissionsResponse { permissions: unknown; princi
|
|
|
47
47
|
export interface GetGovernmentRanksResponse { ranks: unknown }
|
|
48
48
|
export interface GetGradesByBuilderResponse { window_days: unknown; builders: unknown }
|
|
49
49
|
export interface GetHealthzResponse { ok: boolean; auth_configured: unknown }
|
|
50
|
+
export interface GetInboxAwaitingNodResponse { awaiting: unknown; count: unknown }
|
|
50
51
|
export interface GetInboxIdResponse { idea: unknown }
|
|
51
52
|
export interface GetInboxResponse { ideas: unknown; open_count: unknown }
|
|
52
53
|
export interface GetLeaderboardResponse { leaderboard: unknown; page: unknown }
|
|
@@ -659,6 +660,8 @@ export interface BongosClient {
|
|
|
659
660
|
postInboxIdRatify(args?: RequestArgs & { body?: PostInboxIdRatifyRequest }): Promise<ApiResponse>;
|
|
660
661
|
/** POST /inbox/{id}/resubmit — rank: any-builder */
|
|
661
662
|
postInboxIdResubmit(args: RequestArgs & { body: PostInboxIdResubmitRequest }): Promise<ApiResponse>;
|
|
663
|
+
/** GET /inbox/awaiting-nod — rank: metic+archon */
|
|
664
|
+
getInboxAwaitingNod(args?: RequestArgs): Promise<GetInboxAwaitingNodResponse>;
|
|
662
665
|
};
|
|
663
666
|
"instance": {
|
|
664
667
|
/** GET /instance — rank: public */
|
|
@@ -397,6 +397,8 @@ export function createClient(opts = {}) {
|
|
|
397
397
|
postInboxIdRatify: (args) => request("POST", "/inbox/{id}/ratify", { hasBody: true }, args),
|
|
398
398
|
// POST /inbox/{id}/resubmit — rank: any-builder — POST /inbox/:id/resubmit
|
|
399
399
|
postInboxIdResubmit: (args) => request("POST", "/inbox/{id}/resubmit", { hasBody: true }, args),
|
|
400
|
+
// GET /inbox/awaiting-nod — rank: metic+archon — GET /inbox/awaiting-nod
|
|
401
|
+
getInboxAwaitingNod: (args) => request("GET", "/inbox/awaiting-nod", { hasBody: false }, args),
|
|
400
402
|
},
|
|
401
403
|
"instance": {
|
|
402
404
|
// GET /instance — rank: public — GET /instance
|
package/docs/api/openapi.json
CHANGED
|
@@ -6151,6 +6151,47 @@
|
|
|
6151
6151
|
]
|
|
6152
6152
|
}
|
|
6153
6153
|
},
|
|
6154
|
+
"/inbox/awaiting-nod": {
|
|
6155
|
+
"get": {
|
|
6156
|
+
"operationId": "get_inbox_awaiting_nod",
|
|
6157
|
+
"tags": [
|
|
6158
|
+
"inbox"
|
|
6159
|
+
],
|
|
6160
|
+
"summary": "GET /inbox/awaiting-nod",
|
|
6161
|
+
"description": "GET /inbox/awaiting-nod — the NOD QUEUE (task 1003066, BV1.R05). REGISTERED BEFORE /inbox/:id ON PURPOSE. Express matches in registration order, so a literal segment declared after the wildcard is unreachable — this would arrive as /inbox/:id with id='awaiting-nod' and 400 on parseId. rank: metic+ via the EXISTING idea.triage permission, deliberately reused rather than minting a new one. Owner interview Q3: \"any Metic+ gives the nod, in the existing Needs-your-attention slice. No new surface, no new permission.\" The act this queue leads to is POST /tasks/:id/promote, itself gated task.promote (Metic+), so a reader who can see this queue can act on it — the two gates agree by construction instead of by coincidence. Placed on /inbox rather than /tasks because the row is defined by its LINEAGE (origin='route'), and ideas_task_lineage is an ideas-owned table — the lifecycle module must not query it, and this module must not query it from there. \"A task at backlog that a person reported\" is an ideas question.\n\n**Rank:** `metic+archon` — Metic or Archon rank (review/triage powers).\n\n**Permissions:** `idea.triage` (all required).",
|
|
6162
|
+
"x-rank": "metic+archon",
|
|
6163
|
+
"x-source": "modules/ideas/routes/inbox.js",
|
|
6164
|
+
"x-permissions": [
|
|
6165
|
+
"idea.triage"
|
|
6166
|
+
],
|
|
6167
|
+
"responses": {
|
|
6168
|
+
"200": {
|
|
6169
|
+
"description": "Success.",
|
|
6170
|
+
"content": {
|
|
6171
|
+
"application/json": {
|
|
6172
|
+
"schema": {
|
|
6173
|
+
"$ref": "#/components/schemas/GetInboxAwaitingNodResponse"
|
|
6174
|
+
}
|
|
6175
|
+
}
|
|
6176
|
+
}
|
|
6177
|
+
},
|
|
6178
|
+
"400": {
|
|
6179
|
+
"$ref": "#/components/responses/BadRequest"
|
|
6180
|
+
},
|
|
6181
|
+
"401": {
|
|
6182
|
+
"$ref": "#/components/responses/Unauthorized"
|
|
6183
|
+
},
|
|
6184
|
+
"403": {
|
|
6185
|
+
"$ref": "#/components/responses/Forbidden"
|
|
6186
|
+
}
|
|
6187
|
+
},
|
|
6188
|
+
"security": [
|
|
6189
|
+
{
|
|
6190
|
+
"builderSession": []
|
|
6191
|
+
}
|
|
6192
|
+
]
|
|
6193
|
+
}
|
|
6194
|
+
},
|
|
6154
6195
|
"/inbox/{id}": {
|
|
6155
6196
|
"get": {
|
|
6156
6197
|
"operationId": "get_inbox_id",
|
|
@@ -13658,6 +13699,17 @@
|
|
|
13658
13699
|
"auth_configured"
|
|
13659
13700
|
]
|
|
13660
13701
|
},
|
|
13702
|
+
"GetInboxAwaitingNodResponse": {
|
|
13703
|
+
"type": "object",
|
|
13704
|
+
"properties": {
|
|
13705
|
+
"awaiting": {},
|
|
13706
|
+
"count": {}
|
|
13707
|
+
},
|
|
13708
|
+
"required": [
|
|
13709
|
+
"awaiting",
|
|
13710
|
+
"count"
|
|
13711
|
+
]
|
|
13712
|
+
},
|
|
13661
13713
|
"GetInboxIdResponse": {
|
|
13662
13714
|
"type": "object",
|
|
13663
13715
|
"properties": {
|
|
@@ -18301,9 +18353,9 @@
|
|
|
18301
18353
|
"description": "A required dependency/feature is not configured or is temporarily down."
|
|
18302
18354
|
}
|
|
18303
18355
|
},
|
|
18304
|
-
"x-endpoint-count":
|
|
18305
|
-
"x-schema-count":
|
|
18356
|
+
"x-endpoint-count": 290,
|
|
18357
|
+
"x-schema-count": 326,
|
|
18306
18358
|
"x-undocumented-bodies": 8,
|
|
18307
|
-
"x-response-schemas":
|
|
18359
|
+
"x-response-schemas": 218,
|
|
18308
18360
|
"x-generated-by": "scripts/gds/gen-api-docs.js"
|
|
18309
18361
|
}
|
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. 290 endpoints across 47 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`.
|
|
@@ -255,7 +255,7 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/<redacted>
|
|
|
255
255
|
|---|---|---|---|---|
|
|
256
256
|
| GET | `/api/bongos/healthz` | `public` | — | liveness probe; status.example.com hits this anonymously. |
|
|
257
257
|
|
|
258
|
-
## `inbox` (
|
|
258
|
+
## `inbox` (7)
|
|
259
259
|
|
|
260
260
|
| Method | Path | Rank | Body | Description |
|
|
261
261
|
|---|---|---|---|---|
|
|
@@ -265,6 +265,7 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/<redacted>
|
|
|
265
265
|
| PATCH | `/api/bongos/inbox/:id` | `metic+archon` | `status`, `kind`, `promoted_to_task_id`, `reviewed_at`, `merged_into_idea_id`, `triage_note` | Metic+ (task 360 / ADR 0018): idea triage (promote/discard/merge) shapes the backlog. |
|
|
266
266
|
| POST | `/api/bongos/inbox/:id/ratify` | `metic+archon` | `notes_md` | V3.R31 (task 252) — Archon ratifies a criterion-proposal idea, atomically: - INSERT done_when_criteria row on the target version - UPDATE… |
|
|
267
267
|
| POST | `/api/bongos/inbox/:id/resubmit` | `any-builder` | `field_values`, `template_key` | RESUBMIT a Full Idea after a rejection (R13 of goal 1000069, criterion C2: an idea never dies and never stalls). |
|
|
268
|
+
| GET | `/api/bongos/inbox/awaiting-nod` | `metic+archon` | — | GET /inbox/awaiting-nod — the NOD QUEUE (task 1003066, BV1.R05). |
|
|
268
269
|
|
|
269
270
|
## `instance` (1)
|
|
270
271
|
|
package/docs/copy-inventory.md
CHANGED
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
> Deterministic on a given tree — regenerate and commit rather than hand-editing.
|
|
5
5
|
> Machine-readable twin: [`copy-registry.json`](copy-registry.json).
|
|
6
6
|
|
|
7
|
-
**
|
|
7
|
+
**1337 strings** across 3 surfaces · 1186 distinct pieces of copy · 1337 certain, 0 heuristic · 121 shown in more than one place.
|
|
8
8
|
|
|
9
9
|
## Surfaces
|
|
10
10
|
|
|
11
11
|
| surface | lives at | files | strings |
|
|
12
12
|
|---|---|---|---|
|
|
13
|
-
| `builders-hall` | `modules/hall-ui/public` | 60 |
|
|
13
|
+
| `builders-hall` | `modules/hall-ui/public` | 60 | 1053 |
|
|
14
14
|
| `status-dashboard` | `modules/status-ui/public` | 4 | 98 |
|
|
15
15
|
| `landing` | `public-landing` | 2 | 186 |
|
|
16
16
|
|
|
@@ -78,7 +78,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
78
78
|
| `7775fec0fa85` | 2x | Could not load sessions. | modules/hall-ui/public/sessions.js:168, modules/hall-ui/public/sessions.js:207 |
|
|
79
79
|
| … | | _81 more in the JSON registry_ | |
|
|
80
80
|
|
|
81
|
-
## `builders-hall` —
|
|
81
|
+
## `builders-hall` — 1053 strings
|
|
82
82
|
|
|
83
83
|
| id | conf | text | where |
|
|
84
84
|
|---|---|---|---|
|
|
@@ -398,6 +398,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
398
398
|
| `2ae2114b61db` | certain | Get a free key ↗ | `modules/hall-ui/public/settings.js:917` |
|
|
399
399
|
| `4794a991de3d` | certain | Getting started | `modules/hall-ui/public/hall-widgets.js:59` |
|
|
400
400
|
| `a28b1a567f1a` | certain | GitHub username | `modules/hall-ui/public/builders.js:553` |
|
|
401
|
+
| `79934b879a12` | certain | Give the nod | `modules/hall-ui/public/goal-inbox.js:231` |
|
|
401
402
|
| `51bd60197133` | certain | Go back | `modules/hall-ui/public/drachmae.js:162` |
|
|
402
403
|
| `51bd60197133` | certain | Go back | `modules/hall-ui/public/primer.js:620` |
|
|
403
404
|
| `13acaeb4b0bf` | certain | Goal #{…} | `modules/hall-ui/public/task.js:202` |
|
|
@@ -518,7 +519,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
518
519
|
| `670aa6cee309` | certain | My Projects — {{worldName}} | `modules/hall-ui/public/my-projects.html:6` |
|
|
519
520
|
| `ae84ebe1d735` | certain | Name cannot be blank. | `modules/hall-ui/public/settings.js:730` |
|
|
520
521
|
| `31e91ee6ce03` | certain | Name must be {…} characters or fewer. | `modules/hall-ui/public/settings.js:735` |
|
|
521
|
-
| `7def635421ea` | certain | Needs your attention | `modules/hall-ui/public/goal-inbox.js:
|
|
522
|
+
| `7def635421ea` | certain | Needs your attention | `modules/hall-ui/public/goal-inbox.js:274` |
|
|
522
523
|
| `7fcc2583c372` | certain | New custom rank | `modules/hall-ui/public/government.html:58` |
|
|
523
524
|
| `9e06c14d155a` | certain | New here — request access | `modules/hall-ui/public/builders.js:553` |
|
|
524
525
|
| `6ff07874edef` | certain | Newest first. The fifty most recent write operations. | `modules/hall-ui/public/watch.js:433` |
|
|
@@ -1111,6 +1112,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
1111
1112
|
| `68b547166d48` | certain | — {…} confirmed {…} can't land yet, so {…} reward is pending (it lands on ship). Rebase + re-ship or release { | `modules/hall-ui/public/builders.js:752` |
|
|
1112
1113
|
| `ff6b84565e10` | certain | — {…}{…} | `modules/hall-ui/public/government.js:605` |
|
|
1113
1114
|
| `5b9fa7cb4fb0` | certain | …and {…} more waiting — | `modules/hall-ui/public/goal-inbox.js:121` |
|
|
1115
|
+
| `b2a04abfead0` | certain | …{…} more awaiting a nod. | `modules/hall-ui/public/goal-inbox.js:251` |
|
|
1114
1116
|
| `e35f11bdc5d7` | certain | …{…} more open ideas — triage clears them one at a time. | `modules/hall-ui/public/builders.js:1874` |
|
|
1115
1117
|
| `de8fa5223aee` | certain | ‹ Prev | `modules/hall-ui/public/hall-kit.js:71` |
|
|
1116
1118
|
| `d4b84b7fbdeb` | certain | ← All goals | `modules/hall-ui/public/goals.html:56` |
|
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": 1337,
|
|
7
|
+
"unique_ids": 1186,
|
|
8
|
+
"certain": 1337,
|
|
9
9
|
"heuristic": 0,
|
|
10
10
|
"duplicate_ids": 121
|
|
11
11
|
},
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"builders-hall": {
|
|
14
14
|
"at": "modules/hall-ui/public",
|
|
15
15
|
"files": 60,
|
|
16
|
-
"strings":
|
|
16
|
+
"strings": 1053
|
|
17
17
|
},
|
|
18
18
|
"status-dashboard": {
|
|
19
19
|
"at": "modules/status-ui/public",
|
|
@@ -4124,6 +4124,15 @@
|
|
|
4124
4124
|
"origin": "js-markup",
|
|
4125
4125
|
"confidence": "certain"
|
|
4126
4126
|
},
|
|
4127
|
+
{
|
|
4128
|
+
"id": "79934b879a12",
|
|
4129
|
+
"surface": "builders-hall",
|
|
4130
|
+
"text": "Give the nod",
|
|
4131
|
+
"file": "modules/hall-ui/public/goal-inbox.js",
|
|
4132
|
+
"line": 231,
|
|
4133
|
+
"origin": "js-markup",
|
|
4134
|
+
"confidence": "certain"
|
|
4135
|
+
},
|
|
4127
4136
|
{
|
|
4128
4137
|
"id": "51bd60197133",
|
|
4129
4138
|
"surface": "builders-hall",
|
|
@@ -5209,7 +5218,7 @@
|
|
|
5209
5218
|
"surface": "builders-hall",
|
|
5210
5219
|
"text": "Needs your attention",
|
|
5211
5220
|
"file": "modules/hall-ui/public/goal-inbox.js",
|
|
5212
|
-
"line":
|
|
5221
|
+
"line": 274,
|
|
5213
5222
|
"origin": "js-markup",
|
|
5214
5223
|
"confidence": "certain"
|
|
5215
5224
|
},
|
|
@@ -10541,6 +10550,15 @@
|
|
|
10541
10550
|
"origin": "js-markup",
|
|
10542
10551
|
"confidence": "certain"
|
|
10543
10552
|
},
|
|
10553
|
+
{
|
|
10554
|
+
"id": "b2a04abfead0",
|
|
10555
|
+
"surface": "builders-hall",
|
|
10556
|
+
"text": "…{…} more awaiting a nod.",
|
|
10557
|
+
"file": "modules/hall-ui/public/goal-inbox.js",
|
|
10558
|
+
"line": 251,
|
|
10559
|
+
"origin": "js-markup",
|
|
10560
|
+
"confidence": "certain"
|
|
10561
|
+
},
|
|
10544
10562
|
{
|
|
10545
10563
|
"id": "e35f11bdc5d7",
|
|
10546
10564
|
"surface": "builders-hall",
|
|
@@ -400,6 +400,8 @@ function createClient(opts = {}) {
|
|
|
400
400
|
postInboxIdRatify: (args) => request("POST", "/inbox/{id}/ratify", { hasBody: true }, args),
|
|
401
401
|
// POST /inbox/{id}/resubmit — rank: any-builder — POST /inbox/:id/resubmit
|
|
402
402
|
postInboxIdResubmit: (args) => request("POST", "/inbox/{id}/resubmit", { hasBody: true }, args),
|
|
403
|
+
// GET /inbox/awaiting-nod — rank: metic+archon — GET /inbox/awaiting-nod
|
|
404
|
+
getInboxAwaitingNod: (args) => request("GET", "/inbox/awaiting-nod", { hasBody: false }, args),
|
|
403
405
|
},
|
|
404
406
|
"instance": {
|
|
405
407
|
// GET /instance — rank: public — GET /instance
|
|
@@ -146,14 +146,18 @@
|
|
|
146
146
|
// count-pill/live counter re-derive from the fresh inbox). Disable while in flight
|
|
147
147
|
// so a double-click can't fire the resolve twice (the server 409s a re-resolve, but
|
|
148
148
|
// the UI shouldn't invite it).
|
|
149
|
-
|
|
149
|
+
// `refresh` defaults to the goals slice's own load(). task 1003066 (BV1.R05):
|
|
150
|
+
// the nod action lives in a DIFFERENT slice, so it passes its own — otherwise
|
|
151
|
+
// giving a nod would repaint the goals list and leave the nodded row sitting
|
|
152
|
+
// there, still asking to be nodded.
|
|
153
|
+
async function act(fn, okMsg, refresh = load) {
|
|
150
154
|
if (busy) return;
|
|
151
155
|
busy = true;
|
|
152
156
|
host.querySelectorAll('button').forEach((b) => { b.disabled = true; });
|
|
153
157
|
try {
|
|
154
158
|
await fn();
|
|
155
159
|
toast(okMsg);
|
|
156
|
-
await
|
|
160
|
+
await refresh();
|
|
157
161
|
} catch (err) {
|
|
158
162
|
toast((err && err.data && err.data.message) || 'Could not do that just now — refresh and retry.');
|
|
159
163
|
host.querySelectorAll('button').forEach((b) => { b.disabled = false; });
|
|
@@ -163,6 +167,17 @@
|
|
|
163
167
|
}
|
|
164
168
|
|
|
165
169
|
function onClick(e) {
|
|
170
|
+
// task 1003066 (BV1.R05): the nod. It reuses the EXISTING promote route —
|
|
171
|
+
// POST /tasks/:id/promote, already Metic+ via task.promote — so giving a nod
|
|
172
|
+
// adds no endpoint and no permission. Handled before the membership branches
|
|
173
|
+
// because a nod row is a TASK row that merely carries data-goal for styling.
|
|
174
|
+
const nod = e.target.closest('[data-nod-task]');
|
|
175
|
+
if (nod) {
|
|
176
|
+
act(() => postJSON(`${API}/tasks/${encodeURIComponent(nod.dataset.nodTask)}/promote`, {}),
|
|
177
|
+
'Nodded — it’s claimable now.', loadNodQueue);
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
|
|
166
181
|
const item = e.target.closest('.ginbox__item');
|
|
167
182
|
const goalId = item && item.dataset.goal;
|
|
168
183
|
if (!goalId) return;
|
|
@@ -192,6 +207,61 @@
|
|
|
192
207
|
}
|
|
193
208
|
}
|
|
194
209
|
|
|
210
|
+
// ---- the nod queue (task 1003066, BV1.R05) --------------------------------
|
|
211
|
+
//
|
|
212
|
+
// A routed filing that soft-landed is a task at 'backlog' in its goal, one
|
|
213
|
+
// Metic+ promote from claimable — owner interview Q3: any Metic+ gives the nod,
|
|
214
|
+
// through the EXISTING promote route, in this EXISTING card. No new surface, no
|
|
215
|
+
// new permission.
|
|
216
|
+
//
|
|
217
|
+
// WITHOUT THIS SLICE THE SOFT LANDING IS A SILENT DROP: the filing looks
|
|
218
|
+
// accepted, nothing tells anyone a human is the blocker, and it sits at backlog
|
|
219
|
+
// forever. Criterion C2's "one Metic+ promote away" is only true if somebody can
|
|
220
|
+
// SEE it. The copy says "awaiting a nod", never "triage" — triage is the inbox's
|
|
221
|
+
// word, and this work already has a home.
|
|
222
|
+
//
|
|
223
|
+
// No client-side rank gate: GET /inbox/awaiting-nod is Metic+ server-side, so a
|
|
224
|
+
// non-triager's fetch 403s and the slice renders nothing. One gate, on the
|
|
225
|
+
// server, beats a client check that can disagree with it.
|
|
226
|
+
function nodRowHtml(r) {
|
|
227
|
+
const title = escapeHtml(r.title || `task #${r.task_id}`);
|
|
228
|
+
const kind = r.kind ? `<span class="ginbox__sub">${escapeHtml(r.kind)}</span>` : '';
|
|
229
|
+
const who = r.filed_by_login ? ` · filed by ${escapeHtml(r.filed_by_login)}` : '';
|
|
230
|
+
const goal = r.goal_title ? escapeHtml(r.goal_title) : `goal ${escapeHtml(String(r.goal_id))}`;
|
|
231
|
+
return `<li class="ginbox__item" data-goal="${escapeHtml(String(r.goal_id))}">
|
|
232
|
+
<div class="ginbox__main">
|
|
233
|
+
<a class="ginbox__goal" href="/task/${encodeURIComponent(r.task_id)}">${title}</a>
|
|
234
|
+
<span class="ginbox__sub">${goal}${who}</span>
|
|
235
|
+
</div>
|
|
236
|
+
${kind}
|
|
237
|
+
<div class="ginbox__acts">
|
|
238
|
+
<button class="btn-ghost" type="button" data-nod-task="${escapeHtml(String(r.task_id))}">Give the nod</button>
|
|
239
|
+
</div>
|
|
240
|
+
</li>`;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function renderNodQueue(data) {
|
|
244
|
+
const box = host && host.querySelector('#attention-nod');
|
|
245
|
+
if (!box) return;
|
|
246
|
+
const rows = (data && Array.isArray(data.awaiting) ? data.awaiting : []);
|
|
247
|
+
const count = data && data.count != null ? data.count : rows.length;
|
|
248
|
+
if (!rows.length) {
|
|
249
|
+
box.innerHTML = '';
|
|
250
|
+
} else {
|
|
251
|
+
const more = count > 5 ? `<p class="ginbox__pending">…${count - 5} more awaiting a nod.</p>` : '';
|
|
252
|
+
box.innerHTML = '<h3 class="ginbox__sec-h">Reported work awaiting a nod '
|
|
253
|
+
+ `<span class="count-pill">${count}</span></h3>`
|
|
254
|
+
+ `<ul class="ginbox__list">${rows.slice(0, 5).map(nodRowHtml).join('')}</ul>${more}`;
|
|
255
|
+
}
|
|
256
|
+
window.OTBAttention?.refresh();
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function loadNodQueue() {
|
|
260
|
+
return getJSON(`${API}/inbox/awaiting-nod`)
|
|
261
|
+
.then((data) => renderNodQueue(data))
|
|
262
|
+
.catch(() => { /* a non-triager's 403, or a hiccup: never break the hall */ });
|
|
263
|
+
}
|
|
264
|
+
|
|
195
265
|
// task 2169: this widget IS the "Needs your attention" card — ONE capped
|
|
196
266
|
// summary hosting every actionable item class: goal invitations +
|
|
197
267
|
// join-requests (this file) and ideas awaiting triage (builders.js renders
|
|
@@ -203,9 +273,17 @@
|
|
|
203
273
|
host.innerHTML =
|
|
204
274
|
'<h2 id="attention-h" class="scroll__h">Needs your attention<span class="count-pill" id="attention-count" hidden></span></h2>' +
|
|
205
275
|
'<div id="attention-goals"></div>' +
|
|
206
|
-
'<div id="attention-ideas"></div>'
|
|
276
|
+
'<div id="attention-ideas"></div>' +
|
|
277
|
+
// task 1003066 (BV1.R05): routed filings that SOFT-LANDED — a reported bug
|
|
278
|
+
// now sitting at 'backlog' in a real goal, one Metic+ nod from claimable.
|
|
279
|
+
// Rendered by renderNodQueue above: this file owns the card, and a task
|
|
280
|
+
// awaiting a nod inside a goal sits nearer the goals slice than idea
|
|
281
|
+
// triage. Its rows carry the shared .ginbox__item class, so refresh()
|
|
282
|
+
// counts them with no change to the selector below.
|
|
283
|
+
'<div id="attention-nod"></div>';
|
|
207
284
|
host.addEventListener('click', onClick);
|
|
208
285
|
load();
|
|
286
|
+
loadNodQueue();
|
|
209
287
|
}
|
|
210
288
|
|
|
211
289
|
// The card's shared visibility contract: any slice renderer calls refresh()
|