@bongos/core 1.19.1028 → 1.19.1029
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 +12 -12
- package/docs/module-api-changelog.md +2 -0
- package/modules/lifecycle/db-goals.js +14 -2
- package/modules/lifecycle/routes/goals.js +1 -1
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/src/module-api.js +1 -1
- package/tests/goal_member_kinds.mjs +24 -1
package/.bongos-core.json
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
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.1029",
|
|
6
|
+
"core_contract": "1.19.1029",
|
|
7
|
+
"source_commit": "9061b1b634a11e0d3737336b0d59fe110d2a7a17",
|
|
8
8
|
"source_ref": "HEAD",
|
|
9
|
-
"built_at": "2026-09-
|
|
9
|
+
"built_at": "2026-09-25T21:07:08.900Z",
|
|
10
10
|
"redaction": {
|
|
11
11
|
"model": "docs-redacted+functional-verbatim",
|
|
12
12
|
"docs_redacted": 529,
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"gate": "passed"
|
|
18
18
|
},
|
|
19
19
|
"file_count": 3014,
|
|
20
|
-
"tree_sha256": "
|
|
20
|
+
"tree_sha256": "1305b1deb2512746e9b12451812ed65ff0e0364e416b1cbdc3ffacb9d12b8851",
|
|
21
21
|
"files": [
|
|
22
22
|
{
|
|
23
23
|
"path": ".claude/skills/ask-for-help/SKILL.md",
|
|
@@ -2757,7 +2757,7 @@
|
|
|
2757
2757
|
{
|
|
2758
2758
|
"path": "docs/module-api-changelog.md",
|
|
2759
2759
|
"mode": "0000644",
|
|
2760
|
-
"sha256": "
|
|
2760
|
+
"sha256": "bc6a32426c475f26a5257ae634f5cf8c9c0863c53edd9b8981c411323b2f21e4"
|
|
2761
2761
|
},
|
|
2762
2762
|
{
|
|
2763
2763
|
"path": "docs/modules-contract.md",
|
|
@@ -5882,7 +5882,7 @@
|
|
|
5882
5882
|
{
|
|
5883
5883
|
"path": "modules/lifecycle/db-goals.js",
|
|
5884
5884
|
"mode": "0000644",
|
|
5885
|
-
"sha256": "
|
|
5885
|
+
"sha256": "e15bf5a3f2ec8ede9b5a8c90c3e00c472c229f351b809333beebfeb90dad2bcc"
|
|
5886
5886
|
},
|
|
5887
5887
|
{
|
|
5888
5888
|
"path": "modules/lifecycle/db-grade.js",
|
|
@@ -6192,7 +6192,7 @@
|
|
|
6192
6192
|
{
|
|
6193
6193
|
"path": "modules/lifecycle/routes/goals.js",
|
|
6194
6194
|
"mode": "0000644",
|
|
6195
|
-
"sha256": "
|
|
6195
|
+
"sha256": "520b63212462c762fdf23e40ffdb084c22f786616d3a5694b4dc182e334eeaa7"
|
|
6196
6196
|
},
|
|
6197
6197
|
{
|
|
6198
6198
|
"path": "modules/lifecycle/routes/help-requests.js",
|
|
@@ -8362,12 +8362,12 @@
|
|
|
8362
8362
|
{
|
|
8363
8363
|
"path": "package-lock.json",
|
|
8364
8364
|
"mode": "0000644",
|
|
8365
|
-
"sha256": "
|
|
8365
|
+
"sha256": "8608f78a458012a57ffc19e813402909f783c77bcc50f3d45780e4f8b2e3f759"
|
|
8366
8366
|
},
|
|
8367
8367
|
{
|
|
8368
8368
|
"path": "package.json",
|
|
8369
8369
|
"mode": "0000644",
|
|
8370
|
-
"sha256": "
|
|
8370
|
+
"sha256": "32e6fc0b4953d6f15b41649ea9df77918f37ac8a8ed7168ce17d9040d04bf5c6"
|
|
8371
8371
|
},
|
|
8372
8372
|
{
|
|
8373
8373
|
"path": "public-docs/index.html",
|
|
@@ -10412,7 +10412,7 @@
|
|
|
10412
10412
|
{
|
|
10413
10413
|
"path": "src/module-api.js",
|
|
10414
10414
|
"mode": "0000644",
|
|
10415
|
-
"sha256": "
|
|
10415
|
+
"sha256": "9763f23d6375a13a9ce55193be5689f74c04cd9170079735bca1956524f007c7"
|
|
10416
10416
|
},
|
|
10417
10417
|
{
|
|
10418
10418
|
"path": "src/module-loader/catalog.js",
|
|
@@ -11982,7 +11982,7 @@
|
|
|
11982
11982
|
{
|
|
11983
11983
|
"path": "tests/goal_member_kinds.mjs",
|
|
11984
11984
|
"mode": "0000644",
|
|
11985
|
-
"sha256": "
|
|
11985
|
+
"sha256": "5ae48afae42839d5b8ea6002b5d9c892d027be87eda2e60bded481437a3306a6"
|
|
11986
11986
|
},
|
|
11987
11987
|
{
|
|
11988
11988
|
"path": "tests/goal_membership_requests.mjs",
|
|
@@ -2535,5 +2535,7 @@ is load-bearing: the script throws rather than guess if it is missing, and
|
|
|
2535
2535
|
landed since 1.19.1026 with no explicit bump. run 36187742785. (task 1002620)
|
|
2536
2536
|
1.19.1028 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
2537
2537
|
landed since 1.19.1027 with no explicit bump. run 36188894725. (task 1002620)
|
|
2538
|
+
1.19.1029 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
2539
|
+
landed since 1.19.1028 with no explicit bump. run 36189693139. (task 1002620)
|
|
2538
2540
|
---------------------------------------------------------------------------
|
|
2539
2541
|
```
|
|
@@ -942,8 +942,14 @@ async function setGoalMembershipKind({ goalId, builderId, membershipKind }, deps
|
|
|
942
942
|
// "drops to manager" — exactly the handoff semantics the route promises. The
|
|
943
943
|
// route gates WHO may call this (owner | Archon, target Metic+); this helper
|
|
944
944
|
// just performs the move. Returns the updated goal row, or null for unknown id.
|
|
945
|
+
//
|
|
946
|
+
// The new owner arriving as 'lead' is a membership arrival like any other, so it
|
|
947
|
+
// also closes that builder's still-pending ask/invite on this goal (task
|
|
948
|
+
// 1003661, the third path after addGoalMember — see its comment for why
|
|
949
|
+
// 'cancelled'). Same statement, so the cancel commits with the transfer or not
|
|
950
|
+
// at all; resolvedBy is the ACTOR handing the goal over.
|
|
945
951
|
|
|
946
|
-
async function transferGoalOwnership({ goalId, newOwnerId }, deps = {}) {
|
|
952
|
+
async function transferGoalOwnership({ goalId, newOwnerId, resolvedBy = null }, deps = {}) {
|
|
947
953
|
const activePool = (deps.pool && process.env.NODE_ENV === 'test') ? deps.pool : pool;
|
|
948
954
|
const { rows } = await activePool.query(
|
|
949
955
|
`WITH g AS (
|
|
@@ -955,9 +961,15 @@ async function transferGoalOwnership({ goalId, newOwnerId }, deps = {}) {
|
|
|
955
961
|
INSERT INTO goal_members (goal_id, builder_id, membership_kind)
|
|
956
962
|
SELECT g.id, $2, 'lead' FROM g
|
|
957
963
|
ON CONFLICT (goal_id, builder_id) DO UPDATE SET membership_kind = 'lead'
|
|
964
|
+
), cancelled AS (
|
|
965
|
+
UPDATE goal_membership_requests
|
|
966
|
+
SET status = 'cancelled', resolved_by = $3, resolved_at = now(), updated_at = now()
|
|
967
|
+
WHERE goal_id = $1 AND builder_id = $2 AND status = 'pending'
|
|
968
|
+
AND EXISTS (SELECT 1 FROM g)
|
|
969
|
+
RETURNING id
|
|
958
970
|
)
|
|
959
971
|
SELECT * FROM g`,
|
|
960
|
-
[goalId, newOwnerId]
|
|
972
|
+
[goalId, newOwnerId, resolvedBy]
|
|
961
973
|
);
|
|
962
974
|
return rows[0] ?? null;
|
|
963
975
|
}
|
|
@@ -899,7 +899,7 @@ module.exports = function buildGoalsRouter() {
|
|
|
899
899
|
if (decision.noop) {
|
|
900
900
|
return res.json({ ok: true, goal, changed: false });
|
|
901
901
|
}
|
|
902
|
-
const updated = await db.transferGoalOwnership({ goalId: id, newOwnerId });
|
|
902
|
+
const updated = await db.transferGoalOwnership({ goalId: id, newOwnerId, resolvedBy: req.builder.id });
|
|
903
903
|
if (!updated) {
|
|
904
904
|
return res.fail('transfer_conflict', { status: 409, message: 'The goal changed underneath this request — re-read it and retry.' });
|
|
905
905
|
}
|
package/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.19.
|
|
3
|
+
"version": "1.19.1029",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@bongos/core",
|
|
9
|
-
"version": "1.19.
|
|
9
|
+
"version": "1.19.1029",
|
|
10
10
|
"license": "AGPL-3.0-or-later",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"express": "^4.21.2",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.19.
|
|
3
|
+
"version": "1.19.1029",
|
|
4
4
|
"description": "Cloud Bongos — the AI-first build platform core (GDS + platform surfaces + module system), installed as a versioned dependency (ADR 0108).",
|
|
5
5
|
"license": "AGPL-3.0-or-later",
|
|
6
6
|
"main": "src/platform-server.js",
|
package/src/module-api.js
CHANGED
|
@@ -71,7 +71,7 @@ const { responsibilityFor, ROLE_RESPONSIBILITIES } = require('./role-responsibil
|
|
|
71
71
|
// there. scripts/gds/bump-version.js still rewrites the literal below; it appends
|
|
72
72
|
// the entry to that file. Look for a version's history there, not here.
|
|
73
73
|
// ---------------------------------------------------------------------------
|
|
74
|
-
const CORE_VERSION = '1.19.
|
|
74
|
+
const CORE_VERSION = '1.19.1029'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
|
|
75
75
|
|
|
76
76
|
// A namespaced logger so a module's log lines are attributable + consistent.
|
|
77
77
|
// Usage: const log = api.logger('dev-box'); log.info('mounted');
|
|
@@ -400,7 +400,7 @@ await test('transferGoalOwnership: created_by moves and the new owner upserts to
|
|
|
400
400
|
const out = await transferGoalOwnership({ goalId: 7, newOwnerId: 5 }, { pool });
|
|
401
401
|
assert.deepEqual(out, GOAL_ROW);
|
|
402
402
|
const upd = find(pool.queries, /UPDATE goals SET created_by = \$2/);
|
|
403
|
-
assert.deepEqual(upd.params, [7, 5]);
|
|
403
|
+
assert.deepEqual(upd.params, [7, 5, null], 'resolvedBy defaults to null for a non-route caller');
|
|
404
404
|
const sql = String(upd.sql).replace(/\s+/g, ' ');
|
|
405
405
|
assert.match(sql, /INSERT INTO goal_members \(goal_id, builder_id, membership_kind\)/,
|
|
406
406
|
'the new owner\'s membership rides in the same statement');
|
|
@@ -409,6 +409,29 @@ await test('transferGoalOwnership: created_by moves and the new owner upserts to
|
|
|
409
409
|
assert.match(sql, /updated_at = now\(\)/);
|
|
410
410
|
});
|
|
411
411
|
|
|
412
|
+
// task 1003661 — the third arrival path (after join / direct-add, task 1002888):
|
|
413
|
+
// handing a goal to a builder who still has a pending ask outstanding on it must
|
|
414
|
+
// close that ask in the SAME statement, or the stale row lingers in the inbox.
|
|
415
|
+
await test('transferGoalOwnership: cancels the new owner\'s pending ask in the same statement, attributed to the actor', async () => {
|
|
416
|
+
const pool = fakePool((s) => (/UPDATE goals SET created_by = \$2/.test(s) ? { rows: [GOAL_ROW] } : null));
|
|
417
|
+
await transferGoalOwnership({ goalId: 7, newOwnerId: 5, resolvedBy: 99 }, { pool });
|
|
418
|
+
assert.equal(pool.queries.length, 1, 'ONE statement — the cancel commits with the transfer or not at all');
|
|
419
|
+
const upd = find(pool.queries, /UPDATE goals SET created_by = \$2/);
|
|
420
|
+
assert.deepEqual(upd.params, [7, 5, 99], 'goal, new owner, actor');
|
|
421
|
+
const sql = String(upd.sql).replace(/\s+/g, ' ');
|
|
422
|
+
assert.match(sql, /UPDATE goal_membership_requests SET status = 'cancelled', resolved_by = \$3/);
|
|
423
|
+
assert.match(sql, /WHERE goal_id = \$1 AND builder_id = \$2 AND status = 'pending'/,
|
|
424
|
+
'scoped to this goal + new owner, pending rows only');
|
|
425
|
+
assert.doesNotMatch(sql, /status = 'accepted'/);
|
|
426
|
+
assert.match(sql, /AND EXISTS \(SELECT 1 FROM g\)/, 'an unknown goal (no g row) must cancel nothing');
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
await test('routes: POST /goals/:id/transfer passes resolvedBy to transferGoalOwnership', async () => {
|
|
430
|
+
const { readFileSync } = await import('node:fs');
|
|
431
|
+
const src = readFileSync(new URL('../modules/lifecycle/routes/goals.js', import.meta.url), 'utf8');
|
|
432
|
+
assert.match(src, /db\.transferGoalOwnership\(\{[^}]*resolvedBy:\s*req\.builder\.id/);
|
|
433
|
+
});
|
|
434
|
+
|
|
412
435
|
await test('transferGoalOwnership: unknown goal → null', async () => {
|
|
413
436
|
const pool = fakePool(() => ({ rows: [] }));
|
|
414
437
|
assert.equal(await transferGoalOwnership({ goalId: 999, newOwnerId: 5 }, { pool }), null);
|