@bongos/core 1.25.15 → 1.25.17

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 (66) hide show
  1. package/.bongos-core.json +128 -58
  2. package/.claude/skills/goal-create/SKILL.md +1 -0
  3. package/.claude/skills/planning-session/SKILL.md +5 -4
  4. package/bin/bongos.js +1 -0
  5. package/clients/bongos-client/README.md +1 -1
  6. package/clients/bongos-client/bongos-client.global.js +14 -0
  7. package/clients/bongos-client/index.cjs +14 -0
  8. package/clients/bongos-client/index.d.ts +22 -2
  9. package/clients/bongos-client/index.mjs +14 -0
  10. package/docs/adr/0406-every-project-gets-a-sandbox-that-follows-main-and-live-moves-only-when-a-person-promotes.md +8 -0
  11. package/docs/adr/0408-a-genesis-stage-is-three-doors-onto-one-record.md +1 -0
  12. package/docs/api/openapi.json +415 -3
  13. package/docs/api-reference.md +13 -2
  14. package/docs/copy-inventory.md +120 -109
  15. package/docs/copy-registry.json +275 -165
  16. package/docs/module-api-changelog.md +4 -2
  17. package/docs/page-inventory.json +2 -0
  18. package/docs/page-readings.json +107 -107
  19. package/docs/project-context.template.md +1 -0
  20. package/modules/government/decision-rules.js +1 -0
  21. package/modules/hall-ui/public/dom-utils.js +5 -0
  22. package/modules/hall-ui/public/genesis-home.js +23 -8
  23. package/modules/hall-ui/public/setup-gate.js +1 -1
  24. package/modules/hall-ui/public/style.css +21 -1
  25. package/modules/lifecycle/first-read-db.js +152 -0
  26. package/modules/lifecycle/first-read.js +265 -0
  27. package/modules/lifecycle/kickoff-checklist.js +29 -6
  28. package/modules/lifecycle/kickoff-seed.js +27 -4
  29. package/modules/lifecycle/migrations/lifecycle_022_repo_maps.sql +44 -0
  30. package/modules/lifecycle/module.json +2 -1
  31. package/modules/lifecycle/routes/first-read.js +79 -0
  32. package/modules/onboarding/genesis-home.js +11 -2
  33. package/modules/onboarding/genesis-work.js +28 -5
  34. package/modules/provisioning/pollers/app-liveness.js +23 -1
  35. package/modules/provisioning/render-sandbox.js +113 -0
  36. package/modules/provisioning/render-standup.js +3 -1
  37. package/modules/provisioning/routes/provisioning.js +4 -1
  38. package/modules/provisioning/routes/render-standup.js +49 -1
  39. package/modules/public-landing/public/assets/guide-scene.css +245 -0
  40. package/modules/public-landing/public/assets/guide-scene.js +566 -0
  41. package/modules/public-landing/public/index.html +62 -2
  42. package/modules/public-landing/public/projects.html +101 -4
  43. package/package-lock.json +2 -2
  44. package/package.json +1 -1
  45. package/release-notes.json +23 -1
  46. package/scripts/bongos/first-read.js +116 -0
  47. package/scripts/bongos/genesis.js +2 -0
  48. package/scripts/bongos/government-walk.js +4 -4
  49. package/scripts/bongos/provision-render-sandbox.js +171 -0
  50. package/scripts/bongos/provision-render.js +37 -2
  51. package/scripts/bongos/provision-teardown.js +1 -1
  52. package/scripts/bongos/render-api.js +33 -3
  53. package/scripts/bongos/render-payload.js +39 -1
  54. package/scripts/gds/first-read.js +7 -0
  55. package/scripts/gds/provision-render-sandbox.js +6 -0
  56. package/src/module-api.js +1 -1
  57. package/tests/first_read.mjs +303 -0
  58. package/tests/genesis_home.mjs +70 -2
  59. package/tests/genesis_work.mjs +49 -0
  60. package/tests/government_act_alone_buildings.mjs +2 -0
  61. package/tests/landing_guide_scene.mjs +504 -0
  62. package/tests/provisioning_app_status.mjs +3 -2
  63. package/tests/provisioning_render_route.mjs +1 -1
  64. package/tests/provisioning_teardown_intent.mjs +50 -0
  65. package/tests/render_api.mjs +5 -2
  66. package/tests/render_sandbox.mjs +447 -0
