@bongos/core 1.19.350 → 1.19.351
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 +14 -14
- package/docs/copy-inventory.md +1 -1
- package/docs/copy-registry.json +9 -9
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/public-landing/projects.html +30 -10
- package/src/module-api.js +3 -1
- package/tests/projects_hub.mjs +5 -3
- package/tests/projects_hub_pre_uat.mjs +41 -0
- package/tests/public_landing_projects.mjs +1 -1
package/.bongos-core.json
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
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.351",
|
|
6
|
+
"core_contract": "1.19.351",
|
|
7
|
+
"source_commit": "a1a7446c35da856e17ae920f2d2e2a446320edb6",
|
|
8
8
|
"source_ref": "HEAD",
|
|
9
|
-
"built_at": "2026-08-
|
|
9
|
+
"built_at": "2026-08-25T12:53:45.200Z",
|
|
10
10
|
"redaction": {
|
|
11
11
|
"model": "docs-redacted+functional-verbatim",
|
|
12
12
|
"docs_redacted": 329,
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"gate": "passed"
|
|
18
18
|
},
|
|
19
19
|
"file_count": 1857,
|
|
20
|
-
"tree_sha256": "
|
|
20
|
+
"tree_sha256": "fef03d4bf7a70641e028393447ebffd7ca615173e976f25945a0f2846cb9f791",
|
|
21
21
|
"files": [
|
|
22
22
|
{
|
|
23
23
|
"path": ".claude/skills/blocker-review/SKILL.md",
|
|
@@ -1477,12 +1477,12 @@
|
|
|
1477
1477
|
{
|
|
1478
1478
|
"path": "docs/copy-inventory.md",
|
|
1479
1479
|
"mode": "0000644",
|
|
1480
|
-
"sha256": "
|
|
1480
|
+
"sha256": "c517a98c5c2a6f853a441a64accd1cd00d5448a9f3fbf6e2c5a89d21ba110527"
|
|
1481
1481
|
},
|
|
1482
1482
|
{
|
|
1483
1483
|
"path": "docs/copy-registry.json",
|
|
1484
1484
|
"mode": "0000644",
|
|
1485
|
-
"sha256": "
|
|
1485
|
+
"sha256": "47aa5ef6c242988ab5e47123f442e67b47ad03803588b7fecd57027cfb5c36e9"
|
|
1486
1486
|
},
|
|
1487
1487
|
{
|
|
1488
1488
|
"path": "docs/design-contract.md",
|
|
@@ -4787,12 +4787,12 @@
|
|
|
4787
4787
|
{
|
|
4788
4788
|
"path": "package-lock.json",
|
|
4789
4789
|
"mode": "0000644",
|
|
4790
|
-
"sha256": "
|
|
4790
|
+
"sha256": "782cf5fe234b13ce532d23dff2d26511364e0671fc4a706e828bb69a1aa747e5"
|
|
4791
4791
|
},
|
|
4792
4792
|
{
|
|
4793
4793
|
"path": "package.json",
|
|
4794
4794
|
"mode": "0000644",
|
|
4795
|
-
"sha256": "
|
|
4795
|
+
"sha256": "ffa5d64cebc96b2aa32b1e925ec8d128854b565fde7853b1dd6a1a40ae24f1ff"
|
|
4796
4796
|
},
|
|
4797
4797
|
{
|
|
4798
4798
|
"path": "public-docs/index.html",
|
|
@@ -5052,7 +5052,7 @@
|
|
|
5052
5052
|
{
|
|
5053
5053
|
"path": "public-landing/projects.html",
|
|
5054
5054
|
"mode": "0000644",
|
|
5055
|
-
"sha256": "
|
|
5055
|
+
"sha256": "6d57b80519977cc23b3da231164e20b645ced2b6bbf97ebd3e64f3f9b393321b"
|
|
5056
5056
|
},
|
|
5057
5057
|
{
|
|
5058
5058
|
"path": "public-landing/world/assets/clouds/cloud-island-large.png",
|
|
@@ -6652,7 +6652,7 @@
|
|
|
6652
6652
|
{
|
|
6653
6653
|
"path": "src/module-api.js",
|
|
6654
6654
|
"mode": "0000644",
|
|
6655
|
-
"sha256": "
|
|
6655
|
+
"sha256": "227d48d264188e540dda1fb674d6fb282d8eafd3db3d3d876ef075c0690029fa"
|
|
6656
6656
|
},
|
|
6657
6657
|
{
|
|
6658
6658
|
"path": "src/module-loader/catalog.js",
|
|
@@ -8537,12 +8537,12 @@
|
|
|
8537
8537
|
{
|
|
8538
8538
|
"path": "tests/projects_hub.mjs",
|
|
8539
8539
|
"mode": "0000644",
|
|
8540
|
-
"sha256": "
|
|
8540
|
+
"sha256": "3a04673fa06b8319b07998b63829cc83c2ef0ec531c4156ca8823e26172c8ef5"
|
|
8541
8541
|
},
|
|
8542
8542
|
{
|
|
8543
8543
|
"path": "tests/projects_hub_pre_uat.mjs",
|
|
8544
8544
|
"mode": "0000644",
|
|
8545
|
-
"sha256": "
|
|
8545
|
+
"sha256": "4f8b786e8704b418354d2551d20466e4d9ca705ca7ac39d00cd2dc83e3080032"
|
|
8546
8546
|
},
|
|
8547
8547
|
{
|
|
8548
8548
|
"path": "tests/promote_goal_id.mjs",
|
|
@@ -8612,7 +8612,7 @@
|
|
|
8612
8612
|
{
|
|
8613
8613
|
"path": "tests/public_landing_projects.mjs",
|
|
8614
8614
|
"mode": "0000644",
|
|
8615
|
-
"sha256": "
|
|
8615
|
+
"sha256": "5c5fe7821194630d0dc765ea0ad34560049e2b88c5ac5cae19b9fbd770df3168"
|
|
8616
8616
|
},
|
|
8617
8617
|
{
|
|
8618
8618
|
"path": "tests/public_mirror_export.mjs",
|
package/docs/copy-inventory.md
CHANGED
|
@@ -1419,12 +1419,12 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
1419
1419
|
| `f6584b0a728b` | certain | The Verro Labs mark: a galaxy and constellation above a river valley threaded with circuitry | `public-landing/index.html:426` |
|
|
1420
1420
|
| `72e85e8b6f47` | certain | The drums are rolling | `public-landing/projects.html:917` |
|
|
1421
1421
|
| `fb416bf1a26b` | certain | The handle names your project on the platform — and its address comes with it. Once it stands up, a few GitHub | `public-landing/projects.html:871` |
|
|
1422
|
-
| `9dc1eee28cee` | certain | The platform used to deploy every project by reading its code from GitHub with a shared read-only credential — | `public-landing/projects.html:656` |
|
|
1423
1422
|
| `20fcebaa85c4` | certain | The project hub needs JavaScript — the map, your projects, and starting a new one all live here. You can read | `public-landing/projects.html:397` |
|
|
1424
1423
|
| `4a740b5afe73` | certain | The project map | `public-landing/projects.html:407` |
|
|
1425
1424
|
| `2b193468bbb5` | certain | These are the same steps however a project is created — nothing here is special to this page. | `public-landing/projects.html:925` |
|
|
1426
1425
|
| `1eff94c94b66` | certain | This files the request; the control plane does the real standup and nothing touches servers from this page. Yo | `public-landing/projects.html:910` |
|
|
1427
1426
|
| `d83b739afb1e` | certain | This is a project’s management page — it answers only to the person who owns it. Sign in with GitHub to open y | `public-landing/projects.html:605` |
|
|
1427
|
+
| `406e774e0952` | certain | This project’s deploys read its code from GitHub with an older key that only works on public repositories — so | `public-landing/projects.html:656` |
|
|
1428
1428
|
| `8d60f3ee4d86` | certain | Toggle light or dark | `public-landing/index.html:282` |
|
|
1429
1429
|
| `9b514fce13d7` | certain | Torn down | `public-landing/projects.html:574` |
|
|
1430
1430
|
| `b1dd149424ea` | certain | Turn the filter off to see what everyone else is building — or start your own. | `public-landing/projects.html:450` |
|
package/docs/copy-registry.json
CHANGED
|
@@ -12421,15 +12421,6 @@
|
|
|
12421
12421
|
"origin": "html-text",
|
|
12422
12422
|
"confidence": "certain"
|
|
12423
12423
|
},
|
|
12424
|
-
{
|
|
12425
|
-
"id": "9dc1eee28cee",
|
|
12426
|
-
"surface": "landing",
|
|
12427
|
-
"text": "The platform used to deploy every project by reading its code from GitHub with a shared read-only credential — and private repositories don’t admit it. New standups fix this: a private repository now gets the project’s own read-only deploy key, wired automatically",
|
|
12428
|
-
"file": "public-landing/projects.html",
|
|
12429
|
-
"line": 656,
|
|
12430
|
-
"origin": "html-text",
|
|
12431
|
-
"confidence": "certain"
|
|
12432
|
-
},
|
|
12433
12424
|
{
|
|
12434
12425
|
"id": "20fcebaa85c4",
|
|
12435
12426
|
"surface": "landing",
|
|
@@ -12475,6 +12466,15 @@
|
|
|
12475
12466
|
"origin": "html-text",
|
|
12476
12467
|
"confidence": "certain"
|
|
12477
12468
|
},
|
|
12469
|
+
{
|
|
12470
|
+
"id": "406e774e0952",
|
|
12471
|
+
"surface": "landing",
|
|
12472
|
+
"text": "This project’s deploys read its code from GitHub with an older key that only works on public repositories — so making the repository private would break the next deploy. New standups fix this: a private repository now gets the project’s own read-only deploy key, wired automatically",
|
|
12473
|
+
"file": "public-landing/projects.html",
|
|
12474
|
+
"line": 656,
|
|
12475
|
+
"origin": "html-text",
|
|
12476
|
+
"confidence": "certain"
|
|
12477
|
+
},
|
|
12478
12478
|
{
|
|
12479
12479
|
"id": "8d60f3ee4d86",
|
|
12480
12480
|
"surface": "landing",
|
package/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.19.
|
|
3
|
+
"version": "1.19.351",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@bongos/core",
|
|
9
|
-
"version": "1.19.
|
|
9
|
+
"version": "1.19.351",
|
|
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.19.
|
|
3
|
+
"version": "1.19.351",
|
|
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",
|
|
@@ -653,7 +653,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
653
653
|
explanation, not another platform's task tracker. -->
|
|
654
654
|
<details class="finePrint" id="mRepoVisWhy">
|
|
655
655
|
<summary>Why can’t it be private yet?</summary>
|
|
656
|
-
<p>
|
|
656
|
+
<p>This project’s deploys read its code from GitHub with an older key that only works on public repositories — so making the repository private would break the next deploy. New standups fix this: a private repository now gets the project’s own read-only deploy key, wired automatically<!--apex-only:start--> — shipped as <a href="{{buildersOrigin}}#/task/1002735" target="_blank" rel="noopener">task 1002735</a> in the builders’ hall<!--apex-only:end-->. A project set up before that still reads with the older key, so the switch stays off until existing projects are re-wired.</p>
|
|
657
657
|
</details>
|
|
658
658
|
</div>
|
|
659
659
|
|
|
@@ -1152,8 +1152,15 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
1152
1152
|
if (a.dataset.nav === 'home') return; /* a real navigation — leave it alone */
|
|
1153
1153
|
a.addEventListener('click', function (ev) { ev.preventDefault(); setView(a.dataset.nav, true); });
|
|
1154
1154
|
});
|
|
1155
|
-
|
|
1156
|
-
|
|
1155
|
+
/* delegated, not swept: a data-nav-to link injected into a card or the manage
|
|
1156
|
+
page after boot (addressRow, renderDelete) would never be upgraded by a
|
|
1157
|
+
one-shot querySelectorAll — it would cost a whole page load. A modified
|
|
1158
|
+
click keeps its browser meaning, the same contract a[data-manage] has. */
|
|
1159
|
+
document.addEventListener('click', function (ev) {
|
|
1160
|
+
var a = ev.target.closest && ev.target.closest('[data-nav-to]');
|
|
1161
|
+
if (!a || !isPlainClick(ev)) return;
|
|
1162
|
+
ev.preventDefault();
|
|
1163
|
+
setView(a.dataset.navTo, true);
|
|
1157
1164
|
});
|
|
1158
1165
|
/* Back / Forward land on the view the URL names — viewFromUrl() reads the
|
|
1159
1166
|
manage id too, so a manage entry restores its project */
|
|
@@ -3125,7 +3132,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
3125
3132
|
'<p>GitHub → <em>your account’s</em> Settings → Developer settings → OAuth Apps → New OAuth App. (Developer settings live under your account, not the repo.)</p>' +
|
|
3126
3133
|
'<div class="kv"><span class="kk">Homepage URL</span><code>' + esc(oa.homepageUrl) + '</code>' + copyBtn(oa.homepageUrl) + '</div>' +
|
|
3127
3134
|
'<div class="kv"><span class="kk">Callback URL</span><code>' + esc(oa.callbackUrl) + '</code>' + copyBtn(oa.callbackUrl) + '</div>' +
|
|
3128
|
-
'<p>The
|
|
3135
|
+
'<p>The platform team places the generated credentials; this step ticks itself once they land.</p></details>';
|
|
3129
3136
|
}
|
|
3130
3137
|
|
|
3131
3138
|
/* oauth-app — the ADR 0133 one-click GitHub-App manifest flow is the primary path
|
|
@@ -3176,10 +3183,10 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
3176
3183
|
the box. Web sign-in works either way; the CLI also has a web-token fallback. */
|
|
3177
3184
|
function renderStepDeviceFlow() {
|
|
3178
3185
|
if (live.manifest !== 'done') {
|
|
3179
|
-
return '<li class="slocked" data-onboard-step="device-flow"><b>
|
|
3186
|
+
return '<li class="slocked" data-onboard-step="device-flow"><b>Let builders sign in from a command line — one checkbox</b><p>Unlocks once GitHub sign-in above is wired. It lets builders sign in from a terminal — the <code style="font-family:var(--font-mono)">bongos setup</code> command builders run on their own machine; web sign-in works without it.</p></li>';
|
|
3180
3187
|
}
|
|
3181
3188
|
var appUrl = live.appSlug ? 'https://github.com/settings/apps/' + esc(live.appSlug) : null;
|
|
3182
|
-
return '<li data-onboard-step="device-flow"><b>
|
|
3189
|
+
return '<li data-onboard-step="device-flow"><b>Let builders sign in from a command line — one checkbox</b><p>' +
|
|
3183
3190
|
(appUrl
|
|
3184
3191
|
? 'Open <a href="' + appUrl + '" target="_blank" rel="noopener">your app’s settings</a>, check <strong>Enable Device Flow</strong>, and save. '
|
|
3185
3192
|
: 'GitHub → Settings → Developer settings → GitHub Apps → your app → check <strong>Enable Device Flow</strong> → save. ') +
|
|
@@ -3957,6 +3964,11 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
3957
3964
|
address is tracked separately (task 1002897); until then "reserved" is
|
|
3958
3965
|
both the honest word and the accurate one, since a revive re-uses exactly
|
|
3959
3966
|
this hostname. */
|
|
3967
|
+
/* pre-standup: at 'requested' nothing has been built, so the shape arms
|
|
3968
|
+
below would describe a server and a database that never existed. error
|
|
3969
|
+
and provisioning keep the built-world text on purpose — a run that failed
|
|
3970
|
+
partway may already have a database, a port and a DNS record. */
|
|
3971
|
+
if (inst && inst.status === 'requested') return 'Nothing has been stood up yet — this cancels the standup. Anything already on GitHub is untouched, and the name and web address stay reserved for this project.';
|
|
3960
3972
|
return inst && inst.hosting_shape === 'dedicated'
|
|
3961
3973
|
? 'This project has a machine to itself, so the machine goes away and its database goes with it. Your repository is untouched. Its web address stays reserved for this project and shows an error page until you bring it back. Nothing here erases a project.'
|
|
3962
3974
|
: 'The server goes away. Your repository is untouched. The database is kept, so bringing it back later restores its memory. Its web address stays reserved for this project and shows an error page until you bring it back. Nothing here erases a project.';
|
|
@@ -3989,7 +4001,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
3989
4001
|
return 'Address: <code>' + esc(inst.domain) + '</code> — it answers there once the instance is live.';
|
|
3990
4002
|
}
|
|
3991
4003
|
/* the HONEST no-address state: sign-in on the instance needs a real domain */
|
|
3992
|
-
return '<span class="none">No address yet</span> — sign-in on this project can’t be set up until it has one.';
|
|
4004
|
+
return '<span class="none">No address yet</span> — sign-in on this project can’t be set up until it has one. <a href="?view=mine" data-nav-to="mine">Give it an address from your projects</a>.';
|
|
3993
4005
|
}
|
|
3994
4006
|
|
|
3995
4007
|
/* ── the bring-your-own-domain fold (owner decision 2, 2026-08-24). A live
|
|
@@ -4431,11 +4443,18 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
4431
4443
|
if (m === 'handled' || m === 'stale') return;
|
|
4432
4444
|
$('mLoading').hidden = true;
|
|
4433
4445
|
var a = $('mAlert');
|
|
4434
|
-
a.
|
|
4446
|
+
a.innerHTML = 'Couldn’t read this project right now. <button type="button" class="btn small ghost" id="mAlertRetry">Try again</button>';
|
|
4435
4447
|
a.classList.add('on');
|
|
4436
4448
|
});
|
|
4437
4449
|
}
|
|
4438
4450
|
|
|
4451
|
+
/* the alert's own way out (task 1003245): delegated, because the catch above
|
|
4452
|
+
rewrites #mAlert's innerHTML on every failure — a bound button would not
|
|
4453
|
+
survive the next write. A loud re-read: the founder asked. */
|
|
4454
|
+
$('mAlert').addEventListener('click', function (ev) {
|
|
4455
|
+
if (ev.target.closest && ev.target.closest('#mAlertRetry')) loadManage();
|
|
4456
|
+
});
|
|
4457
|
+
|
|
4439
4458
|
function manageChipTick() {
|
|
4440
4459
|
if (document.hidden || currentView !== 'manage' || !manageInst) return;
|
|
4441
4460
|
renderManage(manageInst); /* zero requests — re-dates "checked Xm ago" */
|
|
@@ -4475,7 +4494,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
4475
4494
|
} else {
|
|
4476
4495
|
repoVisMsg(
|
|
4477
4496
|
'<div class="addr">This repository is <b>public</b> — anyone can read its code.</div>' +
|
|
4478
|
-
'<p class="finePrint">Making it private isn’t possible from here yet
|
|
4497
|
+
'<p class="finePrint">Making it private isn’t possible from here yet — see below for why.</p>');
|
|
4479
4498
|
}
|
|
4480
4499
|
}
|
|
4481
4500
|
|
|
@@ -4596,7 +4615,8 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
4596
4615
|
return;
|
|
4597
4616
|
}
|
|
4598
4617
|
/* a project that never finished standing up still reaches here — that is
|
|
4599
|
-
the whole point of the widened gate;
|
|
4618
|
+
the whole point of the widened gate; teardownTruth() scopes the copy to
|
|
4619
|
+
its status */
|
|
4600
4620
|
delMsg('<p class="plain">' + teardownTruth(inst) + '</p>' +
|
|
4601
4621
|
'<div class="actions"><button type="button" class="btn small danger" data-del-ask>Tear it down</button></div>');
|
|
4602
4622
|
}
|
package/src/module-api.js
CHANGED
|
@@ -1130,8 +1130,10 @@ const { validateOrRespond, LIMITS, parseId, asyncHandler, corsPublicGet, parsePa
|
|
|
1130
1130
|
// landed since 1.19.348 with no explicit bump. run 32803276871. (task 1002620)
|
|
1131
1131
|
// 1.19.350 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
1132
1132
|
// landed since 1.19.349 with no explicit bump. run 32810944115. (task 1002620)
|
|
1133
|
+
// 1.19.351 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
1134
|
+
// landed since 1.19.350 with no explicit bump. run 32850120472. (task 1002620)
|
|
1133
1135
|
// ---------------------------------------------------------------------------
|
|
1134
|
-
const CORE_VERSION = '1.19.
|
|
1136
|
+
const CORE_VERSION = '1.19.351'; // CI auto-patch carrier (ADR 0161); see changelog above
|
|
1135
1137
|
|
|
1136
1138
|
// A namespaced logger so a module's log lines are attributable + consistent.
|
|
1137
1139
|
// Usage: const log = api.logger('dev-box'); log.info('mounted');
|
package/tests/projects_hub.mjs
CHANGED
|
@@ -997,8 +997,10 @@ test('flip-to-private cannot travel from this page — only the public direction
|
|
|
997
997
|
'no code path may send the private direction');
|
|
998
998
|
// the refusal is SAID, with its reason, not silently missing — post-ADR-0176 the
|
|
999
999
|
// reason is THIS project's shared-credential wiring, not a platform-wide inability
|
|
1000
|
-
assert.match(SCRIPT, /
|
|
1001
|
-
'the
|
|
1000
|
+
assert.match(SCRIPT, /Making it private isn’t possible from here yet — see below for why\./,
|
|
1001
|
+
'the refusal is SAID inline, and points at the fold that carries the reason');
|
|
1002
|
+
assert.match(HUB, /would break the next deploy/,
|
|
1003
|
+
'the flip-to-private limitation is stated in plain words, in the fold');
|
|
1002
1004
|
});
|
|
1003
1005
|
|
|
1004
1006
|
test('the visibility shown is GitHub\'s answer, never an assumption', () => {
|
|
@@ -1033,7 +1035,7 @@ test('the refusal carries a LINK to the limitation, never prose alone (task 1003
|
|
|
1033
1035
|
assert.match(HUB, /id="mRepoVisWhy"/, 'the why-fold is real markup beside the section body');
|
|
1034
1036
|
const fold = (HUB.match(/<details[^>]*id="mRepoVisWhy"[\s\S]*?<\/details>/) || [''])[0];
|
|
1035
1037
|
assert.ok(fold, 'the fold must be extractable');
|
|
1036
|
-
assert.match(fold, /
|
|
1038
|
+
assert.match(fold, /an older key that only works on public repositories/, 'the WHY is stated in plain words');
|
|
1037
1039
|
assert.match(fold, /\{\{buildersOrigin\}\}#\/task\/1002735/,
|
|
1038
1040
|
'the tracked fix is a real link, hall-origin server-stamped (never client-filled)');
|
|
1039
1041
|
// apex-only: a child instance keeps the explanation, not another platform's tracker
|
|
@@ -363,6 +363,47 @@ test('card action results announce, nothing under the pointer is deleted, and fo
|
|
|
363
363
|
assert.match(fn('focusCardControl'), /li\.querySelector\('\.actions a, \.actions button'\) \|\|\n\s*li\.querySelector\('details\.attachFold summary'\)/, 'nearest control as the fallback');
|
|
364
364
|
});
|
|
365
365
|
|
|
366
|
+
/* ── copy follow-ups (task 1003245) ── */
|
|
367
|
+
test('teardown copy is state-aware: a queued project is told nothing was built', () => {
|
|
368
|
+
const truth = fn('teardownTruth');
|
|
369
|
+
assert.match(truth, /if \(inst && inst\.status === 'requested'\) return 'Nothing has been stood up yet — this cancels the standup\. Anything already on GitHub is untouched, and the name and web address stay reserved for this project\.';/);
|
|
370
|
+
const arm = truth.indexOf("inst.status === 'requested'");
|
|
371
|
+
const shape = truth.indexOf("hosting_shape === 'dedicated'");
|
|
372
|
+
assert.ok(arm > 0 && arm < shape, 'the pre-standup arm comes before the shape arms');
|
|
373
|
+
assert.doesNotMatch(truth, /status === 'error'|status === 'provisioning'/, 'error and provisioning keep today’s text — a failed run may already have built things');
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
test('founder voice on the Device Flow step and the manual OAuth fallback', () => {
|
|
377
|
+
const df = fn('renderStepDeviceFlow');
|
|
378
|
+
assert.equal((df.match(/<b>Let builders sign in from a command line — one checkbox<\/b>/g) || []).length, 2, 'both branches carry the outcome-first title');
|
|
379
|
+
assert.doesNotMatch(df, /<b>Enable Device Flow — one checkbox<\/b>/);
|
|
380
|
+
assert.match(df, /the <code style="font-family:var\(--font-mono\)">bongos setup<\/code> command builders run on their own machine/, 'the command is glossed, not bare-coded');
|
|
381
|
+
assert.doesNotMatch(df, /Optional/, 'not optional — a manifest-born App has Device Flow off');
|
|
382
|
+
assert.equal((df.match(/<strong>Enable Device Flow<\/strong>/g) || []).length, 2, 'GitHub’s own checkbox label stays verbatim in the instructions');
|
|
383
|
+
const manual = fn('manualOauthDetails');
|
|
384
|
+
assert.match(manual, /The platform team places the generated credentials; this step ticks itself once they land\.<\/p><\/details>/);
|
|
385
|
+
assert.doesNotMatch(manual, /auth_configured|healthz/, 'no JSON health check for a founder to perform');
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
test('repo visibility: the refusal is one line, the mechanism lives in the fold', () => {
|
|
389
|
+
const rv = fn('renderRepoVis');
|
|
390
|
+
assert.match(rv, /This repository is <b>public<\/b> — anyone can read its code\./, 'line one stays');
|
|
391
|
+
assert.match(rv, /Making it private isn’t possible from here yet — see below for why\./);
|
|
392
|
+
assert.doesNotMatch(rv, /shared credential/);
|
|
393
|
+
const fold = (HUB.match(/<details[^>]*id="mRepoVisWhy"[\s\S]*?<\/details>/) || [''])[0];
|
|
394
|
+
assert.match(fold, /an older key that only works on public repositories/);
|
|
395
|
+
assert.doesNotMatch(fold, /shared read-only credential/);
|
|
396
|
+
assert.match(fold, /<!--apex-only:start--> — shipped as <a href="\{\{buildersOrigin\}\}#\/task\/1002735"/, 'the hall task link stays inside its apex-only sentinel');
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
test('a failed manage read offers a retry; the no-address sentence offers a door', () => {
|
|
400
|
+
assert.match(SCRIPT, /a\.innerHTML = 'Couldn’t read this project right now\. <button type="button" class="btn small ghost" id="mAlertRetry">Try again<\/button>';/);
|
|
401
|
+
assert.match(SCRIPT, /\$\('mAlert'\)\.addEventListener\('click', function \(ev\) \{\n\s*if \(ev\.target\.closest && ev\.target\.closest\('#mAlertRetry'\)\) loadManage\(\);/, 'delegated — the catch rewrites the alert on every failure');
|
|
402
|
+
assert.match(fn('addressRow'), /No address yet<\/span> — sign-in on this project can’t be set up until it has one\. <a href="\?view=mine" data-nav-to="mine">Give it an address from your projects<\/a>\./);
|
|
403
|
+
assert.match(SCRIPT, /var a = ev\.target\.closest && ev\.target\.closest\('\[data-nav-to\]'\);\n\s*if \(!a \|\| !isPlainClick\(ev\)\) return;/, 'data-nav-to is delegated, so a link injected after boot switches views in place');
|
|
404
|
+
assert.doesNotMatch(SCRIPT, /querySelectorAll\('\[data-nav-to\]'\)/, 'the boot-time sweep is gone');
|
|
405
|
+
});
|
|
406
|
+
|
|
366
407
|
/* ── accessibility follow-ups (task 1003246) ── */
|
|
367
408
|
test('the done panel’s progress region is stable, change-only, and says each stage’s state', () => {
|
|
368
409
|
assert.match(HUB, /<div id="liveProgress" role="status" aria-live="polite"><\/div>/, 'the live region is the static wrapper');
|
|
@@ -157,7 +157,7 @@ test('the repo-visibility section is served live, with the private direction ref
|
|
|
157
157
|
// never shows another platform's tracker). The link itself is pinned inside
|
|
158
158
|
// its sentinels by tests/projects_hub.mjs.
|
|
159
159
|
assert.match(body, /id="mRepoVisWhy"/, 'the why-fold is served');
|
|
160
|
-
assert.match(body, /
|
|
160
|
+
assert.match(body, /an older key that only works on public repositories/, 'the explanation survives the strip');
|
|
161
161
|
assert.doesNotMatch(body, /#\/task\/1002735/,
|
|
162
162
|
'the apex-only task link is stripped from a standalone serve');
|
|
163
163
|
});
|