@bongos/core 1.19.875 → 1.19.877

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 (48) hide show
  1. package/.bongos-core.json +103 -43
  2. package/.gitattributes +6 -2
  3. package/clients/bongos-client/README.md +1 -1
  4. package/clients/bongos-client/bongos-client.global.js +4 -0
  5. package/clients/bongos-client/index.cjs +4 -0
  6. package/clients/bongos-client/index.d.ts +7 -0
  7. package/clients/bongos-client/index.mjs +4 -0
  8. package/docs/adr/0307-autobongos-a-deterministic-supervisor-and-agentic-workers.md +12 -1
  9. package/docs/api/openapi.json +149 -3
  10. package/docs/api-reference.md +4 -2
  11. package/docs/copy-inventory.md +7 -6
  12. package/docs/copy-registry.json +16 -7
  13. package/docs/module-api-changelog.md +4 -0
  14. package/docs/recipes/autobongos-windows-host.md +138 -0
  15. package/docs/recipes/instance-deploy.md +29 -3
  16. package/modules/autonomy/cadence.js +276 -0
  17. package/modules/autonomy/db.js +47 -0
  18. package/modules/autonomy/migrations/autonomy_002_runner_heartbeat.sql +93 -0
  19. package/modules/autonomy/routes/autonomy.js +69 -0
  20. package/modules/autonomy/runner-health.js +97 -0
  21. package/modules/dev-box/app/src/vendor/bongos-client.cjs +4 -0
  22. package/modules/hall-ui/public/gate.html +4 -1
  23. package/modules/hall-ui/public/gate.js +51 -2
  24. package/modules/security/tests/artifact_scan.mjs +32 -9
  25. package/modules/security/tests/mirror.mjs +26 -4
  26. package/modules/security/tests/sanitize_rebuild.mjs +25 -4
  27. package/package-lock.json +2 -2
  28. package/package.json +1 -1
  29. package/scripts/gds/autobongos-run.js +368 -11
  30. package/scripts/gds/autobongos-service.cmd +38 -0
  31. package/scripts/gds/autobongos-service.ps1 +129 -0
  32. package/scripts/gds/deploy-main-audit-gate.sh +90 -0
  33. package/scripts/gds/main-audit.js +26 -4
  34. package/scripts/gds/run-unit-tests.js +46 -5
  35. package/src/module-api.js +1 -1
  36. package/tests/autobongos_cadence.mjs +602 -0
  37. package/tests/autonomy_runner_health.mjs +135 -0
  38. package/tests/bump_version.mjs +12 -1
  39. package/tests/cli_package.mjs +11 -1
  40. package/tests/deploy_audit_gate.mjs +154 -0
  41. package/tests/deploy_divergence_line.mjs +47 -1
  42. package/tests/helpers.mjs +61 -0
  43. package/tests/main_audit_db_roster.mjs +97 -0
  44. package/tests/publish_watch.mjs +9 -0
  45. package/tests/setup_device_flow_fallback.mjs +2 -1
  46. package/tests/skip_is_not_pass.mjs +121 -0
  47. package/tests/tool_scan_engine.mjs +25 -4
  48. package/tests/unit_runner_teardown_abort.mjs +37 -0
@@ -1946,6 +1946,55 @@
1946
1946
  ]
1947
1947
  }
1948
1948
  },
1949
+ "/autonomy/heartbeat": {
1950
+ "post": {
1951
+ "operationId": "post_autonomy_heartbeat",
1952
+ "tags": [
1953
+ "autonomy"
1954
+ ],
1955
+ "summary": "POST /autonomy/heartbeat",
1956
+ "description": "The runner's check-in, once per loop. ANY-BUILDER is safe because the row is keyed by the CALLER: a stranger reporting \"winbox\" writes their own row and cannot touch the owner's, so the liveness signal cannot be forged into reading alive. Keeping the bar low matters — the failure mode of a refused heartbeat is a healthy runner reported dead.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
1957
+ "x-rank": "any-builder",
1958
+ "x-source": "modules/autonomy/routes/autonomy.js",
1959
+ "requestBody": {
1960
+ "required": true,
1961
+ "content": {
1962
+ "application/json": {
1963
+ "schema": {
1964
+ "$ref": "#/components/schemas/PostAutonomyHeartbeatRequest"
1965
+ }
1966
+ }
1967
+ },
1968
+ "x-validated": true
1969
+ },
1970
+ "responses": {
1971
+ "200": {
1972
+ "description": "Success.",
1973
+ "content": {
1974
+ "application/json": {
1975
+ "schema": {
1976
+ "$ref": "#/components/schemas/PostAutonomyHeartbeatResponse"
1977
+ }
1978
+ }
1979
+ }
1980
+ },
1981
+ "400": {
1982
+ "$ref": "#/components/responses/ValidationFailed"
1983
+ },
1984
+ "401": {
1985
+ "$ref": "#/components/responses/Unauthorized"
1986
+ },
1987
+ "403": {
1988
+ "$ref": "#/components/responses/Forbidden"
1989
+ }
1990
+ },
1991
+ "security": [
1992
+ {
1993
+ "builderSession": []
1994
+ }
1995
+ ]
1996
+ }
1997
+ },
1949
1998
  "/autonomy/precheck": {
1950
1999
  "get": {
1951
2000
  "operationId": "get_autonomy_precheck",
@@ -1980,6 +2029,44 @@
1980
2029
  ]
1981
2030
  }
