@bongos/core 1.19.500 → 1.19.501

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,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.500",
6
- "core_contract": "1.19.500",
7
- "source_commit": "a32255a73df577c87bedc922b521fc7374a0eb0b",
5
+ "core_version": "1.19.501",
6
+ "core_contract": "1.19.501",
7
+ "source_commit": "d6bac950eb66f758928e815cf88f2d6ddacaf30a",
8
8
  "source_ref": "HEAD",
9
- "built_at": "2026-09-03T15:26:23.313Z",
9
+ "built_at": "2026-09-03T15:41:46.721Z",
10
10
  "redaction": {
11
11
  "model": "docs-redacted+functional-verbatim",
12
- "docs_redacted": 425,
12
+ "docs_redacted": 426,
13
13
  "agent_docs_stubbed": 24,
14
14
  "functional_verbatim": 1942,
15
15
  "rules": 3,
16
16
  "gate_literals": 3,
17
17
  "gate": "passed"
18
18
  },
19
- "file_count": 2391,
20
- "tree_sha256": "07f04a18dbb583be232b10b4742281dc87feb4a4659b4517acf7e02138fa6d88",
19
+ "file_count": 2392,
20
+ "tree_sha256": "d4ef43893ca56f9d2d4e0df1823f7fdb2692bb3f3a18d8bb2fece9221dc83925",
21
21
  "files": [
22
22
  {
23
23
  "path": ".claude/skills/blocker-review/SKILL.md",
@@ -1677,12 +1677,17 @@
1677
1677
  {
1678
1678
  "path": "docs/adr/0234-idea-routing-capture-time-promotion-landing-matrix-homeless-inbox.md",
1679
1679
  "mode": "0000644",
1680
- "sha256": "de04b3e3a03f66dd92003dc256c1839a4c8bcc213fb26103b60baf940046502e"
1680
+ "sha256": "417d1faffdc644b6dbad3d27fc58fac7d87609550060d0cd4edb0bad702d6b4c"
1681
+ },
1682
+ {
1683
+ "path": "docs/adr/0235-a-fix-category-is-kindbug-under-a-goal-no-column-required.md",
1684
+ "mode": "0000644",
1685
+ "sha256": "f3573d82c77dc2b7d006f4ee8051b9b5a247669d2ac4c046c2de7c282d4e65ff"
1681
1686
  },
1682
1687
  {
1683
1688
  "path": "docs/adr/README.md",
1684
1689
  "mode": "0000644",
1685
- "sha256": "f86a0fd77bda20522e0907c607b3ef9724f092194760563c92254855b681404d"
1690
+ "sha256": "43d782f6ca3f187f280e13466830ceceaf6ba74da2cc669e8b7dd6ece166d657"
1686
1691
  },
1687
1692
  {
1688
1693
  "path": "docs/api-reference.md",
@@ -2567,7 +2572,7 @@
2567
2572
  {
2568
2573
  "path": "docs/module-api-changelog.md",
2569
2574
  "mode": "0000644",
2570
- "sha256": "39d9876101cffec994b779de1ea393541ed9542bc509a4927db1e3012b3b2771"
2575
+ "sha256": "49c673ec2ee31c6174bdc48d1b124905bd1f47a51db4e0a3a75e4d937a25ba0a"
2571
2576
  },
2572
2577
  {
2573
2578
  "path": "docs/modules-contract.md",
@@ -7212,12 +7217,12 @@
7212
7217
  {
7213
7218
  "path": "package-lock.json",
7214
7219
  "mode": "0000644",
7215
- "sha256": "ddc63051177f7e290a4d7ff897edbe1299ea563749a431df4c8c9c82b84ecb29"
7220
+ "sha256": "79dfc35495b354b8e53ac84d6210c5c84e8d1bd6a97fc08c84dcbcfd7cc7379d"
7216
7221
  },
7217
7222
  {
7218
7223
  "path": "package.json",
7219
7224
  "mode": "0000644",
7220
- "sha256": "2540d87863daa2bf32507482a181ac806097ce0600a04aa5d706b8f9457899c7"
7225
+ "sha256": "5c08ffd017c27b4ac3a97a55988bbd1fd9958a1ac15ab9e4a689af04531889b6"
7221
7226
  },
7222
7227
  {
7223
7228
  "path": "public-docs/index.html",
@@ -8887,7 +8892,7 @@
8887
8892
  {
8888
8893
  "path": "src/module-api.js",
8889
8894
  "mode": "0000644",
8890
- "sha256": "bf718372363571b9b3dcafc59cf249690636b5150983bca93114af00adf0643a"
8895
+ "sha256": "980689b2fd9c8e0db4213b6ef449b68cef246f40ff3752925562f0f7ed818a16"
8891
8896
  },
8892
8897
  {
8893
8898
  "path": "src/module-loader/catalog.js",
@@ -155,13 +155,15 @@ as `#ideas` has always given that person, which is the actual "nothing lands unv
155
155
  survived.
156
156
 
157
157
  The companion interview decision — **"Discord `#ideas` files with HINTS only (`suggested_goal_id`),
158
- never routes"** — is recorded here as the design intent, but **is not yet built**: R12 (task 1003068,
159
- "Discord `#ideas` carries routing hints") is still `status='ready'`, not shipped. Today,
160
- `modules/discord/discord-inbound.js`'s `#ideas` capture carries no goal hint at all; every `#ideas`
161
- filing lands exactly as it did before this goal, an ordinary homeless `idea_inbox` row. When R12 ships,
162
- its hint must land as `suggested_goal_id` only (never `goal_id`) — consistent with every other
163
- "classifier guess, not a route" vector this ADR documents — or it would silently convert `#ideas` into
164
- a second bypass of the kind idea 1000771 already named once.
158
+ never routes"** — is what R12 (task 1003068, "Discord `#ideas` carries routing hints") shipped, correcting
159
+ this ADR's earlier divergence note (which read `status='ready'` at the time it was written).
160
+ `modules/discord/discord-inbound.js`'s `#ideas` capture now sets `suggested_goal_id` (a classifier guess
161
+ via `suggestGoalForCapture`) and `suggested_version` (defaulting to the most-recently-started open
162
+ version even when no goal matches) on the filed idea row — both READ-ONLY hints for a human triaging via
163
+ `/idea-triage` (R13) — and never sets `goalId`, the only field that would make `captureIdea` actually
164
+ route. Every `#ideas` filing still lands in `idea_inbox` exactly as the pre-routing path did, now
165
+ carrying a hint rather than none, consistent with every other "classifier guess, not a route" vector
166
+ this ADR documents — the second bypass idea 1000771 named did not reopen.
165
167
 
166
168
  ## Consequences
167
169
 
@@ -0,0 +1,131 @@
1
+ # 0235 — A fix category is `kind='bug'` under a goal, not a new column
2
+
3
+ - **Status:** Accepted
4
+ - **Date:** 2026-09-03
5
+ - **Tasks:** [#1003215](https://cloudbongos.com/builders#/task/1003215) (this decision — the structural half
6
+ of idea 1000828), [#1003214](https://cloudbongos.com/builders#/task/1003214) (the advisory's first quiet
7
+ case), [#1003157](https://cloudbongos.com/builders#/task/1003157) (extended the same exemption to the
8
+ criterion-link advisory and the goal detail view)
9
+ - **Goal:** [#1000071](https://cloudbongos.com/builders#/goal/1000071) — Idea routing
10
+ - **Related:** [ADR 0086](<redacted>.md) (the real work hierarchy this decision keeps
11
+ intact), [ADR 0183](<redacted>.md) (why a container that never finishes is dangerous
12
+ now), [ADR 0192 "a category orients and authorises nothing"](<redacted>.md)
13
+ (the precedent this decision is *not* — see §2)
14
+
15
+ ## 1. The problem
16
+
17
+ A fix for something that should already work needs a home. Filing it with no
18
+ `goal_id` lands it in the version's catch-all — no scope wall, no owner reviewing
19
+ it (the `no_goal`/`catch_all` gap `goal-advisory.js` already flags for everything
20
+ else). Filing it under a real goal used to trip a second, unrelated nudge: every
21
+ goal-bound task with no done-when criterion link reads as unattributed work
22
+ (task 1003157). Neither nudge is wrong for a *feature* — but a bug fix is not
23
+ delivering toward one of a goal's stated outcomes; it is restoring one. Idea
24
+ 1000828 named this a missing **first-class grouping**: "a fix for something that
25
+ should already work," living *under* an existing goal, without a new goal being
26
+ born for it.
27
+
28
+ ## 2. Why this is not a stored category, and not [ADR 0192](<redacted>.md)
29
+
30
+ The obvious-looking answer — add a `category` (or `bucket`) column to `tasks` —
31
+ is the wrong shape for two reasons specific to *this* system's schema, not taste:
32
+
33
+ 1. **`tasks` stores no category at all, by decision.** [ADR 0192 "a category
34
+ orients and authorises nothing"](<redacted>.md)
35
+ already answered a structurally identical question for *goals* — a human label
36
+ from an owner-named set, advisory only, gating nothing — and its own text is
37
+ explicit that "a task stores no category… it inherits its goal's through
38
+ `tasks.goal_id`; a stored copy would be a second answer to one question." A
39
+ `tasks.fix_category` boolean would be exactly that second answer: `kind='bug'`
40
+ already exists, is already required (`migrations/006_pms_v2.sql`,
41
+ `NOT NULL DEFAULT 'unclassified'`), and already means "this is a fix." Adding
42
+ a column to restate it is duplication, not a new fact.
43
+ 2. **This decision is a *narrower*, more binding one than [ADR 0192](<redacted>.md)'s.**
44
+ Its category is purely a label a human reads — nothing may branch on it.
45
+ "A bug fix needs no criterion link" and "a bug fix in the catch-all is quiet"
46
+ are the OPPOSITE: two decision surfaces (`goal-advisory.js`) DO branch on
47
+ `kind='bug'`, on purpose, because the alternative — nagging every bug fix to
48
+ either name a criterion it doesn't serve or justify a goal it doesn't need —
49
+ is the noise idea 1000828 asked to remove. So this ADR does not extend ADR
50
+ 0192's "orients, never authorises" rule to `kind`; `kind` already carries real
51
+ weight elsewhere in this codebase (`task-classifier.js`'s heuristic
52
+ classifier decides it from title/description, and `<redacted>`
53
+ calibrates a task's estimate by it), and this decision adds one more narrow,
54
+ named case to that existing list rather than inventing a second category axis
55
+ beside it.
56
+
57
+ ## 3. Why not a global "Bugs" goal either
58
+
59
+ Idea 1000828's own reasoning is the load-bearing part, and it survives unchanged
60
+ here: a goal carries `scope_modules`, the [ADR 0086](<redacted>.md)
61
+ §3 scope wall — a bugs goal spanning every module makes that wall either
62
+ everything or nothing, which is not a wall. And a goal carries done-when criteria
63
+ and can be marked `achieved`; a bug container never finishes, so making it a goal
64
+ manufactures a goal that can never legitimately reach `achieved` — polluting the
65
+ exact signal [ADR 0183](<redacted>.md)'s auto-satisfy now
66
+ depends on to cascade a goal to `achieved` the moment every linked task ships. A
67
+ category *under* an existing goal keeps that goal's wall, keeps the "things that
68
+ should work in THIS area" context, and never claims to be finishable on its own.
69
+
70
+ ## 4. Decision
71
+
72
+ **A fix category is `kind='bug'` on a task that carries a real `goal_id` — no
73
+ schema change, no new column, no new goal type.** The goal is *finishable* as
74
+ before; the fix category is a lens over its existing `kind` field, exactly the
75
+ way [ADR 0192](<redacted>.md)'s goal category
76
+ is a lens over `goals.category_id`, just enforced more strictly because two real
77
+ gates read it.
78
+
79
+ **As-built** (task 1003214 first, task 1003157 completing it — both already
80
+ shipped on `main` before this ADR was written):
81
+
82
+ - `adviseGoal()` in [`modules/lifecycle/goal-advisory.js`](../../modules/lifecycle/goal-advisory.js)
83
+ is the single place all three exemptions live, in one pure, DB-free function:
84
+ a `kind='bug'` task is silent for `no_goal` (no goal at all — a fix needs no
85
+ home to be filed correctly), `catch_all` (a fix sitting in the version's
86
+ catch-all bucket is already where it belongs), and `no_criterion_link` (a real
87
+ goal's criteria named, but a bug fix delivers no criterion and needs none). The
88
+ function's own doc comment states the rule this ADR records: *"a fix is the
89
+ goal's 'fix category', not a delivery against one of its stated outcomes."*
90
+ - `countTasksWithoutCriterionLink()` in
91
+ [`modules/lifecycle/db-deps-criteria.js`](../../modules/lifecycle/db-deps-criteria.js),
92
+ surfaced on `GET /goals/:id` and rendered on the hall's goal detail view
93
+ (`modules/hall-ui/public/goals-render.js`), excludes `kind='bug'` from its
94
+ count for the identical reason — an intentionally unlinked fix must not read as
95
+ a standing defect on the goal's own page.
96
+ - **No hall/status change was needed for grouping.** Verified against the live
97
+ code, not assumed: every task card in a goal's To-do list already renders its
98
+ `kind` as a visible tag (`goals-render.js`, `task__tag`), and the goal detail
99
+ view's Filters disclosure already offers a `Kind` lens with `bug` as a value
100
+ (`goals-page.js`, `f-goal-kind`) — so "the hall groups bugs by kind" was
101
+ already true before this task, via the *same* general-purpose kind facility
102
+ every other kind uses. Building a bug-specific grouping widget beside it would
103
+ be the second-hierarchy mistake [ADR 0192](<redacted>.md)
104
+ §2 already named once for goal categories.
105
+
106
+ ## 5. What was deliberately not built
107
+
108
+ - **No `tasks.category` / `tasks.fix_category` column, no enum, no CHECK
109
+ constraint.** `kind` already answers the question.
110
+ - **No global "Bugs" goal**, and no goal-creation shortcut that manufactures one
111
+ — §3 above is why that door stays shut.
112
+ - **No bug-specific grouping UI.** The kind tag + Kind filter already exist and
113
+ already work for `bug` the same as every other kind; a second, bug-only lens
114
+ beside a general one would duplicate it for no reader benefit.
115
+
116
+ ## 6. Consequences
117
+
118
+ - Idea 1000820 and idea 1000788 (the `node_modules/pino` worktree-resolution
119
+ bugs cited as this decision's first real customers) now have somewhere to file
120
+ that advances a goal without inventing one — the mechanism task 1003215 asked
121
+ for was already load-bearing on `main` by the time this ADR was written; this
122
+ document is what makes the decision citable rather than three commit messages.
123
+ - The exemption is enforced in exactly one function (`adviseGoal`) and one query
124
+ (`countTasksWithoutCriterionLink`); a third surface that starts branching on
125
+ `kind='bug'` for a similar reason should extend those, not invent a fourth
126
+ definition of "what counts as a fix."
127
+ - If a future need ever wants `kind='bug'` to carry MORE weight than an advisory
128
+ exemption — a claim-time gate, a reward multiplier, a dependency rule — that is
129
+ a new, explicit decision needing its own ADR, the same posture
130
+ [ADR 0192](<redacted>.md) §5 holds for goal
131
+ categories. This ADR does not pre-authorise that.
@@ -322,5 +322,6 @@ This keeps the decision history honest and traceable.
322
322
 
323
323
  | 0233 | [**A copy proposal is a task carrying a patch, and the applier is the only writer** ([task 1003114](https://cloudbongos.com/builders#/task/1003114) · goal 1000074, criterion `artist-edits-land-as-tasks`). Goal 1000074 asks for two things that pull against each other in its own text: the artist must change copy WITHOUT an engineer, and there must be NO LIVE CMS because every copy change is a claimed, graded, shipped task. R02 shipped the half that needs no reconciliation (the flag) and [ADR 0178](<redacted>.md) §3 pinned the absence of any column that could hold replacement text, naming this task as the one that would have to keep it true. Decisions: (1) the shape is **borrowed from the design half, not invented** — ADR 0081 already has a tool authoring and an `adapter.export()` landing the output as a committed diff under a claim inside a path guard, so the artist is the tool, the copy desk is where they author, and the proposal is the export. (2) A proposal is a **TASK carrying a fenced `copy-proposal` patch**, never a row: the ledger is where a proposal belongs anyway, nothing renders a task description as product copy, a reviewer can read the change without running anything, and `copy-desk` gains NO migration (the obvious-but-wrong R03 is a `copy_desk_proposals` table, which is the forbidden column with extra steps). The module gains `consumes: ["lifecycle"]` and calls `createTask` through the port — it can put a request INTO the ledger and nothing can pull copy OUT of it. (3) `scripts/gds/copy-apply.js` **re-derives the position** rather than trusting the patch, which required teaching R01s extractor to record a source SPAN and deliberately dropping it from the committed registry: an offset goes stale the moment anything above it changes, while the id is designed to survive exactly that movement, so the span is recomputed at the moment of the edit by the same code that decided the string was copy. (4) The **placeholder arithmetic** is what makes a patch mechanical rather than a note for an engineer — the applier puts the sources own `${expr}` back, k-th hole to k-th expression, so an artist may MOVE a value within a sentence but never add or drop one, checked at proposal time and again against the real source. (5) Every ambiguity is a **named refusal** (`target_gone`, `ambiguous_target`, `no_exact_span`, `placeholder_mismatch`, `path_outside_surface` — the design adapters path guard, derived from R01s own SURFACES), because a wrong edit is worse than no edit; after writing, the applier regenerates the registry and checks that what it wrote is what the inventory now reads. (6) Proposing is **open to every rank** (an artist is a craft, not a rank) and lands at `backlog`, so a proposal is a request that passes ordinary triage. Rejected: a proposals table, a column beside the flag, trusting the patchs line number, an escape-aware index map to buy spans for nine strings, auto-closing the flag a proposal answers.](<redacted>.md) | copy-desk / the artist loop |
324
324
  | 0234 | [**Idea routing: capture-time promotion, the landing matrix, and the homeless-only inbox** ([task 1003064](https://cloudbongos.com/builders#/task/1003064) · goal 1000071, "Idea routing"). Idea 1000771 named the failure: Discord `#bugs` created tasks DIRECTLY against a hardcoded, already-shipped version — no `captured_by`, no lineage, so the ideator-credit lane had nothing to pay against — while every other open idea sat waiting for a human triage pass that dropped its promotion into a version catch-all, because nothing in capture ever named a goal. Records what R01/R02/R05/R07/R13 shipped. `captureIdea` (`modules/ideas/inbox.js`) stays the ONE capture chokepoint — routing is one optional `goalId` argument, never a second creation door — and when the matrix routes, `routeIdeaToGoal` writes the idea row, the task (via the `lifecycle.createTask` port) and an `ideas_task_lineage` row (`origin='route'`) in ONE transaction, so a route can never mint attribution-free work the way `#bugs` did. `modules/ideas/routing.js`'s `decideLanding` is PURE and fail-closed: a bug from a Metic+ filer hard-lands `ready`, a sub-Metic bug or any other kind with a goal soft-lands `backlog`, a Full Idea or `criterion-proposal`/`decision` never routes, no goal named stays the pre-routing inbox path. `authorizeRoutedLanding` is the BINDING gate underneath the matrix's decision — a goal reaching protected scope raises the task's rank floor to Metic and REFUSES a sub-Metic filer outright, while membership is deliberately NOT required (reporting isn't authoring). `core_222`'s `suggested_goal_id` is an advisory hint only — the real home is `tasks.goal_id`, set by construction — and `/idea-triage` (`scripts/gds/triage.js`) now sends `goal_id` on promotion, so the inbox is homeless-only. Divergence recorded: R11 (Discord `#bugs`) hard-lands a linked Metic+ builder's bug immediately through the SAME shared matrix rather than the spec's "always soft-land, pending queue" design, because a local copy of the rank split would only drift from the one definition; and R12 (Discord `#ideas` hints) is NOT YET SHIPPED, so `#ideas` carries no goal hint today despite the interview decision that it should, hint-only, never route.](<redacted>.md) | ideas / lifecycle |
325
+ | 0235 | [**A fix category is `kind='bug'` under a goal, not a new column** ([task 1003215](https://cloudbongos.com/builders#/task/1003215) · goal 1000071, "Idea routing" — the structural half of idea 1000828; task 1003214 shipped the advisory's first quiet case, task 1003157 extended it). A fix for something that should already work needs a home under an existing goal WITHOUT a new goal being born and WITHOUT a stored column restating what `tasks.kind` already says. Not a global "Bugs" goal either: a goal spanning every module makes the [ADR 0086](<redacted>.md) scope wall either everything or nothing, and a goal that can never reach `achieved` (a bug container never finishes) pollutes the exact signal [ADR 0183](<redacted>.md)'s auto-satisfy depends on. Not [ADR 0192 "a category orients and authorises nothing"](<redacted>.md) either, despite the structural resemblance: that decision forbids any gate from branching on a goal's category, while THIS decision is two decision surfaces deliberately branching on `kind='bug'` — `adviseGoal()` (`modules/lifecycle/goal-advisory.js`) goes silent for a bug under all three of its reasons (`no_goal`, `catch_all`, `no_criterion_link` — "a fix is the goal's 'fix category', not a delivery against one of its stated outcomes," its own doc comment) and `countTasksWithoutCriterionLink()` (`modules/lifecycle/db-deps-criteria.js`, surfaced on the hall's goal detail view) excludes `kind='bug'` from its count for the same reason. No hall/status change was needed for GROUPING bugs under a goal: every task card already renders its `kind` as a visible tag and the goal detail view's Filters already offer a `Kind` lens with `bug` as a value — verified against the live code, not built new. Rejected: a `tasks.category`/`fix_category` column or enum, a global cross-module "Bugs" goal, a bug-specific grouping widget beside the general-purpose kind facility that already works.](<redacted>.md) | ideas / lifecycle |
325
326
 
326
327
  > ⚠️ **Numbering collisions are now machine-enforced, not narrated.** Twenty numbers are shared by two ADRs each — assigned in parallel sessions before anything checked. The files keep their filenames (renumbering would break every existing citation, and a number once assigned is never reused), and this table disambiguates each pair as `NNNN-a` / `NNNN-b`. The authoritative list is `LEGACY_DUPLICATE_ADRS` in [`scripts/gds/adr-namespace.js`](../../scripts/gds/adr-namespace.js), frozen by exact filename: a **new** collision — or a third file joining a legacy number, or a rename of either half — hard-fails the `unit` CI gate, as does an index row that points at no file or an ADR with no row. The list may only shrink. This paragraph used to narrate the collisions one by one and had fallen eight behind reality; see [ADR 0195](<redacted>.md) for why the check exists and why the pairs are grandfathered rather than renumbered.
@@ -1437,5 +1437,7 @@ is load-bearing: the script throws rather than guess if it is missing, and
1437
1437
  landed since 1.19.498 with no explicit bump. run 33769500709. (task 1002620)
1438
1438
  1.19.500 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
1439
1439
  landed since 1.19.499 with no explicit bump. run 33772499045. (task 1002620)
1440
+ 1.19.501 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
1441
+ landed since 1.19.500 with no explicit bump. run 33774087943. (task 1002620)
1440
1442
  ---------------------------------------------------------------------------
1441
1443
  ```
package/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.19.500",
3
+ "version": "1.19.501",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@bongos/core",
9
- "version": "1.19.500",
9
+ "version": "1.19.501",
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.500",
3
+ "version": "1.19.501",
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
@@ -45,7 +45,7 @@ const { validateOrRespond, LIMITS, parseId, asyncHandler, corsPublicGet, parsePa
45
45
  // there. scripts/gds/bump-version.js still rewrites the literal below; it appends
46
46
  // the entry to that file. Look for a version's history there, not here.
47
47
  // ---------------------------------------------------------------------------
48
- const CORE_VERSION = '1.19.500'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
48
+ const CORE_VERSION = '1.19.501'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
49
49
 
50
50
  // A namespaced logger so a module's log lines are attributable + consistent.
51
51
  // Usage: const log = api.logger('dev-box'); log.info('mounted');