@bongos/core 1.21.104 → 1.21.106

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/.bongos-core.json +57 -47
  2. package/docs/copy-inventory.md +368 -366
  3. package/docs/copy-registry.json +475 -457
  4. package/docs/design/project-startup-direction.md +14 -0
  5. package/docs/module-api-changelog.md +4 -0
  6. package/docs/page-inventory.json +10 -3
  7. package/docs/page-readings.json +1023 -977
  8. package/modules/lifecycle/check-rollup.js +11 -1
  9. package/modules/lifecycle/github-push.js +3 -7
  10. package/modules/public-landing/public/projects-hall-live.states.json +3 -2
  11. package/modules/public-landing/public/projects-setup.states.json +91 -0
  12. package/modules/public-landing/public/projects.html +535 -804
  13. package/modules/public-landing/public/projects.probes.json +3 -3
  14. package/modules/public-landing/public/projects.states.json +1 -1
  15. package/modules/ui-design/kit/fixtures/provisioning-instances-hall-live.json +22 -2
  16. package/modules/ui-design/kit/fixtures/provisioning-instances-setup.json +195 -0
  17. package/modules/ui-design/kit/serve.js +22 -4
  18. package/package-lock.json +2 -2
  19. package/package.json +1 -1
  20. package/release-notes.json +12 -0
  21. package/scripts/gds/ship-land.js +2 -2
  22. package/src/module-api.js +1 -1
  23. package/tests/cosmos_token_contrast.mjs +10 -18
  24. package/tests/github_handback_any_device.mjs +4 -3
  25. package/tests/github_one_trip.mjs +45 -47
  26. package/tests/github_org_account.mjs +2 -2
  27. package/tests/github_pick_up.mjs +40 -29
  28. package/tests/github_push_merge_driver.mjs +46 -0
  29. package/tests/onboard.mjs +13 -7
  30. package/tests/project_invite_ui.mjs +6 -3
  31. package/tests/project_modules_ui.mjs +3 -3
  32. package/tests/projects_hub.mjs +8 -9
  33. package/tests/projects_hub_cloud_hop.mjs +77 -125
  34. package/tests/projects_hub_dns_ready.mjs +42 -51
  35. package/tests/projects_hub_pre_uat.mjs +68 -69
  36. package/tests/public_landing_projects.mjs +45 -102
  37. package/tests/setup_status_facts.mjs +400 -0
  38. package/tests/wizard_github_feedback.mjs +90 -87
  39. package/tests/wizard_one_page.mjs +11 -9
  40. package/tests/wizard_auto_open.mjs +0 -94
@@ -167,12 +167,12 @@
167
167
  { "name": "part 02 (task 1004648): Change opens a row in place and reads Done, opening another closes it, and nothing needs confirming", "auth": true, "width": 1440, "url": "/projects?view=new",
168
168
  "steps": [["wait",600],["fill","#newName","Mercury"],["click","#typeCards .tpill[data-type=\"game\"]"],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["select","#physCountry","US"],["wait",100],["click","[data-phys=\"builder_geography\"][data-val=\"global\"]"],["click","[data-phys=\"minors_on_board\"][data-val=\"false\"]"],["click","[data-phys=\"entity\"][data-val=\"intent-solo\"]"],["wait",300],["click","#reviewRows .setRow[data-row=\"team\"] [data-row-chg]"],["wait",200],["click","[data-phys-solo=\"many\"]"],["wait",600],["click","#reviewRows .setRow[data-row=\"run\"] [data-row-chg]"],["wait",300]],
169
169
  "expect": {"visible":["#reviewRows .setRow[data-row=\"rewards\"]","#reviewRows .setRow.open[data-row=\"run\"] .opts"],"hidden":["#reviewRows .setRow[data-row=\"team\"] .opts"],"text":[["#reviewRows .setRow[data-row=\"run\"] [data-row-chg]","Done"],["#reviewRows .setRow[data-row=\"team\"] [data-row-chg]","Change"]]} },