1982
2031
  },
2032
+ "/autonomy/runners": {
2033
+ "get": {
2034
+ "operationId": "get_autonomy_runners",
2035
+ "tags": [
2036
+ "autonomy"
2037
+ ],
2038
+ "summary": "GET /autonomy/runners",
2039
+ "description": "What the hall renders: the CALLER'S OWN runners, with the pure verdict attached so the page and any future alert cannot disagree about what \"dead\" means. A row names a machine, its hostname and a pid — the caller's infrastructure, and nobody else's business.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
2040
+ "x-rank": "any-builder",
2041
+ "x-source": "modules/autonomy/routes/autonomy.js",
2042
+ "responses": {
2043
+ "200": {
2044
+ "description": "Success.",
2045
+ "content": {
2046
+ "application/json": {
2047
+ "schema": {
2048
+ "$ref": "#/components/schemas/GetAutonomyRunnersResponse"
2049
+ }
2050
+ }
2051
+ }
2052
+ },
2053
+ "400": {
2054
+ "$ref": "#/components/responses/BadRequest"
2055
+ },
2056
+ "401": {
2057
+ "$ref": "#/components/responses/Unauthorized"
2058
+ },
2059
+ "403": {
2060
+ "$ref": "#/components/responses/Forbidden"
2061
+ }
2062
+ },
2063
+ "security": [
2064
+ {
2065
+ "builderSession": []
2066
+ }
2067
+ ]
2068
+ }
2069
+ },
1983
2070
  "/backup/status": {
1984
2071
  "get": {
1985
2072
  "operationId": "get_backup_status",
@@ -18634,6 +18721,17 @@
18634
18721
  "admitted"
18635
18722
  ]
18636
18723
  },
18724
+ "GetAutonomyRunnersResponse": {
18725
+ "type": "object",
18726
+ "properties": {
18727
+ "runners": {},
18728
+ "none": {}
18729
+ },
18730
+ "required": [
18731
+ "runners",
18732
+ "none"
18733
+ ]
18734
+ },
18637
18735
  "GetBackupStatusResponse": {
18638
18736
  "type": "object",
18639
18737
  "properties": {
@@ -21381,6 +21479,54 @@
21381
21479
  ],
21382
21480
  "additionalProperties": false
21383
21481
  },
21482
+ "PostAutonomyHeartbeatRequest": {
21483
+ "type": "object",
21484
+ "properties": {
21485
+ "host": {
21486
+ "type": "string",
21487
+ "minLength": 1,
21488
+ "maxLength": 255
21489
+ },
21490
+ "pid": {
21491
+ "type": "number"
21492
+ },
21493
+ "started_at": {
21494
+ "type": "string",
21495
+ "maxLength": 64
21496
+ },
21497
+ "mode": {
21498
+ "type": "string",
21499
+ "maxLength": 32
21500
+ },
21501
+ "consecutive_failures": {
21502
+ "type": "number"
21503
+ },
21504
+ "last_event": {
21505
+ "type": "string",
21506
+ "maxLength": 64
21507
+ },
21508
+ "working_task_id": {
21509
+ "type": "number"
21510
+ }
21511
+ },
21512
+ "required": [
21513
+ "host"
21514
+ ],
21515
+ "additionalProperties": false
21516
+ },
21517
+ "PostAutonomyHeartbeatResponse": {
21518
+ "type": "object",
21519
+ "properties": {
21520
+ "ok": {
21521
+ "type": "boolean"
21522
+ },
21523
+ "heartbeat": {}
21524
+ },
21525
+ "required": [
21526
+ "ok",
21527
+ "heartbeat"
21528
+ ]
21529
+ },
21384
21530
  "PostBackupTriggerResponse": {
21385
21531
  "type": "object",
21386
21532
  "properties": {
@@ -25211,9 +25357,9 @@
25211
25357
  "description": "A required dependency/feature is not configured or is temporarily down."
25212
25358
  }
25213
25359
  },
