@bongos/core 1.19.274 → 1.19.276
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 +39 -24
- 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 +4 -1
- package/clients/bongos-client/index.mjs +2 -0
- package/docs/api/openapi.json +59 -3
- package/docs/api-reference.md +4 -3
- 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 +332 -7
- package/modules/ideas/migrations/ideas_004_lineage_route_index.sql +37 -0
- package/modules/ideas/routes/inbox.js +78 -1
- package/modules/ideas/routing.js +232 -0
- package/modules/lifecycle/db.js +2 -2
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/src/module-api.js +5 -1
- package/tests/idea_routing.mjs +858 -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.276",
|
|
6
|
+
"core_contract": "1.19.276",
|
|
7
|
+
"source_commit": "de2f0fb76790e78b4b2c1bb4878fa88233a36c46",
|
|
8
8
|
"source_ref": "HEAD",
|
|
9
|
-
"built_at": "2026-08-
|
|
9
|
+
"built_at": "2026-08-21T15:45:27.022Z",
|
|
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": 1375,
|
|
15
15
|
"rules": 3,
|
|
16
16
|
"gate_literals": 3,
|
|
17
17
|
"gate": "passed"
|
|
18
18
|
},
|
|
19
|
-
"file_count":
|
|
20
|
-
"tree_sha256": "
|
|
19
|
+
"file_count": 1715,
|
|
20
|
+
"tree_sha256": "abe78982ee6e0304610e16ce97f65fc75baf045c6d210c2ab7ee65ced93b4ee7",
|
|
21
21
|
"files": [
|
|
22
22
|
{
|
|
23
23
|
"path": ".claude/skills/blocker-review/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,7 +3717,12 @@
|
|
|
3712
3717
|
{
|
|
3713
3718
|
"path": "modules/ideas/routes/inbox.js",
|
|
3714
3719
|
"mode": "0000644",
|
|
3715
|
-
"sha256": "
|
|
3720
|
+
"sha256": "9c7027f70daba8cb956ab540567972afcec96900ce8d7f7793647bc58c13abdd"
|
|
3721
|
+
},
|
|
3722
|
+
{
|
|
3723
|
+
"path": "modules/ideas/routing.js",
|
|
3724
|
+
"mode": "0000644",
|
|
3725
|
+
"sha256": "2ca0adb68b0fd44a65b9637c177848648ecd20ecd8ef67e65527c17b7a46414d"
|
|
3716
3726
|
},
|
|
3717
3727
|
{
|
|
3718
3728
|
"path": "modules/ideas/templates.js",
|
|
@@ -3742,7 +3752,7 @@
|
|
|
3742
3752
|
{
|
|
3743
3753
|
"path": "modules/lifecycle/db.js",
|
|
3744
3754
|
"mode": "0000644",
|
|
3745
|
-
"sha256": "
|
|
3755
|
+
"sha256": "64cdde411e3fb8d1263eebf9093a353dde6ee684be2977057c8800e608b52a63"
|
|
3746
3756
|
},
|
|
3747
3757
|
{
|
|
3748
3758
|
"path": "modules/lifecycle/done-when.js",
|
|
@@ -4477,12 +4487,12 @@
|
|
|
4477
4487
|
{
|
|
4478
4488
|
"path": "package-lock.json",
|
|
4479
4489
|
"mode": "0000644",
|
|
4480
|
-
"sha256": "
|
|
4490
|
+
"sha256": "db42d8af206914a247ba771e7d711b22137bea42d6b4464eaa60a02bf8947c74"
|
|
4481
4491
|
},
|
|
4482
4492
|
{
|
|
4483
4493
|
"path": "package.json",
|
|
4484
4494
|
"mode": "0000644",
|
|
4485
|
-
"sha256": "
|
|
4495
|
+
"sha256": "8918824ec6d64703f4976a6f7863aa7ac0f240af95711972715967dfe973f944"
|
|
4486
4496
|
},
|
|
4487
4497
|
{
|
|
4488
4498
|
"path": "public-docs/index.html",
|
|
@@ -6127,7 +6137,7 @@
|
|
|
6127
6137
|
{
|
|
6128
6138
|
"path": "src/module-api.js",
|
|
6129
6139
|
"mode": "0000644",
|
|
6130
|
-
"sha256": "
|
|
6140
|
+
"sha256": "8eb348b653371b264e5c6b6efecddbdf18412e419e7dbd517b87322bdc806aae"
|
|
6131
6141
|
},
|
|
6132
6142
|
{
|
|
6133
6143
|
"path": "src/module-loader/catalog.js",
|
|
@@ -7409,6 +7419,11 @@
|
|
|
7409
7419
|
"mode": "0000644",
|
|
7410
7420
|
"sha256": "51e1286235cbde1b56188f29b0e2bd12ac73a9637dbf1c16b325f10147256f27"
|
|
7411
7421
|
},
|
|
7422
|
+
{
|
|
7423
|
+
"path": "tests/idea_routing.mjs",
|
|
7424
|
+
"mode": "0000644",
|
|
7425
|
+
"sha256": "7bea2d388fad9a6b186c4712d6921a554f1d24c70dcae5760b381782149068e7"
|
|
7426
|
+
},
|
|
7412
7427
|
{
|
|
7413
7428
|
"path": "tests/idea_task_lineage.mjs",
|
|
7414
7429
|
"mode": "0000644",
|
|
@@ -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 }
|
|
@@ -244,7 +245,7 @@ export interface PostGovernmentRanksRequest { rank_key: string; label: string; d
|
|
|
244
245
|
export interface PostGovernmentRanksResponse { rank: unknown }
|
|
245
246
|
export interface PostInboxIdRatifyRequest { notes_md?: string }
|
|
246
247
|
export interface PostInboxIdResubmitRequest { field_values: Record<string, unknown>; template_key?: string }
|
|
247
|
-
export interface PostInboxRequest { title: string; body_md?: string; kind?: string; suggested_version?: string; suggested_priority?: number; grade?: string; template_key?: string; field_values?: Record<string, unknown> }
|
|
248
|
+
export interface PostInboxRequest { title: string; body_md?: string; kind?: string; suggested_version?: string; suggested_priority?: number; goal_id?: number; grade?: string; template_key?: string; field_values?: Record<string, unknown> }
|
|
248
249
|
export interface PostLearningsRequest { title: string; body_md: string; tags?: string[]; related_files?: string[]; source?: string; source_ref?: string; task_id?: number }
|
|
249
250
|
export interface PostLearningsResponse { skipped?: boolean; reason?: unknown; learning?: unknown }
|
|
250
251
|
export interface PostLlmCacheLookupRequest { cache_key?: unknown; tokens_saved_est?: 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": {
|
|
@@ -16610,6 +16662,10 @@
|
|
|
16610
16662
|
"minimum": 0,
|
|
16611
16663
|
"maximum": 100
|
|
16612
16664
|
},
|
|
16665
|
+
"goal_id": {
|
|
16666
|
+
"type": "integer",
|
|
16667
|
+
"minimum": 1
|
|
16668
|
+
},
|
|
16613
16669
|
"grade": {
|
|
16614
16670
|
"type": "string",
|
|
16615
16671
|
"maxLength": 16
|
|
@@ -18297,9 +18353,9 @@
|
|
|
18297
18353
|
"description": "A required dependency/feature is not configured or is temporarily down."
|
|
18298
18354
|
}
|
|
18299
18355
|
},
|
|
18300
|
-
"x-endpoint-count":
|
|
18301
|
-
"x-schema-count":
|
|
18356
|
+
"x-endpoint-count": 290,
|
|
18357
|
+
"x-schema-count": 326,
|
|
18302
18358
|
"x-undocumented-bodies": 8,
|
|
18303
|
-
"x-response-schemas":
|
|
18359
|
+
"x-response-schemas": 218,
|
|
18304
18360
|
"x-generated-by": "scripts/gds/gen-api-docs.js"
|
|
18305
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,16 +255,17 @@ 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
|
|---|---|---|---|---|
|
|
262
262
|
| GET | `/api/bongos/inbox` | `any-builder` | — | read open ideas; skill-friction rows filtered by viewer rank. |
|
|
263
|
-
| POST | `/api/bongos/inbox` | `any-builder` | `title`, `body_md`, `kind`, `suggested_version`, `suggested_priority`, `grade`, `template_key`, `field_values` | for ordinary ideas; metic+ for kind='criterion-proposal'. |
|
|
263
|
+
| POST | `/api/bongos/inbox` | `any-builder` | `title`, `body_md`, `kind`, `suggested_version`, `suggested_priority`, `goal_id`, `grade`, `template_key`, `field_values` | for ordinary ideas; metic+ for kind='criterion-proposal'. |
|
|
264
264
|
| GET | `/api/bongos/inbox/:id` | `any-builder` | — | single idea read for the "#NNN" deep-link resolver (task 1047). |
|
|
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()
|