@@ -468,6 +468,18 @@ function createClient(opts = {}) {
468
468
  // GET /feedback/receipt/{id} — rank: public — GET /feedback/receipt/:id
469
469
  getFeedbackReceiptId: (args) => request("GET", "/feedback/receipt/{id}", { hasBody: false }, args),
470
470
  },
471
+ "firstRead": {
472
+ // POST /first-read/maps — rank: metic+archon — POST /first-read/maps
473
+ postFirstReadMaps: (args) => request("POST", "/first-read/maps", { hasBody: true }, args),
474
+ // GET /first-read/maps/{id} — rank: metic+archon — GET /first-read/maps/:id
475
+ getFirstReadMapsId: (args) => request("GET", "/first-read/maps/{id}", { hasBody: false }, args),
476
+ // POST /first-read/maps/{id}/accept — rank: metic+archon — POST /first-read/maps/:id/accept
477
+ postFirstReadMapsIdAccept: (args) => request("POST", "/first-read/maps/{id}/accept", { hasBody: true }, args),
478
+ // POST /first-read/maps/{id}/reject — rank: metic+archon — POST /first-read/maps/:id/reject
479
+ postFirstReadMapsIdReject: (args) => request("POST", "/first-read/maps/{id}/reject", { hasBody: true }, args),
480
+ // GET /first-read/prompt — rank: any-builder — GET /first-read/prompt
481
+ getFirstReadPrompt: (args) => request("GET", "/first-read/prompt", { hasBody: false }, args),
482
+ },
471
483
  "founding": {
472
484
  // POST /founding/alive — rank: any-builder — POST /founding/alive
473
485
  postFoundingAlive: (args) => request("POST", "/founding/alive", { hasBody: true }, args),
@@ -1307,6 +1319,8 @@ function createClient(opts = {}) {
1307
1319
  getProvisioningInstancesIdRender: (args) => request("GET", "/provisioning/instances/{id}/render", { hasBody: false }, args),
1308
1320
  // POST /provisioning/instances/{id}/render — rank: any-builder — POST /provisioning/instances/:id/render
1309
1321
  postProvisioningInstancesIdRender: (args) => request("POST", "/provisioning/instances/{id}/render", { hasBody: true }, args),
1322
+ // POST /provisioning/instances/{id}/render/sandbox — rank: any-builder — POST /provisioning/instances/:id/render/sandbox
1323
+ postProvisioningInstancesIdRenderSandbox: (args) => request("POST", "/provisioning/instances/{id}/render/sandbox", { hasBody: true }, args),
1310
1324
  // POST /provisioning/instances/{id}/repo-private — rank: any-builder — POST /provisioning/instances/:id/repo-private
1311
1325
  postProvisioningInstancesIdRepoPrivate: (args) => request("POST", "/provisioning/instances/{id}/repo-private", { hasBody: true }, args),
1312
1326
  // POST /provisioning/instances/{id}/restart — rank: any-builder — POST /provisioning/instances/:id/restart
@@ -467,6 +467,18 @@ function createClient(opts = {}) {
467
467
  // GET /feedback/receipt/{id} — rank: public — GET /feedback/receipt/:id
468
468
  getFeedbackReceiptId: (args) => request("GET", "/feedback/receipt/{id}", { hasBody: false }, args),
469
469
  },
470
+ "firstRead": {
471
+ // POST /first-read/maps — rank: metic+archon — POST /first-read/maps
472
+ postFirstReadMaps: (args) => request("POST", "/first-read/maps", { hasBody: true }, args),
473
+ // GET /first-read/maps/{id} — rank: metic+archon — GET /first-read/maps/:id
474
+ getFirstReadMapsId: (args) => request("GET", "/first-read/maps/{id}", { hasBody: false }, args),
475
+ // POST /first-read/maps/{id}/accept — rank: metic+archon — POST /first-read/maps/:id/accept
476
+ postFirstReadMapsIdAccept: (args) => request("POST", "/first-read/maps/{id}/accept", { hasBody: true }, args),
477
+ // POST /first-read/maps/{id}/reject — rank: metic+archon — POST /first-read/maps/:id/reject
478
+ postFirstReadMapsIdReject: (args) => request("POST", "/first-read/maps/{id}/reject", { hasBody: true }, args),
479
+ // GET /first-read/prompt — rank: any-builder — GET /first-read/prompt
480
+ getFirstReadPrompt: (args) => request("GET", "/first-read/prompt", { hasBody: false }, args),
481
+ },
470
482
  "founding": {
471
483
  // POST /founding/alive — rank: any-builder — POST /founding/alive
472
484
  postFoundingAlive: (args) => request("POST", "/founding/alive", { hasBody: true }, args),
@@ -1306,6 +1318,8 @@ function createClient(opts = {}) {
1306
1318
  getProvisioningInstancesIdRender: (args) => request("GET", "/provisioning/instances/{id}/render", { hasBody: false }, args),
1307
1319
  // POST /provisioning/instances/{id}/render — rank: any-builder — POST /provisioning/instances/:id/render
1308
1320
  postProvisioningInstancesIdRender: (args) => request("POST", "/provisioning/instances/{id}/render", { hasBody: true }, args),
1321
+ // POST /provisioning/instances/{id}/render/sandbox — rank: any-builder — POST /provisioning/instances/:id/render/sandbox
1322
+ postProvisioningInstancesIdRenderSandbox: (args) => request("POST", "/provisioning/instances/{id}/render/sandbox", { hasBody: true }, args),
1309
1323
  // POST /provisioning/instances/{id}/repo-private — rank: any-builder — POST /provisioning/instances/:id/repo-private
1310
1324
  postProvisioningInstancesIdRepoPrivate: (args) => request("POST", "/provisioning/instances/{id}/repo-private", { hasBody: true }, args),
1311
1325
  // POST /provisioning/instances/{id}/restart — rank: any-builder — POST /provisioning/instances/:id/restart
@@ -75,6 +75,7 @@ export interface GetCoreUpgradesResponse { ok: boolean; running: unknown; limit:
75
75
  export interface GetDiscordChannelsPlanResponse { ok: boolean; guild_id: unknown; op_count: unknown; ops: unknown; warnings: unknown }
76
76
  export interface GetDiscordChannelsSnapshotResponse { ok: boolean; guild_id: unknown; config: unknown; warnings: unknown }
77
77
  export interface GetDoneWhenPendingReviewResponse { criteria: unknown; count: unknown }
78
+ export interface GetFirstReadPromptResponse { schema: unknown; file: unknown; prompt: unknown; example: unknown; limits: unknown }
78
79
  export interface GetFrontDoorGuideMineResponse { ok: boolean; conversation: unknown }
79
80
  export interface GetGithubOrgsOrgResponse { org: unknown }
80
81
  export interface GetGithubRepoResponse { ok: boolean; repo: unknown; private_deployable: boolean }
@@ -164,7 +165,7 @@ export interface GetProvisioningHealthResponse { module: unknown; ok: boolean; c
164
165
  export interface GetProvisioningInstancesIdEnvManifestResponse { instance: unknown; env_vars: unknown; environments: unknown; values_held: boolean; note: unknown }
165
166
  export interface GetProvisioningInstancesIdInviteSuggestionsResponse { suggested: unknown; seeking: unknown; reason: unknown; unavailable?: unknown }
166
167
  export interface GetProvisioningInstancesIdLookResponse { ok: boolean; look: unknown; options: unknown; logo_max_bytes: unknown }
167
- export interface GetProvisioningInstancesIdRenderResponse { ok: boolean; app: unknown; env_vars: unknown; values_held: boolean }
168
+ export interface GetProvisioningInstancesIdRenderResponse { ok: boolean; app: unknown; sandbox: unknown; env_vars: unknown; values_held: boolean }
168
169
  export interface GetProvisioningInstancesIdResponse { instance: unknown; open_intent: unknown; github_app: unknown; github_setup: unknown }
169
170
  export interface GetProvisioningInstancesIdSettingsResponse { ok: boolean; settings: unknown; planet: unknown; options: unknown }
170
171
  export interface GetProvisioningInstancesResponse { instances: unknown }
@@ -389,6 +390,9 @@ export interface PostDoneWhenCriterionIdUnsatisfyRequest { reason?: string }
389
390
  export interface PostDoneWhenCriterionIdUnsatisfyResponse { criterion: unknown }
390
391
  export interface PostFeedbackReceiptRequest { sha256: string; kind?: "bug" | "idea" }
391
392
  export interface PostFeedbackReceiptResponse { ok: boolean; receipt: unknown; hub: unknown }
393
+ export interface PostFirstReadMapsIdAcceptRequest { all?: boolean; items?: string[] }
394
+ export interface PostFirstReadMapsRequest { map: Record<string, unknown> }
395
+ export interface PostFirstReadMapsResponse { map_id: unknown; status: unknown; items: unknown; next: unknown }
392
396
  export interface PostFoundingPlanRequest { days?: Record<string, unknown>; passes?: number; advisors?: string; government?: string; expected_builders?: number; existing?: boolean }
393
397
  export interface PostFrontDoorGuideConversationsIdAttachRequest { token: string }
394
398
  export interface PostFrontDoorGuideConversationsIdAttachResponse { ok: boolean; conversation: unknown }
@@ -607,9 +611,11 @@ export interface PostProvisioningInstancesIdGithubAppRequest { account?: string;
607
611
  export interface PostProvisioningInstancesIdGithubAppResponse { state: unknown; account: unknown; post_url: unknown; personal_url: unknown; org_url: unknown; org_login: unknown; manifest: unknown; redirect_url: unknown; expires_at: unknown }
608
612
  export interface PostProvisioningInstancesIdRenderRequest { key: string; owner_id: string; mode: string; service_id?: string; web_plan?: string; db_plan?: string; region?: string; runtime?: string; build_command?: string; start_command?: string; database?: boolean }
609
613
  export interface PostProvisioningInstancesIdRenderResponse { ok: boolean; queued: boolean; action: unknown; mode: unknown; with_setup: boolean; message: unknown }
614
+ export interface PostProvisioningInstancesIdRenderSandboxRequest { key: string }
615
+ export interface PostProvisioningInstancesIdRenderSandboxResponse { ok: boolean; queued: boolean; action: unknown; sandbox: boolean; message: unknown }
610
616
  export interface PostProvisioningInstancesIdRepoPrivateResponse { ok: boolean; queued: unknown; action: unknown; status: unknown; message: unknown }
611
617
  export interface PostProvisioningInstancesIdRestartResponse { ok: boolean; queued: unknown; action: unknown; status: unknown; message: unknown }
612
- export interface PostProvisioningInstancesIdTeardownResponse { ok: boolean; queued: unknown; action: unknown; status: unknown; superseded: unknown; message: unknown }
618
+ export interface PostProvisioningInstancesIdTeardownResponse { ok: boolean; queued: unknown; action: unknown; status: unknown; superseded: unknown; sandbox_key_lent: unknown; message: unknown }
613
619
  export interface PostProvisioningInstancesIdUpdateSubscriptionRequest { subscribed: boolean }
614
620
  export interface PostProvisioningInstancesIdUpdateSubscriptionResponse { ok: boolean; update_subscribed: unknown; previous: unknown; changed: unknown }
615
621
  export interface PostProvisioningInstancesRequest { slug: string; target_ref?: string; hosting_shape?: string; domain?: string; no_address?: boolean; tier?: string; onboard_mode?: string; type?: string; description?: string; detail?: Record<string, unknown>; modules?: string[]; terms_acknowledged?: boolean; demo?: Record<string, unknown>; ship_mode?: "auto" | "manual"; genesis?: boolean; test?: boolean }
@@ -1150,6 +1156,18 @@ export interface BongosClient {
1150
1156
  /** GET /feedback/receipt/{id} — rank: public */
1151
1157
  getFeedbackReceiptId(args?: RequestArgs): Promise<ApiResponse>;
1152
1158
  };
1159
+ "firstRead": {
1160
+ /** POST /first-read/maps — rank: metic+archon */
1161
+ postFirstReadMaps(args: RequestArgs & { body: PostFirstReadMapsRequest }): Promise<PostFirstReadMapsResponse>;
1162
+ /** GET /first-read/maps/{id} — rank: metic+archon */
1163
+ getFirstReadMapsId(args?: RequestArgs): Promise<ApiResponse>;
1164
+ /** POST /first-read/maps/{id}/accept — rank: metic+archon */
1165
+ postFirstReadMapsIdAccept(args?: RequestArgs & { body?: PostFirstReadMapsIdAcceptRequest }): Promise<ApiResponse>;
1166
+ /** POST /first-read/maps/{id}/reject — rank: metic+archon */
1167
+ postFirstReadMapsIdReject(args?: RequestArgs): Promise<ApiResponse>;
1168
+ /** GET /first-read/prompt — rank: any-builder */
1169
+ getFirstReadPrompt(args?: RequestArgs): Promise<GetFirstReadPromptResponse>;
1170
+ };
1153
1171
  "founding": {
1154
1172
  /** POST /founding/alive — rank: any-builder */
1155
1173
  postFoundingAlive(args?: RequestArgs): Promise<ApiResponse>;
@@ -1989,6 +2007,8 @@ export interface BongosClient {
1989
2007
  getProvisioningInstancesIdRender(args?: RequestArgs): Promise<GetProvisioningInstancesIdRenderResponse>;
1990
2008
  /** POST /provisioning/instances/{id}/render — rank: any-builder */
1991
2009
  postProvisioningInstancesIdRender(args: RequestArgs & { body: PostProvisioningInstancesIdRenderRequest }): Promise<PostProvisioningInstancesIdRenderResponse>;
2010
+ /** POST /provisioning/instances/{id}/render/sandbox — rank: any-builder */
2011
+ postProvisioningInstancesIdRenderSandbox(args: RequestArgs & { body: PostProvisioningInstancesIdRenderSandboxRequest }): Promise<PostProvisioningInstancesIdRenderSandboxResponse>;
1992
2012
  /** POST /provisioning/instances/{id}/repo-private — rank: any-builder */
1993
2013
  postProvisioningInstancesIdRepoPrivate(args?: RequestArgs): Promise<PostProvisioningInstancesIdRepoPrivateResponse>;
1994
2014
  /** POST /provisioning/instances/{id}/restart — rank: any-builder */
@@ -464,6 +464,18 @@ export function createClient(opts = {}) {
464
464
  // GET /feedback/receipt/{id} — rank: public — GET /feedback/receipt/:id
465
465
  getFeedbackReceiptId: (args) => request("GET", "/feedback/receipt/{id}", { hasBody: false }, args),
466
466
  },
467
+ "firstRead": {
468
+ // POST /first-read/maps — rank: metic+archon — POST /first-read/maps
469
+ postFirstReadMaps: (args) => request("POST", "/first-read/maps", { hasBody: true }, args),
470
+ // GET /first-read/maps/{id} — rank: metic+archon — GET /first-read/maps/:id
471
+ getFirstReadMapsId: (args) => request("GET", "/first-read/maps/{id}", { hasBody: false }, args),
472
+ // POST /first-read/maps/{id}/accept — rank: metic+archon — POST /first-read/maps/:id/accept
473
+ postFirstReadMapsIdAccept: (args) => request("POST", "/first-read/maps/{id}/accept", { hasBody: true }, args),
474
+ // POST /first-read/maps/{id}/reject — rank: metic+archon — POST /first-read/maps/:id/reject
475
+ postFirstReadMapsIdReject: (args) => request("POST", "/first-read/maps/{id}/reject", { hasBody: true }, args),
476
+ // GET /first-read/prompt — rank: any-builder — GET /first-read/prompt
477
+ getFirstReadPrompt: (args) => request("GET", "/first-read/prompt", { hasBody: false }, args),
478
+ },
467
479
  "founding": {
468
480
  // POST /founding/alive — rank: any-builder — POST /founding/alive
469
481
  postFoundingAlive: (args) => request("POST", "/founding/alive", { hasBody: true }, args),
@@ -1303,6 +1315,8 @@ export function createClient(opts = {}) {
1303
1315
  getProvisioningInstancesIdRender: (args) => request("GET", "/provisioning/instances/{id}/render", { hasBody: false }, args),
1304
1316
  // POST /provisioning/instances/{id}/render — rank: any-builder — POST /provisioning/instances/:id/render
1305
1317
  postProvisioningInstancesIdRender: (args) => request("POST", "/provisioning/instances/{id}/render", { hasBody: true }, args),
1318
+ // POST /provisioning/instances/{id}/render/sandbox — rank: any-builder — POST /provisioning/instances/:id/render/sandbox
1319
+ postProvisioningInstancesIdRenderSandbox: (args) => request("POST", "/provisioning/instances/{id}/render/sandbox", { hasBody: true }, args),
1306
1320
  // POST /provisioning/instances/{id}/repo-private — rank: any-builder — POST /provisioning/instances/:id/repo-private
1307
1321
  postProvisioningInstancesIdRepoPrivate: (args) => request("POST", "/provisioning/instances/{id}/repo-private", { hasBody: true }, args),
1308
1322
  // POST /provisioning/instances/{id}/restart — rank: any-builder — POST /provisioning/instances/:id/restart
@@ -106,3 +106,11 @@ Each sibling task's description now opens with a dated note, *"Re-read against A
106
106
  | [task 1005291](https://cloudbongos.com/builders#/task/1005291) | A read-only key is the floor; the gate is an outbound wrapper in the starter active under `BONGOS_SANDBOX=1`, with its limit said plainly; free plan blocks mail ports. |
107
107
  | [task 1005292](https://cloudbongos.com/builders#/task/1005292) | Same rule over the release pin; a second instance takes every release and carries a throwaway test project; owner choice 2 and the patch auto-move question are asked here. |
108
108
  | [task 1005293](https://cloudbongos.com/builders#/task/1005293) | Added checks: no live deploy after a ship, promote refuses without the key, the sandbox band shows, sandbox data is fake, and the lent key is confirmed read-only. |
109
+
110
+ ## 10. Amendment — what setting it up found (2026-11-13, [task 1005289](https://cloudbongos.com/builders#/task/1005289))
111
+
112
+ - **A second database in one server is allowed.** Render's own page ([render.com/docs/postgresql-creating-connecting](https://render.com/docs/postgresql-creating-connecting), section "Adding multiple databases to a single instance", read 2026-11-13) says extra databases can be made in an instance, with plain SQL (`CREATE DATABASE`) over a psql session, and reached on the instance's same addresses with the new name as the last part. Render's API has no call for it, so the runner makes it with SQL over the server's external address. The page names no plan limit and no count limit. **Not yet tried on a real Render account** — no account was available to the session that built it; the walk ([task 1005293](https://cloudbongos.com/builders#/task/1005293)) is the first real run. Owner choice 1 in §6 therefore does not arise unless that run says otherwise; if the database stage fails, the sandbox runs with no database and says why, and nothing paid is bought in its place.
113
+ - **The database starts empty.** The app's own seed fills it (the starter's job under `BONGOS_SANDBOX=1`); the platform cannot know an app's tables.
114
+ - **The live service's switch to manual deploys is left to the promote task** ([task 1005290](https://cloudbongos.com/builders#/task/1005290)), so that live never stops updating before there is a button that moves it.
115
+ - **Teardown needs the owner's key to remove the sandbox**, typed on the teardown screen and used once. The Render client gains one delete, `deleteSandboxService`, which refuses anything not named `…-sandbox` on the free plan. Without the key the sandbox stays on the owner's account and the owner is told exactly what to remove.
116
+
@@ -58,3 +58,4 @@ every stage, not a strategize feature that charter then copies.
58
58
  the hall version (task 1005285). Today a founder works a stage through their AI session
59
59
  and `npx bongos genesis …`.
60
60
  - Task 1005115 renders each stage's record as an editable document from this store.
61
+ - Scope adopted it with the project interview (task 1005114): six questions in three groups. `/goal-create` and `/planning-session` read the answers before planning, through `genesis.js context`.