25214
- "x-endpoint-count": 398,
25215
- "x-schema-count": 436,
25360
+ "x-endpoint-count": 400,
25361
+ "x-schema-count": 439,
25216
25362
  "x-undocumented-bodies": 9,
25217
- "x-response-schemas": 298,
25363
+ "x-response-schemas": 300,
25218
25364
  "x-generated-by": "scripts/gds/gen-api-docs.js"
25219
25365
  }
@@ -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. 398 endpoints across 64 route files.
5
+ > **Generated from the live route files** — the route file is authoritative. 400 endpoints across 64 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`.
@@ -83,7 +83,7 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/0016-trust
83
83
  | GET | `/api/bongos/auth/web/callback` | `public` | — | OAuth callback; the state cookie + code are the bearer. |
84
84
  | GET | `/api/bongos/auth/web/start` | `public` | — | /auth/web — browser flow (used by the /builders page). |
85
85
 
86
- ## `autonomy` (5)
86
+ ## `autonomy` (7)
87
87
 
88
88
  | Method | Path | Rank | Body | Description |
89
89
  |---|---|---|---|---|
@@ -91,7 +91,9 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/0016-trust
91
91
  | POST | `/api/bongos/autonomy/fence` | `archon` | `enabled`, `reason` | The kill switch. |
92
92
  | POST | `/api/bongos/autonomy/fence/goals` | `archon` | `goal_id`, `note` | Add a goal to the allowlist. |
93
93
  | DELETE | `/api/bongos/autonomy/fence/goals/:goalId` | `archon` | — | Revoke one. |
94
+ | 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. |
94
95
  | GET | `/api/bongos/autonomy/precheck` | `metic+archon` | — | |
96
+ | 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
97
 
96
98
  ## `backup` (2)
97
99
 
@@ -4,13 +4,13 @@
4
4
  > Deterministic on a given tree — regenerate and commit rather than hand-editing.
5
5
  > Machine-readable twin: [`copy-registry.json`](copy-registry.json).
6
6
 
7
- **1912 strings** across 3 surfaces · 1656 distinct pieces of copy · 1912 certain, 0 heuristic · 175 shown in more than one place.
7
+ **1913 strings** across 3 surfaces · 1657 distinct pieces of copy · 1913 certain, 0 heuristic · 175 shown in more than one place.
8
8
 
9
9
  ## Surfaces
10
10
 
11
11
  | surface | lives at | files | strings |
12
12
  |---|---|---|---|
13
- | `builders-hall` | `modules/hall-ui/public` | 89 | 1422 |
13
+ | `builders-hall` | `modules/hall-ui/public` | 89 | 1423 |
14
14
  | `status-dashboard` | `modules/status-ui/public` | 4 | 100 |
15
15
  | `landing` | `modules/public-landing/public` | 5 | 390 |
16
16
 
@@ -78,7 +78,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
78
78
  | `22825067f4c5` | 2x | 1 builder | modules/public-landing/public/index.html:747, modules/public-landing/public/index.html:752 |
79
79
  | … | | _135 more in the JSON registry_ | |
80
80
 
81
- ## `builders-hall` — 1422 strings
81
+ ## `builders-hall` — 1423 strings
82
82
 
83
83
  | id | conf | text | where |
84
84
  |---|---|---|---|
@@ -248,7 +248,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
248
248
  | `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:409` |
249
249
  | `52384bdc035c` | certain | Changes save at once. Your new choice plays the next time that event fires. | `modules/hall-ui/public/settings.html:422` |
250
250
  | `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:392` |
251
- | `4b714191b423` | certain | Changes touching protected build surfaces, held for your approval. | `modules/hall-ui/public/gate.js:355` |
251
+ | `4b714191b423` | certain | Changes touching protected build surfaces, held for your approval. | `modules/hall-ui/public/gate.js:403` |
252
252
  | `e6982a9ff948` | certain | Charter library | `modules/hall-ui/public/government.js:799` |
253
253
  | `f8725cf3ba62` | certain | Checking dependency order… | `modules/hall-ui/public/work.js:852` |
254
254
  | `7a41b18c0de8` | certain | Checking for conflicts… | `modules/hall-ui/public/work.js:831` |
@@ -435,7 +435,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
435
435
  | `d59beed97d58` | certain | Drag to pan, scroll to zoom | `modules/hall-ui/public/diagrams.html:33` |
436
436
  | `67f09099c2d3` | certain | Duplicate — should be said once, in one place | `modules/hall-ui/public/copy-desk.html:93` |
437
437
  | `db7f370c0d38` | certain | Each builder’s dev box at a glance. | `modules/hall-ui/public/harbor.js:361` |
438
- | `77b7e3abfb07` | certain | Each one touched a protected surface and stopped at the gate check. Approving records your seal on that commit | `modules/hall-ui/public/gate.html:61` |
438
+ | `77b7e3abfb07` | certain | Each one touched a protected surface and stopped at the gate check. Approving records your seal on that commit | `modules/hall-ui/public/gate.html:64` |
439
439
  | `0ddc87f11713` | certain | Each rank opens more of the system. You see full details for your current rank and the one directly above it; | `modules/hall-ui/public/ranks.html:47` |
440
440
  | `7f1b1c32d360` | certain | Each slash-command can run on a different model. The system has a default for every skill; choose another to o | `modules/hall-ui/public/settings.html:378` |
441
441
  | `854a21d2eb39` | certain | Eight achievements recognize sustained contribution. Earned ones are highlighted; the rest show what’s left to | `modules/hall-ui/public/hall-widgets.js:197` |
@@ -523,7 +523,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
523
523
  | `53eb8a07e0f8` | certain | Harbor — {{worldName}} | `modules/hall-ui/public/harbor.html:6` |
524
524
  | `53eb8a07e0f8` | certain | Harbor — {{worldName}} | `modules/hall-ui/public/harbor.html:6` |
525
525
  | `7cdddb5e2332` | certain | Held changes summary | `modules/hall-ui/public/gate.html:44` |
526
- | `adac4cd8b973` | certain | Held pull requests | `modules/hall-ui/public/gate.html:60` |
526
+ | `adac4cd8b973` | certain | Held pull requests | `modules/hall-ui/public/gate.html:63` |
527
527
  | `ce8a068a34cf` | certain | Higher ranks only | `modules/hall-ui/public/sessions.html:40` |
528
528
  | `d9bd3b703fe4` | certain | Hover an island to light its links, click one for its details, or open it from the index below. | `modules/hall-ui/public/atlas.html:68` |
529
529
  | `6dd3c797943b` | certain | How Claude should engage you in it | `modules/hall-ui/public/settings.html:311` |
@@ -1308,6 +1308,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
1308
1308
  | `c767b3e07826` | certain | is only the screen; the | `modules/hall-ui/public/diagrams.html:74` |
1309
1309
  | `d0e722302840` | certain | is published and this box is not on it yet. | `modules/hall-ui/public/deploy.js:108` |
1310
1310
  | `aa530bd15088` | certain | itself). The registry stays the single source of truth for what the hall shows; a fitness check (scripts/gds/f | `modules/hall-ui/public/index.html:53` |
1311
+ | `966b32c8af7e` | certain | last check-in {…} ago | `modules/hall-ui/public/gate.js:360` |
1311
1312
  | `9018bf6e99eb` | certain | last used {…} · signed in {…} | `modules/hall-ui/public/settings-sessions.js:46` |
1312
1313
  | `2ce7738b1eb0` | certain | loading goals… | `modules/hall-ui/public/task-detail.js:482` |
1313
1314
  | `754bdec368ed` | certain | lowest credits | `modules/hall-ui/public/hall-widgets.js:136` |
@@ -3,9 +3,9 @@
3
3
  "generator": "scripts/gds/copy-inventory.js",
4
4
  "goal": 1000074,
5
5
  "counts": {
6
- "strings": 1912,
7
- "unique_ids": 1656,
8
- "certain": 1912,
6
+ "strings": 1913,
7
+ "unique_ids": 1657,
8
+ "certain": 1913,
9
9
  "heuristic": 0,
10
10
  "duplicate_ids": 175
11
11
  },
@@ -13,7 +13,7 @@
13
13
  "builders-hall": {
14
14
  "at": "modules/hall-ui/public",
15
15
  "files": 89,
16
- "strings": 1422
16
+ "strings": 1423
17
17
  },
18
18
  "status-dashboard": {
19
19
  "at": "modules/status-ui/public",
@@ -3370,7 +3370,7 @@
3370
3370
  "surface": "builders-hall",
3371
3371
  "text": "Changes touching protected build surfaces, held for your approval.",
3372
3372
  "file": "modules/hall-ui/public/gate.js",
3373
- "line": 355,
3373
+ "line": 403,
3374
3374
  "origin": "js-text-assign",
3375
3375
  "confidence": "certain"
3376
3376
  },
@@ -5053,7 +5053,7 @@
5053
5053
  "surface": "builders-hall",
5054
5054
  "text": "Each one touched a protected surface and stopped at the gate check. Approving records your seal on that commit and re-runs the check.",
5055
5055
  "file": "modules/hall-ui/public/gate.html",
5056
- "line": 61,
5056
+ "line": 64,
5057
5057
  "origin": "html-text",
5058
5058
  "confidence": "certain"
5059
5059
  },
@@ -5845,7 +5845,7 @@
5845
5845
  "surface": "builders-hall",
5846
5846
  "text": "Held pull requests",
5847
5847
  "file": "modules/hall-ui/public/gate.html",
5848
- "line": 60,
5848
+ "line": 63,
5849
5849
  "origin": "html-text",
5850
5850
  "confidence": "certain"
5851
5851
  },
@@ -12905,6 +12905,15 @@
12905
12905
  "origin": "html-text",
12906
12906
  "confidence": "certain"
12907
12907
  },
12908
+ {
12909
+ "id": "966b32c8af7e",
12910
+ "surface": "builders-hall",
12911
+ "text": "last check-in {…} ago",
12912
+ "file": "modules/hall-ui/public/gate.js",
12913
+ "line": 360,
12914
+ "origin": "js-markup",
12915
+ "confidence": "certain"
12916
+ },
12908
12917
  {
12909
12918
  "id": "9018bf6e99eb",
12910
12919
  "surface": "builders-hall",
@@ -2224,5 +2224,9 @@ is load-bearing: the script throws rather than guess if it is missing, and
2224
2224
  landed since 1.19.873 with no explicit bump. run 35419921833. (task 1002620)
2225
2225
  1.19.875 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
2226
2226
  landed since 1.19.874 with no explicit bump. run 35420682750. (task 1002620)
2227
+ 1.19.876 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
2228
+ landed since 1.19.875 with no explicit bump. run 35420916304. (task 1002620)
2229
+ 1.19.877 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
2230
+ landed since 1.19.876 with no explicit bump. run 35438291185. (task 1002620)
2227
2231
  ---------------------------------------------------------------------------
2228
2232
  ```
