@bongos/core 1.19.120 → 1.19.122
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 +60 -30
- package/.claude/skills/builder-end/SKILL.md +3 -3
- package/clients/bongos-client/index.d.ts +1 -1
- package/config/branding.neutral.json +1 -0
- package/docs/api/openapi.json +3 -0
- package/docs/api-reference.md +1 -1
- package/docs/branding-contract.md +1 -0
- package/docs/file-map.md +2 -0
- package/docs/recipes/ops-gotchas.md +2 -0
- package/docs/recipes/windows-builders.md +103 -0
- package/modules/provisioning/provisioning.js +37 -0
- package/modules/provisioning/routes/provisioning.js +93 -3
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/public-landing/projects.html +38 -2
- package/scripts/gds/api.js +12 -2
- package/scripts/gds/cli-lib.js +29 -0
- package/scripts/gds/init.js +8 -2
- package/scripts/gds/onboard.js +1 -1
- package/scripts/gds/ship.js +52 -7
- package/scripts/gds/worktree.js +252 -0
- package/src/bongos/serve-internal.js +11 -2
- package/src/module-api.js +5 -1
- package/tests/api_msys_path_repair.mjs +104 -0
- package/tests/provisioning_default_domain.mjs +331 -0
- package/tests/provisioning_domain_attach.mjs +1 -0
- package/tests/provisioning_teardown_intent.mjs +1 -0
- package/tests/ship_post_land_verify.mjs +114 -0
- package/tests/worktree_helper.mjs +145 -0
package/.bongos-core.json
CHANGED
|
@@ -2,22 +2,22 @@
|
|
|
2
2
|
"artifact": "bongos-core",
|
|
3
3
|
"manifest_schema": 1,
|
|
4
4
|
"generator": "scripts/gds/package-core.js",
|
|
5
|
-
"core_version": "1.19.
|
|
6
|
-
"core_contract": "1.19.
|
|
7
|
-
"source_commit": "
|
|
5
|
+
"core_version": "1.19.122",
|
|
6
|
+
"core_contract": "1.19.122",
|
|
7
|
+
"source_commit": "b8e5d6f6d62653ae415e42551ccb3c3c4e6c6f8a",
|
|
8
8
|
"source_ref": "HEAD",
|
|
9
|
-
"built_at": "2026-08-
|
|
9
|
+
"built_at": "2026-08-14T21:05:40.247Z",
|
|
10
10
|
"redaction": {
|
|
11
11
|
"model": "docs-redacted+functional-verbatim",
|
|
12
|
-
"docs_redacted":
|
|
12
|
+
"docs_redacted": 303,
|
|
13
13
|
"agent_docs_stubbed": 21,
|
|
14
|
-
"functional_verbatim":
|
|
14
|
+
"functional_verbatim": 1244,
|
|
15
15
|
"rules": 3,
|
|
16
16
|
"gate_literals": 3,
|
|
17
17
|
"gate": "passed"
|
|
18
18
|
},
|
|
19
|
-
"file_count":
|
|
20
|
-
"tree_sha256": "
|
|
19
|
+
"file_count": 1568,
|
|
20
|
+
"tree_sha256": "03f0574ec4219110a53d6b8faaa4b93bcc96f0371d85d2a2e412d06d21364892",
|
|
21
21
|
"files": [
|
|
22
22
|
{
|
|
23
23
|
"path": ".claude/skills/blocker-review/SKILL.md",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
{
|
|
58
58
|
"path": ".claude/skills/builder-end/SKILL.md",
|
|
59
59
|
"mode": "0000644",
|
|
60
|
-
"sha256": "
|
|
60
|
+
"sha256": "79afe09324f8b9ac27e0500972af701020d502f4a2502323b821ff5234216f70"
|
|
61
61
|
},
|
|
62
62
|
{
|
|
63
63
|
"path": ".claude/skills/builder-exit/SKILL.md",
|
|
@@ -367,7 +367,7 @@
|
|
|
367
367
|
{
|
|
368
368
|
"path": "clients/bongos-client/index.d.ts",
|
|
369
369
|
"mode": "0000644",
|
|
370
|
-
"sha256": "
|
|
370
|
+
"sha256": "eeb9b7bdf6054c92e3c605201c846d67ea20dd927355d2dc72479477c073fc7c"
|
|
371
371
|
},
|
|
372
372
|
{
|
|
373
373
|
"path": "clients/bongos-client/index.mjs",
|
|
@@ -382,7 +382,7 @@
|
|
|
382
382
|
{
|
|
383
383
|
"path": "config/branding.neutral.json",
|
|
384
384
|
"mode": "0000644",
|
|
385
|
-
"sha256": "
|
|
385
|
+
"sha256": "dc69c5c9e9041da9cd3c297c3e7c81c8311f42952524297d9f228cc1751af3ea"
|
|
386
386
|
},
|
|
387
387
|
{
|
|
388
388
|
"path": "config/design-tokens.neutral.json",
|
|
@@ -1337,12 +1337,12 @@
|
|
|
1337
1337
|
{
|
|
1338
1338
|
"path": "docs/api-reference.md",
|
|
1339
1339
|
"mode": "0000644",
|
|
1340
|
-
"sha256": "
|
|
1340
|
+
"sha256": "b9af2341b7017c6e21b53a611a824b8d3a59653f967e6f83218c9f1d25d0ff58"
|
|
1341
1341
|
},
|
|
1342
1342
|
{
|
|
1343
1343
|
"path": "docs/api/openapi.json",
|
|
1344
1344
|
"mode": "0000644",
|
|
1345
|
-
"sha256": "
|
|
1345
|
+
"sha256": "35762381d39e1943558131e97d3541e28d47161a56ec0a3d664942c90fb9fa9b"
|
|
1346
1346
|
},
|
|
1347
1347
|
{
|
|
1348
1348
|
"path": "docs/architecture.md",
|
|
@@ -1352,7 +1352,7 @@
|
|
|
1352
1352
|
{
|
|
1353
1353
|
"path": "docs/branding-contract.md",
|
|
1354
1354
|
"mode": "0000644",
|
|
1355
|
-
"sha256": "
|
|
1355
|
+
"sha256": "f5918fa955f90ca30412ebce209bf2d51b67fa318f7f04d667262cd42c134745"
|
|
1356
1356
|
},
|
|
1357
1357
|
{
|
|
1358
1358
|
"path": "docs/branding-fill-prompt.md",
|
|
@@ -1467,7 +1467,7 @@
|
|
|
1467
1467
|
{
|
|
1468
1468
|
"path": "docs/file-map.md",
|
|
1469
1469
|
"mode": "0000644",
|
|
1470
|
-
"sha256": "
|
|
1470
|
+
"sha256": "f76f816dbbab7668c7dbd1ff7406dee095e043f23262a2c6afd900ff9c59b337"
|
|
1471
1471
|
},
|
|
1472
1472
|
{
|
|
1473
1473
|
"path": "docs/handoff-template.md",
|
|
@@ -1642,7 +1642,7 @@
|
|
|
1642
1642
|
{
|
|
1643
1643
|
"path": "docs/recipes/ops-gotchas.md",
|
|
1644
1644
|
"mode": "0000644",
|
|
1645
|
-
"sha256": "
|
|
1645
|
+
"sha256": "6374ff40b5b054d57761d25bf7b21059c8b2d8d35354120cc221431edd3260a2"
|
|
1646
1646
|
},
|
|
1647
1647
|
{
|
|
1648
1648
|
"path": "docs/recipes/overnight-builder.md",
|
|
@@ -1699,6 +1699,11 @@
|
|
|
1699
1699
|
"mode": "0000644",
|
|
1700
1700
|
"sha256": "732f3b01b7d2e6cc238dd5f48d5ed774f6c2c27ecc737710047758bf85f2d9e5"
|
|
1701
1701
|
},
|
|
1702
|
+
{
|
|
1703
|
+
"path": "docs/recipes/windows-builders.md",
|
|
1704
|
+
"mode": "0000644",
|
|
1705
|
+
"sha256": "2e24454839aa02d1f3205dd92a6856254e59ca04f88573a1f42641ddb5924e32"
|
|
1706
|
+
},
|
|
1702
1707
|
{
|
|
1703
1708
|
"path": "docs/recipes/work-on-a-task-from-your-dev-box.md",
|
|
1704
1709
|
"mode": "0000644",
|
|
@@ -3857,7 +3862,7 @@
|
|
|
3857
3862
|
{
|
|
3858
3863
|
"path": "modules/provisioning/provisioning.js",
|
|
3859
3864
|
"mode": "0000644",
|
|
3860
|
-
"sha256": "
|
|
3865
|
+
"sha256": "59fd212df421b2bdcdfaef4871aa1927c371d3f7d6affafe44e810135acd12b6"
|
|
3861
3866
|
},
|
|
3862
3867
|
{
|
|
3863
3868
|
"path": "modules/provisioning/rate-limit.js",
|
|
@@ -3867,7 +3872,7 @@
|
|
|
3867
3872
|
{
|
|
3868
3873
|
"path": "modules/provisioning/routes/provisioning.js",
|
|
3869
3874
|
"mode": "0000644",
|
|
3870
|
-
"sha256": "
|
|
3875
|
+
"sha256": "321db8769eda7c5f6f385e90edaeec70fc071f0bc2e53e6147705153b0d32d3a"
|
|
3871
3876
|
},
|
|
3872
3877
|
{
|
|
3873
3878
|
"path": "modules/provisioning/tests/liveness.mjs",
|
|
@@ -4162,12 +4167,12 @@
|
|
|
4162
4167
|
{
|
|
4163
4168
|
"path": "package-lock.json",
|
|
4164
4169
|
"mode": "0000644",
|
|
4165
|
-
"sha256": "
|
|
4170
|
+
"sha256": "969a257b3ae8148774d7d64cef01f68be0eec703043a129ae34984f3399208d9"
|
|
4166
4171
|
},
|
|
4167
4172
|
{
|
|
4168
4173
|
"path": "package.json",
|
|
4169
4174
|
"mode": "0000644",
|
|
4170
|
-
"sha256": "
|
|
4175
|
+
"sha256": "904c4fce25eeb089d80da1a5a0cfced1a96b99aea4f2bc28e5ce07d66bd8a880"
|
|
4171
4176
|
},
|
|
4172
4177
|
{
|
|
4173
4178
|
"path": "public-docs/index.html",
|
|
@@ -4422,7 +4427,7 @@
|
|
|
4422
4427
|
{
|
|
4423
4428
|
"path": "public-landing/projects.html",
|
|
4424
4429
|
"mode": "0000644",
|
|
4425
|
-
"sha256": "
|
|
4430
|
+
"sha256": "925e7964f66d59f2df260a611e602bdeafe3f8f3b73d3d16db7bdfa073b4163c"
|
|
4426
4431
|
},
|
|
4427
4432
|
{
|
|
4428
4433
|
"path": "public-landing/world/assets/clouds/cloud-island-large.png",
|
|
@@ -4507,7 +4512,7 @@
|
|
|
4507
4512
|
{
|
|
4508
4513
|
"path": "scripts/gds/api.js",
|
|
4509
4514
|
"mode": "0000644",
|
|
4510
|
-
"sha256": "
|
|
4515
|
+
"sha256": "96d6b69e9440dac3ed81c490e460a832d385714de0b379650af80817f89ded0f"
|
|
4511
4516
|
},
|
|
4512
4517
|
{
|
|
4513
4518
|
"path": "scripts/gds/api.ps1",
|
|
@@ -4657,7 +4662,7 @@
|
|
|
4657
4662
|
{
|
|
4658
4663
|
"path": "scripts/gds/cli-lib.js",
|
|
4659
4664
|
"mode": "0000644",
|
|
4660
|
-
"sha256": "
|
|
4665
|
+
"sha256": "83d27d14600c4c8ec8912c7ad8ce771e0e34903ccc9b567dcc27cb95aeb3c37d"
|
|
4661
4666
|
},
|
|
4662
4667
|
{
|
|
4663
4668
|
"path": "scripts/gds/code.js",
|
|
@@ -4887,7 +4892,7 @@
|
|
|
4887
4892
|
{
|
|
4888
4893
|
"path": "scripts/gds/init.js",
|
|
4889
4894
|
"mode": "0000644",
|
|
4890
|
-
"sha256": "
|
|
4895
|
+
"sha256": "bde86f3f65cdd4a1ad0e143c58f6517328dd7cdee7c1194c0fa614aaf9df56f6"
|
|
4891
4896
|
},
|
|
4892
4897
|
{
|
|
4893
4898
|
"path": "scripts/gds/install-git-hooks.js",
|
|
@@ -5032,7 +5037,7 @@
|
|
|
5032
5037
|
{
|
|
5033
5038
|
"path": "scripts/gds/onboard.js",
|
|
5034
5039
|
"mode": "0000644",
|
|
5035
|
-
"sha256": "
|
|
5040
|
+
"sha256": "c6fb2c531c6d84dcb16daea50984e1b24021b6379cf992a01482951b119bf9e4"
|
|
5036
5041
|
},
|
|
5037
5042
|
{
|
|
5038
5043
|
"path": "scripts/gds/onboarding-analyze.js",
|
|
@@ -5307,7 +5312,7 @@
|
|
|
5307
5312
|
{
|
|
5308
5313
|
"path": "scripts/gds/ship.js",
|
|
5309
5314
|
"mode": "0000644",
|
|
5310
|
-
"sha256": "
|
|
5315
|
+
"sha256": "7ae14021dbae94ffc5a70cf05081e645ca2dcf9685ccf135658538cb44e79dde"
|
|
5311
5316
|
},
|
|
5312
5317
|
{
|
|
5313
5318
|
"path": "scripts/gds/smoke-batch-claim.sh",
|
|
@@ -5384,6 +5389,11 @@
|
|
|
5384
5389
|
"mode": "0000644",
|
|
5385
5390
|
"sha256": "32e0c1f2a955d4cabeae00d3749b283abd70f05f34b5fcbd84be3f35e2e655c8"
|
|
5386
5391
|
},
|
|
5392
|
+
{
|
|
5393
|
+
"path": "scripts/gds/worktree.js",
|
|
5394
|
+
"mode": "0000644",
|
|
5395
|
+
"sha256": "74fc8349287498ede068156f904aaef3f7dbeafce2b40942dd5a8a2a0208564a"
|
|
5396
|
+
},
|
|
5387
5397
|
{
|
|
5388
5398
|
"path": "scripts/hall-preview/README.md",
|
|
5389
5399
|
"mode": "0000644",
|
|
@@ -5707,7 +5717,7 @@
|
|
|
5707
5717
|
{
|
|
5708
5718
|
"path": "src/bongos/serve-internal.js",
|
|
5709
5719
|
"mode": "0000644",
|
|
5710
|
-
"sha256": "
|
|
5720
|
+
"sha256": "465211ef9e62fd74828d326ab427b0b21b7b73f6124e842b55f8b23d51660ebe"
|
|
5711
5721
|
},
|
|
5712
5722
|
{
|
|
5713
5723
|
"path": "src/bongos/stealth-gate.js",
|
|
@@ -5742,7 +5752,7 @@
|
|
|
5742
5752
|
{
|
|
5743
5753
|
"path": "src/module-api.js",
|
|
5744
5754
|
"mode": "0000644",
|
|
5745
|
-
"sha256": "
|
|
5755
|
+
"sha256": "79041166a496039eff11ecc00334671609fadace4a54645cf2b287a5b5ff1a53"
|
|
5746
5756
|
},
|
|
5747
5757
|
{
|
|
5748
5758
|
"path": "src/module-loader/catalog.js",
|
|
@@ -5854,6 +5864,11 @@
|
|
|
5854
5864
|
"mode": "0000644",
|
|
5855
5865
|
"sha256": "3a54640e1707b27916b9f0168e1ca12141f34148be975d7cad74f02aac166977"
|
|
5856
5866
|
},
|
|
5867
|
+
{
|
|
5868
|
+
"path": "tests/api_msys_path_repair.mjs",
|
|
5869
|
+
"mode": "0000644",
|
|
5870
|
+
"sha256": "ebb0a0183ca30ebe5207c4703e85e49c32e958778d76373f597553cf259feb39"
|
|
5871
|
+
},
|
|
5857
5872
|
{
|
|
5858
5873
|
"path": "tests/api_pagination_contract.mjs",
|
|
5859
5874
|
"mode": "0000644",
|
|
@@ -7279,10 +7294,15 @@
|
|
|
7279
7294
|
"mode": "0000644",
|
|
7280
7295
|
"sha256": "edb6c5da9ec32536d50f7cb648b81b026b7926f73f891feb0906fc7343b5b11d"
|
|
7281
7296
|
},
|
|
7297
|
+
{
|
|
7298
|
+
"path": "tests/provisioning_default_domain.mjs",
|
|
7299
|
+
"mode": "0000644",
|
|
7300
|
+
"sha256": "1403cc764270e796b985cc0dc38cbf498001e4726b2bfe53020cc55d12d1ca66"
|
|
7301
|
+
},
|
|
7282
7302
|
{
|
|
7283
7303
|
"path": "tests/provisioning_domain_attach.mjs",
|
|
7284
7304
|
"mode": "0000644",
|
|
7285
|
-
"sha256": "
|
|
7305
|
+
"sha256": "fbbd7397fd03181e9c2ea58ed8accb1a9d9d66d4c904a09265161e1034b02f9f"
|
|
7286
7306
|
},
|
|
7287
7307
|
{
|
|
7288
7308
|
"path": "tests/provisioning_github_app_routes.mjs",
|
|
@@ -7297,7 +7317,7 @@
|
|
|
7297
7317
|
{
|
|
7298
7318
|
"path": "tests/provisioning_teardown_intent.mjs",
|
|
7299
7319
|
"mode": "0000644",
|
|
7300
|
-
"sha256": "
|
|
7320
|
+
"sha256": "68d328b69cd8b981e8454d679c00a757abeeafb4e083249489eec744cdd4898d"
|
|
7301
7321
|
},
|
|
7302
7322
|
{
|
|
7303
7323
|
"path": "tests/pruned_lockfile_integrity.mjs",
|
|
@@ -7609,6 +7629,11 @@
|
|
|
7609
7629
|
"mode": "0000644",
|
|
7610
7630
|
"sha256": "e236bc3d6882bc6ddf5d389371a92a96aec62769f14c37bbca31810bcbea0d61"
|
|
7611
7631
|
},
|
|
7632
|
+
{
|
|
7633
|
+
"path": "tests/ship_post_land_verify.mjs",
|
|
7634
|
+
"mode": "0000644",
|
|
7635
|
+
"sha256": "6df2fb6fde081c9d98baab346a794946a51e4e51e70d154d41d9e94939180d52"
|
|
7636
|
+
},
|
|
7612
7637
|
{
|
|
7613
7638
|
"path": "tests/ship_preflight.mjs",
|
|
7614
7639
|
"mode": "0000644",
|
|
@@ -7824,6 +7849,11 @@
|
|
|
7824
7849
|
"mode": "0000644",
|
|
7825
7850
|
"sha256": "aa1aab27bdfc5761586514fa07dacfad125fb1d5dcc7f01c060cbe3556985454"
|
|
7826
7851
|
},
|
|
7852
|
+
{
|
|
7853
|
+
"path": "tests/worktree_helper.mjs",
|
|
7854
|
+
"mode": "0000644",
|
|
7855
|
+
"sha256": "367e4c9a63bc8752b94d0fc7af171d34390034adc2a75c8ec15f00b335c077ca"
|
|
7856
|
+
},
|
|
7827
7857
|
{
|
|
7828
7858
|
"path": "tests/write_validation_gaps.mjs",
|
|
7829
7859
|
"mode": "0000644",
|
|
@@ -13,7 +13,7 @@ Composes operations that already exist, in a safe order, with the destructive on
|
|
|
13
13
|
|
|
14
14
|
1. **Resolve the claim** — `/builder-ship` when there's committed, shippable work; `/builder-release` when there isn't. (It calls the sibling skills; it does not re-implement shipping.)
|
|
15
15
|
2. **Clean-git verify** — refuse to go further if any *tracked* file is uncommitted. This is the same guard `scripts/gds/ship.js` enforces (`trackedDirty` in [`src/bongos/ship-preflight.js`](../../../src/bongos/ship-preflight.js)): untracked scratch is ignored, but a modified/staged/deleted tracked file means real work isn't committed — stop before anything is lost.
|
|
16
|
-
3. **Worktree teardown** — from the main checkout,
|
|
16
|
+
3. **Worktree teardown** — from the main checkout, remove this session's linked worktree via `node scripts/gds/worktree.js remove` (junction-aware), `prune`, and delete the now-merged `claude/<name>` branch.
|
|
17
17
|
4. **Box close-out (dev box only)** — if running on a dev box (`/etc/otb/box.env` exists), offer to `close-box` so the box stops billing. Optional and gated on a yes; declining just lets the box idle-park. On a laptop this step is skipped — there's no box to close.
|
|
18
18
|
|
|
19
19
|
It never pushes to `main`, never `ssh`-es, never runs a deploy — landing is `/builder-ship`'s job (server-mediated). It only ever touches the caller's **own** claim, **own** worktree, and **own** box.
|
|
@@ -46,7 +46,7 @@ Proceed only when **all** hold: we're in a linked worktree, the claim is resolve
|
|
|
46
46
|
You can't remove the worktree you're standing in, so run the removal **from the main checkout** — resolve its path the way `ship.js` does (`findMainWorktree`: parse `git worktree list --porcelain` for the block whose `branch` is `main`). From there:
|
|
47
47
|
|
|
48
48
|
```bash
|
|
49
|
-
|
|
49
|
+
node scripts/gds/worktree.js remove <this-worktree-path> # junction-aware wrapper: unlinks a node_modules junction FIRST, then runs `git worktree remove` (which still refuses a dirty tree; do not --force)
|
|
50
50
|
git worktree prune
|
|
51
51
|
git branch -d claude/<worktree-name> # -d (not -D): git refuses an unmerged branch, by design
|
|
52
52
|
```
|
|
@@ -69,7 +69,7 @@ Skip this entirely if step 0 found no `/etc/otb/box.env` (a laptop — there's n
|
|
|
69
69
|
## Constraints
|
|
70
70
|
|
|
71
71
|
- **Own-scoped.** Only this session's claim, this session's worktree, and the caller's own box — never another builder's claim, never another worktree, never `git worktree remove` a path you didn't create, never another builder's box.
|
|
72
|
-
- **Never destroy uncommitted work.** The clean-git verify gates teardown; `git worktree remove`
|
|
72
|
+
- **Never destroy uncommitted work.** The clean-git verify gates teardown; the dirty-tree refusal in `git worktree remove` and `git branch -d` (not `-D`) are the load-bearing safety nets — keep them as written. But note: that refusal does NOT protect a Windows worktree carrying a `node_modules` junction — node_modules is gitignored, so the clean check passes and `git worktree remove` (even without `--force`) follows the junction and deletes the SHARED node_modules (task 1002809). That is why teardown runs through `node scripts/gds/worktree.js remove`, which unlinks the junction first.
|
|
73
73
|
- **Box close is opt-in and destructive.** On a box, never `close-box` without an explicit yes — it deprovisions the box and any unshipped `/workspace` work is gone. Declining is always fine; the box idle-parks on its own.
|
|
74
74
|
- **Never push / ssh / deploy.** Landing goes through `/builder-ship` (server-mediated); this skill stays local to the builder's machine (its one possible API write is the opt-in own-scoped `close-box`).
|
|
75
75
|
- **The destructive steps (teardown, box-close) never run unattended without a clear go.** Ship vs. release can be inferred from state (commits ⇒ ship, none ⇒ release) and proceed; removing the worktree ends the session and closing the box destroys it, so wait for an explicit yes before steps 3 and 4.
|
|
@@ -252,7 +252,7 @@ export interface PostProvisioningInstancesIdForceTeardownResponse { ok: boolean;
|
|
|
252
252
|
export interface PostProvisioningInstancesIdGithubAppRequest { account?: string }
|
|
253
253
|
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 }
|
|
254
254
|
export interface PostProvisioningInstancesIdTeardownResponse { ok: boolean; queued: unknown; action: unknown; status: unknown; superseded: unknown; message: unknown }
|
|
255
|
-
export interface PostProvisioningInstancesRequest { slug: string; target_ref?: string; hosting_shape?: string; domain?: string; tier?: string; onboard_mode?: string; type?: string }
|
|
255
|
+
export interface PostProvisioningInstancesRequest { slug: string; target_ref?: string; hosting_shape?: string; domain?: string; no_address?: boolean; tier?: string; onboard_mode?: string; type?: string }
|
|
256
256
|
export interface PostSearchMarkRequest { chunk_id?: StringifiableId; useful?: unknown }
|
|
257
257
|
export interface PostSearchRequest { expand?: unknown; q?: string; source_kind?: string; limit?: unknown }
|
|
258
258
|
export interface PostSearchResponse { expand?: unknown; chunk?: unknown; query?: unknown; count?: unknown; total_full_tokens?: unknown; results?: unknown }
|
package/docs/api/openapi.json
CHANGED
|
@@ -15826,6 +15826,9 @@
|
|
|
15826
15826
|
"type": "string",
|
|
15827
15827
|
"maxLength": 253
|
|
15828
15828
|
},
|
|
15829
|
+
"no_address": {
|
|
15830
|
+
"type": "boolean"
|
|
15831
|
+
},
|
|
15829
15832
|
"tier": {
|
|
15830
15833
|
"type": "string",
|
|
15831
15834
|
"maxLength": 40
|
package/docs/api-reference.md
CHANGED
|
@@ -368,7 +368,7 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/<redacted>
|
|
|
368
368
|
| GET | `/api/bongos/provisioning/github-app/status` | `public` | — | GET /provisioning/github-app/status?state=<> — the PUBLIC progress read the onboarding callback page polls (task 2096) to know when setup… |
|
|
369
369
|
| GET | `/api/bongos/provisioning/health` | `public` | — | GET /provisioning/health — liveness + the core version this module mounted against. |
|
|
370
370
|
| GET | `/api/bongos/provisioning/instances` | `any-builder` | — | GET /provisioning/instances — the caller's own instances + each open intent. |
|
|
371
|
-
| POST | `/api/bongos/provisioning/instances` | `any-builder` | `slug`, `target_ref`, `hosting_shape`, `domain`, `tier`, `onboard_mode`, `type` | POST /provisioning/instances — request a new instance. |
|
|
371
|
+
| POST | `/api/bongos/provisioning/instances` | `any-builder` | `slug`, `target_ref`, `hosting_shape`, `domain`, `no_address`, `tier`, `onboard_mode`, `type` | POST /provisioning/instances — request a new instance. |
|
|
372
372
|
| GET | `/api/bongos/provisioning/instances/:id` | `any-builder` | — | GET /provisioning/instances/:id — read one of the caller's own instances. |
|
|
373
373
|
| POST | `/api/bongos/provisioning/instances/:id/domain` | `any-builder` | `domain` | POST /provisioning/instances/:id/domain — give the caller's OWN instance its address (task 1002692, gap 5: no path existed to add a domai… |
|
|
374
374
|
| POST | `/api/bongos/provisioning/instances/:id/force-teardown` | `metic+archon` | — | POST /provisioning/instances/:id/force-teardown — Archon tears down ANY instance. |
|
|
@@ -31,6 +31,7 @@ env override → instance config (config/branding.json) → neutral star
|
|
|
31
31
|
| `domains.provisioningOrigin` | **Optional.** Control-plane front-door origin the [provisioning module](../../modules/provisioning/CLAUDE.md) uses to build a new customer's GitHub-App `redirect_url`. Set it when the control plane co-hosts a game whose `publicOrigin` is the game's own domain (OTB = customer 0) so the customer's App carries the PLATFORM brand (e.g. `https://get.cloudbongos.com`), not the game's. **Falls back to `publicOrigin` when unset** — an instance whose `publicOrigin` is already the platform needs no override. Env-overridable: `<PREFIX>_PROVISIONING_ORIGIN`. ([#2101](https://example.com/builders#/task/2101)) |
|
|
32
32
|
| `domains.devBoxBase` | Apex zone the **proxied** browser-terminal + sandbox hosts ride (`term-<login>.<devBoxBase>`, `sandbox-<login>.<devBoxBase>`). Must be a one-label-under-apex zone so free edge TLS (`*.<apex>`) covers it — a two-label host fails edge TLS (the [#771](https://example.com/builders#/task/771) lesson). Empty ⇒ no managed boxes. |
|
|
33
33
|
| `domains.sshBoxBase` | Zone for the **legacy direct-IP SSH** box host (`box-<login>.<sshBoxBase>`, unproxied). Deliberately distinct from `devBoxBase` (one proxied/edge-TLS, one direct-IP). |
|
|
34
|
+
| `domains.instanceBase` | Apex zone new projects get their **auto-assigned** address under (`<slug>.<instanceBase>`, task 1002704 — every project's hall reachable day one; `no_address: true` on the create call opts out). Same one-label-under-apex/edge-TLS constraint as `devBoxBase`. Deliberately NOT derived from `publicOrigin` (on a co-hosting control plane that is the game's domain). Empty ⇒ no auto-assign — creates are domainless unless the caller brings a domain. |
|
|
34
35
|
| `domains.sandboxPrefix` / `termPrefix` | Subdomain prefixes for the sandbox-preview + browser-terminal hosts. |
|
|
35
36
|
| `repo` | `{ owner, name }` GitHub binding. |
|
|
36
37
|
| `db.database` | DB name the GDS pool connects to when neither `DATABASE_URL` nor `PGHOST`/`PGDATABASE` is set (`src/bongos/pool.js`, ADR 0062 §5). `null` in the neutral starter = **fail loud** rather than silently target a host DB. |
|
package/docs/file-map.md
CHANGED
|
@@ -56,6 +56,7 @@
|
|
|
56
56
|
│ ├── recipes/ ← long-form operational guides (formerly learnings/) — Postgres, Caddy, the pixel-art pipeline, etc.
|
|
57
57
|
│ │ ├── README.md
|
|
58
58
|
│ │ ├── ops-gotchas.md ← Postgres, Caddy, SSH, Mac toolchain recipes
|
|
59
|
+
│ │ ├── windows-builders.md ← (task 1002809) the Windows + Git Bash builder loop: worktree junction trap, api.js MSYS auto-repair, --body-file pattern, local test baseline
|
|
59
60
|
│ │ ├── pixel-art-pipeline.md
|
|
60
61
|
│ │ ├── overnight-builder.md ← (#358) operator runbook for the autonomous overnight session-runner
|
|
61
62
|
│ │ ├── builder-box-lifecycle.md ← (#598/ADR 0031) operator runbook: provision/park/wake/deprovision dev boxes, the two sweeps, config env, going-live steps
|
|
@@ -170,6 +171,7 @@
|
|
|
170
171
|
│ ├── smoke-box.sh ← (#598) hermetic box-lifecycle smoke (no DB/DO/network): runs tests/boxes.mjs + tests/cf_tunnel.mjs (#771 named tunnel) + route-rank + module-load
|
|
171
172
|
│ ├── recall.js ← `/recall` CLI: two-call progressive-disclosure search (summary → `--expand <id>`) over the GDS retrieval layer (ADR 0060); `node scripts/gds/recall.js <query>`
|
|
172
173
|
│ ├── capture.js ← file an idea_inbox row from the CLI (the ideas.capture kernel port); backs the "capture a tangent" flow across skills
|
|
174
|
+
│ ├── worktree.js ← (task 1002809) junction-safe worktree add/remove/list — outside-repo worktrees get a node_modules junction via node (no shell quoting), removed BEFORE `git worktree remove`
|
|
173
175
|
│ ├── learning-capture.js ← file a `learnings` row (DB-backed short-form rule capture, replacing hand-edited recipe files for a single gotcha)
|
|
174
176
|
│ ├── docs-entropy.js ← ([#…] docs-entropy) markdown-corpus linter: broken internal links + cross-file duplicate-prose detector across every tracked `.md`; `--verbose` / `--file-ideas`
|
|
175
177
|
│ ├── gen-diagrams.js ← generates the 5 onboarding diagrams (`.mmd`/`.svg`/`.png` + `assertions.json`) from templates in this file — never hand-edit a `.mmd`/assertions.json; runs on deploy
|
|
@@ -149,6 +149,8 @@ Organized by topic, not chronology. New entries go in the matching section; crea
|
|
|
149
149
|
|
|
150
150
|
## Windows / local dev (PowerShell)
|
|
151
151
|
|
|
152
|
+
> Git Bash builder-loop gotchas (worktree junctions, api.js path mangling, local test baseline) live in their own recipe: [windows-builders.md](windows-builders.md).
|
|
153
|
+
|
|
152
154
|
### PowerShell 5.1 turns a clean `node scripts/gds/*.js` exit into a false failure
|
|
153
155
|
|
|
154
156
|
- **Symptom:** Running `node scripts/gds/api.js GET /api/gds/me 2>&1` (or the same on `claim.js`/`ship.js`) inside a PowerShell 5.1 session reports failure — `$?` is `$false` and the stderr line surfaces as a `NativeCommandError` — even though node exited 0 and the JSON on stdout is exactly right.
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
---
|
|
2
|
+
track: internal
|
|
3
|
+
scope: builder tooling — the Windows + Git Bash builder loop (worktrees, api.js, ship.js, local tests)
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Building on Windows (Git Bash) — the gotchas, and what the tooling now does for you
|
|
7
|
+
|
|
8
|
+
Everything here was paid for at least once on a real Windows box (task 1002548's learnings, the
|
|
9
|
+
HANDOFF-apex-ui session, task 1002809). Most of it is now **fixed in the tooling** — this recipe
|
|
10
|
+
records what changed, what you still have to know, and the one destructive trap to respect.
|
|
11
|
+
PowerShell-specific gotchas (stderr false-failures, BOM) live in
|
|
12
|
+
[ops-gotchas.md → Windows / local dev](ops-gotchas.md#windows--local-dev-powershell).
|
|
13
|
+
|
|
14
|
+
## api.js: MSYS path mangling is auto-repaired (no more `MSYS_NO_PATHCONV=1`)
|
|
15
|
+
|
|
16
|
+
- **Was:** Git Bash rewrites a leading-slash argument before node sees it — `node scripts/gds/api.js GET /tasks/123`
|
|
17
|
+
arrived as `GET C:/Program Files/Git/tasks/123` and hit the usage error, unless every call was
|
|
18
|
+
prefixed `MSYS_NO_PATHCONV=1`.
|
|
19
|
+
- **Now (task 1002809):** `api.js` detects the mangled prefix via `EXEPATH` and strips it itself
|
|
20
|
+
(`repairMsysMangledPath` in `cli-lib.js`). Call it plain; the old env prefix is harmless if you
|
|
21
|
+
still type it out of habit.
|
|
22
|
+
- **Still true:** judge success by the JSON + status line, not folklore about exit codes — and if
|
|
23
|
+
you ever see the libuv `UV_HANDLE_CLOSING` assertion after the JSON printed, that teardown class
|
|
24
|
+
of bug is tracked in [scripts/gds/CLAUDE.md](../../scripts/gds/CLAUDE.md) (task 1002734's
|
|
25
|
+
`cliExit` rule).
|
|
26
|
+
|
|
27
|
+
## api.js: inline `--body` loses its quotes — use `--body-file`
|
|
28
|
+
|
|
29
|
+
Shells on Windows strip/re-split inline JSON quoting. The durable pattern for any POST/PATCH body:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# write the JSON with a real editor/tool, then:
|
|
33
|
+
node scripts/gds/api.js POST /tasks --body-file C:/tmp/body.json
|
|
34
|
+
# or pipe it (no temp file):
|
|
35
|
+
node scripts/gds/api.js POST /claims --body-file - <<'EOF'
|
|
36
|
+
{"task_id": 123, "worktree_name": "task-123"}
|
|
37
|
+
EOF
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
`api.js` now points you here when an inline `--body` fails to parse (task 1002809).
|
|
41
|
+
|
|
42
|
+
## Worktrees: prefer inside-repo; outside-repo needs the junction helper
|
|
43
|
+
|
|
44
|
+
Every claim gets its own real worktree (owner directive — see the `/builder-claim` skill). Two
|
|
45
|
+
placements work on Windows:
|
|
46
|
+
|
|
47
|
+
- **Default — `.claude/worktrees/<name>` (inside the repo).** No `node_modules` setup at all:
|
|
48
|
+
node's resolution walks up to the main checkout's copy. This is what the harness `EnterWorktree`
|
|
49
|
+
primitive creates.
|
|
50
|
+
- **Outside the repo (e.g. `C:/tmp/task-N`)** — useful because OneDrive briefly locks in-repo
|
|
51
|
+
dirs. An outside worktree can't walk up to `node_modules`, so it needs a **junction** — and this
|
|
52
|
+
is where the destructive trap lives. Use the helper, never hand-rolled `mklink`:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
node scripts/gds/worktree.js add <task-id> --outside # worktree + junction, no shell quoting
|
|
56
|
+
node scripts/gds/worktree.js remove task-<id> # unlinks the junction FIRST
|
|
57
|
+
node scripts/gds/worktree.js list # shows which worktrees carry junctions
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### ⚠ The trap (why the helper exists — task 1002809)
|
|
61
|
+
|
|
62
|
+
- `cmd //c mklink /J` from Git Bash **mangles quoted targets containing spaces** (the target grows
|
|
63
|
+
a leading `\`), producing a junction that resolves to nothing. The helper uses node's
|
|
64
|
+
`fs.symlinkSync(target, link, 'junction')` — no shell, no quoting, no elevation.
|
|
65
|
+
- `git worktree remove` (and `--force`) **follows a junction into its target** — with a hand-made
|
|
66
|
+
junction in place it deletes the **shared `node_modules` of the main checkout**. The helper
|
|
67
|
+
always unlinks the junction (link only) before calling git. If you ever bypass the helper:
|
|
68
|
+
remove the junction yourself first (`fs.rmdirSync` / `rmdir` on the link), then
|
|
69
|
+
`git worktree remove`.
|
|
70
|
+
|
|
71
|
+
## `Cannot find module 'pg'` (or any dep) inside a worktree
|
|
72
|
+
|
|
73
|
+
Run `npm install` in the **main checkout**, never in the worktree. Worktrees share the main
|
|
74
|
+
checkout's `node_modules` (by walk-up inside the repo, by junction outside); a second
|
|
75
|
+
`node_modules` inside a worktree only creates drift.
|
|
76
|
+
|
|
77
|
+
## OneDrive locks `git worktree remove` — the first attempt usually still worked
|
|
78
|
+
|
|
79
|
+
`git worktree remove` on an in-repo worktree often errors `Permission denied` / `Device or
|
|
80
|
+
resource busy` because OneDrive briefly locks the directory. The failed attempt usually still
|
|
81
|
+
**deregisters** the worktree (`git worktree list` to confirm — the helper's `remove` does this
|
|
82
|
+
check for you); the empty husk directory deletes on its own later. Don't fight it with retries.
|
|
83
|
+
|
|
84
|
+
## Local unit tests: baseline first, CI is truth
|
|
85
|
+
|
|
86
|
+
The local `tests/*.mjs` suite has a **large stable failure baseline on Windows boxes** (mostly
|
|
87
|
+
DB-backed tests with no local Postgres — ~184 failures at last count, and the count drifts).
|
|
88
|
+
Before blaming your change: run the suite once *before* touching anything (or on a clean
|
|
89
|
+
checkout), and compare against that. The CI `unit` check on the PR is the authoritative verdict.
|
|
90
|
+
|
|
91
|
+
## Never pipe `ship.js` through `head`/`tail`
|
|
92
|
+
|
|
93
|
+
When the pager closes the pipe mid-run, node dies on EPIPE and the land chain aborts silently —
|
|
94
|
+
the task strands at `confirmed` (hit on task 1001860). Run it unpiped or `> file`; a stranded
|
|
95
|
+
confirmed task re-lands by re-running `node scripts/gds/ship.js <id>` (resume is idempotent).
|
|
96
|
+
|
|
97
|
+
## ship.js: a failed post-land ship call may be a success — now auto-verified
|
|
98
|
+
|
|
99
|
+
The final `POST /tasks/<id>/ship` after a successful merge can be refused (`task_not_confirmed`)
|
|
100
|
+
because the server already landed the task first (reconcile-on-read or the ~5-min reconciler).
|
|
101
|
+
`ship.js` now normalizes both API error shapes and **verifies the live task status with a GET
|
|
102
|
+
before reporting failure** (task 1002809) — a verified `shipped` prints as the success it is. If
|
|
103
|
+
you see a ship-call failure from older tooling, check `GET /tasks/<id>` before reacting.
|
|
@@ -111,6 +111,42 @@ function normalizeHostname(h) {
|
|
|
111
111
|
return s;
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
+
// The auto-assigned address for a new project: <slug>.<apex> (task 1002704 — the
|
|
115
|
+
// owner's auto-assign/opt-out decision; every project's hall reachable day one).
|
|
116
|
+
// The apex is branding domains.instanceBase; blank or unparseable → null, so a
|
|
117
|
+
// self-host or unconfigured instance keeps creating domainless instead of
|
|
118
|
+
// guessing (the client's location.hostname guess stays client-side only). PURE.
|
|
119
|
+
function defaultDomainForSlug(slug, apex) {
|
|
120
|
+
if (!isValidSlug(slug)) return null;
|
|
121
|
+
const a = String(apex == null ? '' : apex).trim();
|
|
122
|
+
if (!a) return null;
|
|
123
|
+
return normalizeHostname(`${slug}.${a}`) || null;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Labels the platform itself occupies (or has planned) directly under the instance
|
|
127
|
+
// apex, plus the dev-box hostname prefixes. The runner's DNS write is an UPSERT,
|
|
128
|
+
// so a project claiming one of these would overwrite platform records — refuse at
|
|
129
|
+
// the API layer instead (task 1002704; the guard applies to auto-assigned AND
|
|
130
|
+
// bring-your-own hostnames, on create and on attach). Anything deeper than one
|
|
131
|
+
// label under the apex is also refused: it breaks the wildcard-cert rule (one
|
|
132
|
+
// label under the apex — the #771 lesson) and nothing legitimate creates it.
|
|
133
|
+
const RESERVED_APEX_LABELS = new Set([
|
|
134
|
+
'www', 'api', 'get', 'status', 'builders', 'docs', 'mail', 'admin', 'app',
|
|
135
|
+
'cdn', 'ns1', 'ns2', 'demo', 'gate', 'downloads',
|
|
136
|
+
]);
|
|
137
|
+
const RESERVED_APEX_PREFIXES = ['term-', 'sandbox-'];
|
|
138
|
+
function isReservedHostname(domain, apex) {
|
|
139
|
+
const host = normalizeHostname(domain);
|
|
140
|
+
const zone = normalizeHostname(apex);
|
|
141
|
+
if (!host || !zone) return false;
|
|
142
|
+
if (host === zone) return true;
|
|
143
|
+
if (!host.endsWith(`.${zone}`)) return false;
|
|
144
|
+
const label = host.slice(0, -(zone.length + 1));
|
|
145
|
+
if (label.includes('.')) return true;
|
|
146
|
+
if (RESERVED_APEX_LABELS.has(label)) return true;
|
|
147
|
+
return RESERVED_APEX_PREFIXES.some((p) => label.startsWith(p));
|
|
148
|
+
}
|
|
149
|
+
|
|
114
150
|
// The instance lifecycle states for which an on-demand TLS cert may be minted: a
|
|
115
151
|
// host mid-standup ('provisioning' — Caddy's first handshake can land here, while
|
|
116
152
|
// the snippet is written + reloaded) or live ('active'). NOT 'requested' (nothing
|
|
@@ -658,6 +694,7 @@ module.exports = {
|
|
|
658
694
|
PROVISION_ENQUEUE_FROM, DOMAIN_ATTACH_FROM, TIER_MONTHLY_USD, CERT_ELIGIBLE_STATES,
|
|
659
695
|
// pure
|
|
660
696
|
isValidSlug, costEstimateUsd, publicInstance, normalizeHostname,
|
|
697
|
+
defaultDomainForSlug, isReservedHostname,
|
|
661
698
|
// pure — GitHub App Manifest flow (task 2080)
|
|
662
699
|
githubAppName, buildGithubAppManifest, manifestPostUrl,
|
|
663
700
|
// data access
|