@bongos/core 1.19.377 → 1.19.378

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 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.377",
6
- "core_contract": "1.19.377",
7
- "source_commit": "90c7b43a6f0265aaf5d5c117cbe2721c18bd6c35",
5
+ "core_version": "1.19.378",
6
+ "core_contract": "1.19.378",
7
+ "source_commit": "71bcea42aeb104d9931a45ea2fdc5b1816bead92",
8
8
  "source_ref": "HEAD",
9
- "built_at": "2026-08-26T23:56:55.300Z",
9
+ "built_at": "2026-08-27T00:03:57.043Z",
10
10
  "redaction": {
11
11
  "model": "docs-redacted+functional-verbatim",
12
12
  "docs_redacted": 335,
@@ -17,7 +17,7 @@
17
17
  "gate": "passed"
18
18
  },
19
19
  "file_count": 1922,
20
- "tree_sha256": "ef3ea529acb199c38d7dc4bb8bc657b694727f8e8ffaa8fdf2af230913416726",
20
+ "tree_sha256": "0a04e3d05efdc0ba120a60c0d163afc0c7ac5075cf143d082d047fe6c56fcd16",
21
21
  "files": [
22
22
  {
23
23
  "path": ".claude/skills/blocker-review/SKILL.md",
@@ -367,7 +367,7 @@
367
367
  {
368
368
  "path": "clients/bongos-client/index.d.ts",
369
369
  "mode": "0000644",
370
- "sha256": "28f456a1b259b898b4bfc0d353c9877b5f10828beae478c2ee6aa1a66e64c33a"
370
+ "sha256": "e9a6dd8d60741347814d184016bb3eaae1b319ba299121e7a39a55367bc12e56"
371
371
  },
372
372
  {
373
373
  "path": "clients/bongos-client/index.mjs",
@@ -1477,12 +1477,12 @@
1477
1477
  {
1478
1478
  "path": "docs/api-reference.md",
1479
1479
  "mode": "0000644",
1480
- "sha256": "96e9749fd1a6061c3ae96edf1da81a42fc6f89144bca6844870e5abcc7aeb7fe"
1480
+ "sha256": "1d40e3666f05b4b28d7b9433e84c0ae4bfccc907660053006694814799365bf0"
1481
1481
  },
1482
1482
  {
1483
1483
  "path": "docs/api/openapi.json",
1484
1484
  "mode": "0000644",
1485
- "sha256": "a743ea7c9fbe29419a6efc5978472c8fa27da2178eef34edbc988574990733f8"
1485
+ "sha256": "57b66bbfe0c1d7aa8274a43d813c77c83986a3e4cf43046e9e0a637ac4fe308d"
1486
1486
  },
1487
1487
  {
1488
1488
  "path": "docs/architecture.md",
@@ -4077,7 +4077,7 @@
4077
4077
  {
4078
4078
  "path": "modules/lifecycle/db-tasks.js",
4079
4079
  "mode": "0000644",
4080
- "sha256": "94b785f970615056c9c3e896009868ef762fe78ab9f640889b9286ccef46fcf0"
4080
+ "sha256": "745663b0a264ae742702919fc9486f49723010dd797e1fe7151de5d65b98bf21"
4081
4081
  },
4082
4082
  {
4083
4083
  "path": "modules/lifecycle/db-versions.js",
@@ -4087,7 +4087,7 @@
4087
4087
  {
4088
4088
  "path": "modules/lifecycle/db.js",
4089
4089
  "mode": "0000644",
4090
- "sha256": "70448ebd079d5167bcf0c9c2b4473d46e996a54202f09f5a8ebc30980aba4166"
4090
+ "sha256": "b7f0d36dc13ebad0206b94879262e661e6c2524539732f31e7cec25f61fd9fd6"
4091
4091
  },
4092
4092
  {
4093
4093
  "path": "modules/lifecycle/dead-deps.js",
@@ -4277,7 +4277,7 @@
4277
4277
  {
4278
4278
  "path": "modules/lifecycle/routes/task-write-routes.js",
4279
4279
  "mode": "0000644",
4280
- "sha256": "4ef343018b69528ab9518683ba0c6878bfcf5b9398ee7a2ade21780c20218538"
4280
+ "sha256": "10313e3a6bd619fe2cf5cd691927032914fcb25d52ba743e8ae16d51d8d97d5c"
4281
4281
  },
4282
4282
  {
4283
4283
  "path": "modules/lifecycle/routes/tasks.js",
@@ -4942,12 +4942,12 @@
4942
4942
  {
4943
4943
  "path": "package-lock.json",
4944
4944
  "mode": "0000644",
4945
- "sha256": "e5e8b0e3c6879a8636f96f6bdce1c4fd8d9b06521e431bd6051bb2be2ea96518"
4945
+ "sha256": "f96269625487590e9dc70bff805db37a0f00592178fc6614f6c82b4610ec3c0d"
4946
4946
  },
4947
4947
  {
4948
4948
  "path": "package.json",
4949
4949
  "mode": "0000644",
4950
- "sha256": "3057a201c65b95c06512dfbf5642b4d3de10c513382e771b478f0eb43dad3ff8"
4950
+ "sha256": "40e93caa20eab8a0602a3fe4a1073e63aca106888f5afcbe28627200e17d84f6"
4951
4951
  },
4952
4952
  {
4953
4953
  "path": "public-docs/index.html",
@@ -6837,7 +6837,7 @@
6837
6837
  {
6838
6838
  "path": "src/module-api.js",
6839
6839
  "mode": "0000644",
6840
- "sha256": "5287468c8e1a2ba691e02ff2150bcb425b00db6c0ce676b063d32cb20ef640c5"
6840
+ "sha256": "f291431298b7e0b6369f71f944d87c5fcf67a651da063a6a7af0f4935d99e33a"
6841
6841
  },
6842
6842
  {
6843
6843
  "path": "src/module-loader/catalog.js",
@@ -8532,7 +8532,7 @@
8532
8532
  {
8533
8533
  "path": "tests/migration_allocation.mjs",
8534
8534
  "mode": "0000644",
8535
- "sha256": "7b0e40f4b3e348a45ccdc543dd1f3dfd78113ae86348823001e4eabb78f126de"
8535
+ "sha256": "e2f03570b76b4d5af7af3c87a2a4989827eb71d1b50c92ab546a456e85c4024e"
8536
8536
  },
8537
8537
  {
8538
8538
  "path": "tests/migration_namespace.mjs",
@@ -163,7 +163,7 @@ export interface PatchProvisioningInstancesIdSettingsRequest { platform_visibili
163
163
  export interface PatchProvisioningInstancesIdSettingsResponse { ok: boolean; saved: unknown; push: unknown }
164
164
  export interface PatchTaskRecommendationsIdRequest { status: "declined" | "withdrawn" }
165
165
  export interface PatchTaskRecommendationsIdResponse { ok: boolean; recommendation: unknown }
166
- export interface PatchTasksIdRequest { kind?: string; discipline?: string; requires_rank?: string; module_key?: string; goal_id?: number; parent_task_id?: StringifiableId; parallel_safe?: unknown; newcomer_friendly?: boolean; xenos_claimable?: boolean; security_sensitive?: boolean; automation_tag?: string; needs_migration?: boolean; description?: string; status?: unknown }
166
+ export interface PatchTasksIdRequest { kind?: string; discipline?: string; requires_rank?: string; module_key?: string; goal_id?: number; parent_task_id?: StringifiableId; parallel_safe?: unknown; newcomer_friendly?: boolean; xenos_claimable?: boolean; security_sensitive?: boolean; automation_tag?: string; needs_migration?: boolean; description?: string; title?: string; status?: unknown }
167
167
  export interface PostAccessRequestsInviteRequest { github_login: string }
168
168
  export interface PostAccessRequestsInviteResponse { ok: boolean; already_invited?: boolean; github_login?: unknown; request?: unknown }
169
169
  export interface PostAccessRequestsRequest { github_login: string; display_name?: string; note?: string }
@@ -16737,6 +16737,11 @@
16737
16737
  "minLength": 1,
16738
16738
  "maxLength": 50000
16739
16739
  },
16740
+ "title": {
16741
+ "type": "string",
16742
+ "minLength": 1,
16743
+ "maxLength": 200
16744
+ },
16740
16745
  "status": {}
16741
16746
  },
16742
16747
  "additionalProperties": false
@@ -542,7 +542,7 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/<redacted>
542
542
  | GET | `/api/bongos/tasks` | `any-builder` | — | |
543
543
  | POST | `/api/bongos/tasks` | `metic+archon` | `version_id`, `title`, `description`, `status`, `touches`, `est_minutes`, `est_cost_usd`, `manual_degree`, `priority`, `automation_tag`, `credits_reward`, `source`, `source_ref`, `value_summary`, `kind`, `discipline`, `parallel_safe`, `newcomer_friendly`, `security_sensitive`, `requires_rank`, `auto_detect_touches`, `criterion_ids`, `module_key`, `goal_id` | Task create/promote/edit (plan/scope mutation) is Metic+ as of ADR 0090 (owner decision 2026-06-26): a Metic who can run idea-triage may … |
544
544
  | GET | `/api/bongos/tasks/:id` | `any-builder` | — | single-task read; preserved per CRITICAL §4 (supervisor hot path). |
545
- | PATCH | `/api/bongos/tasks/:id` | `metic+archon` | `kind`, `discipline`, `requires_rank`, `module_key`, `goal_id`, `parent_task_id`, `parallel_safe`, `newcomer_friendly`, `xenos_claimable`, `security_sensitive`, `automation_tag`, `needs_migration`, `description`, `status` | PATCH /tasks/:id — supports body.parent_task_id (V2 C2), body.kind (V2 B1), body.discipline (mig 014), body.parallel_safe (mig 028), and … |
545
+ | PATCH | `/api/bongos/tasks/:id` | `metic+archon` | `kind`, `discipline`, `requires_rank`, `module_key`, `goal_id`, `parent_task_id`, `parallel_safe`, `newcomer_friendly`, `xenos_claimable`, `security_sensitive`, `automation_tag`, `needs_migration`, `description`, `title`, `status` | PATCH /tasks/:id — supports body.parent_task_id (V2 C2), body.kind (V2 B1), body.discipline (mig 014), body.parallel_safe (mig 028), and … |
546
546
  | POST | `/api/bongos/tasks/:id/abandon` | `metic+archon` | `reason` | POST /tasks/:id/abandon — terminal "retire this task" transition (task 987). |
547
547
  | POST | `/api/bongos/tasks/:id/attest-gate` | `any-builder` | `head_sha` | POST /tasks/:id/attest-gate — body: { head_sha }. |
548
548
  | POST | `/api/bongos/tasks/:id/confirm` | `any-builder` | `verified` | |
@@ -203,7 +203,7 @@ async function findTaskBySourceRef({ source, sourceRef } = {}, deps = {}) {
203
203
 
204
204
  const TASK_SETTER_COLUMNS = new Set([
205
205
  'kind', 'discipline', 'newcomer_friendly', 'security_sensitive', 'parallel_safe', 'automation_tag',
206
- 'needs_migration', 'module_key', 'description',
206
+ 'needs_migration', 'module_key', 'description', 'title',
207
207
  ]);
208
208
 
209
209
  async function updateTaskColumn(id, column, value) {
@@ -264,6 +264,12 @@ async function updateTaskKind(id, kind) { return updateTaskColumn(id, 'kind', ki
264
264
  // write-audit middleware captures each edit's new body in audit_log.
265
265
  async function updateTaskDescription(id, description) { return updateTaskColumn(id, 'description', description); }
266
266
 
267
+ // task 1002792: the title is the MORE visible half of that same prompt — what
268
+ // /builder-start lists and the hall shows — and was write-once at every rank,
269
+ // so a wrong title (two seeded briefs naming tables that hard-fail CI, task
270
+ // 1002791) was permanent. Same permission, same audit trail as the body.
271
+ async function updateTaskTitle(id, title) { return updateTaskColumn(id, 'title', title); }
272
+
267
273
 
268
274
  async function updateTaskDiscipline(id, discipline) { return updateTaskColumn(id, 'discipline', discipline); }
269
275
 
@@ -853,6 +859,7 @@ module.exports = {
853
859
  taskTouchesProtectedPath,
854
860
  updateTaskAutomationTag,
855
861
  updateTaskDescription,
862
+ updateTaskTitle,
856
863
  updateTaskDiscipline,
857
864
  updateTaskGoal,
858
865
  updateTaskKind,
@@ -112,6 +112,7 @@ const {
112
112
  taskTouchesProtectedPath,
113
113
  updateTaskAutomationTag,
114
114
  updateTaskDescription,
115
+ updateTaskTitle,
115
116
  updateTaskDiscipline,
116
117
  updateTaskGoal,
117
118
  updateTaskKind,
@@ -244,6 +245,7 @@ module.exports = {
244
245
  createCriterion,
245
246
  updateTaskKind,
246
247
  updateTaskDescription,
248
+ updateTaskTitle,
247
249
  updateTaskDiscipline,
248
250
  updateTaskNewcomerFriendly,
249
251
  updateTaskRequiresRank,
@@ -285,6 +285,11 @@ module.exports = function registerTaskWriteRoutes(router) {
285
285
  // can be rewritten, never blanked (and null is refused by the type check).
286
286
  // Each edit's new body lands in audit_log via the write-audit middleware.
287
287
  description: { type: 'string', minLength: 1, maxLength: LIMITS.DESCRIPTION },
288
+ // task 1002792: the title — the more visible half of the same prompt — was
289
+ // write-once at every rank, so a wrong one was permanent (task 1002791's two
290
+ // briefs naming tables that hard-fail CI). Same shape as create, same
291
+ // task.edit permission, same audit_log trail as a description edit.
292
+ title: { type: 'string', minLength: 1, maxLength: LIMITS.TITLE },
288
293
  // task 1002614 (map D-18): DECLARED so strict-mode admits the request far
289
294
  // enough to reach the deliberate status_not_patchable hint below (#514) —
290
295
  // the hint had been unreachable dead code behind unknown_field since the
@@ -311,6 +316,7 @@ module.exports = function registerTaskWriteRoutes(router) {
311
316
  const hasModuleKey = Object.prototype.hasOwnProperty.call(body, 'module_key');
312
317
  const hasGoalId = Object.prototype.hasOwnProperty.call(body, 'goal_id');
313
318
  const hasDescription = Object.prototype.hasOwnProperty.call(body, 'description');
319
+ const hasTitle = Object.prototype.hasOwnProperty.call(body, 'title');
314
320
  // #514: status is a lifecycle field, not a PATCH-able column — it moves only
315
321
  // through the dedicated transition routes. The #506 session tried
316
322
  // `PATCH status=ready`, got the generic no_supported_fields error, and had
@@ -322,8 +328,8 @@ module.exports = function registerTaskWriteRoutes(router) {
322
328
  if (Object.prototype.hasOwnProperty.call(body, 'status')) {
323
329
  return res.fail('status_not_patchable', { status: 400, message: STATUS_HINT });
324
330
  }
325
- if (!hasParent && !hasKind && !hasDiscipline && !hasNewcomerOrXenos && !hasParallelSafe && !hasSecuritySensitive && !hasAutomationTag && !hasNeedsMigration && !hasRequiresRank && !hasModuleKey && !hasGoalId && !hasDescription) {
326
- return res.fail('no_supported_fields', { status: 400, message: 'PATCH /tasks/:id supports parent_task_id, kind, discipline, description, parallel_safe, security_sensitive, automation_tag, needs_migration, requires_rank, module_key, goal_id, and newcomer_friendly (alias: xenos_claimable). ' + STATUS_HINT });
331
+ if (!hasParent && !hasKind && !hasDiscipline && !hasNewcomerOrXenos && !hasParallelSafe && !hasSecuritySensitive && !hasAutomationTag && !hasNeedsMigration && !hasRequiresRank && !hasModuleKey && !hasGoalId && !hasDescription && !hasTitle) {
332
+ return res.fail('no_supported_fields', { status: 400, message: 'PATCH /tasks/:id supports parent_task_id, kind, discipline, title, description, parallel_safe, security_sensitive, automation_tag, needs_migration, requires_rank, module_key, goal_id, and newcomer_friendly (alias: xenos_claimable). ' + STATUS_HINT });
327
333
  }
328
334
  // ---- task 1002609 (G-22): settle EVERY gate and validation before the ----
329
335
  // ---- FIRST write. The previous shape validated-and-wrote per field in ----
@@ -478,6 +484,15 @@ module.exports = function registerTaskWriteRoutes(router) {
478
484
  return res.fail('patch_failed', { status: 500, message: 'internal error' });
479
485
  }
480
486
  }
487
+ if (hasTitle) {
488
+ try {
489
+ updated = await db.updateTaskTitle(id, body.title.trim());
490
+ if (!updated) return res.fail('task_not_found', 404);
491
+ } catch (err) {
492
+ log.error('[gds] PATCH /tasks/:id title', err);
493
+ return res.fail('patch_failed', { status: 500, message: 'internal error' });
494
+ }
495
+ }
481
496
  if (hasGoalId) {
482
497
  try {
483
498
  updated = await db.updateTaskGoal(id, body.goal_id);
package/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.19.377",
3
+ "version": "1.19.378",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@bongos/core",
9
- "version": "1.19.377",
9
+ "version": "1.19.378",
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.377",
3
+ "version": "1.19.378",
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
@@ -1194,8 +1194,10 @@ const { validateOrRespond, LIMITS, parseId, asyncHandler, corsPublicGet, parsePa
1194
1194
  // landed since 1.19.375 with no explicit bump. run 32910331206. (task 1002620)
1195
1195
  // 1.19.377 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
1196
1196
  // landed since 1.19.376 with no explicit bump. run 33025011131. (task 1002620)
1197
+ // 1.19.378 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
1198
+ // landed since 1.19.377 with no explicit bump. run 33025512093. (task 1002620)
1197
1199
  // ---------------------------------------------------------------------------
1198
- const CORE_VERSION = '1.19.377'; // CI auto-patch carrier (ADR 0161); see changelog above
1200
+ const CORE_VERSION = '1.19.378'; // CI auto-patch carrier (ADR 0161); see changelog above
1199
1201
 
1200
1202
  // A namespaced logger so a module's log lines are attributable + consistent.
1201
1203
  // Usage: const log = api.logger('dev-box'); log.info('mounted');
@@ -203,6 +203,7 @@ function shouldReserveMigrationNumber(task) {
203
203
  [() => db.updateTaskNeedsMigration(1, false), 'needs_migration'],
204
204
  [() => db.updateTaskModuleKey(1, null), 'module_key'],
205
205
  [() => db.updateTaskDescription(1, 'edited body'), 'description'], // task 1002647
206
+ [() => db.updateTaskTitle(1, 'corrected title'), 'title'], // task 1002792
206
207
  ];
207
208
  for (const [call, column] of setters) {
208
209
  const before = seen.length;
@@ -218,6 +219,16 @@ function shouldReserveMigrationNumber(task) {
218
219
  }
219
220
  });
220
221
 
222
+ await test('PATCH /tasks/:id accepts title so a wrong title is correctable (task 1002792)', () => {
223
+ assert.ok(
224
+ /title: \{ type: 'string', minLength: 1, maxLength: LIMITS\.TITLE \}/.test(routesSrc),
225
+ 'the PATCH schema must declare title with the create-time limits — a title can be rewritten, never blanked'
226
+ );
227
+ assert.ok(/const hasTitle = Object\.prototype\.hasOwnProperty\.call\(body, 'title'\)/.test(routesSrc), 'title is gated like every other field');
228
+ assert.ok(/&& !hasTitle\) \{/.test(routesSrc), 'a title-only PATCH is a supported request, not no_supported_fields');
229
+ assert.ok(/db\.updateTaskTitle\(id, body\.title\.trim\(\)\)/.test(routesSrc), 'the write goes through the allowlisted setter');
230
+ });
231
+
221
232
  await test('PATCH /tasks/:id accepts needs_migration so a wrong flag is correctable', () => {
222
233
  assert.ok(
223
234
  /needs_migration: \{ type: 'boolean' \}/.test(routesSrc),