@bongos/core 1.20.37 → 1.20.38

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.
Files changed (50) hide show
  1. package/.bongos-core.json +93 -48
  2. package/.claude/skills/backlog-review/SKILL.md +1 -1
  3. package/.claude/skills/bongos-feedback/SKILL.md +66 -0
  4. package/.claude/skills/collab-review/SKILL.md +1 -1
  5. package/.claude/skills/priority-session/SKILL.md +1 -1
  6. package/.claude/skills/session-handoff/SKILL.md +1 -1
  7. package/.claude/skills/status/SKILL.md +1 -1
  8. package/bin/bongos.js +1 -0
  9. package/clients/bongos-client/README.md +1 -1
  10. package/clients/bongos-client/bongos-client.global.js +8 -0
  11. package/clients/bongos-client/index.cjs +8 -0
  12. package/clients/bongos-client/index.d.ts +12 -1
  13. package/clients/bongos-client/index.mjs +8 -0
  14. package/docs/adr/0136-update-channel-subscription-policy.md +1 -1
  15. package/docs/adr/0357-the-update-rule-set-on-deploy-is-the-one-the-sweep-follows.md +41 -0
  16. package/docs/adr/README.md +1 -0
  17. package/docs/api/openapi.json +188 -2
  18. package/docs/api-reference.md +12 -4
  19. package/docs/copy-inventory.md +9 -9
  20. package/docs/copy-registry.json +9 -9
  21. package/docs/file-map.md +1 -0
  22. package/docs/module-api-changelog.md +2 -0
  23. package/docs/page-readings.json +2 -2
  24. package/docs/recipes/upgrading-the-core.md +2 -0
  25. package/modules/autonomy/db.js +39 -8
  26. package/modules/autonomy/fence.js +26 -4
  27. package/modules/autonomy/migrations/autonomy_003_priority_goal.sql +32 -0
  28. package/modules/autonomy/routes/autonomy.js +28 -1
  29. package/modules/hall-ui/public/gate.js +33 -4
  30. package/modules/ideas/routing.js +8 -1
  31. package/modules/platform-identity/instance-feedback.js +142 -0
  32. package/modules/platform-identity/module.json +1 -1
  33. package/modules/platform-identity/routes/sso.js +62 -0
  34. package/package-lock.json +2 -2
  35. package/package.json +1 -1
  36. package/release-notes.json +20 -0
  37. package/scripts/gds/autobongos-run.js +14 -4
  38. package/scripts/gds/feedback-send.js +131 -0
  39. package/scripts/gds/update-channel.js +82 -0
  40. package/src/bongos/routes/feedback.js +110 -0
  41. package/src/bongos/routes.js +2 -0
  42. package/src/module-api.js +1 -1
  43. package/tests/autobongos_fence.mjs +62 -0
  44. package/tests/autobongos_loop.mjs +76 -0
  45. package/tests/autonomy_fence_priority.mjs +211 -0
  46. package/tests/bongos_cli.mjs +7 -1
  47. package/tests/filing_abuse_matrix.mjs +7 -2
  48. package/tests/idea_routing.mjs +1 -1
  49. package/tests/instance_feedback.mjs +327 -0
  50. package/tests/update_channel_db.mjs +124 -0