170
- { "name": "the wizard driver (task 1004648): part 01, the checks, the address row (the dotless stub host takes a domain the founder owns), the tick, then Create — part 03 goes live with the checklist, the cloud hop and its status line", "auth": true, "width": 1440, "url": "/projects?view=new",
170
+ { "name": "the wizard driver (task 1004648): part 01, the checks, the address row (the dotless stub host takes a domain the founder owns), the tick, then Create — part 03 goes live as Getting <name> ready: one sentence, the checked facts, and the cloud hop behind its link", "auth": true, "width": 1440, "url": "/projects?view=new",
171
171
  "steps": [["wait",600],["fill","#newName","Mercury"],["click","#typeCards .tpill[data-type=\"game\"]"],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["select","#physCountry","US"],["wait",100],["click","[data-phys=\"builder_geography\"][data-val=\"global\"]"],["click","[data-phys=\"minors_on_board\"][data-val=\"false\"]"],["click","[data-phys=\"entity\"][data-val=\"intent-solo\"]"],["wait",300],["click","#reviewRows .setRow[data-row=\"address\"] [data-row-chg]"],["wait",200],["fill","#f-slug","mercury"],["wait",900],["fill","#f-domain","mercury.example.com"],["wait",200],["click","#reviewRows .setRow[data-row=\"address\"] [data-row-chg]"],["wait",200],["click","#termsAck"],["wait",100],["click","#doCreate"],["wait",1500]],
172
- "expect": {"visible":["#panel-done","#humanSteps","#hop","#hopCanvas","#hopStatus","#hopJump"],"hidden":["#wizParts","#liveProgress"],"text":[["#done-h","Setting up Mercury"],["#hopStatus","Raising the server, database, and address — nothing needed from you."]]} },
172
+ "expect": {"visible":["#panel-done","#setupNow","#homeFacts","#ghFacts","#hopLink"],"hidden":["#wizParts","#hop","#doneAlive"],"text":[["#donePartT","Getting Mercury ready"]]} },
173
173
  { "name": "the wizard driver at 320 (narrower than a 375 phone): the page stacks, nothing scrolls sideways, and the walk still reaches part 03", "auth": true, "width": 320, "url": "/projects?view=new",
174
174
  "steps": [["wait",600],["fill","#newName","Mercury"],["click","#typeCards .tpill[data-type=\"game\"]"],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["select","#physCountry","US"],["wait",100],["click","[data-phys=\"builder_geography\"][data-val=\"global\"]"],["click","[data-phys=\"minors_on_board\"][data-val=\"false\"]"],["click","[data-phys=\"entity\"][data-val=\"intent-solo\"]"],["wait",300],["click","#reviewRows .setRow[data-row=\"address\"] [data-row-chg]"],["wait",200],["fill","#f-slug","mercury"],["wait",900],["fill","#f-domain","mercury.example.com"],["wait",200],["click","#reviewRows .setRow[data-row=\"address\"] [data-row-chg]"],["wait",200],["click","#termsAck"],["wait",100],["click","#doCreate"],["wait",1500]],
175
- "expect": {"noOverflow":true,"visible":["#panel-done","#humanSteps"],"hidden":["#wizParts"]} },
175
+ "expect": {"noOverflow":true,"visible":["#panel-done","#homeFacts","#ghFacts"],"hidden":["#wizParts"]} },
176
176
  { "name": "invite a guild (task 1002303, R27): a /g/ address gives one pending line per member on its public page, each a link to the hall", "auth": true, "width": 1440, "url": "/projects?view=manage&id=101",
177
177
  "steps": [["wait",900],["fill","#mInviteGuild","/g/forge-crew"],["click","#mInvite [data-invite-guild]"],["wait",400]],
178
178
  "expect": { "count": [["#mInviteList li", 4]], "value": [["#mInviteGuild", ""]],
@@ -56,7 +56,7 @@
56
56
  "in-new-look": {"auth":true,"url":"/projects?view=new","actions":[["wait",600],["fill","#newName","Mercury"],["click","#typeCards .tpill[data-type=\"game\"]"],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["select","#physCountry","US"],["wait",100],["click","[data-phys=\"builder_geography\"][data-val=\"global\"]"],["click","[data-phys=\"minors_on_board\"][data-val=\"false\"]"],["click","[data-phys=\"entity\"][data-val=\"intent-solo\"]"],["wait",300],["click","#reviewRows .setRow[data-row=\"look\"] [data-row-chg]"],["wait",400]],"expect":{"visible":["#reviewRows .setRow.open[data-row=\"look\"] .opts","#wizLook"]}},
57
57
  "in-new-look-custom": {"auth":true,"url":"/projects?view=new","actions":[["wait",600],["fill","#newName","Mercury"],["click","#typeCards .tpill[data-type=\"game\"]"],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["select","#physCountry","US"],["wait",100],["click","[data-phys=\"builder_geography\"][data-val=\"global\"]"],["click","[data-phys=\"minors_on_board\"][data-val=\"false\"]"],["click","[data-phys=\"entity\"][data-val=\"intent-solo\"]"],["wait",300],["click","#reviewRows .setRow[data-row=\"look\"] [data-row-chg]"],["wait",400],["click","#wizLook-custom"],["wait",200]],"expect":{"visible":["#reviewRows .setRow.open[data-row=\"look\"] .opts","#wizLook","#wizAccent","#wizAccentNote"]}},
58
58
  "in-new-create-blocked": {"auth":true,"url":"/projects?view=new","actions":[["wait",600],["fill","#newName","Mercury"],["click","#typeCards .tpill[data-type=\"game\"]"],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["click","#termsAck"],["wait",100],["click","#doCreate"],["wait",400]],"expect":{"visible":["#reviewRows .setRow.open[data-row=\"address\"] .opts","#h-domain"],"hidden":["#doneBody"],"text":[["#createWhy","Fix the row that’s open, then create."]]}},
59
- "in-new-done": {"auth":true,"url":"/projects?view=new","actions":[["wait",600],["fill","#newName","Mercury"],["click","#typeCards .tpill[data-type=\"game\"]"],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["select","#physCountry","US"],["wait",100],["click","[data-phys=\"builder_geography\"][data-val=\"global\"]"],["click","[data-phys=\"minors_on_board\"][data-val=\"false\"]"],["click","[data-phys=\"entity\"][data-val=\"intent-solo\"]"],["wait",300],["click","#reviewRows .setRow[data-row=\"address\"] [data-row-chg]"],["wait",200],["fill","#f-slug","mercury"],["wait",900],["fill","#f-domain","mercury.example.com"],["wait",200],["click","#reviewRows .setRow[data-row=\"address\"] [data-row-chg]"],["wait",200],["click","#termsAck"],["wait",100],["click","#doCreate"],["wait",1500]],"expect":{"visible":["#panel-done","#doneBody","#humanSteps","#hop","#hopCanvas","#hopStatus","#hopJump","#wizRecap"],"hidden":["#wizParts","#qWrap","#wizInvite","#liveProgress","#wizInviteLater"],"attr":[["#doCreate","disabled",""],["#wizRoom","data-screen","done"]],"text":[["#done-h","Setting up Mercury"],["#doCreate","Created"]]}},
59
+ "in-new-done": {"auth":true,"url":"/projects?view=new","actions":[["wait",600],["fill","#newName","Mercury"],["click","#typeCards .tpill[data-type=\"game\"]"],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["select","#physCountry","US"],["wait",100],["click","[data-phys=\"builder_geography\"][data-val=\"global\"]"],["click","[data-phys=\"minors_on_board\"][data-val=\"false\"]"],["click","[data-phys=\"entity\"][data-val=\"intent-solo\"]"],["wait",300],["click","#reviewRows .setRow[data-row=\"address\"] [data-row-chg]"],["wait",200],["fill","#f-slug","mercury"],["wait",900],["fill","#f-domain","mercury.example.com"],["wait",200],["click","#reviewRows .setRow[data-row=\"address\"] [data-row-chg]"],["wait",200],["click","#termsAck"],["wait",100],["click","#doCreate"],["wait",1500]],"expect":{"visible":["#panel-done","#doneBody","#setupNow","#homeFacts","#ghFacts","#hopLink","#wizRecap"],"hidden":["#wizParts","#qWrap","#wizInvite","#hop","#doneAlive"],"attr":[["#doCreate","disabled",""],["#wizRoom","data-screen","done"]],"text":[["#donePartT","Getting Mercury ready"],["#doCreate","Created"]]}},
60
60
  "in-new-resume-offer": {"auth":true,"url":"/projects?view=new","actions":[["wait",600],["fill","#newName","Mercury"],["click","#typeCards .tpill[data-type=\"game\"]"],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["select","#physCountry","US"],["wait",100],["click","[data-phys=\"builder_geography\"][data-val=\"global\"]"],["click","[data-phys=\"minors_on_board\"][data-val=\"false\"]"],["click","[data-phys=\"entity\"][data-val=\"intent-solo\"]"],["wait",300],["click","#reviewRows .setRow[data-row=\"address\"] [data-row-chg]"],["wait",200],["fill","#f-slug","mercury"],["wait",900],["fill","#f-domain","mercury.example.com"],["wait",200],["click","#reviewRows .setRow[data-row=\"address\"] [data-row-chg]"],["wait",200],["click","#termsAck"],["wait",100],["click","#doCreate"],["wait",1500],["click","#projTrig"],["wait",350],["click","#menuProjects [data-nav=\"new\"]"],["wait",500]],"expect":{"visible":["#panel-page","#wizResume","#wizResumeGo","#wizParts"],"hidden":["#doneBody"],"text":[["#wizResumeName","Mercury"]]}},
61
61
  "out-new": {"auth":false,"url":"/projects?view=new","expect":{"visible":["#panel-gate","#wizSignin"],"hidden":["#qWrap","#panel-page"]}},
62
62
  "out-map-projects": { "auth": false, "actions": [["click", "#projTrig"], ["wait", 350]], "expect": { "expanded": true, "hidden": ["#menuProjects [data-nav=\"mine\"]"] } },
@@ -1,5 +1,5 @@
1
1
  {
2
- "_": "The owner's projects for the kit (task 1003345): four states the mine list and the manage page render — live, standing up, snagged, torn down. Timestamps written \"$now-3m\" / \"$now-1d\" are resolved by the stub at request time so \"checked 3m ago\" stays true. Mooring (task 1003345, the grade's finding): live but unreachable since its last probe, so the restart door renders and the restart probe has a row to drive.",
2
+ "_": "The owner's projects for the kit (task 1003345): four states the mine list and the manage page render — live, standing up, snagged, torn down. Timestamps written \"$now-3m\" / \"$now-1d\" are resolved by the stub at request time so \"checked 3m ago\" stays true. Mooring (task 1003345, the grade's finding): live but unreachable since its last probe, so the restart door renders and the restart probe has a row to drive. Mercury (102) also carries the owner read's GitHub halves (github_app, github_setup), produced by the REAL projections with the app approved, installed and signed in, so part 03 reaches every required fact done (task 1004683).",
3
3
  "instances": [
4
4
  {
5
5
  "id": 101,
@@ -44,7 +44,27 @@
44
44
  "state": "running",
45
45
  "created_at": "$now-6m"
46
46
  },
47
- "dns_resolves": true
47
+ "dns_resolves": true,
48
+ "github_app": {
49
+ "status": "done",
50
+ "app_slug": "mercury-cloudbongos-com",
51
+ "failure": null,
52
+ "started_at": "2026-10-09T12:52:53.145Z"
53
+ },
54
+ "github_setup": {
55
+ "checklist": {
56
+ "approve": "done",
57
+ "install": "done",
58
+ "sign_in": "done",
59
+ "device_flow": "later",
60
+ "connected": true
61
+ },
62
+ "install_url": null,
63
+ "repo": "builder/mercury",
64
+ "verifying": true,
65
+ "pick_up": null,
66
+ "app_org": null
67
+ }
48
68
  },
49
69
  {
50
70
  "id": 103,
@@ -0,0 +1,195 @@
1
+ {
2
+ "_": "Part 03 after Create, one project per scenario of the design of record docs/design/mocks/day-night-rooms/setup-status.html (task 1004683): 201 just created, 202 waiting on GitHub, 203 installing, 204 stopped (the install never confirmed, the checking window over), 205 all done. Each row carries the github_app and github_setup halves of the owner's instance read, produced by the REAL projections (manifest-truth publicGithubApp, github-setup githubSetupRead); serve.js hands them out beside the instance on the single read. Regenerate the GitHub halves rather than hand-editing them.",
3
+ "instances": [
4
+ {
5
+ "id": 201,
6
+ "slug": "kestrel",
7
+ "domain": "kestrel.cloudbongos.com",
8
+ "target_ref": "founder/kestrel",
9
+ "hosting_shape": "cloud-host",
10
+ "onboard_mode": "greenfield",
11
+ "error_note": null,
12
+ "dns_note": null,
13
+ "torn_down_at": null,
14
+ "open_intent": null,
15
+ "status": "provisioning",
16
+ "created_at": "$now-1m",
17
+ "provisioned_at": null,
18
+ "updated_at": "$now-1m",
19
+ "last_verified_at": null,
20
+ "last_verified_up": null,
21
+ "dns_resolves": false,
22
+ "github_app": null,
23
+ "github_setup": {
24
+ "checklist": {
25
+ "approve": "todo",
26
+ "install": "todo",
27
+ "sign_in": "todo",
28
+ "device_flow": "todo",
29
+ "connected": false
30
+ },
31
+ "install_url": null,
32
+ "repo": "founder/kestrel",
33
+ "verifying": false,
34
+ "app_org": null,
35
+ "pick_up": null
36
+ }
37
+ },
38
+ {
39
+ "id": 202,
40
+ "slug": "heron",
41
+ "domain": "heron.cloudbongos.com",
42
+ "target_ref": "founder/heron",
43
+ "hosting_shape": "cloud-host",
44
+ "onboard_mode": "greenfield",
45
+ "error_note": null,
46
+ "dns_note": null,
47
+ "torn_down_at": null,
48
+ "open_intent": null,
49
+ "status": "active",
50
+ "created_at": "$now-9m",
51
+ "provisioned_at": "$now-6m",
52
+ "updated_at": "$now-6m",
53
+ "last_verified_at": null,
54
+ "last_verified_up": null,
55
+ "dns_resolves": false,
56
+ "github_app": {
57
+ "status": "pending",
58
+ "app_slug": null,
59
+ "failure": null,
60
+ "started_at": "2026-10-09T12:48:57.326Z"
61
+ },
62
+ "github_setup": {
63
+ "checklist": {
64
+ "approve": "now",
65
+ "install": "todo",
66
+ "sign_in": "todo",
67
+ "device_flow": "todo",
68
+ "connected": false
69
+ },
70
+ "install_url": null,
71
+ "repo": "founder/heron",
72
+ "verifying": false,
73
+ "pick_up": "reopen",
74
+ "app_org": null
75
+ }
76
+ },
77
+ {
78
+ "id": 203,
79
+ "slug": "plover",
80
+ "domain": "plover.cloudbongos.com",
81
+ "target_ref": "founder/plover",
82
+ "hosting_shape": "cloud-host",
83
+ "onboard_mode": "greenfield",
84
+ "error_note": null,
85
+ "dns_note": null,
86
+ "torn_down_at": null,
87
+ "open_intent": null,
88
+ "status": "active",
89
+ "created_at": "$now-14m",
90
+ "provisioned_at": "$now-11m",
91
+ "updated_at": "$now-11m",
92
+ "last_verified_at": "$now-9s",
93
+ "last_verified_up": true,
94
+ "dns_resolves": true,
95
+ "github_app": {
96
+ "status": "converting",
97
+ "app_slug": "plover-cloudbongos-com",
98
+ "failure": null,
99
+ "started_at": "2026-10-09T12:45:57.326Z"
100
+ },
101
+ "github_setup": {
102
+ "checklist": {
103
+ "approve": "done",
104
+ "install": "now",
105
+ "sign_in": "now",
106
+ "device_flow": "todo",
107
+ "connected": false
108
+ },
109
+ "install_url": "https://github.com/apps/plover-cloudbongos-com/installations/new",
110
+ "repo": "founder/plover",
111
+ "verifying": true,
112
+ "pick_up": null,
113
+ "app_org": null
114
+ }
115
+ },
116
+ {
117
+ "id": 204,
118
+ "slug": "tern",
119
+ "domain": "tern.cloudbongos.com",
120
+ "target_ref": "founder/tern",
121
+ "hosting_shape": "cloud-host",
122
+ "onboard_mode": "greenfield",
123
+ "error_note": null,
124
+ "dns_note": null,
125
+ "torn_down_at": null,
126
+ "open_intent": null,
127
+ "status": "active",
128
+ "created_at": "$now-4h",
129
+ "provisioned_at": "$now-235m",
130
+ "updated_at": "$now-235m",
131
+ "last_verified_at": "$now-9s",
132
+ "last_verified_up": true,
133
+ "dns_resolves": true,
134
+ "github_app": {
135
+ "status": "done",
136
+ "app_slug": "tern-cloudbongos-com",
137
+ "failure": null,
138
+ "started_at": "2026-10-09T08:59:57.326Z"
139
+ },
140
+ "github_setup": {
141
+ "checklist": {
142
+ "approve": "done",
143
+ "install": "now",
144
+ "sign_in": "done",
145
+ "device_flow": "later",
146
+ "connected": false
147
+ },
148
+ "install_url": "https://github.com/apps/tern-cloudbongos-com/installations/new",
149
+ "repo": "founder/tern",
150
+ "verifying": false,
151
+ "pick_up": "check",
152
+ "app_org": null
153
+ }
154
+ },
155
+ {
156
+ "id": 205,
157
+ "slug": "wren",
158
+ "domain": "wren.cloudbongos.com",
159
+ "target_ref": "founder/wren",
160
+ "hosting_shape": "cloud-host",
161
+ "onboard_mode": "greenfield",
162
+ "error_note": null,
163
+ "dns_note": null,
164
+ "torn_down_at": null,
165
+ "open_intent": null,
166
+ "status": "active",
167
+ "created_at": "$now-30m",
168
+ "provisioned_at": "$now-27m",
169
+ "updated_at": "$now-27m",
170
+ "last_verified_at": "$now-3s",
171
+ "last_verified_up": true,
172
+ "dns_resolves": true,
173
+ "github_app": {
174
+ "status": "done",
175
+ "app_slug": "wren-cloudbongos-com",
176
+ "failure": null,
177
+ "started_at": "2026-10-09T12:25:57.326Z"
178
+ },
179
+ "github_setup": {
180
+ "checklist": {
181
+ "approve": "done",
182
+ "install": "done",
183
+ "sign_in": "done",
184
+ "device_flow": "later",
185
+ "connected": true
186
+ },
187
+ "install_url": null,
188
+ "repo": "founder/wren",
189
+ "verifying": true,
190
+ "pick_up": null,
191
+ "app_org": null
192
+ }
193
+ }
194
+ ]
195
+ }
@@ -309,12 +309,27 @@ function instances(res, id, settings) {
309
309
  if (FAIL.has(name)) return json(res, 500, { error: { code: 'stub_failure', message: `FAIL=${name}` } });
310
310
  const file = path.join(FIXTURES, (ALIAS[name] || name) + '.json');
311
311
  if (!fs.existsSync(file)) return json(res, 404, { error: { code: 'no_fixture', message: name } });
312
- const list = stamp((JSON.parse(fs.readFileSync(file, 'utf8')).instances || []).map(withAsk).map(withPlanet));
312
+ // a fixture row may carry the owner read's two GitHub halves (github_app, github_setup —
313
+ // the shapes modules/provisioning/routes/provisioning.js adds, task 1004683); they ride
314
+ // the single read beside the instance, never inside it, and never the list
315
+ const rows = stamp((JSON.parse(fs.readFileSync(file, 'utf8')).instances || []).map(withAsk).map(withPlanet));
316
+ const bare = (i) => { const { github_app, github_setup, ...rest } = i; return rest; };
317
+ const list = rows.map(bare);
313
318
  if (id === null) return json(res, 200, { instances: list });
314
- const inst = list.find((i) => String(i.id) === String(id));
315
- if (!inst) return json(res, 404, { error: { code: 'not_found', message: 'no such instance' } });
319
+ const row = rows.find((i) => String(i.id) === String(id));
320
+ if (!row) return json(res, 404, { error: { code: 'not_found', message: 'no such instance' } });
321
+ const inst = bare(row);
316
322
  if (settings) return json(res, 200, { settings: { platform_visibility: 'public', joinability: 'open', visibility: 'public' }, planet: PLANETS.get(String(id)) || NO_PLANET, options: { platform_visibility: ['public', 'gated'], joinability: ['open', 'apply', 'invite_only'], visibility: ['public', 'private', 'stealth'] } });
317
- return json(res, 200, { instance: inst, open_intent: inst.open_intent || null });
323
+ return json(res, 200, { instance: inst, open_intent: inst.open_intent || null, github_app: row.github_app || null, github_setup: row.github_setup || null });
324
+ }
325
+ // GET /provisioning/github-app/resume?id=N — the route's resume record (routes/github-setup.js
326
+ // resumeRecord) for a fixture project, so a render can open part 03 on it by URL alone
327
+ function resumeAnswer(res, id) {
328
+ const file = path.join(FIXTURES, (ALIAS['provisioning-instances'] || 'provisioning-instances') + '.json');
329
+ const rows = fs.existsSync(file) ? (JSON.parse(fs.readFileSync(file, 'utf8')).instances || []) : [];
330
+ const inst = id ? rows.find((i) => String(i.id) === String(id)) : null;
331
+ const repo = inst && /^[A-Za-z0-9][A-Za-z0-9-]{0,38}\/[A-Za-z0-9._-]{1,100}$/.test(String(inst.target_ref || '')) ? inst.target_ref : null;
332
+ return json(res, 200, { ok: true, project: inst ? { id: inst.id, slug: inst.slug, domain: inst.domain || null, onboard_mode: inst.onboard_mode || 'greenfield', repo } : null });
318
333
  }
319
334
  // A project's art in the featured fixture may be root-relative (the surface's
320
335
  // own /assets/…, served by this stub) — the page accepts only an http(s) art
@@ -644,6 +659,9 @@ const server = http.createServer((req, res) => {
644
659
  if (/^\/provisioning\/instances\/\d+\/invite-suggestions$/.test(rest) && req.method === 'GET') {
645
660
  return AUTH ? json(res, 200, { suggested: [], seeking: null, reason: null }) : json(res, 401, UNAUTH);
646
661
  }
662
+ if (rest === '/provisioning/github-app/resume' && req.method === 'GET') {
663
+ return AUTH ? resumeAnswer(res, u.searchParams.get('id')) : json(res, 401, UNAUTH);
664
+ }
647
665
  const one = rest.match(/^\/provisioning\/instances\/(\d+)(\/settings)?$/);
648
666
  if (one && req.method === 'GET') return AUTH ? instances(res, one[1], !!one[2]) : json(res, 401, UNAUTH);
649
667
  // the hub's own cross-project surface (task 1003774): the requested/leave/
package/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.21.104",
3
+ "version": "1.21.106",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@bongos/core",
9
- "version": "1.21.104",
9
+ "version": "1.21.106",
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.21.104",
3
+ "version": "1.21.106",
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",
@@ -9470,5 +9470,17 @@
9470
9470
  "id": "1004665",
9471
9471
  "text": "When a builder re-runs a review and attaches a screenshot, the screenshot now actually gets attached to the task. Before, it was quietly thrown away, so reviewers asking for a picture never saw one unless someone added it by h"
9472
9472
  }
9473
+ ],
9474
+ "1.21.105": [
9475
+ {
9476
+ "id": "1004666",
9477
+ "text": "A check that is still running is no longer reported as a failed one. Before, a project whose test service posts a \"still working\" status would see its change called broken and trigger a pointless repair attempt; now it is corr"
9478
+ }
9479
+ ],
9480
+ "1.21.106": [
9481
+ {
9482
+ "id": "1004683",
9483
+ "text": "After pressing Create, a founder now sees \"Getting <name> ready\" with a plain count (\"4 of 6 done\", or \"ready\" with a tick) and one sentence saying what is happening and whether it is their turn. Below it are two short lists,"
9484
+ }
9473
9485
  ]
9474
9486
  }
@@ -18,7 +18,7 @@ const { normalizeApiError } = require('./ship-io.js');
18
18
  const { plainCardLines } = require('./plain-cards.js');
19
19
  // The server's own reader of a PR's check rollup (task 1003988), reused so the laptop
20
20
  // poll names a red PR exactly the way publish-status does (task 1003764). Dependency-free.
21
- const { readCheckRollup, UNIT_REPORT_CONTEXT } = require('../../modules/lifecycle/check-rollup.js');
21
+ const { readCheckRollup, UNIT_REPORT_CONTEXT, RED_CONCLUSIONS } = require('../../modules/lifecycle/check-rollup.js');
22
22
  const { prMergeSentence } = require('../../modules/lifecycle/page-tweak-hold.js');
23
23
 
24
24
  // ---------- the land outcome (task 1002541, part 1) ----------
@@ -474,7 +474,7 @@ function redBlocksMerge(md) {
474
474
  // A check conclusion (CheckRun) or state (status context) that means FAILED. Pending and
475
475
  // expected are waiting, not red — reporting them as failures would be the mirror image of
476
476
  // the bug this names (a failure dressed as waiting).
477
- const RED_CONCLUSIONS = new Set(['FAILURE', 'ERROR', 'TIMED_OUT', 'CANCELLED', 'ACTION_REQUIRED', 'STARTUP_FAILURE']);
477
+ // The set itself lives in check-rollup.js, shared with the server's mergeBlockReason (task 1004666).
478
478
 
479
479
  // localMergeDriver — task 1003764. The laptop path watches its PR with the builder's own
480
480
  // gh, and read only state + mergeCommit, so a red required check was invisible for the
package/src/module-api.js CHANGED
@@ -75,7 +75,7 @@ const { responsibilityFor, ROLE_RESPONSIBILITIES } = require('./role-responsibil
75
75
  // MAJOR (see allowBoxScope below): passes the request through untouched.
76
76
  function deprecatedNoopMiddleware(_req, _res, next) { next(); }
77
77
 
78
- const CORE_VERSION = '1.21.104'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
78
+ const CORE_VERSION = '1.21.106'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
79
79
 
80
80
  // A namespaced logger so a module's log lines are attributable + consistent.
81
81
  // Usage: const log = api.logger('discord'); log.info('mounted');
@@ -515,24 +515,16 @@ test('text is never dimmed by subtree opacity', () => {
515
515
  assert.deepEqual(offenders, [], `\n ${offenders.join('\n ')}\n`);
516
516
  });
517
517
 
518
- test('the .prog strip mirrors .strip: state marks are --sea-ink, ticks are --on-ok', () => {
519
- // /create's done panel renders the page-local .prog, NOT cosmos's .strip —
520
- // a re-point of one and not the other is exactly how the 1.74:1 dark tick
521
- // shipped the first time. State-mark rules (done fill/connector, now
522
- // ring/pulse, the tick) must use the derived tokens; raw --sea is only legal
523
- // as a tint ingredient (color-mix) or the idle -soft rail.
524
- const progRules = [...pageSrc.matchAll(/\.prog[^{}]*\{([^}]*)\}/g)];
525
- assert.ok(progRules.length >= 5, 'the .prog rules moved out of projects.html — update this test');
526
- const bad = [];
527
- for (const m of progRules) {
528
- const body = m[1];
529
- if (/(?:border(?:-\w+)?|background)\s*:\s*var\(\s*--sea\s*\)/.test(body)) {
530
- bad.push(`raw --sea state mark: ${m[0].slice(0, 80)}`);
531
- }
532
- if (/border-(?:left|bottom)\s*:[^;]*#fff\b/i.test(body)) {
533
- bad.push(`hardcoded #fff tick: ${m[0].slice(0, 80)}`);
534
- }
535
- }
518
+ test('part 03 draws no stage strip, and its fact marks use the status inks, never raw --sea or #fff (task 1004683)', () => {
519
+ // The done panel's page-local .prog strip (a mirror of cosmos's .strip) left with the
520
+ // stage dots: part 03 is one list of checked facts now. The mine and manage views keep
521
+ // cosmos's own .strip. A fact's mark carries its state in the --ok / --err / --accent
522
+ // inks (which the day room re-points through --wz-*); raw --sea or a literal white
523
+ // would be the 1.74:1 dark tick this test was first written for.
524
+ assert.equal([...pageSrc.matchAll(/\.prog[^{}]*\{([^}]*)\}/g)].length, 0, 'no .prog rules are left in projects.html');
525
+ const marks = [...pageSrc.matchAll(/\.setFact\.(done|bad|now|you) \.d\{([^}]*)\}/g)];
526
+ assert.ok(marks.length >= 4, 'the four marked fact states are found');
527
+ const bad = marks.filter((m) => /var\(\s*--sea\s*\)|#fff\b/i.test(m[2])).map((m) => m[0].slice(0, 80));
536
528
  assert.deepEqual(bad, [], `\n ${bad.join('\n ')}\n`);
537
529
  });
538
530
 
@@ -82,8 +82,8 @@ function region(startMark, endMark) {
82
82
  const e = s < 0 ? -1 : SCRIPT.indexOf(endMark, s);
83
83
  return s > 0 && e > s ? SCRIPT.slice(s, e) : null;
84
84
  }
85
- const POLLS = region(" /* ── C8: the wizard's polls run only while the create view is on stage", ' /* ── live build progress (task 2083)');
86
- const WATCH_VARS = region(' var pollTimer = null;', " /* The done panel's own flow vocabularies");
85
+ const POLLS = region(" /* ── C8: the wizard's polls run only while the create view is on stage", " /* ── the owner's instance read (task 2083)");
86
+ const WATCH_VARS = region(' var pollTimer = null;', ' function startProgress(id) {');
87
87
  const START_PROGRESS = (SCRIPT.match(/ {4}function startProgress\(id\) \{[\s\S]*?\n {4}\}/) || [null])[0];
88
88
  const DOORS = region(" /* ── the hub's three doors ── */", ' return { enter: enter, leave: leave, onAuth: onAuth };');
89
89
 
@@ -136,7 +136,8 @@ function page({ url, who, storage = 'empty', name = '', hidden = false, instance
136
136
  renderDone() { log.rendered += 1; }, renderSteps() { log.rendered += 1; },
137
137
  resetForNewProject() { log.resets += 1; },
138
138
  saveDraft() {},
139
- setProgress() {}, progressMarkup: () => '', setMoment() {}, renderProgress: () => false, addressReady: () => true,
139
+ // part 03's facts (task 1004683) are tests/setup_status_facts.mjs; here they only have to exist
140
+ paintFacts() {}, homeFacts: () => [], ghFacts: () => [], setupReady: () => false, hostOk: () => true, addressReady: () => true,
140
141
  };
141
142
  sandbox.globalThis = sandbox;
142
143
  vm.createContext(sandbox);