@@ -0,0 +1,138 @@
1
+ # Setting up the Autobongos runner on the Windows PC
2
+
3
+ The runner is a program that claims tasks and spawns Claude Code sessions to work
4
+ them, on an always-on machine with nobody at the keyboard. This is how it gets
5
+ installed so it survives a reboot, and how you check on it afterwards.
6
+
7
+ **Design of record:** [ADR 0307](../adr/0307-autobongos-a-deterministic-supervisor-and-agentic-workers.md).
8
+ Task [1003905](https://cloudbongos.com/builders#/task/1003905).
9
+
10
+ > **NOT YET VERIFIED ON THE REAL MACHINE.** Everything below was written and
11
+ > reviewed on a Mac; the install, the cold reboot and the crash-restart have not
12
+ > been run on the Windows PC, because that machine is not reachable from where
13
+ > this was built. The heartbeat half — the part that tells you whether the runner
14
+ > is alive — *was* verified end to end against a real database. Treat step 3 as
15
+ > the acceptance test, not as a formality.
16
+
17
+ ---
18
+
19
+ ## What you need on the box first
20
+
21
+ Open PowerShell as your normal user (not Administrator) and check all three:
22
+
23
+ ```powershell
24
+ node --version ; git --version ; claude --version
25
+ ```
26
+
27
+ All three must print a version. The installer refuses to proceed otherwise —
28
+ a runner that starts without `claude` on its PATH fails every worker and looks
29
+ like a mysterious outage in the log rather than a missing program.
30
+
31
+ You also need, as **your own user** (not an administrator account):
32
+
33
+ - a `git` credential that can fetch the repo,
34
+ - a signed-in Claude Code session,
35
+ - a Bongos CLI session (`/builder-reauth` if it has expired).
36
+
37
+ The runner deliberately runs as you, not as SYSTEM: SYSTEM has none of those
38
+ credentials, and "as you" is also the smaller blast radius for a process that
39
+ spawns workers with blanket permissions.
40
+
41
+ ## 1. Turn the runner on in the hall — *before* installing anything
42
+
43
+ The kill switch and the goal allowlist live on the server, and both ship **off**.
44
+ A runner installed before this step will start, find it is not allowed to do
45
+ anything, and idle — which is correct, but looks like a broken install.
46
+
47
+ 1. Open **cloudbongos.com/builders/gate** (you must be the Archon).
48
+ 2. Under **Autobongos runner**, add the goal(s) it may work.
49
+ 3. Press **Start the runner**.
50
+
51
+ Nothing on the PC can change either of those. That is the point: anything the
52
+ machine can write, the worker running on it can write too.
53
+
54
+ ## 2. Install the scheduled task
55
+
56
+ From the checkout:
57
+
58
+ ```powershell
59
+ powershell -ExecutionPolicy Bypass -File scripts\gds\autobongos-service.ps1 install
60
+ powershell -ExecutionPolicy Bypass -File scripts\gds\autobongos-service.ps1 start
61
+ ```
62
+
63
+ That registers a task called `Autobongos` that starts **at boot** (not at sign-in
64
+ — nobody should have to log in), restarts if it crashes, and never times out.
65
+
66
+ It is Task Scheduler rather than a real Windows service on purpose: node cannot
67
+ speak the service protocol, so every "node as a service" route needs a
68
+ third-party wrapper to download, verify and keep updated. Task Scheduler is
69
+ already on the machine and does everything needed except appear in the Services
70
+ panel.
71
+
72
+ ## 3. The acceptance test — do this, do not skip it
73
+
74
+ **A cold reboot must bring the runner back with nobody at the keyboard.**
75
+
76
+ 1. Reboot the PC. Do **not** sign in.
77
+ 2. From any other device, open **cloudbongos.com/builders/gate**.
78
+ 3. Within a few minutes the runner line should read **Checking in**.
79
+
80
+ If it does not, sign in on the box and run:
81
+
82
+ ```powershell
83
+ powershell -ExecutionPolicy Bypass -File scripts\gds\autobongos-service.ps1 status
84
+ ```
85
+
86
+ which prints the task state, the last result, and the tail of the log.
87
+
88
+ ## 4. Watching it from anywhere
89
+
90
+ The **Gate** page is the remote view. It shows two separate things, and the
91
+ difference matters:
92
+
93
+ | Line | Means |
94
+ |---|---|
95
+ | **Checking in** | the process is alive and talking to the server |
96
+ | **Quiet** | no check-in for a while — normal while a worker builds (they can take 90 minutes) |
97
+ | **Not checking in** | nothing for longer than any worker takes: the runner is not running |
98
+ | **Allowed to work** / **Stopped** | the kill switch — nothing to do with whether the process is up |
99
+
100
+ A runner can be **Allowed to work** and **Not checking in** at the same time:
101
+ that is a machine that is off, unplugged or wedged, and it is the state worth
102
+ noticing.
103
+
104
+ The full log lives on the box at `%LOCALAPPDATA%\cloudbongos\autobongos.log`.
105
+
106
+ ## 5. Stopping it
107
+
108
+ Use the **kill switch in the hall**, not the scheduled task. The switch survives
109
+ a reboot and cannot be undone by anything running on the machine; stopping the
110
+ task only stops this run, and the next boot starts it again.
111
+
112
+ `autobongos-service.ps1 stop` exists for maintenance on the box itself and says
113
+ this when you use it.
114
+
115
+ ## Keeping the checkout current
116
+
117
+ `autobongos-service.cmd` runs `git fetch` + `git reset --hard origin/main` before
118
+ each start, on the **main checkout only** — worker trees are separate worktrees
119
+ and are never touched. A fetch that fails does not stop the runner: being one
120
+ commit behind beats not running at all.
121
+
122
+ Because of that reset, **never leave uncommitted work in the runner's checkout.**
123
+ It is the machine's working copy, not a place to edit.
124
+
125
+ ## If something looks wrong
126
+
127
+ | Symptom | Where to look |
128
+ |---|---|
129
+ | Runner line says **Not checking in** | is the PC on? `...\autobongos-service.ps1 status` on the box |
130
+ | **Checking in** but nothing ever ships | the Gate page — is a goal allowlisted, and is the switch on? |
131
+ | Shipping stopped after a while | the log: the runner backs off after three failures and probes; the reason is in the log |
132
+ | It keeps restarting | `status` shows the last result; the `====` banners in the log mark each start |
133
+
134
+ The runner is built not to stop: three failures in a row drop it to a slow probe
135
+ rather than an exit, and it returns to full speed on its own once the cause
136
+ clears ([task 1003904](https://cloudbongos.com/builders#/task/1003904)). If the
137
+ scheduled task's restart counter is climbing, something is wrong that the
138
+ internal backoff should have absorbed — that is worth reading the log over.
@@ -15,11 +15,35 @@
15
15
 
16
16
  1. **`git pull --ff-only origin main`** the *instance* repo — host content only: `config/`, `migrations/instance/`, and the pinned core version in `package.json`.
17
17
  2. **`npm ci --omit=dev`** — installs the pinned `@bongos/core` + instance deps. This is what replaces `git reset --hard`: the core is a dependency, so an upgrade is a pin bump + `npm ci`, not a source merge.
18
- 3. **`bash <core>/scripts/migrate.sh`** — the core's **three-root** migrate (W5 / ADR 0108 §5) merges `<core>/migrations` + `<instance>/migrations/instance` + each enabled module's migrations, keyed by namespaced filename stems (`core_NNN_`, `<key>_NNN_`, bare instance) so the two repos never collide. It resolves core-root vs instance-root via `src/instance-config.js`.
19
- 4. **restart the platform** — a systemd unit runs `node <core>/src/platform-server.js` (Bongos-only) with `WorkingDirectory` = the instance root (so `resolveInstanceRoot()` resolves to the instance) + `PORT`/`HOST` env; then poll `/healthz`.
18
+ 3. **`sh <core>/scripts/gds/deploy-main-audit-gate.sh`** — the SEC #863 gate (ADR 0043). Refuses the deploy if a below-Metic author touched a permission-sensitive path in the delta being deployed, and on refusal **restores the checkout** to the previously-deployed SHA. See below; it is not optional and it is not last.
19
+ 4. **`bash <core>/scripts/migrate.sh`** — the core's **three-root** migrate (W5 / ADR 0108 §5) merges `<core>/migrations` + `<instance>/migrations/instance` + each enabled module's migrations, keyed by namespaced filename stems (`core_NNN_`, `<key>_NNN_`, bare instance) so the two repos never collide. It resolves core-root vs instance-root via `src/instance-config.js`.
20
+ 5. **restart the platform** — a systemd unit runs `node <core>/src/platform-server.js` (Bongos-only) with `WorkingDirectory` = the instance root (so `resolveInstanceRoot()` resolves to the instance) + `PORT`/`HOST` env; then poll `/healthz`.
20
21
 
21
22
  `docker-compose.yml` + `.github/workflows/selfhost-boot.yml` already model this shape (fresh Postgres → `npm ci` → `migrate.sh` → `platform-server`), so the flow is validated end-to-end there.
22
23
 
24
+ ## The audit gate: where it goes, and why exactly there
25
+
26
+ **Between `npm ci` and `migrate`.** Both neighbours are load-bearing (task 1001426):
27
+
28
+ - **After `npm ci`**, because the gate runs `main-audit.js` out of the core it is deploying. Run it before the install and it audits with the *previous* core's copy — which, until this task, had a `--db` roster read pointing at a function the per-domain `db.js` carve had moved, so it resolved nobody and passed everything.
29
+ - **Before `migrate`**, because nothing from the new commit has EXECUTED yet at that point. `npm ci` installs; `migrate` and the restart are what run. A gate placed after either of them is a report, not a gate.
30
+
31
+ **The deployed marker is the checkout's HEAD, and it advances only on success.** There is no marker file. The gate can only audit what was pulled, so the tree has already moved when it runs; if a refusal left it moved, the next deploy would compute its "previously deployed" SHA from the refused commit, never re-audit that delta, and find it already checked out. So the gate resets the tree back to `OTB_DEPLOY_PREV_SHA` before exiting non-zero. That restore lives inside the gate rather than in each caller's `~/deploy.sh`, so a new caller cannot forget it. `tests/deploy_audit_gate.mjs` pins it.
32
+
33
+ Capture the previous SHA **before** the pull:
34
+
35
+ ```sh
36
+ PREV_SHA="$(git rev-parse HEAD)" # BEFORE git reset/pull
37
+ git reset --hard origin/main
38
+ npm ci --omit=dev
39
+ export OTB_DEPLOY_PREV_SHA="$PREV_SHA"
40
+ sh node_modules/@bongos/core/scripts/gds/deploy-main-audit-gate.sh || exit 1
41
+ ```
42
+
43
+ **`OTB_AUDIT_STRICT` stays off.** Ranks resolve on `github_login` only — deliberately, since `display_name` is builder-controlled and keying it let one builder alias another's rank. A deploy lane whose commits are authored under a human display name (`Firstname Lastname`) rather than the builder's `github_login` therefore resolves to nothing, and strict would refuse every deploy forever. Non-strict still hard-blocks the incident class this exists for: a *resolved* below-Metic author on a protected path. Turn strict on once the lane commits under logins.
44
+
45
+ **Known limit, stated rather than buried.** If the roster cannot be read at all, every author is unresolved and non-strict passes. `main-audit.js` now announces that loudly and falls through to the public roster instead of silently returning an empty map. Availability is chosen over a hard stop on purpose — a database blip must not freeze deploys — so read the stderr.
46
+
23
47
  ## Status — ready, not yet the live path
24
48
 
25
49
  `deploy-instance.sh` is **additive and inactive**: the live `example` droplet still deploys via `deploy-prod.sh` (`git reset --hard`). The cutover is deliberately deferred:
@@ -29,10 +53,12 @@
29
53
 
30
54
  `ship.js` needs no change: its deploy **trigger** SSHes `~/deploy.sh` (or fires the CI workflow) and is agnostic to what that script does internally — a consumer instance installs `deploy-instance.sh` as its `~/deploy.sh`.
31
55
 
56
+ **The audit gate is the exception, and it is live.** Do not read the paragraph above as covering it: the deferred thing is the `deploy-instance.sh` *model*, not the gate. The gate was wired into `cloudbongos.com`'s existing `~/deploy.sh` under task 1001426 — between its `npm ci` and its `migrate`, with the previous SHA captured before the pull — and verified both ways against that real script on a throwaway clone. That host's `~/deploy.sh` is host state and lives in no repository, so **this diff is not where you can see it**; the wiring, its backup path and its one loose end are recorded on the task. The loose end: until a core carrying `scripts/gds/deploy-main-audit-gate.sh` is published and pinned there, the host runs a byte-identical transitional copy beside `~/deploy.sh`, and `deploy.sh` prefers the core's copy the moment it appears.
57
+
32
58
  ## Wiring it on a consumer host (R85/R89)
33
59
 
34
60
  1. Install the script as the droplet's `~/deploy.sh` (the CI deploy key is forced-command-locked to `~/deploy.sh` — ADR 0043 — so it stays hand-installed, like `deploy-prod.sh`).
35
61
  2. Create a systemd unit for the instance: `ExecStart=/usr/bin/node <instanceRoot>/node_modules/@bongos/core/src/platform-server.js`, `WorkingDirectory=<instanceRoot>`, `Environment=PORT=… HOST=127.0.0.1 <PREFIX>_INSTANCE_ROOT=<instanceRoot>`.
36
- **`bongos serve` now writes exactly this unit for you** (plus the DB/migrate/health legs) — see [`server-bring-up.md`](server-bring-up.md) / [ADR 0169](../adr/0169-bongos-serve-server-bring-up.md). Step 4 of the flow above ("restart the platform") is `systemctl restart bongos-<db>` once it has.
62
+ **`bongos serve` now writes exactly this unit for you** (plus the DB/migrate/health legs) — see [`server-bring-up.md`](server-bring-up.md) / [ADR 0169](../adr/0169-bongos-serve-server-bring-up.md). Step 5 of the flow above ("restart the platform") is `systemctl restart bongos-<db>` once it has.
37
63
  3. Set `INSTANCE_SERVICE=<unit>` + `PORT=<port>` in the deploy environment.
38
64
  4. Front it with TLS and point the origins at the real domain (see [self-host.md](self-host.md)).