@@ -176,6 +176,8 @@ function createClient(opts = {}) {
176
176
  postAutonomyFenceGoals: (args) => request("POST", "/autonomy/fence/goals", { hasBody: true }, args),
177
177
  // DELETE /autonomy/fence/goals/{goalId} — rank: archon — DELETE /autonomy/fence/goals/:goalId
178
178
  deleteAutonomyFenceGoalsGoalId: (args) => request("DELETE", "/autonomy/fence/goals/{goalId}", { hasBody: false }, args),
179
+ // POST /autonomy/fence/priority — rank: archon — POST /autonomy/fence/priority
180
+ postAutonomyFencePriority: (args) => request("POST", "/autonomy/fence/priority", { hasBody: true }, args),
179
181
  // POST /autonomy/heartbeat — rank: any-builder — POST /autonomy/heartbeat
180
182
  postAutonomyHeartbeat: (args) => request("POST", "/autonomy/heartbeat", { hasBody: true }, args),
181
183
  // GET /autonomy/precheck — rank: metic+archon — GET /autonomy/precheck
@@ -367,6 +369,10 @@ function createClient(opts = {}) {
367
369
  // GET /done-when/pending-review — rank: metic+archon — GET /done-when/pending-review
368
370
  getDoneWhenPendingReview: (args) => request("GET", "/done-when/pending-review", { hasBody: false }, args),
369
371
  },
372
+ "feedback": {
373
+ // POST /feedback — rank: any-builder — POST /feedback
374
+ postFeedback: (args) => request("POST", "/feedback", { hasBody: true }, args),
375
+ },
370
376
  "gateApprovals": {
371
377
  // GET /gate-approvals — rank: metic+archon — GET /gate-approvals
372
378
  getGateApprovals: (args) => request("GET", "/gate-approvals", { hasBody: false }, args),
@@ -1018,6 +1024,8 @@ function createClient(opts = {}) {
1018
1024
  postSsoDevicePoll: (args) => request("POST", "/sso/device/poll", { hasBody: true }, args),
1019
1025
  // POST /sso/device/start — rank: public — POST /sso/device/start
1020
1026
  postSsoDeviceStart: (args) => request("POST", "/sso/device/start", { hasBody: true }, args),
1027
+ // POST /sso/feedback — rank: public — POST /sso/feedback
1028
+ postSsoFeedback: (args) => request("POST", "/sso/feedback", { hasBody: true }, args),
1021
1029
  // POST /sso/invites/clear — rank: public — POST /sso/invites/clear
1022
1030
  postSsoInvitesClear: (args) => request("POST", "/sso/invites/clear", { hasBody: true }, args),
1023
1031
  // POST /sso/invites/notify — rank: public — POST /sso/invites/notify
@@ -251,8 +251,9 @@ export interface PostAuthRevokeRequest { session_id?: StringifiableId }
251
251
  export interface PostAuthRevokeResponse { ok: boolean; revoked: unknown }
252
252
  export interface PostAutonomyFenceGoalsRequest { goal_id: StringifiableId; note?: string }
253
253
  export interface PostAutonomyFenceGoalsResponse { goal: unknown }
254
+ export interface PostAutonomyFencePriorityRequest { goal_id?: StringifiableId }
254
255
  export interface PostAutonomyFenceRequest { enabled: boolean; reason?: string }
255
- export interface PostAutonomyHeartbeatRequest { host: string; pid?: number; started_at?: string; mode?: string; consecutive_failures?: number; last_event?: string; working_task_id?: number }
256
+ export interface PostAutonomyHeartbeatRequest { host: string; pid?: number; started_at?: string; mode?: string; consecutive_failures?: number; last_event?: string; working_task_id?: number; working_goal_id?: number }
256
257
  export interface PostAutonomyHeartbeatResponse { ok: boolean; heartbeat: unknown }
257
258
  export interface PostBackupTriggerResponse { ok: boolean; message: unknown; started_at: unknown }
258
259
  export interface PostBlockersIdLinkRequest { task_id: StringifiableId }
@@ -293,6 +294,7 @@ export interface PostDoneWhenCriterionIdUatRecordingResponse { ok: boolean; reco
293
294
  export interface PostDoneWhenCriterionIdUatRequest { kind: string; recording?: string; live_attested?: boolean; note?: string }
294
295
  export interface PostDoneWhenCriterionIdUatResponse { ok: boolean; signoff: unknown; criterion_closed: unknown; achieved_goals: unknown; closed_versions: unknown }
295
296
  export interface PostDoneWhenCriterionIdUnsatisfyResponse { criterion: unknown }
297
+ export interface PostFeedbackRequest { message: string; kind?: "bug" | "idea"; context?: unknown }
296
298
  export interface PostGateApprovalsPrApproveResponse { ok: boolean; pr: unknown; already_clear?: boolean; message: unknown; head_sha?: unknown; status_set?: boolean; recheck?: unknown; held_for_artist?: unknown }
297
299
  export interface PostGithubRepoVisibilityRequest { repo: string; visibility: "public" | "private" }
298
300
  export interface PostGithubRepoVisibilityResponse { ok: boolean; repo: unknown; private_deployable: boolean }
@@ -445,6 +447,7 @@ export interface PostSsoApplicantProfileRequest { client_id: string; client_secr
445
447
  export interface PostSsoApplicantProfileResponse { profile: unknown }
446
448
  export interface PostSsoDevicePollRequest { device_code: string }
447
449
  export interface PostSsoDeviceStartRequest { origin: string }
450
+ export interface PostSsoFeedbackRequest { client_id: string; client_secret: string; github_id: StringifiableId; message: string; kind?: string; context?: unknown }
448
451
  export interface PostSsoInvitesClearRequest { client_id: string; client_secret: string; github_login: string }
449
452
  export interface PostSsoInvitesNotifyRequest { client_id: string; client_secret: string; github_login: string }
450
453
  export interface PostSsoMembershipCheckInRequest { client_id: string; client_secret: string; github_id: StringifiableId; github_login: string; display_name?: string; avatar_url?: string; membership_kind?: string }
@@ -608,6 +611,8 @@ export interface BongosClient {
608
611
  postAutonomyFenceGoals(args: RequestArgs & { body: PostAutonomyFenceGoalsRequest }): Promise<PostAutonomyFenceGoalsResponse>;
609
612
  /** DELETE /autonomy/fence/goals/{goalId} — rank: archon */
610
613
  deleteAutonomyFenceGoalsGoalId(args?: RequestArgs): Promise<ApiResponse>;
614
+ /** POST /autonomy/fence/priority — rank: archon */
615
+ postAutonomyFencePriority(args?: RequestArgs & { body?: PostAutonomyFencePriorityRequest }): Promise<ApiResponse>;
611
616
  /** POST /autonomy/heartbeat — rank: any-builder */
612
617
  postAutonomyHeartbeat(args: RequestArgs & { body: PostAutonomyHeartbeatRequest }): Promise<PostAutonomyHeartbeatResponse>;
613
618
  /** GET /autonomy/precheck — rank: metic+archon */
@@ -799,6 +804,10 @@ export interface BongosClient {
799
804
  /** GET /done-when/pending-review — rank: metic+archon */
800
805
  getDoneWhenPendingReview(args?: RequestArgs): Promise<GetDoneWhenPendingReviewResponse>;
801
806
  };
807
+ "feedback": {
808
+ /** POST /feedback — rank: any-builder */
809
+ postFeedback(args: RequestArgs & { body: PostFeedbackRequest }): Promise<ApiResponse>;
810
+ };
802
811
  "gateApprovals": {
803
812
  /** GET /gate-approvals — rank: metic+archon */
804
813
  getGateApprovals(args?: RequestArgs): Promise<ApiResponse>;
@@ -1450,6 +1459,8 @@ export interface BongosClient {
1450
1459
  postSsoDevicePoll(args: RequestArgs & { body: PostSsoDevicePollRequest }): Promise<ApiResponse>;
1451
1460
  /** POST /sso/device/start — rank: public */
1452
1461
  postSsoDeviceStart(args: RequestArgs & { body: PostSsoDeviceStartRequest }): Promise<ApiResponse>;
1462
+ /** POST /sso/feedback — rank: public */
1463
+ postSsoFeedback(args: RequestArgs & { body: PostSsoFeedbackRequest }): Promise<ApiResponse>;
1453
1464
  /** POST /sso/invites/clear — rank: public */
1454
1465
  postSsoInvitesClear(args: RequestArgs & { body: PostSsoInvitesClearRequest }): Promise<ApiResponse>;
1455
1466
  /** POST /sso/invites/notify — rank: public */
@@ -173,6 +173,8 @@ export function createClient(opts = {}) {
173
173
  postAutonomyFenceGoals: (args) => request("POST", "/autonomy/fence/goals", { hasBody: true }, args),
174
174
  // DELETE /autonomy/fence/goals/{goalId} — rank: archon — DELETE /autonomy/fence/goals/:goalId
175
175
  deleteAutonomyFenceGoalsGoalId: (args) => request("DELETE", "/autonomy/fence/goals/{goalId}", { hasBody: false }, args),
176
+ // POST /autonomy/fence/priority — rank: archon — POST /autonomy/fence/priority
177
+ postAutonomyFencePriority: (args) => request("POST", "/autonomy/fence/priority", { hasBody: true }, args),
176
178
  // POST /autonomy/heartbeat — rank: any-builder — POST /autonomy/heartbeat
177
179
  postAutonomyHeartbeat: (args) => request("POST", "/autonomy/heartbeat", { hasBody: true }, args),
178
180
  // GET /autonomy/precheck — rank: metic+archon — GET /autonomy/precheck
@@ -364,6 +366,10 @@ export function createClient(opts = {}) {
364
366
  // GET /done-when/pending-review — rank: metic+archon — GET /done-when/pending-review
365
367
  getDoneWhenPendingReview: (args) => request("GET", "/done-when/pending-review", { hasBody: false }, args),
366
368
  },
369
+ "feedback": {
370
+ // POST /feedback — rank: any-builder — POST /feedback
371
+ postFeedback: (args) => request("POST", "/feedback", { hasBody: true }, args),
372
+ },
367
373
  "gateApprovals": {
368
374
  // GET /gate-approvals — rank: metic+archon — GET /gate-approvals
369
375
  getGateApprovals: (args) => request("GET", "/gate-approvals", { hasBody: false }, args),
@@ -1015,6 +1021,8 @@ export function createClient(opts = {}) {
1015
1021
  postSsoDevicePoll: (args) => request("POST", "/sso/device/poll", { hasBody: true }, args),
1016
1022
  // POST /sso/device/start — rank: public — POST /sso/device/start
1017
1023
  postSsoDeviceStart: (args) => request("POST", "/sso/device/start", { hasBody: true }, args),
1024
+ // POST /sso/feedback — rank: public — POST /sso/feedback
1025
+ postSsoFeedback: (args) => request("POST", "/sso/feedback", { hasBody: true }, args),
1018
1026
  // POST /sso/invites/clear — rank: public — POST /sso/invites/clear
1019
1027
  postSsoInvitesClear: (args) => request("POST", "/sso/invites/clear", { hasBody: true }, args),
1020
1028
  // POST /sso/invites/notify — rank: public — POST /sso/invites/notify
@@ -1,7 +1,7 @@
1
1
  # ADR 0136 — Update-channel subscription policy (patch-only, health-gated, opt-in, autonomy-gated)
2
2
 
3
3
  **Date:** 2026-07-10
4
- **Status:** Accepted.
4
+ **Status:** Accepted. Amended by [ADR 0357](0357-the-update-rule-set-on-deploy-is-the-one-the-sweep-follows.md) (2026-09-30): a project's channel is now its `provisioning_instances.update_channel`, set on /deploy; the roster's `channel` is only the fallback.
5
5
  **Context:** [task 2150](https://example.com/builders#/task/2150) (BONGOS-V1, goal 26). The last piece of the update-consumption workstream: [ADR 0100](0100-two-repo-instance-model.md) §2 / [task 1690](https://example.com/builders#/task/1690) gave a consumer the manual `bongos upgrade` channel; [ADR 0134](0134-private-first-npm-distribution.md) / [task 2090](https://example.com/builders#/task/2090) added the private-registry source; [task 2149](https://example.com/builders#/task/2149) added auto-rollback; [task 2157](https://example.com/builders#/task/2157) proved rollback live on the demo instance. What was missing is the **subscription** — how a consumer instance takes new releases *on a cadence, unattended*, rather than a human running `bongos upgrade` each time. Builds on the scheduled-routines portability contract ([ADR 0115](0115-scheduled-routines-portability.md)).
6
6
 
7
7
  ## Problem
@@ -0,0 +1,41 @@
1
+ # ADR 0357 — The update rule set on /deploy is the one the sweep follows
2
+
3
+ - **Status:** accepted
4
+ - **Date:** 2026-09-30
5
+ - **Task:** [task 1004468](https://cloudbongos.com/builders#/task/1004468) (goal 1000090, BONGOS-V2)
6
+ - **Amends:** [ADR 0136](0136-update-channel-subscription-policy.md), "Alternatives considered" (a `provisioning_instances` column for the channel) and its Consequences line naming `config/update-subscriptions.json` as the one place a channel is set
7
+ - **Builds on:** [task 1004445](https://cloudbongos.com/builders#/task/1004445) (migration provisioning_029, `POST /provisioning/instances/:id/update-channel`), [ADR 0293](0293-the-owners-deploy-door-is-an-intent-the-control-plane-drains.md) (the deploy door)
8
+ - **Decided with:** the owner, 2026-09-30. Asked "which one decides how far a project auto-updates, the site setting or the server file?", they chose the site setting.
9
+
10
+ ## Context
11
+
12
+ ADR 0136 put each subscribed instance's update channel (`pinned` / `patch` / `minor`) in the roster file `config/update-subscriptions.json`, and it rejected a `provisioning_instances` column because the fleet registry was not yet designed. By the time of [ADR 0325](0325-the-managed-fleet-control-plane-is-the-hub-we-already-run.md), `provisioning_instances` *was* the registry. Task 1004445 then added `update_channel` to it, so the owner could set the rule on /deploy, and the deploy door's runner obeys it.
13
+
14
+ That left two rules for one project. On 2026-09-30 cloudbongos.com was set to `minor` on /deploy and still `patch` in the box roster. The button followed the first and the unattended sweep the second, so a step-up release (1.20 → 1.21) would never land unattended even though /deploy said it would. Task 1004451's proof was graded down for exactly this.
15
+
16
+ ## Decision
17
+
18
+ **D1. The project row is the rule.** For a roster entry whose `slug` matches a `provisioning_instances` row, the sweep uses that row's `update_channel`. The match is by slug, the only stable key the table carries (it records no directory).
19
+
20
+ **D2. The roster's `channel` is a fallback, not a second vote.** It applies only when no row matches (an instance the control plane never provisioned) or when the sweep cannot read the database. The roster keeps everything else it holds — `dir`, service, health URL, topology, `env`, pin mode — because the registry doesn't record those.
21
+
22
+ **D3. Every fallback says so.** The sweep prints each entry's channel and where it came from ("set on /deploy", or "from the roster — <reason>"). When the row overrides a different roster value, the log names the ignored value too. A silent fallback is how two rules drifted apart in the first place.
23
+
24
+ **D4. It reads the control plane's database, over psql, from the sweep's own environment** — `DATABASE_URL`, else `PGDATABASE` (socket + peer auth). These are the two variables `upgrade.js` `recordLedger` reads. Unlike recordLedger, it hands a `DATABASE_URL` to `psql -d` rather than the pg driver, because the sweep is synchronous. An entry's `env` is never used, because it names *that instance's* database. A core too old to carry the reader keeps the roster behaviour unchanged. A failure is logged as a fixed class (unreachable, login refused, table missing…), never psql's own text, which can name a user or host.
25
+
26
+ **D1a. Why not slug *or* directory.** The task brief suggested matching by slug or dir. `provisioning_instances` stores no directory, so there is nothing to match a dir against, and a roster slug that differs from its row's slug falls back to the roster, visibly (D3).
27
+
28
+ **D5. Nothing is migrated or copied.** Every row already has a channel (the column defaults to `patch`, the old behaviour). So once this is live, an entry the roster listed as `minor` but whose row was never changed on /deploy is swept as `patch`. That is the ruling applied, not a regression, and D3 makes it visible in the log.
29
+
30
+ ## Consequences
31
+
32
+ - One place to change how far a project auto-updates, on the site, with no SSH.
33
+ - ADR 0136's policy is otherwise unchanged: majors and prereleases are never automatic, every move is health-gated with auto-rollback, and the routine stays opt-in and autonomy-gated. Enrollment itself (which instances the sweep touches, and where they live) is still the roster.
34
+ - **Delivery depends on the sweep running current code.** On cloudbongos.com the sweep runs from a checkout frozen at 2026-08-25 ([task 1004307](https://cloudbongos.com/builders#/task/1004307)). Until that is fixed, or the checkout is updated, a release carrying this change does not reach the sweep.
35
+ - The rule is now testable in isolation: `tests/update_channel_db.mjs`.
36
+
37
+ ## Alternatives considered
38
+
39
+ - **Keep the roster in charge (ADR 0136 as written).** Rejected by the owner: changing the unattended behaviour would stay an SSH edit, and /deploy would keep showing a setting the sweep ignores.
40
+ - **Take the stricter of the two.** Rejected: safe, but setting `minor` on the site would do nothing until someone also edited the file, which is the same confusion in a new form.
41
+ - **Copy the roster's channels into the rows first.** Rejected: the rows already hold the owner's deliberate choices (cloudbongos = `minor`), and a copy would overwrite a newer decision with an older file.
@@ -475,3 +475,4 @@ These 20 numbers are each shared by exactly two files. They are **accepted histo
475
475
  | 0354 | [**A builder hosts one project for free, and more takes the fleet permission** ([task 1004412](https://cloudbongos.com/builders#/task/1004412), goal 1000106 — working area 1, the owner's ruling of 2026-09-30). The create wizard always asks for `cloud-host`, which task 1003370 had gated behind `provisioning.fleet.manage`, so every new (Xenos) user was refused at "Create my project" — against ADR 0345 decision 1. **D1:** a builder's first live `cloud-host` project needs no permission; a further one needs the fleet permission (a retry of your own slug is the same project; only `torn_down` frees the place; an unreadable count refuses). **D2:** one first-free request per builder at a time (409 `create_in_progress`), held as a Postgres advisory lock so it holds across processes. **D3:** the wizard states `permission_forbidden` and `box_full` in plain words. Nothing yet caps a hosted project's memory.](0354-a-builder-hosts-one-project-free-and-more-takes-the-fleet-permission.md) | provisioning / security / project creation |
476
476
  | 0355 | [**A soft limit is a rule with a reason, and nobody enforces it** ([task 1004416](https://cloudbongos.com/builders#/task/1004416), goal 1000121 — BV2.PS02). The startup flow's seven planet-physics answers and what they rule out. **D1:** the answers are more provisioning `detail` keys under `team_shape`'s contract (no defaults, refused loudly, `null` un-answers), with two new kinds — a list (`many`) and a whole number (`count`); the country is a closed ISO list. **D2:** answers must agree only within one request, so a merge patch's edit order never matters. **D3:** one declarative soft-limit table (`soft-limits.js`) — data conditions, `hide`/`grey`/`note`, a reason on every rule — and every resolution says `enforced: false`. **D4:** screening is a seam (`screening.js`) with a deliberately small rule set; a stop is 422 `screened_out` before anything exists. **D5:** the edit route screens a new description too.](0355-a-soft-limit-is-a-rule-with-a-reason-and-nobody-enforces-it.md) | provisioning / project startup |
477
477
  | 0356 | [**A recruit invite expires 30 days after it is sent, decided at read time** ([task 1002969](https://cloudbongos.com/builders#/task/1002969), goal 1000110 — privacy spec D4, owner-signed). **D1:** one definition, `src/bongos/invite-expiry.js` (`INVITE_EXPIRY_DAYS` + the SQL), read by the sign-in gate, the waiting-page probe, the onboarding routes and, through the doorway's `inviteExpiry`, the hub. Nothing is stored and nothing sweeps. **D2:** only `kind='invite'` rows expire; approved applications and goal invites do not. **D3:** amends ADR 0335 D2.5: the gate reads `kind` only inside the expiry unit, which can close a door and never open one. **D4:** an expired invite is refused, marked `expired` + `expires_at` in the queues, reported `expired` by the status probe (the CLI stops), and replaced by a re-invite's fresh row. **D5:** the hub hides a `pending` notice past 30 days and a re-invite restamps it. Split out: `seen_at` (task 1004443), the decline relay (task 1004444).](0356-a-recruit-invite-expires-30-days-after-it-is-sent-read-time.md) | platform identity / admission / invites |
478
+ | 0357 | [**The update rule set on /deploy is the one the sweep follows** ([task 1004468](https://cloudbongos.com/builders#/task/1004468), goal 1000090 — BONGOS-V2, owner's ruling 2026-09-30). Amends [ADR 0136](0136-update-channel-subscription-policy.md)'s rejected DB-column alternative. **D1:** for a roster entry whose slug matches a `provisioning_instances` row, the unattended sweep uses that row's `update_channel` (set on /deploy, task 1004445). **D2:** the roster's `channel` is only the fallback — no matching row, or the database unreadable; enrollment and topology stay in the roster. **D3:** the sweep logs each entry's channel and its source, naming an overridden roster value. **D4:** read over psql from the sweep's own `DATABASE_URL`/`PGDATABASE`, never an entry's `env`. **D5:** nothing is copied; a row never changed is `patch`. Delivery to cloudbongos.com waits on the frozen sweep checkout (task 1004307). Rejected: roster stays in charge; stricter-of-the-two; copying roster values into rows.](0357-the-update-rule-set-on-deploy-is-the-one-the-sweep-follows.md) | distribution / updates |
@@ -121,6 +121,10 @@
121
121
  "name": "done-when",
122
122
  "description": "Endpoints under `/api/bongos/done-when`."
123
123
  },
124
+ {
125
+ "name": "feedback",
126
+ "description": "Endpoints under `/api/bongos/feedback`."
127
+ },
124
128
  {
125
129
  "name": "gate-approvals",
126
130
  "description": "Endpoints under `/api/bongos/gate-approvals`."
@@ -1890,6 +1894,51 @@
1890
1894
  ]
1891
1895
  }
1892
1896
  },
1897
+ "/autonomy/fence/priority": {
1898
+ "post": {
1899
+ "operationId": "post_autonomy_fence_priority",
1900
+ "tags": [
1901
+ "autonomy"
1902
+ ],
1903
+ "summary": "POST /autonomy/fence/priority",
1904
+ "description": "The priority goal (task 1004453): which allowlisted goal the runner works first. Same gate as the allowlist — choosing what an unattended machine does first is part of choosing what it may do. The goal must already be on the allowlist (409 otherwise), so a priority can order the list and never widen it. `goal_id: null` clears it.\n\n**Rank:** `archon` — Archon only (rank and identity management + the escalation keys — the trust boundary).\n\n**Permissions:** `autonomy.fence.manage` (all required).",
1905
+ "x-rank": "archon",
1906
+ "x-source": "modules/autonomy/routes/autonomy.js",
1907
+ "x-permissions": [
1908
+ "autonomy.fence.manage"
1909
+ ],
1910
+ "requestBody": {
1911
+ "required": false,
1912
+ "content": {
1913
+ "application/json": {
1914
+ "schema": {
1915
+ "$ref": "#/components/schemas/PostAutonomyFencePriorityRequest"
1916
+ }
1917
+ }
1918
+ },
1919
+ "x-validated": true
1920
+ },
1921
+ "responses": {
1922
+ "200": {
1923
+ "description": "Success."
1924
+ },
1925
+ "400": {
1926
+ "$ref": "#/components/responses/ValidationFailed"
1927
+ },
1928
+ "401": {
1929
+ "$ref": "#/components/responses/Unauthorized"
1930
+ },
1931
+ "403": {
1932
+ "$ref": "#/components/responses/Forbidden"
1933
+ }
1934
+ },
1935
+ "security": [
1936
+ {
1937
+ "builderSession": []
1938
+ }
1939
+ ]
1940
+ }
1941
+ },
1893
1942
  "/autonomy/heartbeat": {
1894
1943
  "post": {
1895
1944
  "operationId": "post_autonomy_heartbeat",
@@ -5637,6 +5686,48 @@
5637
5686
  ]
5638
5687
  }
5639
5688
  },
5689
+ "/feedback": {
5690
+ "post": {
5691
+ "operationId": "post_feedback",
5692
+ "tags": [
5693
+ "feedback"
5694
+ ],
5695
+ "summary": "POST /feedback",
5696
+ "description": "signed-in builder — reporting a problem with Bongos grants nothing here, and the hub files every report at 'backlog' behind a Metic+ nod.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
5697
+ "x-rank": "any-builder",
5698
+ "x-source": "src/bongos/routes/feedback.js",
5699
+ "requestBody": {
5700
+ "required": true,
5701
+ "content": {
5702
+ "application/json": {
5703
+ "schema": {
5704
+ "$ref": "#/components/schemas/PostFeedbackRequest"
5705
+ }
5706
+ }
5707
+ },
5708
+ "x-validated": true
5709
+ },
5710
+ "responses": {
5711
+ "200": {
5712
+ "description": "Success."
5713
+ },
5714
+ "400": {
5715
+ "$ref": "#/components/responses/ValidationFailed"
5716
+ },
5717
+ "401": {
5718
+ "$ref": "#/components/responses/Unauthorized"
5719
+ },
5720
+ "403": {
5721
+ "$ref": "#/components/responses/Forbidden"
5722
+ }
5723
+ },
5724
+ "security": [
5725
+ {
5726
+ "builderSession": []
5727
+ }
5728
+ ]
5729
+ }
5730
+ },
5640
5731
  "/gate-approvals": {
5641
5732
  "get": {
5642
5733
  "operationId": "get_gate_approvals",
@@ -18773,6 +18864,38 @@
18773
18864
  "security": []
18774
18865
  }
18775
18866
  },
18867
+ "/sso/feedback": {
18868
+ "post": {
18869
+ "operationId": "post_sso_feedback",
18870
+ "tags": [
18871
+ "sso"
18872
+ ],
18873
+ "summary": "POST /sso/feedback",
18874
+ "description": "POST /sso/feedback — a federated project relays one builder's feedback about Bongos itself (task 1004462). A bug becomes a 'backlog' task in the building version's maintenance goal; an idea becomes an inbox row. Why always backlog, and why the sender must be a witnessed member: ../instance-feedback.js. rank: public — authenticated by client_id + client_secret, not a builder rank. The per-project and per-sender caps run after the client check, so an unauthenticated caller cannot spend a real project's allowance.\n\n**Rank:** `public` — No authentication — any caller.",
18875
+ "x-rank": "public",
18876
+ "x-source": "modules/platform-identity/routes/sso.js",
18877
+ "requestBody": {
18878
+ "required": true,
18879
+ "content": {
18880
+ "application/json": {
18881
+ "schema": {
18882
+ "$ref": "#/components/schemas/PostSsoFeedbackRequest"
18883
+ }
18884
+ }
18885
+ },
18886
+ "x-validated": true
18887
+ },
18888
+ "responses": {
18889
+ "200": {
18890
+ "description": "Success."
18891
+ },
18892
+ "400": {
18893
+ "$ref": "#/components/responses/ValidationFailed"
18894
+ }
18895
+ },
18896
+ "security": []
18897
+ }
18898
+ },
18776
18899
  "/sso/invites/clear": {
18777
18900
  "post": {
18778
18901
  "operationId": "post_sso_invites_clear",
@@ -25188,6 +25311,15 @@
25188
25311
  "goal"
25189
25312
  ]
25190
25313
  },
25314
+ "PostAutonomyFencePriorityRequest": {
25315
+ "type": "object",
25316
+ "properties": {
25317
+ "goal_id": {
25318
+ "$ref": "#/components/schemas/StringifiableId"
25319
+ }
25320
+ },
25321
+ "additionalProperties": false
25322
+ },
25191
25323
  "PostAutonomyFenceRequest": {
25192
25324
  "type": "object",
25193
25325
  "properties": {
@@ -25232,6 +25364,9 @@
25232
25364
  },
25233
25365
  "working_task_id": {
25234
25366
  "type": "number"
25367
+ },
25368
+ "working_goal_id": {
25369
+ "type": "number"
25235
25370
  }
25236
25371
  },
25237
25372
  "required": [
@@ -25977,6 +26112,27 @@
25977
26112
  "criterion"
25978
26113
  ]
25979
26114
  },
26115
+ "PostFeedbackRequest": {
26116
+ "type": "object",
26117
+ "properties": {
26118
+ "message": {
26119
+ "type": "string",
26120
+ "maxLength": 4000
26121
+ },
26122
+ "kind": {
26123
+ "type": "string",
26124
+ "enum": [
26125
+ "bug",
26126
+ "idea"
26127
+ ]
26128
+ },
26129
+ "context": {}
26130
+ },
26131
+ "required": [
26132
+ "message"
26133
+ ],
26134
+ "additionalProperties": false
26135
+ },
25980
26136
  "PostGateApprovalsPrApproveResponse": {
25981
26137
  "type": "object",
25982
26138
  "properties": {
@@ -28652,6 +28808,36 @@
28652
28808
  ],
28653
28809
  "additionalProperties": false
28654
28810
  },
28811
+ "PostSsoFeedbackRequest": {
28812
+ "type": "object",
28813
+ "properties": {
28814
+ "client_id": {
28815
+ "type": "string",
28816
+ "maxLength": 200
28817
+ },
28818
+ "client_secret": {
28819
+ "type": "string",
28820
+ "maxLength": 512
28821
+ },
28822
+ "github_id": {
28823
+ "$ref": "#/components/schemas/StringifiableId"
28824
+ },
28825
+ "message": {
28826
+ "type": "string"
28827
+ },
28828
+ "kind": {
28829
+ "type": "string"
28830
+ },
28831
+ "context": {}
28832
+ },
28833
+ "required": [
28834
+ "client_id",
28835
+ "client_secret",
28836
+ "github_id",
28837
+ "message"
28838
+ ],
28839
+ "additionalProperties": false
28840
+ },
28655
28841
  "PostSsoInvitesClearRequest": {
28656
28842
  "type": "object",
28657
28843
  "properties": {
@@ -29812,8 +29998,8 @@
29812
29998
  "description": "A required dependency/feature is not configured or is temporarily down."
29813
29999
  }
29814
30000
  },
29815
- "x-endpoint-count": 466,
29816
- "x-schema-count": 498,
30001
+ "x-endpoint-count": 469,
30002
+ "x-schema-count": 501,
29817
30003
  "x-undocumented-bodies": 12,
29818
30004
  "x-response-schemas": 337,
29819
30005
  "x-generated-by": "scripts/gds/gen-api-docs.js"
@@ -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. 466 endpoints across 83 route files.
5
+ > **Generated from the live route files** — the route file is authoritative. 469 endpoints across 84 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/0016-trust-boundary-server-enforced-permissions.md)): `public` < `any-builder` < `metic+archon` < `archon`.
@@ -81,7 +81,7 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/0016-trust
81
81
  | GET | `/api/bongos/auth/web/handoff` | `public` | — | GET /auth/web/handoff?code=&return= — the far side of the one-time session handoff (task 1004357). |
82
82
  | GET | `/api/bongos/auth/web/start` | `public` | — | /auth/web — browser flow (used by the /builders page). |
83
83
 
84
- ## `autonomy` (8)
84
+ ## `autonomy` (9)
85
85
 
86
86
  | Method | Path | Rank | Body | Description |
87
87
  |---|---|---|---|---|
@@ -89,7 +89,8 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/0016-trust
89
89
  | POST | `/api/bongos/autonomy/fence` | `archon` | `enabled`, `reason` | The kill switch. |
90
90
  | POST | `/api/bongos/autonomy/fence/goals` | `archon` | `goal_id`, `note` | Add a goal to the allowlist. |
91
91
  | DELETE | `/api/bongos/autonomy/fence/goals/:goalId` | `archon` | — | Revoke one. |
92
- | POST | `/api/bongos/autonomy/heartbeat` | `any-builder` | `host`, `pid`, `started_at`, `mode`, `consecutive_failures`, `last_event`, `working_task_id` | The runner's check-in, once per loop. |
92
+ | POST | `/api/bongos/autonomy/fence/priority` | `archon` | `goal_id` | The priority goal (task 1004453): which allowlisted goal the runner works first. |
93
+ | POST | `/api/bongos/autonomy/heartbeat` | `any-builder` | `host`, `pid`, `started_at`, `mode`, `consecutive_failures`, `last_event`, `working_task_id`, `working_goal_id` | The runner's check-in, once per loop. |
93
94
  | GET | `/api/bongos/autonomy/precheck` | `metic+archon` | — | |
94
95
  | GET | `/api/bongos/autonomy/runners` | `any-builder` | — | What the hall renders: the CALLER'S OWN runners, with the pure verdict attached so the page and any future alert cannot disagree about wh… |
95
96
  | GET | `/api/bongos/autonomy/runs` | `metic+archon` | — | The gate's past decisions — did a routine fire, and what did it decide, and why (task 1002669). |
@@ -249,6 +250,12 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/0016-trust
249
250
  | POST | `/api/bongos/done-when/:criterionId/unsatisfy` | `metic+archon` | — | Auth: flip a criterion back to unsatisfied (rare; for corrections). |
250
251
  | GET | `/api/bongos/done-when/pending-review` | `metic+archon` | — | Auth (Metic+): the criterion review queue — every criterion auto-flagged "met — pending review" (≥1 linked task, all shipped, not yet con… |
251
252
 
253
+ ## `feedback` (1)
254
+
255
+ | Method | Path | Rank | Body | Description |
256
+ |---|---|---|---|---|
257
+ | POST | `/api/bongos/feedback` | `any-builder` | `message`, `kind`, `context` | signed-in builder — reporting a problem with Bongos grants nothing here, and the hub files every report at 'backlog' behind a Metic+ nod. |
258
+
252
259
  ## `gate-approvals` (2)
253
260
 
254
261
  | Method | Path | Rank | Body | Description |
@@ -721,7 +728,7 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/0016-trust
721
728
  | GET | `/api/bongos/specialities/installed-skills` | `any-builder` | — | GET /specialities/installed-skills — every skill THIS instance has, each explained the way the adoption walkthrough explains it, so a spe… |
722
729
  | GET | `/api/bongos/specialities/offered` | `any-builder` | — | GET /specialities/offered — the suggestions for THIS builder. |
723
730
 
724
- ## `sso` (10)
731
+ ## `sso` (11)
725
732
 
726
733
  | Method | Path | Rank | Body | Description |
727
734
  |---|---|---|---|---|
@@ -730,6 +737,7 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/0016-trust
730
737
  | GET | `/api/bongos/sso/authorize` | `public` | — | GET /sso/authorize?client_id=&redirect_uri=&state= — the browser authorize leg. |
731
738
  | POST | `/api/bongos/sso/device/poll` | `public` | `device_code` | POST /sso/device/poll — poll the hub device flow. |
732
739
  | POST | `/api/bongos/sso/device/start` | `public` | `origin` | POST /sso/device/start — begin CLI federation. |
740
+ | POST | `/api/bongos/sso/feedback` | `public` | `client_id`, `client_secret`, `github_id`, `message`, `kind`, `context` | POST /sso/feedback — a federated project relays one builder's feedback about Bongos itself (task 1004462). |
733
741
  | POST | `/api/bongos/sso/invites/clear` | `public` | `client_id`, `client_secret`, `github_login` | authenticated by client_id + client_secret, not a builder rank. |
734
742
  | POST | `/api/bongos/sso/invites/notify` | `public` | `client_id`, `client_secret`, `github_login` | authenticated by client_id + client_secret, not a builder rank. |
735
743
  | POST | `/api/bongos/sso/membership/check-in` | `public` | `client_id`, `client_secret`, `github_id`, `github_login`, `display_name`, `avatar_url`, `membership_kind` | POST /sso/membership/check-in — a federated instance reports, on every sign-in, that a builder builds on its project (ADR 0141 §3). |
@@ -164,10 +164,10 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
164
164
  | `bea7817e57a4` | certain | All surfaces | `modules/hall-ui/public/copy-desk.js:301` |
165
165
  | `627c683a5e5d` | certain | All time | `modules/hall-ui/public/hall-widgets.js:130` |
166
166
  | `b38c01691857` | certain | All your work → | `modules/hall-ui/public/hall-widgets.js:110` |
167
- | `efa803555625` | certain | Allow goal | `modules/hall-ui/public/gate.js:288` |
167
+ | `efa803555625` | certain | Allow goal | `modules/hall-ui/public/gate.js:303` |
168
168
  | `375b0e67bc30` | certain | Allow new releases and move to {…} | `modules/hall-ui/public/deploy.js:249` |
169
169
  | `375b0e67bc30` | certain | Allow new releases and move to {…} | `modules/hall-ui/public/deploy.js:677` |
170
- | `86ea8d57d34e` | certain | Allowlisted goals | `modules/hall-ui/public/gate.js:286` |
170
+ | `86ea8d57d34e` | certain | Allowlisted goals | `modules/hall-ui/public/gate.js:300` |
171
171
  | `e99cc5d37404` | certain | Already a member? | `modules/hall-ui/public/hall-render.js:367` |
172
172
  | `da5368d10f85` | certain | Amendment {…} passed{…}, and the constitution below is not the one it decided: | `modules/hall-ui/public/government.js:633` |
173
173
  | `2ca420e19dbb` | certain | An earlier attempt did not land. | `modules/hall-ui/public/deploy.js:366` |
@@ -249,7 +249,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
249
249
  | `906c2947dfc1` | certain | Changes save at once and take effect the next time you start a session on this machine. | `modules/hall-ui/public/settings.html:346` |
250
250
  | `52384bdc035c` | certain | Changes save at once. Your new choice plays the next time that event fires. | `modules/hall-ui/public/settings.html:359` |
251
251
  | `cab7a9526ca1` | certain | Changes save the moment you pick. “Default” clears your override and falls back to the system's choice. | `modules/hall-ui/public/settings.html:329` |
252
- | `4b714191b423` | certain | Changes touching protected build surfaces, held for your approval. | `modules/hall-ui/public/gate.js:403` |
252
+ | `4b714191b423` | certain | Changes touching protected build surfaces, held for your approval. | `modules/hall-ui/public/gate.js:432` |
253
253
  | `864503935eca` | certain | Changing the rule… | `modules/hall-ui/public/deploy.js:671` |
254
254
  | `55ad21bd03eb` | certain | Chart the routes | `modules/hall-ui/public/goal-map.html:91` |
255
255
  | `55ad21bd03eb` | certain | Chart the routes | `modules/hall-ui/public/thinking.html:108` |
@@ -430,7 +430,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
430
430
  | `8d2b4f119ee3` | certain | End session | `modules/hall-ui/public/settings-sessions.js:46` |
431
431
  | `8e82771e5b63` | certain | Ending a session takes effect immediately; the token stops working on its very next request. | `modules/hall-ui/public/settings.html:163` |
432
432
  | `58d381535285` | certain | Engagement reports | `modules/hall-ui/public/watch.html:130` |
433
- | `690609c8e9a9` | certain | Enter a goal number. | `modules/hall-ui/public/gate.js:300` |
433
+ | `690609c8e9a9` | certain | Enter a goal number. | `modules/hall-ui/public/gate.js:315` |
434
434
  | `1825c9c467d8` | certain | Enter the id of the task this one should wait for. | `modules/hall-ui/public/task.js:928` |
435
435
  | `bd7a40639a1c` | certain | Estimate (min) | `modules/hall-ui/public/task-detail.js:460` |
436
436
  | `c15d1f0ddfb6` | certain | Estimation accuracy | `modules/hall-ui/public/watch.html:148` |
@@ -506,9 +506,9 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
506
506
  | `9e70797b7e97` | certain | Goal id | `modules/hall-ui/public/goals-render.js:832` |
507
507
  | `529460e82058` | certain | Goal invitations to you | `modules/hall-ui/public/goal-inbox.js:150` |
508
508
  | `e2a9e33abe60` | certain | Goal tasks | `modules/hall-ui/public/goals.html:151` |
509
- | `ec88b946ad16` | certain | Goal {…} | `modules/hall-ui/public/gate.js:280` |
510
- | `7b02827535c2` | certain | Goal {…} allowlisted. | `modules/hall-ui/public/gate.js:303` |
511
- | `8a421ae268e6` | certain | Goal {…} removed. | `modules/hall-ui/public/gate.js:313` |
509
+ | `ec88b946ad16` | certain | Goal {…} | `modules/hall-ui/public/gate.js:288` |
510
+ | `7b02827535c2` | certain | Goal {…} allowlisted. | `modules/hall-ui/public/gate.js:318` |
511
+ | `8a421ae268e6` | certain | Goal {…} removed. | `modules/hall-ui/public/gate.js:341` |
512
512
  | `e0bc28d10785` | certain | Goals could not be loaded. Refresh to try again. | `modules/hall-ui/public/goals-page.js:893` |
513
513
  | `4517f2253d0f` | certain | Goals couldn’t be loaded just now. Refresh to try again. | `modules/hall-ui/public/goals.js:121` |
514
514
  | `6a85997bda21` | certain | Goals created | `modules/hall-ui/public/profile.html:145` |
@@ -1438,7 +1438,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
1438
1438
  | `6b530a7007bc` | certain | jump to a goal or a thought | `modules/hall-ui/public/goal-map.html:75` |
1439
1439
  | `6b530a7007bc` | certain | jump to a goal or a thought | `modules/hall-ui/public/thinking.html:92` |
1440
1440
  | `9328033a890a` | certain | land every shuttle | `modules/hall-ui/public/sky-interaction.js:45` |
1441
- | `966b32c8af7e` | certain | last check-in {…} ago | `modules/hall-ui/public/gate.js:360` |
1441
+ | `966b32c8af7e` | certain | last check-in {…} ago | `modules/hall-ui/public/gate.js:391` |
1442
1442
  | `9018bf6e99eb` | certain | last used {…} · signed in {…} | `modules/hall-ui/public/settings-sessions.js:46` |
1443
1443
  | `2ce7738b1eb0` | certain | loading goals… | `modules/hall-ui/public/task-detail.js:482` |
1444
1444
  | `754bdec368ed` | certain | lowest credits | `modules/hall-ui/public/hall-widgets.js:136` |
@@ -1594,7 +1594,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
1594
1594
  | `81f05d9b2bbf` | certain | what's wrong, or what you'd like to see | `modules/hall-ui/public/ideas.html:65` |
1595
1595
  | `c3959ea9d43b` | certain | where my thoughts are | `modules/hall-ui/public/sky-layout.js:50` |
1596
1596
  | `1651cb1876f5` | certain | who sits on the board | `modules/hall-ui/public/government.html:55` |
1597
- | `57f45f7812ba` | certain | why (optional) | `modules/hall-ui/public/gate.js:288` |
1597
+ | `57f45f7812ba` | certain | why (optional) | `modules/hall-ui/public/gate.js:303` |
1598
1598
  | `143f77e2b782` | certain | why these are the same | `modules/hall-ui/public/task-detail.js:565` |
1599
1599
  | `ec7c228cb4ce` | certain | why this isn’t worth doing | `modules/hall-ui/public/task-detail.js:616` |
1600
1600
  | `c612ab426c2f` | certain | your sky | `modules/hall-ui/public/thinking.html:72` |
@@ -2976,7 +2976,7 @@
2976
2976
  "surface": "builders-hall",
2977
2977
  "text": "Allow goal",
2978
2978
  "file": "modules/hall-ui/public/gate.js",
2979
- "line": 288,
2979
+ "line": 303,
2980
2980
  "origin": "js-markup",
2981
2981
  "confidence": "certain"
2982
2982
  },
@@ -3003,7 +3003,7 @@
3003
3003
  "surface": "builders-hall",
3004
3004
  "text": "Allowlisted goals",
3005
3005
  "file": "modules/hall-ui/public/gate.js",
3006
- "line": 286,
3006
+ "line": 300,
3007
3007
  "origin": "js-markup",
3008
3008
  "confidence": "certain"
3009
3009
  },
@@ -3741,7 +3741,7 @@
3741
3741
  "surface": "builders-hall",
3742
3742
  "text": "Changes touching protected build surfaces, held for your approval.",
3743
3743
  "file": "modules/hall-ui/public/gate.js",
3744
- "line": 403,
3744
+ "line": 432,
3745
3745
  "origin": "js-text-assign",
3746
3746
  "confidence": "certain"
3747
3747
  },
@@ -5370,7 +5370,7 @@
5370
5370
  "surface": "builders-hall",
5371
5371
  "text": "Enter a goal number.",
5372
5372
  "file": "modules/hall-ui/public/gate.js",
5373
- "line": 300,
5373
+ "line": 315,
5374
5374
  "origin": "js-notice",
5375
5375
  "confidence": "certain"
5376
5376
  },
@@ -6054,7 +6054,7 @@
6054
6054
  "surface": "builders-hall",
6055
6055
  "text": "Goal {…}",
6056
6056
  "file": "modules/hall-ui/public/gate.js",
6057
- "line": 280,
6057
+ "line": 288,
6058
6058
  "origin": "js-markup",
6059
6059
  "confidence": "certain"
6060
6060
  },
@@ -6063,7 +6063,7 @@
6063
6063
  "surface": "builders-hall",
6064
6064
  "text": "Goal {…} allowlisted.",
6065
6065
  "file": "modules/hall-ui/public/gate.js",
6066
- "line": 303,
6066
+ "line": 318,
6067
6067
  "origin": "js-notice",
6068
6068
  "confidence": "certain"
6069
6069
  },
@@ -6072,7 +6072,7 @@
6072
6072
  "surface": "builders-hall",
6073
6073
  "text": "Goal {…} removed.",
6074
6074
  "file": "modules/hall-ui/public/gate.js",
6075
- "line": 313,
6075
+ "line": 341,
6076
6076
  "origin": "js-notice",
6077
6077
  "confidence": "certain"
6078
6078
  },
@@ -14442,7 +14442,7 @@
14442
14442
  "surface": "builders-hall",
14443
14443
  "text": "last check-in {…} ago",
14444
14444
  "file": "modules/hall-ui/public/gate.js",
14445
- "line": 360,
14445
+ "line": 391,
14446
14446
  "origin": "js-markup",
14447
14447
  "confidence": "certain"
14448
14448
  },
@@ -15846,7 +15846,7 @@
15846
15846
  "surface": "builders-hall",
15847
15847
  "text": "why (optional)",
15848
15848
  "file": "modules/hall-ui/public/gate.js",
15849
- "line": 288,
15849
+ "line": 303,
15850
15850
  "origin": "js-markup",
15851
15851
  "confidence": "certain"
15852
15852
  },