@bongos/core 1.25.32 → 1.25.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.bongos-core.json +25 -20
- package/docs/copy-inventory.md +15 -15
- package/docs/copy-registry.json +16 -16
- package/docs/module-api-changelog.md +2 -0
- package/docs/page-readings.json +3 -3
- package/modules/autonomy/runner-health.js +19 -0
- package/modules/hall-ui/public/gate.js +9 -5
- package/modules/hall-ui/public/runner-button.js +7 -0
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/release-notes.json +6 -0
- package/scripts/bongos/autobongos-host.js +22 -11
- package/scripts/bongos/autobongos-run.js +37 -5
- package/src/module-api.js +1 -1
- package/tests/autobongos_cannot_fetch.mjs +123 -0
package/.bongos-core.json
CHANGED
|
@@ -2,22 +2,22 @@
|
|
|
2
2
|
"artifact": "bongos-core",
|
|
3
3
|
"manifest_schema": 1,
|
|
4
4
|
"generator": "scripts/bongos/package-core.js",
|
|
5
|
-
"core_version": "1.25.
|
|
6
|
-
"core_contract": "1.25.
|
|
7
|
-
"source_commit": "
|
|
5
|
+
"core_version": "1.25.33",
|
|
6
|
+
"core_contract": "1.25.33",
|
|
7
|
+
"source_commit": "4b5c8d701067bdfbff18b430afc31b42d93bc473",
|
|
8
8
|
"source_ref": "HEAD",
|
|
9
|
-
"built_at": "2026-11-14T14:
|
|
9
|
+
"built_at": "2026-11-14T14:37:07.493Z",
|
|
10
10
|
"redaction": {
|
|
11
11
|
"model": "docs-redacted+functional-verbatim",
|
|
12
12
|
"docs_redacted": 659,
|
|
13
13
|
"agent_docs_stubbed": 34,
|
|
14
|
-
"functional_verbatim":
|
|
14
|
+
"functional_verbatim": 4092,
|
|
15
15
|
"rules": 3,
|
|
16
16
|
"gate_literals": 3,
|
|
17
17
|
"gate": "passed"
|
|
18
18
|
},
|
|
19
|
-
"file_count":
|
|
20
|
-
"tree_sha256": "
|
|
19
|
+
"file_count": 4786,
|
|
20
|
+
"tree_sha256": "98b5b7a87754177055b0767a010c3c7376170c614a91d857e51705d09be541ad",
|
|
21
21
|
"files": [
|
|
22
22
|
{
|
|
23
23
|
"path": ".claude/skills/ask-for-help/SKILL.md",
|
|
@@ -2542,12 +2542,12 @@
|
|
|
2542
2542
|
{
|
|
2543
2543
|
"path": "docs/copy-inventory.md",
|
|
2544
2544
|
"mode": "0000644",
|
|
2545
|
-
"sha256": "
|
|
2545
|
+
"sha256": "1d0c71ce2c00fb0f2c6d0ef9718f2deae87bfedfda15e0fd907d2d74258f5d14"
|
|
2546
2546
|
},
|
|
2547
2547
|
{
|
|
2548
2548
|
"path": "docs/copy-registry.json",
|
|
2549
2549
|
"mode": "0000644",
|
|
2550
|
-
"sha256": "
|
|
2550
|
+
"sha256": "dbd60962cf08e2cdec6a2e59a7d89acaf106ebf163234d8e92fb58a33d3ae2ca"
|
|
2551
2551
|
},
|
|
2552
2552
|
{
|
|
2553
2553
|
"path": "docs/design/apex-pass-2-direction.md",
|
|
@@ -3102,7 +3102,7 @@
|
|
|
3102
3102
|
{
|
|
3103
3103
|
"path": "docs/module-api-changelog.md",
|
|
3104
3104
|
"mode": "0000644",
|
|
3105
|
-
"sha256": "
|
|
3105
|
+
"sha256": "33db3faa1834a96618182e25a012b6cc98ca87236d346953c987fa6c1f1c7997"
|
|
3106
3106
|
},
|
|
3107
3107
|
{
|
|
3108
3108
|
"path": "docs/modules-contract.md",
|
|
@@ -3187,7 +3187,7 @@
|
|
|
3187
3187
|
{
|
|
3188
3188
|
"path": "docs/page-readings.json",
|
|
3189
3189
|
"mode": "0000644",
|
|
3190
|
-
"sha256": "
|
|
3190
|
+
"sha256": "a19d45806423cb1f44f40f6bc6f5cc130db29e4ccefe8d85af8967fb68334d63"
|
|
3191
3191
|
},
|
|
3192
3192
|
{
|
|
3193
3193
|
"path": "docs/project-context.template.md",
|
|
@@ -4752,7 +4752,7 @@
|
|
|
4752
4752
|
{
|
|
4753
4753
|
"path": "modules/autonomy/runner-health.js",
|
|
4754
4754
|
"mode": "0000644",
|
|
4755
|
-
"sha256": "
|
|
4755
|
+
"sha256": "dfab3899749342a6e1f0684d0f4b1aab8c42550024b8e555e8cc1413e7d05e67"
|
|
4756
4756
|
},
|
|
4757
4757
|
{
|
|
4758
4758
|
"path": "modules/autonomy/server-schedule.js",
|
|
@@ -6662,7 +6662,7 @@
|
|
|
6662
6662
|
{
|
|
6663
6663
|
"path": "modules/hall-ui/public/gate.js",
|
|
6664
6664
|
"mode": "0000644",
|
|
6665
|
-
"sha256": "
|
|
6665
|
+
"sha256": "3d1e7683f27eb30c11647e89a3ae6138c9d2e459606deb6a334d7231490f5576"
|
|
6666
6666
|
},
|
|
6667
6667
|
{
|
|
6668
6668
|
"path": "modules/hall-ui/public/genesis-home.js",
|
|
@@ -7337,7 +7337,7 @@
|
|
|
7337
7337
|
{
|
|
7338
7338
|
"path": "modules/hall-ui/public/runner-button.js",
|
|
7339
7339
|
"mode": "0000644",
|
|
7340
|
-
"sha256": "
|
|
7340
|
+
"sha256": "83f065223dbf6903bc0426adc92459fc486bc46b877537aa2944b8d71aade49d"
|
|
7341
7341
|
},
|
|
7342
7342
|
{
|
|
7343
7343
|
"path": "modules/hall-ui/public/sessions.css",
|
|
@@ -12517,12 +12517,12 @@
|
|
|
12517
12517
|
{
|
|
12518
12518
|
"path": "package-lock.json",
|
|
12519
12519
|
"mode": "0000644",
|
|
12520
|
-
"sha256": "
|
|
12520
|
+
"sha256": "1855476688c40e5b761ea79b3ad14f908dc4ca9204de3d2c1eed4972e669e625"
|
|
12521
12521
|
},
|
|
12522
12522
|
{
|
|
12523
12523
|
"path": "package.json",
|
|
12524
12524
|
"mode": "0000644",
|
|
12525
|
-
"sha256": "
|
|
12525
|
+
"sha256": "cbfcba84dcf5ffd88672a1e50168bc45df2c385babf24f21ae0f6f401fb9f6a4"
|
|
12526
12526
|
},
|
|
12527
12527
|
{
|
|
12528
12528
|
"path": "public-docs/index.html",
|
|
@@ -12542,7 +12542,7 @@
|
|
|
12542
12542
|
{
|
|
12543
12543
|
"path": "release-notes.json",
|
|
12544
12544
|
"mode": "0000644",
|
|
12545
|
-
"sha256": "
|
|
12545
|
+
"sha256": "5cb90b68209691dda5d1d1834ee42c3cec56272605119bedb2465a0ac1302abb"
|
|
12546
12546
|
},
|
|
12547
12547
|
{
|
|
12548
12548
|
"path": "scripts/bongos/CLAUDE.md",
|
|
@@ -12682,7 +12682,7 @@
|
|
|
12682
12682
|
{
|
|
12683
12683
|
"path": "scripts/bongos/autobongos-host.js",
|
|
12684
12684
|
"mode": "0000755",
|
|
12685
|
-
"sha256": "
|
|
12685
|
+
"sha256": "92caf5cebcaa06eb71b0bc514f3616fc7b29bc5e04e8b1c2ee4011849dfb2042"
|
|
12686
12686
|
},
|
|
12687
12687
|
{
|
|
12688
12688
|
"path": "scripts/bongos/autobongos-loop.js",
|
|
@@ -12692,7 +12692,7 @@
|
|
|
12692
12692
|
{
|
|
12693
12693
|
"path": "scripts/bongos/autobongos-run.js",
|
|
12694
12694
|
"mode": "0000644",
|
|
12695
|
-
"sha256": "
|
|
12695
|
+
"sha256": "e366b9995bef2f1d6313634f483a182b288272ed40af3496c4d0a4ad0655e9d6"
|
|
12696
12696
|
},
|
|
12697
12697
|
{
|
|
12698
12698
|
"path": "scripts/bongos/autobongos-service.cmd",
|
|
@@ -16622,7 +16622,7 @@
|
|
|
16622
16622
|
{
|
|
16623
16623
|
"path": "src/module-api.js",
|
|
16624
16624
|
"mode": "0000644",
|
|
16625
|
-
"sha256": "
|
|
16625
|
+
"sha256": "ae2ad3a3e6b66f1e03369e0b40df1417f17519792ccd2a5cd90bf509cb7b3a51"
|
|
16626
16626
|
},
|
|
16627
16627
|
{
|
|
16628
16628
|
"path": "src/module-loader/catalog.js",
|
|
@@ -17179,6 +17179,11 @@
|
|
|
17179
17179
|
"mode": "0000644",
|
|
17180
17180
|
"sha256": "3c55fd843bb0e8e5c9eaf3e8be4d32fe9a46eba077eaaf30a45ad7bea959d27f"
|
|
17181
17181
|
},
|
|
17182
|
+
{
|
|
17183
|
+
"path": "tests/autobongos_cannot_fetch.mjs",
|
|
17184
|
+
"mode": "0000644",
|
|
17185
|
+
"sha256": "64d6f7783afb4e692653983fab4c67b61a59abee8d2e2279807605f64df6b4ef"
|
|
17186
|
+
},
|
|
17182
17187
|
{
|
|
17183
17188
|
"path": "tests/autobongos_fence.mjs",
|
|
17184
17189
|
"mode": "0000644",
|
package/docs/copy-inventory.md
CHANGED
|
@@ -91,7 +91,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
91
91
|
| `af615fa9f404` | certain | (checked {…}) | `modules/hall-ui/public/deploy.js:516` |
|
|
92
92
|
| `e2c5af6b2815` | certain | (the desktop app, or Claude Code in a terminal). | `modules/hall-ui/public/setup-gate.js:33` |
|
|
93
93
|
| `c7aecadc8133` | certain | (with {…}) | `modules/hall-ui/public/goals-render.js:594` |
|
|
94
|
-
| `c81e3a97b531` | certain | + Add goal | `modules/hall-ui/public/gate.js:
|
|
94
|
+
| `c81e3a97b531` | certain | + Add goal | `modules/hall-ui/public/gate.js:221` |
|
|
95
95
|
| `27d9721f358f` | certain | + Invite | `modules/hall-ui/public/goals-render.js:1213` |
|
|
96
96
|
| `74815c8882ba` | certain | + send a new scout | `modules/hall-ui/public/market-watch.html:51` |
|
|
97
97
|
| `646fab1157fe` | certain | + {…} more project{…} not publicly listed. | `modules/hall-ui/public/profile.js:395` |
|
|
@@ -151,7 +151,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
151
151
|
| `524188fe0078` | certain | Active sessions | `modules/hall-ui/public/settings.html:190` |
|
|
152
152
|
| `e4da002ae135` | certain | Add ${…} | `modules/hall-ui/public/ai-studio.js:567` |
|
|
153
153
|
| `e271eaeba3ba` | certain | Add a card | `modules/hall-ui/public/settings.html:218` |
|
|
154
|
-
| `1bdd78d8e7c5` | certain | Add a device | `modules/hall-ui/public/gate.js:
|
|
154
|
+
| `1bdd78d8e7c5` | certain | Add a device | `modules/hall-ui/public/gate.js:192` |
|
|
155
155
|
| `1bdd78d8e7c5` | certain | Add a device | `modules/hall-ui/public/settings-autobongos.js:211` |
|
|
156
156
|
| `ff277763b4ce` | certain | Add a device, press Run on its card, and it builds the goals you choose below while you are away. Any Windows | `modules/hall-ui/public/settings.html:233` |
|
|
157
157
|
| `32509514479f` | certain | Add a done-when criterion | `modules/hall-ui/public/goal-author.js:38` |
|
|
@@ -305,7 +305,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
305
305
|
| `aa3ba7d28a76` | certain | Checking your key… | `modules/hall-ui/public/settings.js:794` |
|
|
306
306
|
| `834f8c6f3b72` | certain | Choose a builder… | `modules/hall-ui/public/goals-render.js:1249` |
|
|
307
307
|
| `b3d0e2af5176` | certain | Choose a goal first. | `modules/hall-ui/public/task.js:1023` |
|
|
308
|
-
| `89ddfeda9566` | certain | Choose goals | `modules/hall-ui/public/gate.js:
|
|
308
|
+
| `89ddfeda9566` | certain | Choose goals | `modules/hall-ui/public/gate.js:190` |
|
|
309
309
|
| `6bf684ebc1c3` | certain | Choose the skills for {…} | `modules/hall-ui/public/speciality-tools.js:199` |
|
|
310
310
|
| `6c88cdf417f1` | certain | Choose which sound plays for each build event — one when Claude waits for your input, another when a task ship | `modules/hall-ui/public/settings.html:368` |
|
|
311
311
|
| `7b984c01b6a8` | certain | Choose your character | `modules/hall-ui/public/craft-mode.js:910` |
|
|
@@ -485,7 +485,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
485
485
|
| `64f6af887b28` | certain | Drag to go back in time | `modules/hall-ui/public/visor.js:577` |
|
|
486
486
|
| `39f897eaff3c` | certain | Drop sketches, pictures or a PDF here, paste a picture, | `modules/hall-ui/public/ai-studio.js:180` |
|
|
487
487
|
| `67f09099c2d3` | certain | Duplicate — should be said once, in one place | `modules/hall-ui/public/copy-desk.html:93` |
|
|
488
|
-
| `1de61111bc00` | certain | Each builder's runner | `modules/hall-ui/public/gate.js:
|
|
488
|
+
| `1de61111bc00` | certain | Each builder's runner | `modules/hall-ui/public/gate.js:422` |
|
|
489
489
|
| `1f3b826a05d4` | certain | Each month is recorded spend ({…} over these {…} months) plus payouts and fees out of the project account. Rea | `modules/hall-ui/public/money.js:126` |
|
|
490
490
|
| `3a6916fa79d4` | certain | Each one links back to this page. | `modules/hall-ui/public/lightbulb.js:103` |
|
|
491
491
|
| `3f7d82a0d9b1` | certain | Each was filed when a ship changed copy or visuals. No new ones arrive; answer these and the door goes. | `modules/hall-ui/public/studio.html:197` |
|
|
@@ -498,7 +498,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
498
498
|
| `8e82771e5b63` | certain | Ending a session takes effect immediately; the token stops working on its very next request. | `modules/hall-ui/public/settings.html:202` |
|
|
499
499
|
| `58d381535285` | certain | Engagement reports | `modules/hall-ui/public/watch.html:129` |
|
|
500
500
|
| `6fd9b1bf8d97` | certain | Engineering work is open on this page ({…}), so code may change around your words. You can keep writing. | `modules/hall-ui/public/tweak-editor.js:304` |
|
|
501
|
-
| `690609c8e9a9` | certain | Enter a goal number. | `modules/hall-ui/public/gate.js:
|
|
501
|
+
| `690609c8e9a9` | certain | Enter a goal number. | `modules/hall-ui/public/gate.js:327` |
|
|
502
502
|
| `8eabe3d69bf3` | certain | Enter files the idea. Shift and Enter starts a new line. | `modules/hall-ui/public/home-idea-box.js:55` |
|
|
503
503
|
| `4f776bc33d5f` | certain | Enter the builders’ hall | `modules/hall-ui/public/genesis-home.js:421` |
|
|
504
504
|
| `1825c9c467d8` | certain | Enter the id of the task this one should wait for. | `modules/hall-ui/public/task.js:965` |
|
|
@@ -577,15 +577,15 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
577
577
|
| `9e70797b7e97` | certain | Goal id | `modules/hall-ui/public/goals-render.js:852` |
|
|
578
578
|
| `529460e82058` | certain | Goal invitations to you | `modules/hall-ui/public/goal-inbox.js:149` |
|
|
579
579
|
| `3807521c5db7` | certain | Goal map | `modules/hall-ui/public/goals.html:70` |
|
|
580
|
-
| `ed1966d824a5` | certain | Goal number | `modules/hall-ui/public/gate.js:
|
|
580
|
+
| `ed1966d824a5` | certain | Goal number | `modules/hall-ui/public/gate.js:213` |
|
|
581
581
|
| `e2a9e33abe60` | certain | Goal tasks | `modules/hall-ui/public/goals.html:155` |
|
|
582
|
-
| `ec88b946ad16` | certain | Goal {…} | `modules/hall-ui/public/gate.js:
|
|
583
|
-
| `6f0deb0b667d` | certain | Goal {…} added. | `modules/hall-ui/public/gate.js:
|
|
584
|
-
| `8a421ae268e6` | certain | Goal {…} removed. | `modules/hall-ui/public/gate.js:
|
|
582
|
+
| `ec88b946ad16` | certain | Goal {…} | `modules/hall-ui/public/gate.js:206` |
|
|
583
|
+
| `6f0deb0b667d` | certain | Goal {…} added. | `modules/hall-ui/public/gate.js:330` |
|
|
584
|
+
| `8a421ae268e6` | certain | Goal {…} removed. | `modules/hall-ui/public/gate.js:354` |
|
|
585
585
|
| `e0bc28d10785` | certain | Goals could not be loaded. Refresh to try again. | `modules/hall-ui/public/goals-page.js:875` |
|
|
586
586
|
| `4517f2253d0f` | certain | Goals couldn’t be loaded just now. Refresh to try again. | `modules/hall-ui/public/goals.js:142` |
|
|
587
587
|
| `6a85997bda21` | certain | Goals created | `modules/hall-ui/public/profile.html:152` |
|
|
588
|
-
| `6bbd703b5aad` | certain | Goals it can work on | `modules/hall-ui/public/gate.js:
|
|
588
|
+
| `6bbd703b5aad` | certain | Goals it can work on | `modules/hall-ui/public/gate.js:222` |
|
|
589
589
|
| `bba4caf837e9` | certain | Goals — {{worldName}} | `modules/hall-ui/public/goals.html:6` |
|
|
590
590
|
| `bba4caf837e9` | certain | Goals — {{worldName}} | `modules/hall-ui/public/goals.html:6` |
|
|
591
591
|
| `d0f76a295d09` | certain | Good afternoon. | `modules/hall-ui/public/studio.js:1059` |
|
|
@@ -822,7 +822,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
822
822
|
| `b5839a34590c` | certain | My agents — {{worldName}} | `modules/hall-ui/public/my-agents.html:6` |
|
|
823
823
|
| `b5839a34590c` | certain | My agents — {{worldName}} | `modules/hall-ui/public/my-agents.html:6` |
|
|
824
824
|
| `39afdc03594a` | certain | My balance | `modules/hall-ui/public/ai-studio.js:340` |
|
|
825
|
-
| `3d0d554cd684` | certain | Name (optional) | `modules/hall-ui/public/gate.js:
|
|
825
|
+
| `3d0d554cd684` | certain | Name (optional) | `modules/hall-ui/public/gate.js:213` |
|
|
826
826
|
| `ae84ebe1d735` | certain | Name cannot be blank. | `modules/hall-ui/public/settings.js:458` |
|
|
827
827
|
| `31e91ee6ce03` | certain | Name must be {…} characters or fewer. | `modules/hall-ui/public/settings.js:463` |
|
|
828
828
|
| `00461d24cd51` | certain | Name this card (optional) | `modules/hall-ui/public/settings.html:217` |
|
|
@@ -984,7 +984,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
984
984
|
| `fa818ee444b4` | certain | Only this goal's owner or a manager (or an Archon) may do this. | `modules/hall-ui/public/goals-render.js:1363` |
|
|
985
985
|
| `fa818ee444b4` | certain | Only this goal's owner or a manager (or an Archon) may do this. | `modules/hall-ui/public/goals-render.js:1379` |
|
|
986
986
|
| `544011db314a` | certain | Only this goal's owner or a manager (or an Archon) may invite. | `modules/hall-ui/public/goals-render.js:1311` |
|
|
987
|
-
| `42bb75e4297c` | certain | Open Settings | `modules/hall-ui/public/gate.js:
|
|
987
|
+
| `42bb75e4297c` | certain | Open Settings | `modules/hall-ui/public/gate.js:191` |
|
|
988
988
|
| `5f3e0b179839` | certain | Open in Sessions | `modules/hall-ui/public/task.js:491` |
|
|
989
989
|
| `9f55e4674ebb` | certain | Open in the copy desk | `modules/hall-ui/public/studio.js:253` |
|
|
990
990
|
| `03197f066323` | certain | Open it in the tweak editor | `modules/hall-ui/public/paintbrush.js:440` |
|
|
@@ -1125,7 +1125,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
1125
1125
|
| `58af483d7a84` | certain | Release task {…} | `modules/hall-ui/public/goals-render.js:374` |
|
|
1126
1126
|
| `c49f9b9f8864` | certain | Remake or tweak | `modules/hall-ui/public/studio.js:216` |
|
|
1127
1127
|
| `65e3399a8fbf` | certain | Remove filter | `modules/hall-ui/public/hall-kit.js:311` |
|
|
1128
|
-
| `12c3328b937c` | certain | Remove goal {…} | `modules/hall-ui/public/gate.js:
|
|
1128
|
+
| `12c3328b937c` | certain | Remove goal {…} | `modules/hall-ui/public/gate.js:206` |
|
|
1129
1129
|
| `1c755c04e705` | certain | Remove this line | `modules/hall-ui/public/paintbrush.js:129` |
|
|
1130
1130
|
| `20882d6ffdd0` | certain | Removed {…} from builder {…}. | `modules/hall-ui/public/government.js:411` |
|
|
1131
1131
|
| `9be75ebd8d67` | certain | Replay the sky from the first day | `modules/hall-ui/public/goal-map.html:127` |
|
|
@@ -1167,8 +1167,8 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
1167
1167
|
| `c56d9a6451a7` | certain | Rewrite them in the tweak editor | `modules/hall-ui/public/paintbrush.js:248` |
|
|
1168
1168
|
| `12af2af5acf2` | certain | Role it sits under | `modules/hall-ui/public/speciality-tools.js:614` |
|
|
1169
1169
|
| `4c1e8ab8e1de` | certain | Run this command instead (same folder). When it asks for the token, click Copy token and paste it there; nothi | `modules/hall-ui/public/settings.js:652` |
|
|
1170
|
-
| `48e5f1d19e90` | certain | Runner allowed to work | `modules/hall-ui/public/gate.js:
|
|
1171
|
-
| `41730c113dd5` | certain | Runners work only the goals above, and only while the switch is on. Each builder picks which of them their own | `modules/hall-ui/public/gate.js:
|
|
1170
|
+
| `48e5f1d19e90` | certain | Runner allowed to work | `modules/hall-ui/public/gate.js:271` |
|
|
1171
|
+
| `41730c113dd5` | certain | Runners work only the goals above, and only while the switch is on. Each builder picks which of them their own | `modules/hall-ui/public/gate.js:271` |
|
|
1172
1172
|
| `6fb37ca50950` | certain | Runs use this key, so the project's Anthropic account pays for them. It is stored encrypted and never shown ag | `modules/hall-ui/public/market-watch.html:170` |
|
|
1173
1173
|
| `b6596905f845` | certain | Said more than once | `modules/hall-ui/public/copy-desk.html:56` |
|
|
1174
1174
|
| `ce046dcbd8e1` | certain | Save as PDF | `modules/hall-ui/public/modules.html:112` |
|
package/docs/copy-registry.json
CHANGED
|
@@ -1136,7 +1136,7 @@
|
|
|
1136
1136
|
"text": "Add a device",
|
|
1137
1137
|
"occurrences": 2,
|
|
1138
1138
|
"at": [
|
|
1139
|
-
"modules/hall-ui/public/gate.js:
|
|
1139
|
+
"modules/hall-ui/public/gate.js:192",
|
|
1140
1140
|
"modules/hall-ui/public/settings-autobongos.js:211"
|
|
1141
1141
|
]
|
|
1142
1142
|
},
|
|
@@ -3238,7 +3238,7 @@
|
|
|
3238
3238
|
"surface": "builders-hall",
|
|
3239
3239
|
"text": "+ Add goal",
|
|
3240
3240
|
"file": "modules/hall-ui/public/gate.js",
|
|
3241
|
-
"line":
|
|
3241
|
+
"line": 221,
|
|
3242
3242
|
"origin": "js-markup",
|
|
3243
3243
|
"confidence": "certain"
|
|
3244
3244
|
},
|
|
@@ -3778,7 +3778,7 @@
|
|
|
3778
3778
|
"surface": "builders-hall",
|
|
3779
3779
|
"text": "Add a device",
|
|
3780
3780
|
"file": "modules/hall-ui/public/gate.js",
|
|
3781
|
-
"line":
|
|
3781
|
+
"line": 192,
|
|
3782
3782
|
"origin": "js-markup",
|
|
3783
3783
|
"confidence": "certain"
|
|
3784
3784
|
},
|
|
@@ -5164,7 +5164,7 @@
|
|
|
5164
5164
|
"surface": "builders-hall",
|
|
5165
5165
|
"text": "Choose goals",
|
|
5166
5166
|
"file": "modules/hall-ui/public/gate.js",
|
|
5167
|
-
"line":
|
|
5167
|
+
"line": 190,
|
|
5168
5168
|
"origin": "js-markup",
|
|
5169
5169
|
"confidence": "certain"
|
|
5170
5170
|
},
|
|
@@ -6784,7 +6784,7 @@
|
|
|
6784
6784
|
"surface": "builders-hall",
|
|
6785
6785
|
"text": "Each builder's runner",
|
|
6786
6786
|
"file": "modules/hall-ui/public/gate.js",
|
|
6787
|
-
"line":
|
|
6787
|
+
"line": 422,
|
|
6788
6788
|
"origin": "js-markup",
|
|
6789
6789
|
"confidence": "certain"
|
|
6790
6790
|
},
|
|
@@ -6901,7 +6901,7 @@
|
|
|
6901
6901
|
"surface": "builders-hall",
|
|
6902
6902
|
"text": "Enter a goal number.",
|
|
6903
6903
|
"file": "modules/hall-ui/public/gate.js",
|
|
6904
|
-
"line":
|
|
6904
|
+
"line": 327,
|
|
6905
6905
|
"origin": "js-notice",
|
|
6906
6906
|
"confidence": "certain"
|
|
6907
6907
|
},
|
|
@@ -7612,7 +7612,7 @@
|
|
|
7612
7612
|
"surface": "builders-hall",
|
|
7613
7613
|
"text": "Goal number",
|
|
7614
7614
|
"file": "modules/hall-ui/public/gate.js",
|
|
7615
|
-
"line":
|
|
7615
|
+
"line": 213,
|
|
7616
7616
|
"origin": "js-markup",
|
|
7617
7617
|
"confidence": "certain"
|
|
7618
7618
|
},
|
|
@@ -7630,7 +7630,7 @@
|
|
|
7630
7630
|
"surface": "builders-hall",
|
|
7631
7631
|
"text": "Goal {…}",
|
|
7632
7632
|
"file": "modules/hall-ui/public/gate.js",
|
|
7633
|
-
"line":
|
|
7633
|
+
"line": 206,
|
|
7634
7634
|
"origin": "js-markup",
|
|
7635
7635
|
"confidence": "certain"
|
|
7636
7636
|
},
|
|
@@ -7639,7 +7639,7 @@
|
|
|
7639
7639
|
"surface": "builders-hall",
|
|
7640
7640
|
"text": "Goal {…} added.",
|
|
7641
7641
|
"file": "modules/hall-ui/public/gate.js",
|
|
7642
|
-
"line":
|
|
7642
|
+
"line": 330,
|
|
7643
7643
|
"origin": "js-notice",
|
|
7644
7644
|
"confidence": "certain"
|
|
7645
7645
|
},
|
|
@@ -7648,7 +7648,7 @@
|
|
|
7648
7648
|
"surface": "builders-hall",
|
|
7649
7649
|
"text": "Goal {…} removed.",
|
|
7650
7650
|
"file": "modules/hall-ui/public/gate.js",
|
|
7651
|
-
"line":
|
|
7651
|
+
"line": 354,
|
|
7652
7652
|
"origin": "js-notice",
|
|
7653
7653
|
"confidence": "certain"
|
|
7654
7654
|
},
|
|
@@ -7684,7 +7684,7 @@
|
|
|
7684
7684
|
"surface": "builders-hall",
|
|
7685
7685
|
"text": "Goals it can work on",
|
|
7686
7686
|
"file": "modules/hall-ui/public/gate.js",
|
|
7687
|
-
"line":
|
|
7687
|
+
"line": 222,
|
|
7688
7688
|
"origin": "js-markup",
|
|
7689
7689
|
"confidence": "certain"
|
|
7690
7690
|
},
|
|
@@ -9817,7 +9817,7 @@
|
|
|
9817
9817
|
"surface": "builders-hall",
|
|
9818
9818
|
"text": "Name (optional)",
|
|
9819
9819
|
"file": "modules/hall-ui/public/gate.js",
|
|
9820
|
-
"line":
|
|
9820
|
+
"line": 213,
|
|
9821
9821
|
"origin": "js-markup",
|
|
9822
9822
|
"confidence": "certain"
|
|
9823
9823
|
},
|
|
@@ -11275,7 +11275,7 @@
|
|
|
11275
11275
|
"surface": "builders-hall",
|
|
11276
11276
|
"text": "Open Settings",
|
|
11277
11277
|
"file": "modules/hall-ui/public/gate.js",
|
|
11278
|
-
"line":
|
|
11278
|
+
"line": 191,
|
|
11279
11279
|
"origin": "js-markup",
|
|
11280
11280
|
"confidence": "certain"
|
|
11281
11281
|
},
|
|
@@ -12544,7 +12544,7 @@
|
|
|
12544
12544
|
"surface": "builders-hall",
|
|
12545
12545
|
"text": "Remove goal {…}",
|
|
12546
12546
|
"file": "modules/hall-ui/public/gate.js",
|
|
12547
|
-
"line":
|
|
12547
|
+
"line": 206,
|
|
12548
12548
|
"origin": "js-markup",
|
|
12549
12549
|
"confidence": "certain"
|
|
12550
12550
|
},
|
|
@@ -12922,7 +12922,7 @@
|
|
|
12922
12922
|
"surface": "builders-hall",
|
|
12923
12923
|
"text": "Runner allowed to work",
|
|
12924
12924
|
"file": "modules/hall-ui/public/gate.js",
|
|
12925
|
-
"line":
|
|
12925
|
+
"line": 271,
|
|
12926
12926
|
"origin": "js-markup",
|
|
12927
12927
|
"confidence": "certain"
|
|
12928
12928
|
},
|
|
@@ -12931,7 +12931,7 @@
|
|
|
12931
12931
|
"surface": "builders-hall",
|
|
12932
12932
|
"text": "Runners work only the goals above, and only while the switch is on. Each builder picks which of them their own runner takes, and you can pause any one builder's runner below. All of it lives on the server, so a runner's PC can read it but cannot change it.",
|
|
12933
12933
|
"file": "modules/hall-ui/public/gate.js",
|
|
12934
|
-
"line":
|
|
12934
|
+
"line": 271,
|
|
12935
12935
|
"origin": "js-markup",
|
|
12936
12936
|
"confidence": "certain"
|
|
12937
12937
|
},
|
|
@@ -3502,5 +3502,7 @@ is load-bearing: the script throws rather than guess if it is missing, and
|
|
|
3502
3502
|
landed since 1.25.30 with no explicit bump. run 43602884082. (task 1002620)
|
|
3503
3503
|
1.25.32 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
3504
3504
|
landed since 1.25.31 with no explicit bump. run 43604349792. (task 1002620)
|
|
3505
|
+
1.25.33 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
3506
|
+
landed since 1.25.32 with no explicit bump. run 43605667657. (task 1002620)
|
|
3505
3507
|
---------------------------------------------------------------------------
|
|
3506
3508
|
```
|
package/docs/page-readings.json
CHANGED
|
@@ -954,7 +954,7 @@
|
|
|
954
954
|
"surface": "builders",
|
|
955
955
|
"title": "Builders' Hall",
|
|
956
956
|
"states_read": ["home","out","founding","genesis","decide","demo","votes"],
|
|
957
|
-
"files_hash": "
|
|
957
|
+
"files_hash": "0f2d40cf76c32eb9",
|
|
958
958
|
"reading_hash": "c5f4986bd90e2a2a",
|
|
959
959
|
"counts": {"lines":29,"placed":8,"shared":8,"unplaced":13},
|
|
960
960
|
"omitted": {"data":4},
|
|
@@ -2415,7 +2415,7 @@
|
|
|
2415
2415
|
"surface": "builders",
|
|
2416
2416
|
"title": "Options",
|
|
2417
2417
|
"states_read": ["account","access","preferences","install-reports","sound","update"],
|
|
2418
|
-
"files_hash": "
|
|
2418
|
+
"files_hash": "23bd832511bb89db",
|
|
2419
2419
|
"reading_hash": "a6d3194ed1b751ca",
|
|
2420
2420
|
"counts": {"lines":163,"placed":104,"shared":7,"unplaced":52},
|
|
2421
2421
|
"omitted": {"data":23},
|
|
@@ -3259,7 +3259,7 @@
|
|
|
3259
3259
|
"surface": "builders",
|
|
3260
3260
|
"title": "Watch",
|
|
3261
3261
|
"states_read": ["board","out","operations","security","sessions","autobongos"],
|
|
3262
|
-
"files_hash": "
|
|
3262
|
+
"files_hash": "78a1c17cb7e1331f",
|
|
3263
3263
|
"reading_hash": "1961a0c06b9d8477",
|
|
3264
3264
|
"counts": {"lines":72,"placed":33,"shared":7,"unplaced":32},
|
|
3265
3265
|
"omitted": {"data":52},
|
|
@@ -30,6 +30,9 @@
|
|
|
30
30
|
// it carries the fix as `remedy`. The runner decides the grace and says
|
|
31
31
|
// `config_idle:<code>` on its heartbeat; only a code config-idle.js knows is
|
|
32
32
|
// honoured, so the owner's kill switch and pause can never read as an alarm.
|
|
33
|
+
// · cannot_fetch — alive, but it has failed to reach the project several times
|
|
34
|
+
// in a row (task 1005202), so it is pinned to the code it has. NOT ok, and it
|
|
35
|
+
// carries the fix as `remedy`, like idle_config.
|
|
33
36
|
// · stopped — alive, and its builder pressed Stop on this device (task
|
|
34
37
|
// 1005094). Not an alarm and not "running": the device is doing what it was
|
|
35
38
|
// told, and its card shows Run. Only a runner that is still checking in can
|
|
@@ -56,6 +59,11 @@ const RESTART_S = 10 * 60;
|
|
|
56
59
|
|
|
57
60
|
const configIdle = require('./config-idle.js');
|
|
58
61
|
|
|
62
|
+
// The fix for `cannot_fetch` (task 1005202). Seen on a real Mac: the GitHub
|
|
63
|
+
// account git was using could not see the project. The runner's own log names
|
|
64
|
+
// that account; this is the step to take on the device.
|
|
65
|
+
const CANNOT_FETCH_REMEDY = 'On that device, git cannot reach this project on GitHub — usually it is signed in to a GitHub account that cannot see it. Run gh auth switch there to pick one that can (or gh auth login to add it); the runner\'s log names the account it is using. It picks up new code by itself once it can.';
|
|
66
|
+
|
|
59
67
|
const SHA_RE = /^[0-9a-f]{40}$/;
|
|
60
68
|
const sha = (v) => (typeof v === 'string' && SHA_RE.test(v) ? v : null);
|
|
61
69
|
|
|
@@ -141,6 +149,17 @@ function describeRunner(heartbeat, { nowMs = Date.now(), aliveS = ALIVE_S, lateS
|
|
|
141
149
|
holdUntil: Number.isFinite(holdMs) && holdMs > nowMs ? new Date(holdMs).toISOString() : null,
|
|
142
150
|
};
|
|
143
151
|
|
|
152
|
+
// Talking, but it cannot reach the project to fetch new code (task 1005202), so
|
|
153
|
+
// it works forever on the code it has. NOT ok, and it carries the fix. Only
|
|
154
|
+
// while it is still checking in: past that, silence is the truth.
|
|
155
|
+
if (heartbeat.last_event === 'cannot_fetch' && age <= aliveS) {
|
|
156
|
+
return {
|
|
157
|
+
state: 'cannot_fetch', ok: false, ageS: age, age: humanAge(age), ...ident,
|
|
158
|
+
why: 'it cannot fetch new code from GitHub', remedy: CANNOT_FETCH_REMEDY,
|
|
159
|
+
detail: `running old code${where} — it cannot fetch new code from GitHub`,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
144
163
|
if (heartbeat.last_event === 'upgrade_exit') {
|
|
145
164
|
if (age <= RESTART_S) {
|
|
146
165
|
return {
|
|
@@ -99,8 +99,10 @@
|
|
|
99
99
|
// stopped (task 1005094): checking in, and its builder pressed Stop on that
|
|
100
100
|
// device in Settings. Connected, not an alarm, and not the one to describe
|
|
101
101
|
// while another device is working.
|
|
102
|
-
|
|
103
|
-
|
|
102
|
+
// cannot_fetch (task 1005202): talking, but stuck on old code because it cannot
|
|
103
|
+
// reach the project on GitHub. A warning with its fix, like idle_config.
|
|
104
|
+
const HEALTH_RANK = { alive: 0, late: 1, idle_config: 2, cannot_fetch: 2, restarting: 3, stopped: 4, dead: 5, never_seen: 6 };
|
|
105
|
+
const HEALTH_DOT = { alive: 'ok', late: 'ok', idle_config: 'warn', cannot_fetch: 'warn', restarting: 'info', stopped: 'info', dead: 'danger', never_seen: 'info' };
|
|
104
106
|
|
|
105
107
|
// The panel is drawn from both reads at once; each is kept so a write that only
|
|
106
108
|
// reloads one of them redraws with the other's last answer.
|
|
@@ -124,7 +126,7 @@
|
|
|
124
126
|
// `project`, and then there is no second layer to check.
|
|
125
127
|
function readiness(runner, fence, mine) {
|
|
126
128
|
const h = (runner && runner.health) || {};
|
|
127
|
-
const connected = ['alive', 'late', 'restarting', 'idle_config', 'stopped'].includes(h.state);
|
|
129
|
+
const connected = ['alive', 'late', 'restarting', 'idle_config', 'cannot_fetch', 'stopped'].includes(h.state);
|
|
128
130
|
const goals = (fence && fence.goals) || [];
|
|
129
131
|
const items = [];
|
|
130
132
|
if (!runner) {
|
|
@@ -138,7 +140,9 @@
|
|
|
138
140
|
}
|
|
139
141
|
if (!connected) items.push({ key: 'claude', state: 'wait', text: 'Claude signed in' });
|
|
140
142
|
else if (h.account) items.push({ key: 'claude', state: 'ok', text: 'Claude signed in' });
|
|
141
|
-
if (
|
|
143
|
+
if (h.state === 'cannot_fetch') {
|
|
144
|
+
items.push({ key: 'code', state: 'todo', text: 'Cannot fetch new code', hint: h.remedy || '' });
|
|
145
|
+
} else if (connected && h.code && h.code.behind === true) {
|
|
142
146
|
items.push({ key: 'code', state: 'wait', text: 'Updating to the latest code', hint: 'It does this by itself.' });
|
|
143
147
|
} else if (connected && h.code) {
|
|
144
148
|
items.push({ key: 'code', state: 'ok', text: 'Up to date' });
|
|
@@ -388,7 +392,7 @@
|
|
|
388
392
|
: 'has picked no goals, so their runner takes no work';
|
|
389
393
|
const beats = (b.runners || []).map((r) => {
|
|
390
394
|
const h = r.health || {};
|
|
391
|
-
const label = { dead: 'not checking in', late: 'quiet', alive: 'checking in', restarting: 'restarting', stopped: 'stopped on that device', idle_config: `idle on a setting — ${h.remedy || 'see Settings'}
|
|
395
|
+
const label = { dead: 'not checking in', late: 'quiet', alive: 'checking in', restarting: 'restarting', stopped: 'stopped on that device', idle_config: `idle on a setting — ${h.remedy || 'see Settings'}`, cannot_fetch: 'stuck on old code — it cannot fetch from GitHub' }[h.state] || 'unknown';
|
|
392
396
|
return `<span class="ov-fact"><span class="rn-dot rn-dot--sm rn-dot--${HEALTH_DOT[h.state] || 'info'}" aria-hidden="true"></span> ${escapeHtml(h.host || r.host || '')} ${escapeHtml(label)}</span>`;
|
|
393
397
|
}).join('');
|
|
394
398
|
const paused = b.owner_paused === true;
|
|
@@ -126,6 +126,13 @@
|
|
|
126
126
|
sub: `It is on, but ${hold}.` };
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
+
// Checking in, but pinned to the code it has: it cannot reach the project on
|
|
130
|
+
// GitHub (task 1005202). Said the way "off or asleep" is, with the fix under it.
|
|
131
|
+
if (h.state === 'cannot_fetch') {
|
|
132
|
+
return { status: 'Stuck on old code', act: 'stop', label: 'Stop', tone: 'warn', busy: false, alt: null,
|
|
133
|
+
sub: `It is on, but it cannot fetch new code from GitHub. ${h.remedy || ''}`.trim() };
|
|
134
|
+
}
|
|
135
|
+
|
|
129
136
|
if (h.state === 'idle_config') {
|
|
130
137
|
return { status: 'Ready', act: 'stop', label: 'Stop', tone: 'warn', busy: false, alt: null,
|
|
131
138
|
sub: `It is on, but idle because ${h.why || 'of a setting'}. ${h.remedy || ''}`.trim() };
|
package/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.25.
|
|
3
|
+
"version": "1.25.33",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@bongos/core",
|
|
9
|
-
"version": "1.25.
|
|
9
|
+
"version": "1.25.33",
|
|
10
10
|
"license": "AGPL-3.0-or-later",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"express": "^4.21.2",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.25.
|
|
3
|
+
"version": "1.25.33",
|
|
4
4
|
"description": "Cloud Bongos — the AI-first build platform core (GDS + platform surfaces + module system), installed as a versioned dependency (ADR 0108).",
|
|
5
5
|
"license": "AGPL-3.0-or-later",
|
|
6
6
|
"main": "src/platform-server.js",
|
package/release-notes.json
CHANGED
|
@@ -11967,5 +11967,11 @@
|
|
|
11967
11967
|
"id": "1005308",
|
|
11968
11968
|
"text": "The old circuit-city painting is gone. The welcome screen and the game's start screens now open on the city in the clouds, coloured for the time of day: deep night with lit windows, a warm dawn, a bright midday."
|
|
11969
11969
|
}
|
|
11970
|
+
],
|
|
11971
|
+
"1.25.33": [
|
|
11972
|
+
{
|
|
11973
|
+
"id": "1005202",
|
|
11974
|
+
"text": "A runner that cannot download new code from GitHub now shows \"Stuck on old code\" on its card, with the fix, instead of looking healthy."
|
|
11975
|
+
}
|
|
11970
11976
|
]
|
|
11971
11977
|
}
|
|
@@ -308,18 +308,28 @@ function git(args, opts = {}) {
|
|
|
308
308
|
}
|
|
309
309
|
|
|
310
310
|
// refreshCheckout — the .cmd's fetch + reset, on the runner's own copy only.
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
311
|
+
//
|
|
312
|
+
// Straight fetch failures are counted in `counter` and handed to the supervisor
|
|
313
|
+
// through `env` (AUTOBONGOS_FETCH_FAILURES), which seeds its own count, so its
|
|
314
|
+
// check-in can say `cannot_fetch` and the device's card stops reading healthy
|
|
315
|
+
// (task 1005202). The collaborators are injectable for the test only.
|
|
316
|
+
function refreshCheckout(log = () => {}, {
|
|
317
|
+
git: gitFn = git, assert = assertRunnerCopy, remedy = githubRemedy, counter = null, env = null,
|
|
318
|
+
} = {}) {
|
|
319
|
+
assert();
|
|
320
|
+
const f = gitFn(['fetch', '--quiet', 'origin', 'main']);
|
|
321
|
+
const fetched = f.status === 0;
|
|
322
|
+
if (counter) counter.fetchFailures = fetched ? 0 : (counter.fetchFailures || 0) + 1;
|
|
323
|
+
if (counter && env) env.AUTOBONGOS_FETCH_FAILURES = String(counter.fetchFailures);
|
|
324
|
+
if (!fetched) {
|
|
325
|
+
// A fetch that fails for a credential reason fails every loop, and the runner then
|
|
326
|
+
// works forever on the code it happens to have (task 1005096), so the log carries
|
|
327
|
+
// the remedy, and the count above carries the fact to the card.
|
|
318
328
|
log(`git fetch failed — running the code already here (${String(f.stderr || '').trim().slice(0, 200)})`);
|
|
319
|
-
log(` if that keeps happening, it is not transient: ${
|
|
329
|
+
log(` if that keeps happening, it is not transient: ${remedy()}`);
|
|
320
330
|
return false;
|
|
321
331
|
}
|
|
322
|
-
const r =
|
|
332
|
+
const r = gitFn(['reset', '--quiet', '--hard', 'origin/main']);
|
|
323
333
|
if (r.status !== 0) { log(`git reset failed (${String(r.stderr || '').trim().slice(0, 200)})`); return false; }
|
|
324
334
|
return true;
|
|
325
335
|
}
|
|
@@ -821,6 +831,7 @@ async function runCommand({ paths = hostPaths() } = {}) {
|
|
|
821
831
|
const log = makeLogger(paths, { echo: !!process.stdout.isTTY });
|
|
822
832
|
const env = supervisorEnv(process.env, paths, dirName);
|
|
823
833
|
const state = { child: null, stopping: false };
|
|
834
|
+
const fetchCounter = { fetchFailures: 0 }; // straight failed fetches, handed to the supervisor (task 1005202)
|
|
824
835
|
const keepAwake = makeKeepAwake();
|
|
825
836
|
const selfSha = fileSha(__filename);
|
|
826
837
|
writeLock(paths);
|
|
@@ -836,7 +847,7 @@ async function runCommand({ paths = hostPaths() } = {}) {
|
|
|
836
847
|
rotateLog(paths);
|
|
837
848
|
const out = await runLoop({}, {
|
|
838
849
|
log, shouldStop: () => state.stopping,
|
|
839
|
-
refresh: () => refreshCheckout(log),
|
|
850
|
+
refresh: () => refreshCheckout(log, { counter: fetchCounter, env }),
|
|
840
851
|
ensureDeps: () => ensureDeps(paths, log),
|
|
841
852
|
spawnSupervisor: () => spawnSupervisorReal({ paths, env, log, keepAwake, state }),
|
|
842
853
|
selfChanged: () => fileSha(__filename) !== selfSha,
|
|
@@ -924,5 +935,5 @@ module.exports = {
|
|
|
924
935
|
windowsRunArgv, windowsRunCommand, windowsStartSpawn, legacyBootTaskInstalled, launchdPlist,
|
|
925
936
|
stopRunner, stopReport, exchangeCode, claudeState, waitForCheckIn,
|
|
926
937
|
signIn, cleanBase, install, removeStartEntry, installedState, status, digestArgv,
|
|
927
|
-
githubRemedy, GITHUB_REMEDY_GENERIC,
|
|
938
|
+
githubRemedy, GITHUB_REMEDY_GENERIC, refreshCheckout,
|
|
928
939
|
};
|
|
@@ -511,8 +511,19 @@ const MAX_CLAIM_ATTEMPTS = 5;
|
|
|
511
511
|
// guess that is wrong costs one wasted spawn per half hour, not one per wake.
|
|
512
512
|
const LIMIT_UNKNOWN_RESET_MS = 30 * 60 * 1000;
|
|
513
513
|
|
|
514
|
+
// How many straight failures to reach origin before the check-in says
|
|
515
|
+
// `cannot_fetch` (task 1005202). A blip fails once or twice and clears; a
|
|
516
|
+
// credential fault (the active GitHub account cannot see the project) fails
|
|
517
|
+
// every time, forever, and the runner then works on whatever code it has. The
|
|
518
|
+
// polls inside a wait are a minute apart, so this is a few minutes of failing.
|
|
519
|
+
const CANNOT_FETCH_AFTER = 3;
|
|
520
|
+
|
|
521
|
+
// fetchFailures starts from the host wrapper's own count (AUTOBONGOS_FETCH_FAILURES,
|
|
522
|
+
// set by autobongos-host.js), so a restart does not reset the card to healthy.
|
|
514
523
|
function newRunnerState() {
|
|
515
|
-
|
|
524
|
+
const seeded = Number.parseInt(process.env.AUTOBONGOS_FETCH_FAILURES, 10);
|
|
525
|
+
return { setAside: new Map(), queueGate: null, limitUntil: null, diskHead: null, mainHead: null, landSweepAt: null,
|
|
526
|
+
fetchFailures: Number.isInteger(seeded) && seeded > 0 ? seeded : 0 };
|
|
516
527
|
}
|
|
517
528
|
const RUNNER_STATE = newRunnerState();
|
|
518
529
|
|
|
@@ -920,9 +931,23 @@ function heartbeatIdentity(deps = {}) {
|
|
|
920
931
|
return out;
|
|
921
932
|
}
|
|
922
933
|
|
|
934
|
+
// cannotFetchEvent — what a beat says once the runner has failed to reach the
|
|
935
|
+
// project CANNOT_FETCH_AFTER times in a row (task 1005202). It replaces the idle
|
|
936
|
+
// words ("waiting", "loop", nothing), which would otherwise read as healthy. It
|
|
937
|
+
// never hides a restart, a setting holding the runner, or the task in its hands:
|
|
938
|
+
// each of those is its own truth about this minute.
|
|
939
|
+
function cannotFetchEvent(fields = {}, state = RUNNER_STATE) {
|
|
940
|
+
if (!state || !((state.fetchFailures || 0) >= CANNOT_FETCH_AFTER)) return fields.last_event;
|
|
941
|
+
if (fields.working_task_id) return fields.last_event;
|
|
942
|
+
const ev = fields.last_event;
|
|
943
|
+
if (ev === 'upgrade_exit' || (typeof ev === 'string' && ev.startsWith('config_idle:'))) return ev;
|
|
944
|
+
return 'cannot_fetch';
|
|
945
|
+
}
|
|
946
|
+
|
|
923
947
|
async function postHeartbeat(fields = {}, deps = {}) {
|
|
924
948
|
try {
|
|
925
949
|
const api = deps.api || await (require('./cli-lib').cliClient)();
|
|
950
|
+
const lastEvent = cannotFetchEvent(fields, deps.state || RUNNER_STATE);
|
|
926
951
|
await api.autonomy.postAutonomyHeartbeat({
|
|
927
952
|
body: {
|
|
928
953
|
host: os.hostname(),
|
|
@@ -930,6 +955,7 @@ async function postHeartbeat(fields = {}, deps = {}) {
|
|
|
930
955
|
started_at: RUNNER_STARTED_AT,
|
|
931
956
|
...heartbeatIdentity(deps),
|
|
932
957
|
...fields,
|
|
958
|
+
...(lastEvent ? { last_event: lastEvent } : {}),
|
|
933
959
|
},
|
|
934
960
|
});
|
|
935
961
|
return true;
|
|
@@ -1165,11 +1191,17 @@ async function refreshCheckout(deps = {}) {
|
|
|
1165
1191
|
// The head of origin/main, or null. `git ls-remote` rather than `fetch`: it moves
|
|
1166
1192
|
// no refs and writes nothing, so polling it every few minutes cannot interfere
|
|
1167
1193
|
// with a worker building in a tree beside it.
|
|
1194
|
+
//
|
|
1195
|
+
// Every call also counts toward `fetchFailures` (task 1005202): a success clears
|
|
1196
|
+
// it, anything else adds one, so the heartbeat can say the runner cannot reach
|
|
1197
|
+
// the project instead of reading healthy on code it can never update.
|
|
1168
1198
|
async function runFetchHead(deps = {}) {
|
|
1169
1199
|
const runCmd = deps.run || run;
|
|
1170
|
-
const
|
|
1171
|
-
|
|
1172
|
-
|
|
1200
|
+
const st = deps.state || RUNNER_STATE;
|
|
1201
|
+
let r = null;
|
|
1202
|
+
try { r = await runCmd('git', ['ls-remote', 'origin', 'refs/heads/main']); } catch (_) { r = null; }
|
|
1203
|
+
const m = r && r.ok ? /^([0-9a-f]{40})/.exec(String(r.stdout).trim()) : null;
|
|
1204
|
+
st.fetchFailures = m ? 0 : (st.fetchFailures || 0) + 1;
|
|
1173
1205
|
return m ? m[1] : null;
|
|
1174
1206
|
}
|
|
1175
1207
|
|
|
@@ -1395,6 +1427,6 @@ module.exports = {
|
|
|
1395
1427
|
worktreeName, readFence, gradeLedgerPath, gradeCapReader, reconcileLeftoverClaims, pollSignals, waitOrJump, forever, CLAIM_PREFIX, codeDrifted, loadedHead, UPGRADE_EXIT_CODE, MIN_UPTIME_BEFORE_UPGRADE_MS,
|
|
1396
1428
|
heartbeatPath, writeHeartbeat, readHeartbeat, pidAlive, anotherRunnerIsAlive, HEARTBEAT_STALE_MS,
|
|
1397
1429
|
isRunnerTree, RUNNER_TREE_RE, postHeartbeat, claudeAccountLabel, RUNNER_STARTED_AT, failureReason,
|
|
1398
|
-
newRunnerState, loadedFiles, supervisorTouched, refreshCheckout, LIMIT_UNKNOWN_RESET_MS, QUEUE_GATED_EXIT, CLAIM_SET_ASIDE_MS, MAX_CLAIM_ATTEMPTS, owedTaskIds,
|
|
1430
|
+
newRunnerState, runFetchHead, cannotFetchEvent, CANNOT_FETCH_AFTER, loadedFiles, supervisorTouched, refreshCheckout, LIMIT_UNKNOWN_RESET_MS, QUEUE_GATED_EXIT, CLAIM_SET_ASIDE_MS, MAX_CLAIM_ATTEMPTS, owedTaskIds,
|
|
1399
1431
|
readRunLogRows, recheckPendingLands, LAND_SWEEP_MS,
|
|
1400
1432
|
};
|
package/src/module-api.js
CHANGED
|
@@ -81,7 +81,7 @@ const { sleep } = require('./sleep');
|
|
|
81
81
|
// MAJOR (see allowBoxScope below): passes the request through untouched.
|
|
82
82
|
function deprecatedNoopMiddleware(_req, _res, next) { next(); }
|
|
83
83
|
|
|
84
|
-
const CORE_VERSION = '1.25.
|
|
84
|
+
const CORE_VERSION = '1.25.33'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
|
|
85
85
|
|
|
86
86
|
// A namespaced logger so a module's log lines are attributable + consistent.
|
|
87
87
|
// Usage: const log = api.logger('discord'); log.info('mounted');
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
// tests/autobongos_cannot_fetch.mjs — a runner that can never fetch says so on
|
|
2
|
+
// its card (task 1005202).
|
|
3
|
+
//
|
|
4
|
+
// Found on a real Mac: two GitHub accounts were signed in, the active one could
|
|
5
|
+
// not see the private project, and every `git fetch` 404'd. The runner checked in
|
|
6
|
+
// as healthy and worked on the code it happened to clone, forever; only its own
|
|
7
|
+
// log said otherwise. These pin the signal end to end: the host and the
|
|
8
|
+
// supervisor count straight fetch failures, past CANNOT_FETCH_AFTER the check-in
|
|
9
|
+
// says `cannot_fetch`, the verdict is not ok and carries the remedy, and the
|
|
10
|
+
// device's button and checklist stop reading healthy. One good fetch clears it.
|
|
11
|
+
//
|
|
12
|
+
// DB-free, no network. Run: node --test tests/autobongos_cannot_fetch.mjs
|
|
13
|
+
|
|
14
|
+
import { test } from 'node:test';
|
|
15
|
+
import assert from 'node:assert/strict';
|
|
16
|
+
import path from 'node:path';
|
|
17
|
+
import { createRequire } from 'node:module';
|
|
18
|
+
import { fileURLToPath } from 'node:url';
|
|
19
|
+
|
|
20
|
+
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
21
|
+
const req = createRequire(import.meta.url);
|
|
22
|
+
const runner = req(path.join(ROOT, 'scripts/bongos/autobongos-run.js'));
|
|
23
|
+
const host = req(path.join(ROOT, 'scripts/bongos/autobongos-host.js'));
|
|
24
|
+
const health = req(path.join(ROOT, 'modules/autonomy/runner-health.js'));
|
|
25
|
+
const RB = req(path.join(ROOT, 'modules/hall-ui/public/runner-button.js'));
|
|
26
|
+
|
|
27
|
+
const A = 'a'.repeat(40);
|
|
28
|
+
const NOW = Date.parse('2026-11-14T12:00:00.000Z');
|
|
29
|
+
const agoS = (s) => new Date(NOW - s * 1000).toISOString();
|
|
30
|
+
|
|
31
|
+
const failing = async () => ({ ok: false, stdout: '', stderr: 'remote: Repository not found.' });
|
|
32
|
+
const working = async () => ({ ok: true, stdout: `${A}\trefs/heads/main\n` });
|
|
33
|
+
|
|
34
|
+
function recorder() {
|
|
35
|
+
const bodies = [];
|
|
36
|
+
const api = { autonomy: { postAutonomyHeartbeat: async ({ body }) => { bodies.push(body); return { ok: true }; } } };
|
|
37
|
+
return { bodies, api };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
test('the supervisor counts straight failures to reach main, and one success clears the count', async () => {
|
|
41
|
+
const state = runner.newRunnerState();
|
|
42
|
+
assert.equal(state.fetchFailures, 0);
|
|
43
|
+
for (let i = 1; i <= 3; i++) {
|
|
44
|
+
assert.equal(await runner.runFetchHead({ run: failing, state }), null);
|
|
45
|
+
assert.equal(state.fetchFailures, i);
|
|
46
|
+
}
|
|
47
|
+
await runner.runFetchHead({ run: async () => { throw new Error('spawn git ENOENT'); }, state });
|
|
48
|
+
assert.equal(state.fetchFailures, 4, 'a git that cannot even start is a failure too');
|
|
49
|
+
assert.equal(await runner.runFetchHead({ run: working, state }), A);
|
|
50
|
+
assert.equal(state.fetchFailures, 0);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test('past the threshold the check-in says cannot_fetch instead of a healthy idle', async () => {
|
|
54
|
+
const { bodies, api } = recorder();
|
|
55
|
+
const state = runner.newRunnerState();
|
|
56
|
+
const deps = { api, state, claudeAccountLabel: () => null };
|
|
57
|
+
for (let i = 0; i < runner.CANNOT_FETCH_AFTER - 1; i++) await runner.runFetchHead({ run: failing, state });
|
|
58
|
+
await runner.postHeartbeat({ last_event: 'waiting' }, deps);
|
|
59
|
+
assert.equal(bodies.at(-1).last_event, 'waiting', 'a blip below the threshold is not an alarm');
|
|
60
|
+
|
|
61
|
+
await runner.runFetchHead({ run: failing, state });
|
|
62
|
+
for (const ev of ['waiting', 'loop', 'nothing_claimable', undefined]) {
|
|
63
|
+
await runner.postHeartbeat(ev ? { last_event: ev } : {}, deps);
|
|
64
|
+
assert.equal(bodies.at(-1).last_event, 'cannot_fetch', String(ev));
|
|
65
|
+
}
|
|
66
|
+
// What it must never hide: a restart, a setting holding it, or the task in its hands.
|
|
67
|
+
await runner.postHeartbeat({ last_event: 'upgrade_exit' }, deps);
|
|
68
|
+
assert.equal(bodies.at(-1).last_event, 'upgrade_exit');
|
|
69
|
+
await runner.postHeartbeat({ last_event: 'config_idle:no_goals' }, deps);
|
|
70
|
+
assert.equal(bodies.at(-1).last_event, 'config_idle:no_goals');
|
|
71
|
+
await runner.postHeartbeat({ last_event: 'claimed', working_task_id: 7 }, deps);
|
|
72
|
+
assert.equal(bodies.at(-1).last_event, 'claimed');
|
|
73
|
+
|
|
74
|
+
await runner.runFetchHead({ run: working, state });
|
|
75
|
+
await runner.postHeartbeat({ last_event: 'waiting' }, deps);
|
|
76
|
+
assert.equal(bodies.at(-1).last_event, 'waiting', 'one good fetch and the card reads healthy again');
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test('the host counts its own failed fetches and hands the count to the supervisor it starts', () => {
|
|
80
|
+
const env = {};
|
|
81
|
+
const counter = { fetchFailures: 0 };
|
|
82
|
+
const bad = () => ({ status: 128, stdout: '', stderr: 'fatal: repository not found' });
|
|
83
|
+
const good = () => ({ status: 0, stdout: '', stderr: '' });
|
|
84
|
+
const opts = { git: bad, assert: () => {}, remedy: () => 'switch account', counter, env };
|
|
85
|
+
assert.equal(host.refreshCheckout(() => {}, opts), false);
|
|
86
|
+
assert.equal(host.refreshCheckout(() => {}, opts), false);
|
|
87
|
+
assert.equal(counter.fetchFailures, 2);
|
|
88
|
+
assert.equal(env.AUTOBONGOS_FETCH_FAILURES, '2');
|
|
89
|
+
// The supervisor it starts begins from that count, so the card does not wait
|
|
90
|
+
// for a fresh run of failures after every restart.
|
|
91
|
+
const saved = process.env.AUTOBONGOS_FETCH_FAILURES;
|
|
92
|
+
process.env.AUTOBONGOS_FETCH_FAILURES = env.AUTOBONGOS_FETCH_FAILURES;
|
|
93
|
+
try { assert.equal(runner.newRunnerState().fetchFailures, 2); } finally {
|
|
94
|
+
if (saved === undefined) delete process.env.AUTOBONGOS_FETCH_FAILURES; else process.env.AUTOBONGOS_FETCH_FAILURES = saved;
|
|
95
|
+
}
|
|
96
|
+
assert.equal(host.refreshCheckout(() => {}, { ...opts, git: good }), true);
|
|
97
|
+
assert.equal(counter.fetchFailures, 0);
|
|
98
|
+
assert.equal(env.AUTOBONGOS_FETCH_FAILURES, '0');
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test('the verdict is cannot_fetch: not ok, and it carries the remedy', () => {
|
|
102
|
+
const d = health.describeRunner({ host: 'mac-mini', mode: 'full', last_event: 'cannot_fetch', last_seen_at: agoS(30) }, { nowMs: NOW });
|
|
103
|
+
assert.equal(d.state, 'cannot_fetch');
|
|
104
|
+
assert.equal(d.ok, false, 'a runner pinned to old code is not healthy');
|
|
105
|
+
assert.match(d.detail, /mac-mini/);
|
|
106
|
+
assert.match(d.remedy, /gh auth switch/);
|
|
107
|
+
// Silence still wins: a runner nobody has heard from cannot vouch for anything.
|
|
108
|
+
assert.equal(health.describeRunner({ host: 'mac-mini', last_event: 'cannot_fetch', last_seen_at: agoS(3 * 3600) }, { nowMs: NOW }).state, 'dead');
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
test("the device's button says it is stuck on old code, and names the fix", () => {
|
|
112
|
+
const fence = { enabled: true, scope: { goals: [1] }, project: { enabled: true, goals: [{ goal_id: 1 }] } };
|
|
113
|
+
const runnerRow = {
|
|
114
|
+
host: 'mac-mini', run_requested: true, run_changed_at: agoS(3600), last_seen_at: agoS(30),
|
|
115
|
+
health: { state: 'cannot_fetch', host: 'mac-mini', age: '30s', remedy: 'Run gh auth switch on it.' },
|
|
116
|
+
};
|
|
117
|
+
const b = RB.buttonState({ runner: runnerRow, fence, nowMs: NOW });
|
|
118
|
+
assert.equal(b.status, 'Stuck on old code');
|
|
119
|
+
assert.equal(b.tone, 'warn');
|
|
120
|
+
assert.equal(b.act, 'stop');
|
|
121
|
+
assert.match(b.sub, /cannot fetch new code/);
|
|
122
|
+
assert.match(b.sub, /gh auth switch/);
|
|
123
|
+
});
|