@bongos/core 1.19.442 → 1.19.444

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 (168) hide show
  1. package/.bongos-core.json +470 -455
  2. package/config/branding.neutral.json +1 -1
  3. package/docs/adr/0054-session-token-reward-cost-plus.md +14 -0
  4. package/docs/adr/0218-the-apex-root-web-surface.md +55 -0
  5. package/docs/adr/README.md +1 -0
  6. package/docs/architecture.md +2 -1
  7. package/docs/copy-inventory.md +360 -360
  8. package/docs/copy-registry.json +456 -456
  9. package/docs/design/mocks/hub/mine.html +1 -1
  10. package/docs/design/mocks/hub/picker.html +1 -1
  11. package/docs/design/mocks/hub/planets.html +1 -1
  12. package/docs/design/mocks/hub/v1.html +3 -3
  13. package/docs/design/mocks/hub/v2.html +2 -2
  14. package/docs/design/mocks/hub/v3.html +5 -5
  15. package/docs/design/mocks/hub/wizard.html +1 -1
  16. package/docs/design/mocks/landing/v1.html +1 -1
  17. package/docs/design/mocks/landing/v2.html +1 -1
  18. package/docs/design/mocks/landing/v3.html +1 -1
  19. package/docs/design/mocks/landing-page-mock.html +3 -3
  20. package/docs/design/mocks/projects-hub-mock.html +1 -1
  21. package/docs/design/mocks/projects-hub-variants.html +1 -1
  22. package/docs/design/mocks/projects-page-mock.html +1 -1
  23. package/docs/file-map.md +3 -3
  24. package/docs/module-api-changelog.md +4 -0
  25. package/docs/modules-contract.md +9 -2
  26. package/docs/recipes/ui-look-before-you-ship.md +4 -4
  27. package/modules/copy-desk/tests/copy_flags.mjs +4 -4
  28. package/modules/public-landing/CLAUDE.md +15 -0
  29. package/modules/public-landing/module.json +15 -0
  30. package/modules/ui-design/kit/lib.js +2 -2
  31. package/modules/ui-design/kit/render.js +1 -1
  32. package/modules/ui-design/kit/serve.js +3 -3
  33. package/package-lock.json +2 -2
  34. package/package.json +1 -1
  35. package/scripts/gds/copy-inventory.js +3 -3
  36. package/scripts/gds/fitness-checks-identity.js +18 -1
  37. package/scripts/gds/publish-manifest.js +1 -1
  38. package/scripts/gds/session-digest-build.js +49 -17
  39. package/scripts/gds/session-digest.js +11 -1
  40. package/scripts/gds/ship-session-upload.js +102 -12
  41. package/scripts/gds/ship.js +7 -1
  42. package/src/bongos/module-scope-map.js +9 -7
  43. package/src/bongos/serve-internal.js +13 -1
  44. package/src/module-api.js +1 -1
  45. package/src/module-loader/loader.js +34 -17
  46. package/src/module-loader/manifest-schema.js +16 -8
  47. package/src/platform-server.js +50 -18
  48. package/tests/copy_inventory.mjs +0 -0
  49. package/tests/cosmos_token_contrast.mjs +6 -6
  50. package/tests/credit_grant.mjs +236 -0
  51. package/tests/fitness.mjs +20 -0
  52. package/tests/landing_legal_pages.mjs +2 -1
  53. package/tests/landing_page.mjs +7 -5
  54. package/tests/module-scope-map.mjs +2 -2
  55. package/tests/module_loader.mjs +4 -1
  56. package/tests/onboard.mjs +5 -5
  57. package/tests/projects_hub.mjs +22 -20
  58. package/tests/projects_hub_pre_uat.mjs +5 -3
  59. package/tests/public_landing_projects.mjs +2 -2
  60. package/tests/terms_acceptance.mjs +1 -1
  61. package/tests/ui_design_kit.mjs +3 -3
  62. package/tests/world_tokens.mjs +3 -2
  63. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_00.webp +0 -0
  64. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_01.webp +0 -0
  65. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_02.webp +0 -0
  66. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_03.webp +0 -0
  67. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_04.webp +0 -0
  68. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_05.webp +0 -0
  69. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_06.webp +0 -0
  70. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_07.webp +0 -0
  71. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_08.webp +0 -0
  72. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_09.webp +0 -0
  73. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_10.webp +0 -0
  74. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_11.webp +0 -0
  75. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_12.webp +0 -0
  76. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_13.webp +0 -0
  77. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_14.webp +0 -0
  78. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_15.webp +0 -0
  79. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_16.webp +0 -0
  80. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_17.webp +0 -0
  81. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_18.webp +0 -0
  82. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_19.webp +0 -0
  83. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_20.webp +0 -0
  84. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_21.webp +0 -0
  85. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_22.webp +0 -0
  86. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_23.webp +0 -0
  87. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_24.webp +0 -0
  88. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_25.webp +0 -0
  89. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_26.webp +0 -0
  90. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_27.webp +0 -0
  91. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_28.webp +0 -0
  92. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_29.webp +0 -0
  93. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_30.webp +0 -0
  94. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_31.webp +0 -0
  95. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_32.webp +0 -0
  96. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_33.webp +0 -0
  97. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_34.webp +0 -0
  98. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_35.webp +0 -0
  99. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_36.webp +0 -0
  100. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_37.webp +0 -0
  101. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_38.webp +0 -0
  102. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_39.webp +0 -0
  103. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_40.webp +0 -0
  104. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_41.webp +0 -0
  105. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_42.webp +0 -0
  106. /package/{public-landing → modules/public-landing/public}/assets/anim/idle/frame_43.webp +0 -0
  107. /package/{public-landing → modules/public-landing/public}/assets/cosmos.css +0 -0
  108. /package/{public-landing → modules/public-landing/public}/assets/verro-medallion.png +0 -0
  109. /package/{public-landing → modules/public-landing/public}/assets/world/og-card.jpg +0 -0
  110. /package/{public-landing → modules/public-landing/public}/assets/world/r2-bongos-chrome-a-cut.webp +0 -0
  111. /package/{public-landing → modules/public-landing/public}/assets/world/r2-bongos-chrome-a-cut.webp.json +0 -0
  112. /package/{public-landing → modules/public-landing/public}/assets/world/r2-bongos-chrome-b.jpg +0 -0
  113. /package/{public-landing → modules/public-landing/public}/assets/world/r2-bongos-chrome-b.jpg.json +0 -0
  114. /package/{public-landing → modules/public-landing/public}/assets/world/r2-chrome-blob-one-cut.webp +0 -0
  115. /package/{public-landing → modules/public-landing/public}/assets/world/r2-chrome-blob-one-cut.webp.json +0 -0
  116. /package/{public-landing → modules/public-landing/public}/assets/world/r2-chrome-blob-one.jpg +0 -0
  117. /package/{public-landing → modules/public-landing/public}/assets/world/r2-chrome-blob-one.jpg.json +0 -0
  118. /package/{public-landing → modules/public-landing/public}/assets/world/r2-chrome-blobs-set-cut.webp +0 -0
  119. /package/{public-landing → modules/public-landing/public}/assets/world/r2-chrome-blobs-set-cut.webp.json +0 -0
  120. /package/{public-landing → modules/public-landing/public}/assets/world/r2-chrome-blobs-set.jpg +0 -0
  121. /package/{public-landing → modules/public-landing/public}/assets/world/r2-chrome-blobs-set.jpg.json +0 -0
  122. /package/{public-landing → modules/public-landing/public}/assets/world/r3-frost-bead-cut.webp +0 -0
  123. /package/{public-landing → modules/public-landing/public}/assets/world/r3-frost-bead-cut.webp.json +0 -0
  124. /package/{public-landing → modules/public-landing/public}/assets/world/r3-frost-blob-cut.webp +0 -0
  125. /package/{public-landing → modules/public-landing/public}/assets/world/r3-frost-blob-cut.webp.json +0 -0
  126. /package/{public-landing → modules/public-landing/public}/assets/world/r3-frost-pair-cut.webp +0 -0
  127. /package/{public-landing → modules/public-landing/public}/assets/world/r3-frost-pair-cut.webp.json +0 -0
  128. /package/{public-landing → modules/public-landing/public}/assets/world/r3-gold-bead-cut.webp +0 -0
  129. /package/{public-landing → modules/public-landing/public}/assets/world/r3-gold-bead-cut.webp.json +0 -0
  130. /package/{public-landing → modules/public-landing/public}/assets/world/r3-gold-blob-cut.webp +0 -0
  131. /package/{public-landing → modules/public-landing/public}/assets/world/r3-gold-blob-cut.webp.json +0 -0
  132. /package/{public-landing → modules/public-landing/public}/assets/world/r3-gold-pair-cut.webp +0 -0
  133. /package/{public-landing → modules/public-landing/public}/assets/world/r3-gold-pair-cut.webp.json +0 -0
  134. /package/{public-landing → modules/public-landing/public}/assets/world/r3-obsidian-bead-cut.webp +0 -0
  135. /package/{public-landing → modules/public-landing/public}/assets/world/r3-obsidian-bead-cut.webp.json +0 -0
  136. /package/{public-landing → modules/public-landing/public}/assets/world/r3-obsidian-blob-cut.webp +0 -0
  137. /package/{public-landing → modules/public-landing/public}/assets/world/r3-obsidian-blob-cut.webp.json +0 -0
  138. /package/{public-landing → modules/public-landing/public}/assets/world/r3-obsidian-pair-cut.webp +0 -0
  139. /package/{public-landing → modules/public-landing/public}/assets/world/r3-obsidian-pair-cut.webp.json +0 -0
  140. /package/{public-landing → modules/public-landing/public}/assets/world/r3-space-nebula.jpg +0 -0
  141. /package/{public-landing → modules/public-landing/public}/assets/world/r3-space-nebula.jpg.json +0 -0
  142. /package/{public-landing → modules/public-landing/public}/assets/world/r4-card-chrome.jpg +0 -0
  143. /package/{public-landing → modules/public-landing/public}/assets/world/r4-card-chrome.jpg.json +0 -0
  144. /package/{public-landing → modules/public-landing/public}/assets/world/r4-card-deepfield.jpg +0 -0
  145. /package/{public-landing → modules/public-landing/public}/assets/world/r4-card-deepfield.jpg.json +0 -0
  146. /package/{public-landing → modules/public-landing/public}/assets/world/r4-card-dust.jpg +0 -0
  147. /package/{public-landing → modules/public-landing/public}/assets/world/r4-card-dust.jpg.json +0 -0
  148. /package/{public-landing → modules/public-landing/public}/assets/world/r4-card-nebula.jpg +0 -0
  149. /package/{public-landing → modules/public-landing/public}/assets/world/r4-card-nebula.jpg.json +0 -0
  150. /package/{public-landing → modules/public-landing/public}/assets/world.css +0 -0
  151. /package/{public-landing → modules/public-landing/public}/buddha.png +0 -0
  152. /package/{public-landing → modules/public-landing/public}/contact.html +0 -0
  153. /package/{public-landing → modules/public-landing/public}/index.html +0 -0
  154. /package/{public-landing → modules/public-landing/public}/index.probes.json +0 -0
  155. /package/{public-landing → modules/public-landing/public}/index.states.json +0 -0
  156. /package/{public-landing → modules/public-landing/public}/privacy.html +0 -0
  157. /package/{public-landing → modules/public-landing/public}/projects-empty.states.json +0 -0
  158. /package/{public-landing → modules/public-landing/public}/projects-floor.states.json +0 -0
  159. /package/{public-landing → modules/public-landing/public}/projects.html +0 -0
  160. /package/{public-landing → modules/public-landing/public}/projects.probes.json +0 -0
  161. /package/{public-landing → modules/public-landing/public}/projects.states.json +0 -0
  162. /package/{public-landing → modules/public-landing/public}/terms.html +0 -0
  163. /package/{public-landing → modules/public-landing/public}/world/assets/clouds/cloud-island-large.png +0 -0
  164. /package/{public-landing → modules/public-landing/public}/world/assets/clouds/cloud-puff.png +0 -0
  165. /package/{public-landing → modules/public-landing/public}/world/assets/creatures/creature-whale-cargo.png +0 -0
  166. /package/{public-landing → modules/public-landing/public}/world/assets/creatures/creature-whale-glide.png +0 -0
  167. /package/{public-landing → modules/public-landing/public}/world/assets/plates/plate-clouds-near.png +0 -0
  168. /package/{public-landing → modules/public-landing/public}/world/assets/plates/scene-establishing.png +0 -0
@@ -8,7 +8,7 @@
8
8
  <link rel="preconnect" href="https://fonts.googleapis.com">
9
9
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
10
10
  <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400&family=Manrope:wght@300;400;500;600&display=swap">
11
- <link rel="stylesheet" href="../../../../public-landing/assets/cosmos.css">
11
+ <link rel="stylesheet" href="../../../../modules/public-landing/public/assets/cosmos.css">
12
12
  <style>
13
13
  body{
14
14
  /* The composition round for task 1003345 (docs/design/projects-hub-direction-v2.md §14). cosmos.css
@@ -8,7 +8,7 @@
8
8
  <link rel="preconnect" href="https://fonts.googleapis.com">
9
9
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
10
10
  <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400&family=Manrope:wght@300;400;500;600&display=swap">
11
- <link rel="stylesheet" href="../../../../public-landing/assets/cosmos.css">
11
+ <link rel="stylesheet" href="../../../../modules/public-landing/public/assets/cosmos.css">
12
12
  <style>
13
13
  body{
14
14
  /* The composition round for task 1003347 (docs/design/projects-hub-direction-v2.md §16): the
@@ -11,7 +11,7 @@
11
11
  <link rel="preconnect" href="https://fonts.googleapis.com">
12
12
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
13
13
  <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400&family=Manrope:wght@300;400;500;600&display=swap">
14
- <link rel="stylesheet" href="../../../../public-landing/assets/cosmos.css">
14
+ <link rel="stylesheet" href="../../../../modules/public-landing/public/assets/cosmos.css">
15
15
  <style>
16
16
  body{
17
17
  /* The composition round for task 1003319 (docs/design/projects-hub-direction-v2.md §11). cosmos.css
@@ -11,7 +11,7 @@
11
11
  <link rel="preconnect" href="https://fonts.googleapis.com">
12
12
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
13
13
  <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400&family=Manrope:wght@300;400;500;600&display=swap">
14
- <link rel="stylesheet" href="../../../../public-landing/assets/cosmos.css">
14
+ <link rel="stylesheet" href="../../../../modules/public-landing/public/assets/cosmos.css">
15
15
  <style>
16
16
  /* ═══════════════ v1 "the shelf" — the page tier ═══════════════════════════
17
17
  cosmos.css above carries the fifteen contract tokens, the sky, the orbs, the
@@ -757,7 +757,7 @@ not a width), --ok, --warn and --err keep cosmos's meaning and are not redeclare
757
757
  <div class="cardScrim" id="cardScrim" hidden>
758
758
  <div class="projCard" id="projCard" role="dialog" aria-modal="true" aria-labelledby="cardName" data-art="on" data-faces="on" data-figs="two" data-facts="on" data-hall="on" style="--acc:var(--accent)">
759
759
  <button type="button" class="cardX" id="cardClose" aria-label="Close"><svg viewBox="0 0 20 20" aria-hidden="true"><path d="M5.4 5.4l9.2 9.2M14.6 5.4l-9.2 9.2"/></svg></button>
760
- <img class="cardArt" id="cardArt" src="../../../../public-landing/assets/world/og-card.jpg" alt="">
760
+ <img class="cardArt" id="cardArt" src="../../../../modules/public-landing/public/assets/world/og-card.jpg" alt="">
761
761
  <span class="cardDot" id="cardDot"></span>
762
762
  <h2 class="cardName" id="cardName">Cloud Bongos</h2>
763
763
  <p class="cardTag" id="cardTag">Building Digitally, as simple as Bongos.</p>
@@ -903,7 +903,7 @@ not a width), --ok, --warn and --err keep cosmos's meaning and are not redeclare
903
903
  var AV = 'https://avatars.githubusercontent.com/u/';
904
904
  var PLATFORM = {
905
905
  acc: 'var(--accent)', name: 'Cloud Bongos', tag: 'Building Digitally, as simple as Bongos.',
906
- rel: 'you build here', art: '../../../../public-landing/assets/world/og-card.jpg',
906
+ rel: 'you build here', art: '../../../../modules/public-landing/public/assets/world/og-card.jpg',
907
907
  faces: [[AV + '64553469?v=4', 'jaxri'], [AV + '283020391?v=4', 'lars589'], [AV + '290184380?v=4', 'IAMMASTERQUA'],
908
908
  [AV + '295990394?v=4', 'scootermack'], [AV + '35337514?v=4', 'LarsCode']],
909
909
  type: null, more: '+4', builders: '9', shipped: '30+', runs: 'cloudbongos.com',
@@ -12,7 +12,7 @@
12
12
  <link rel="preconnect" href="https://fonts.googleapis.com">
13
13
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
14
14
  <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400&family=Manrope:wght@300;400;500;600&display=swap">
15
- <link rel="stylesheet" href="../../../../public-landing/assets/cosmos.css">
15
+ <link rel="stylesheet" href="../../../../modules/public-landing/public/assets/cosmos.css">
16
16
  <style>
17
17
  body{
18
18
  /* v2 "the hairline" — the world's derived tier for this surface, by the recipes in DESIGN.md's
@@ -753,7 +753,7 @@ vocabulary its chips depend on). Two recipes are adapted because a mock may carr
753
753
  <div class="cardScrim" id="cardScrim" hidden>
754
754
  <div class="projCard has-art" id="projCard" role="dialog" aria-modal="true" aria-labelledby="cardName">
755
755
  <button type="button" class="cardX" id="cardClose" aria-label="Close"><svg aria-hidden="true"><use href="#i-close"></use></svg></button>
756
- <img class="cardArt" id="cardArt" src="../../../../public-landing/assets/world/og-card.jpg" alt="">
756
+ <img class="cardArt" id="cardArt" src="../../../../modules/public-landing/public/assets/world/og-card.jpg" alt="">
757
757
  <p class="cardFigs" id="cardFigs">
758
758
  <span class="cardCall a" id="figA"><svg class="lead" viewBox="0 0 68 26" preserveAspectRatio="none" aria-hidden="true"><line x1="0" y1="25" x2="67" y2="1" stroke="currentColor" stroke-width="1" vector-effect="non-scaling-stroke"/></svg><span class="fig" id="figABig">9</span><span class="cap">builders</span></span>
759
759
  <span class="cardCall b" id="figB"><svg class="lead" viewBox="0 0 68 26" preserveAspectRatio="none" aria-hidden="true"><line x1="0" y1="25" x2="67" y2="1" stroke="currentColor" stroke-width="1" vector-effect="non-scaling-stroke"/></svg><span class="fig" id="figBBig">30+</span><span class="cap">shipped in 30 days</span></span>
@@ -11,7 +11,7 @@
11
11
  <link rel="preconnect" href="https://fonts.googleapis.com">
12
12
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
13
13
  <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400&family=Manrope:wght@300;400;500;600&display=swap">
14
- <link rel="stylesheet" href="../../../../public-landing/assets/cosmos.css">
14
+ <link rel="stylesheet" href="../../../../modules/public-landing/public/assets/cosmos.css">
15
15
  <style>
16
16
  /* ══ v3 THE GLASS STRIP. Page tier only. cosmos.css owns the fifteen contract
17
17
  tokens, the sky, the orbs, the hover card, the toolbar, the table, the
@@ -875,7 +875,7 @@ the hub's fixed verification vocabulary.
875
875
  <div class="ladderCell" data-card="card"><span class="boardLbl">card</span>
876
876
  <div class="projCard" id="projCard" role="dialog" aria-modal="true" aria-labelledby="cardName" style="--acc:var(--accent)">
877
877
  <button type="button" class="cardX" id="cardClose" aria-label="Close"><svg class="ic" aria-hidden="true"><use href="#i-close"></use></svg></button>
878
- <img class="cardArt" src="../../../../public-landing/assets/world/og-card.jpg" alt="">
878
+ <img class="cardArt" src="../../../../modules/public-landing/public/assets/world/og-card.jpg" alt="">
879
879
  <span class="artScrim" aria-hidden="true"></span>
880
880
  <span class="cardDot" id="cardDot"></span>
881
881
  <h3 class="cardName" id="cardName">Cloud Bongos</h3>
@@ -967,7 +967,7 @@ the hub's fixed verification vocabulary.
967
967
  <div class="ladderCell" data-card="card-nofaces" hidden><span class="boardLbl">card-nofaces</span>
968
968
  <div class="projCard" style="--acc:var(--accent)">
969
969
  <button type="button" class="cardX" aria-label="Close"><svg class="ic" aria-hidden="true"><use href="#i-close"></use></svg></button>
970
- <img class="cardArt" src="../../../../public-landing/assets/world/og-card.jpg" alt="">
970
+ <img class="cardArt" src="../../../../modules/public-landing/public/assets/world/og-card.jpg" alt="">
971
971
  <span class="artScrim" aria-hidden="true"></span>
972
972
  <span class="cardDot"></span>
973
973
  <h3 class="cardName" id="cardName-nofaces">Cloud Bongos</h3>
@@ -990,7 +990,7 @@ the hub's fixed verification vocabulary.
990
990
  <div class="ladderCell" data-card="card-onefig" hidden><span class="boardLbl">card-onefig</span>
991
991
  <div class="projCard" style="--acc:var(--accent)">
992
992
  <button type="button" class="cardX" aria-label="Close"><svg class="ic" aria-hidden="true"><use href="#i-close"></use></svg></button>
993
- <img class="cardArt" src="../../../../public-landing/assets/world/og-card.jpg" alt="">
993
+ <img class="cardArt" src="../../../../modules/public-landing/public/assets/world/og-card.jpg" alt="">
994
994
  <span class="artScrim" aria-hidden="true"></span>
995
995
  <span class="cardDot"></span>
996
996
  <h3 class="cardName" id="cardName-onefig">Cloud Bongos</h3>
@@ -1020,7 +1020,7 @@ the hub's fixed verification vocabulary.
1020
1020
  <div class="ladderCell" data-card="card-nofig" hidden><span class="boardLbl">card-nofig</span>
1021
1021
  <div class="projCard" style="--acc:var(--accent)">
1022
1022
  <button type="button" class="cardX" aria-label="Close"><svg class="ic" aria-hidden="true"><use href="#i-close"></use></svg></button>
1023
- <img class="cardArt" src="../../../../public-landing/assets/world/og-card.jpg" alt="">
1023
+ <img class="cardArt" src="../../../../modules/public-landing/public/assets/world/og-card.jpg" alt="">
1024
1024
  <span class="artScrim" aria-hidden="true"></span>
1025
1025
  <span class="cardDot"></span>
1026
1026
  <h3 class="cardName" id="cardName-nofig">Cloud Bongos</h3>
@@ -8,7 +8,7 @@
8
8
  <link rel="preconnect" href="https://fonts.googleapis.com">
9
9
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
10
10
  <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400&family=Manrope:wght@300;400;500;600&display=swap">
11
- <link rel="stylesheet" href="../../../../public-landing/assets/cosmos.css">
11
+ <link rel="stylesheet" href="../../../../modules/public-landing/public/assets/cosmos.css">
12
12
  <style>
13
13
  body{
14
14
  /* The composition round for task 1003346 (docs/design/projects-hub-direction-v2.md §15). cosmos.css
@@ -803,7 +803,7 @@ in the h1 is the server-stamped {{tagline}}. Apex-only regions are stripped on a
803
803
  <!--apex-only:start-->
804
804
  <section class="band">
805
805
  <div class="wrap verro">
806
- <img src="../../../../public-landing/assets/verro-medallion.png" width="384" height="384"
806
+ <img src="../../../../modules/public-landing/public/assets/verro-medallion.png" width="384" height="384"
807
807
  alt="The Verro Labs mark: a galaxy and constellation above a river valley threaded with circuitry">
808
808
  <div>
809
809
  <h2>VERRO LABS</h2>
@@ -614,7 +614,7 @@ data-link-hall); the h1 string is the server-stamped {{tagline}}.
614
614
  <!--apex-only:start-->
615
615
  <section class="page">
616
616
  <div class="wrap verro">
617
- <img src="../../../../public-landing/assets/verro-medallion.png" width="292" height="292"
617
+ <img src="../../../../modules/public-landing/public/assets/verro-medallion.png" width="292" height="292"
618
618
  alt="The Verro Labs mark: a galaxy and constellation above a river valley threaded with circuitry">
619
619
  <div>
620
620
  <span class="wordmark">VERRO LABS</span>
@@ -825,7 +825,7 @@ composition A, pinned by the owner 2026-08-27. No roll.
825
825
  <!--apex-only:start-->
826
826
  <section class="band">
827
827
  <div class="wrap verro">
828
- <img src="../../../../public-landing/assets/verro-medallion.png"
828
+ <img src="../../../../modules/public-landing/public/assets/verro-medallion.png"
829
829
  alt="The Verro Labs mark: a galaxy and constellation above a river valley threaded with circuitry">
830
830
  <div>
831
831
  <p class="wordmark">VERRO LABS</p>
@@ -32,7 +32,7 @@
32
32
  <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Baloo+2:wght@500;600;700&family=Quicksand:wght@400;500;600;700&family=Fira+Code:wght@400;500&display=swap">
33
33
  <!-- Same convention as projects-page-mock.html: this links the REAL token layer
34
34
  the live pages use, so what you review is what ships. Toggle ☾/☀ in the header. -->
35
- <link rel="stylesheet" href="../../../public-landing/assets/cosmos.css">
35
+ <link rel="stylesheet" href="../../../modules/public-landing/public/assets/cosmos.css">
36
36
  <!-- Candidate palettes. MOCK-ONLY: on a real instance exactly one of these
37
37
  exists and arrives via config/branding.json → themeMarkup(). See the file
38
38
  header for the contrast audit. -->
@@ -339,7 +339,7 @@ body:not([data-mascot="bongos"]) .mascot-bongos{display:none;}
339
339
  </div>
340
340
  </div>
341
341
  <div class="mascot">
342
- <img class="mascot-buddha" id="buddha" src="../../../public-landing/buddha.png"
342
+ <img class="mascot-buddha" id="buddha" src="../../../modules/public-landing/public/buddha.png"
343
343
  alt="A laughing Cloud Bongos buddha playing the bongos on a cloud">
344
344
 
345
345
  <svg class="mascot-bongos bongos" viewBox="0 0 440 320" role="img"
@@ -611,7 +611,7 @@ body:not([data-mascot="bongos"]) .mascot-bongos{display:none;}
611
611
  only ever been visible behind a 401. buddha.png stays the poster so the
612
612
  hero is never blank while frames load. */
613
613
  if(!reduce){
614
- var img=document.getElementById('buddha'), FR=44, base='../../../public-landing/assets/anim/idle/frame_';
614
+ var img=document.getElementById('buddha'), FR=44, base='../../../modules/public-landing/public/assets/anim/idle/frame_';
615
615
  var srcs=[], loaded=0;
616
616
  for(var i=0;i<FR;i++){
617
617
  var p=new Image();
@@ -8,7 +8,7 @@
8
8
  <!-- The mock links the SHIPPING stylesheet by relative path so what you see is
9
9
  what the build inherits. Serve over HTTP (python -m http.server 8899) — a
10
10
  file:// open still resolves this, but the fonts do not. -->
11
- <link rel="stylesheet" href="../../../public-landing/assets/cosmos.css">
11
+ <link rel="stylesheet" href="../../../modules/public-landing/public/assets/cosmos.css">
12
12
  <link rel="preconnect" href="https://fonts.googleapis.com">
13
13
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
14
14
  <link href="https://fonts.googleapis.com/css2?family=Baloo+2:wght@500;600;700&family=Quicksand:wght@400;500;600;700&family=Fira+Code:wght@400;500&display=swap" rel="stylesheet">
@@ -4,7 +4,7 @@
4
4
  <meta charset="utf-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1">
6
6
  <title>The hub's ground — three candidates (task 1002758)</title>
7
- <link rel="stylesheet" href="../../../public-landing/assets/cosmos.css">
7
+ <link rel="stylesheet" href="../../../modules/public-landing/public/assets/cosmos.css">
8
8
  <link href="https://fonts.googleapis.com/css2?family=Baloo+2:wght@500;600;700&family=Quicksand:wght@400;500;600;700&family=Fira+Code:wght@400;500&display=swap" rel="stylesheet">
9
9
  <style>
10
10
  /* Contact sheet — the same pattern landing-palettes.html used for the palette
@@ -9,7 +9,7 @@
9
9
  <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Baloo+2:wght@500;600;700&family=Quicksand:wght@400;500;600;700&family=Fira+Code:wght@400;500&display=swap">
10
10
  <!-- This mock links the REAL token/component layer the live pages use, so what
11
11
  you review here is what ships. Toggle ☾/☀ in the header to see both modes. -->
12
- <link rel="stylesheet" href="../../../public-landing/assets/cosmos.css">
12
+ <link rel="stylesheet" href="../../../modules/public-landing/public/assets/cosmos.css">
13
13
  <script>
14
14
  try{var _m=localStorage.getItem('cb-color-mode');if(_m==='light'||_m==='dark')document.documentElement.setAttribute('data-mode',_m);}catch(e){}
15
15
  </script>
package/docs/file-map.md CHANGED
@@ -11,7 +11,7 @@
11
11
  ├── README.md ← public-facing one-paragraph summary
12
12
  ├── PRODUCT.md ← durable product truth for the apex/hall/status surfaces (impeccable init, task 1003296): users, positioning, constraints, brand commitments, principles — no palette, no type
13
13
  ├── DESIGN.md ← the visual rulebook written FROM the built landing (task 1003298, ADR 0196): palette + derived recipes, type, materials (the chrome plates), components, the motion grammar, both modes; what H1 (hall) and S1 (status) build against. Sidecar .impeccable/design.json
14
- ├── .impeccable/ ← impeccable skill artifacts: config.json (buildPath: code), surfaces/<route>.md (per-route briefs), mocks/world-assets/ (Higgsfield renders + prompt sidecars; the SOURCE of public-landing/assets/world/), mocks/decision/ (A1 comps), design.json (DESIGN.md sidecar), review/ (finish captures)
14
+ ├── .impeccable/ ← impeccable skill artifacts: config.json (buildPath: code), surfaces/<route>.md (per-route briefs), mocks/world-assets/ (Higgsfield renders + prompt sidecars; the SOURCE of modules/public-landing/public/assets/world/), mocks/decision/ (A1 comps), design.json (DESIGN.md sidecar), review/ (finish captures)
15
15
  ├── .gitignore
16
16
  ├── package.json / package-lock.json
17
17
  ├── CODEOWNERS ← owner review on the merge-gate surfaces (real since task 1002611, ADR 0159); inert until branch protection is on (scripts/gds/gating.js) — keep aligned with gate-review.js HARD_FLOOR_GLOBS
@@ -130,7 +130,7 @@
130
130
  │ ├── hall-ui/ ← CORE-DOMAIN WEB-SURFACE carve (BV1.R85, default-on): the authenticated builders' hall at builders.<apex>, moved from public-builders/ (~13k LOC, the largest). NO routes/db/port — declares contributes.webSurfaces:[{host:"builders.",dir:"public"}] for discovery, but UNLIKE status-ui keeps its DEDICATED serving block in serve-internal (the /builders shim + canonical redirects + citizen/Archon page gates + asset-stamping + hall-widget injection), partitioned out of the generic web-surface loop and served from BUILDERS_DIR. CLAUDE.md, module.json, public/{index.html,builders.js,style.css,work,watch,harbor,gate,pair,settings,ranks,sessions,primer,diagrams,atlas,...}.{html,js},cursors/,chime.wav.
131
131
  │ ├── lifecycle/ ← CORE-DOMAIN carve (BV1.R86, default-on): the build state machine — tasks · claims · versions · done-when · goals · dependencies · claim→ship→grade→credit · github-push + merge-lock + conflict-resolve + publish-reconciler. The LAST, most-coupled carve; registers the `lifecycle` kernel port (createTask, classifyTaskKind, tallyPeerVotes, work-tracking reads). CLAUDE.md, module.json, routes/{tasks,claims,versions,done-when,goals,dependencies,gate-approvals,analytics}.js, lifecycle.js, github-push.js, merge-lock.js, conflict-resolve.js, publish-reconciler.js, task-visuals.js + task-visual-db.js + routes/visuals.js (the optional ship-time visual, task 1003109 — the route file is NOT named task-*.js on purpose; see the module CLAUDE.md).
132
132
  │ ├── copy-desk/ ← CORE-DOMAIN module (task 1003113 / R02 of goal 1000074, default-on): the COPY half of the design contract — ADR 0081 gave design TOKENS a repo-owned source of truth, text had none. Owns the FLAG (anyone in any role marks a string or a whole surface as needing an artist's attention, with a reason required in BOTH the route and a CHECK constraint) and the QUEUE an artist reads it from. READS R01's committed registry (docs/copy-registry.json, generated by scripts/gds/copy-inventory.js) and never writes it. NO LIVE CMS is the hard non-goal: no column here could hold replacement text, and copy_no_cms.mjs pins that. Key is `copy-desk`, not `copy` — the branding contract already owns a `copy` block, so the bare word reds the "core carries no module code" fitness check. CLAUDE.md, module.json, registry.js, flags.js, routes/copy-desk.js, migrations/copy_desk_001_flags.sql, tests/{copy_flags,copy_queue,copy_no_cms}.mjs. Its hall surface lives with hall-ui (public/copy-desk.{html,js,css}), per the one-key-per-web-surface precedent.
133
- │ ├── ui-design/ ← CORE-DOMAIN module (task 1003324 / ADR 0197, default-on): the design capability every builder on every instance gets — ships METHOD, never a world. Absorbs ADR 0081's layer: adapters/{claude-design,figma}/index.js (moved from src/ui/adapters/), scripts/{design-sync,figma-design-sync,validate-design}.js (moved from scripts/gds/, which keeps thin shims), docs/design-contract.md (moved from docs/). Declaration-only: contributes.skills design (the /design playbook, new) + design-sync + figma-design-sync; no routes/port/migrations, so disabling it touches no served surface. CLAUDE.md separates the platform FLOORS (the Fifteen Rule, the dark twins, no page :root, the 24px floor, AA in both modes, the kill switch) from the instance's WORLD (its packs + DESIGN.md). kit/ (task 1003320) is the look-before-you-ship kit: lib.js (the floors, the states/probes contracts, the action + expectation vocabularies, the WCAG maths, the stub spawner), serve.js (any surface through the doorway's real transforms + fixtures/), render.js (states × 1440/390/320 × dark/light, audited), probe.js (PASS/FAIL contracts), check-mock.js (platform rules + the instance's DESIGN.md taste bans), contrast.js + png.js; a page's <page>.states.json / <page>.probes.json sit BESIDE the surface (public-landing/, modules/hall-ui/public/). Recipe: docs/recipes/ui-look-before-you-ship.md. skills/ (task 1003321 / ADR 0198) is the vendoring policy: policy.json (licence allowlist, verdicts that may land, sidecar fields, preamble markers), PREAMBLE.md (the platform preamble every vendored SKILL.md opens with), README.md (the roster — both origins scanned dangerous on 2026-08-28, landed as rebuild specs; nothing vendored — and the landing recipe); a landable copy goes under skills/vendor/<name>/ with PROVENANCE.md + LICENSE and is materialised into an instance's .claude/skills/ by claude-materialize.js step 1b. Reserved home styles/ (1003323) with a README. config/design-tokens.* + design-sources.json STAY in config/ as the host boundary; public-landing keeps its own key (first customer, not owner).
133
+ │ ├── ui-design/ ← CORE-DOMAIN module (task 1003324 / ADR 0197, default-on): the design capability every builder on every instance gets — ships METHOD, never a world. Absorbs ADR 0081's layer: adapters/{claude-design,figma}/index.js (moved from src/ui/adapters/), scripts/{design-sync,figma-design-sync,validate-design}.js (moved from scripts/gds/, which keeps thin shims), docs/design-contract.md (moved from docs/). Declaration-only: contributes.skills design (the /design playbook, new) + design-sync + figma-design-sync; no routes/port/migrations, so disabling it touches no served surface. CLAUDE.md separates the platform FLOORS (the Fifteen Rule, the dark twins, no page :root, the 24px floor, AA in both modes, the kill switch) from the instance's WORLD (its packs + DESIGN.md). kit/ (task 1003320) is the look-before-you-ship kit: lib.js (the floors, the states/probes contracts, the action + expectation vocabularies, the WCAG maths, the stub spawner), serve.js (any surface through the doorway's real transforms + fixtures/), render.js (states × 1440/390/320 × dark/light, audited), probe.js (PASS/FAIL contracts), check-mock.js (platform rules + the instance's DESIGN.md taste bans), contrast.js + png.js; a page's <page>.states.json / <page>.probes.json sit BESIDE the surface (modules/public-landing/public/, modules/hall-ui/public/). Recipe: docs/recipes/ui-look-before-you-ship.md. skills/ (task 1003321 / ADR 0198) is the vendoring policy: policy.json (licence allowlist, verdicts that may land, sidecar fields, preamble markers), PREAMBLE.md (the platform preamble every vendored SKILL.md opens with), README.md (the roster — both origins scanned dangerous on 2026-08-28, landed as rebuild specs; nothing vendored — and the landing recipe); a landable copy goes under skills/vendor/<name>/ with PROVENANCE.md + LICENSE and is materialised into an instance's .claude/skills/ by claude-materialize.js step 1b. Reserved home styles/ (1003323) with a README. config/design-tokens.* + design-sources.json STAY in config/ as the host boundary; public-landing keeps its own key (first customer, not owner).
134
134
  │ ├── character-anim/ ← consistent-character generative animation (ADR 0088) — graded painterly frame sets + manifest, the otb-character-review skill. CLAUDE.md, module.json.
135
135
  │ ├── provisioning/ ← stands up + operates a Cloud Bongos instance's own infra (server/DB/domain/DNS/TLS) via the API (ADR 0111); web-tier request+state only, no cloud tokens — a separate control-plane runner drains the intents. Distinct from the `hosting` module (ADR 0092), which brokers compute workloads. CLAUDE.md, module.json.
136
136
  │ └── demo/ ← BV1.R52 acceptance-proof module: one rank-gated write route + one namespaced migration proving the loader mounts a scaffolded module with zero core edits. CLAUDE.md, module.json.
@@ -254,7 +254,7 @@
254
254
  │ ├── assets/tray/ + build-resources/ ← generated icons (scripts/gen-icons.js; build-resources name dodges the global build/ gitignore)
255
255
  │ └── test/unit.mjs ← hermetic unit tests (run by the CI workflow, not the root gate)
256
256
  │
257
- ├── public-landing/ ← the APEX front door + hub surfaces served by src/platform-server.js (landingPage(): apex-only strip → brand-token stamp → theme injection → ?v= asset stamp). Ships to EVERY instance; <!--apex-only:start/end--> regions are removed on a child
257
+ ├── modules/public-landing/public/ ← the APEX front door + hub surfaces. Its OWN MODULE since task 1003322 / ADR 0218 (manifest declares { apexRoot: true, dir: "public" } — the apex is not a Host prefix), still served by src/platform-server.js (landingPage(): apex-only strip → brand-token stamp → theme injection → ?v= asset stamp). Ships to EVERY instance; <!--apex-only:start/end--> regions are removed on a child
258
258
  │ ├── index.html ← the landing (/) — v3 "the template's page" of the chrome world (task 1003298, ADR 0196): server-stamped head, the breath (CSS-only signature), live figures/ledger/orbs from the public feeds baked inside sentinels; page-local <style> only (no :root), links /assets/world.css
259
259
  │ ├── projects.html ← the hub (/projects?view=map|mine|manage|new) on cosmos.css (A4, task 1003299, rebuilds it in the world)
260
260
  │ ├── privacy.html / terms.html / contact.html ← the footer doors (task 1003251), on cosmos.css
@@ -1321,5 +1321,9 @@ is load-bearing: the script throws rather than guess if it is missing, and
1321
1321
  landed since 1.19.440 with no explicit bump. run 33323478836. (task 1002620)
1322
1322
  1.19.442 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
1323
1323
  landed since 1.19.441 with no explicit bump. run 33326781131. (task 1002620)
1324
+ 1.19.443 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
1325
+ landed since 1.19.442 with no explicit bump. run 33330337830. (task 1002620)
1326
+ 1.19.444 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
1327
+ landed since 1.19.443 with no explicit bump. run 33334908383. (task 1002620)
1324
1328
  ---------------------------------------------------------------------------
1325
1329
  ```
@@ -99,7 +99,9 @@ Every module must have a `module.json` at its root (`modules/<key>/module.json`)
99
99
  "disciplines": ["artist"], // builder disciplines this module adds
100
100
  "skills": ["otb-tile-generate"], // slash-command skills it ships
101
101
  "uiSections": ["boxes"], // hall/status UI sections gated by window.__MODULES__
102
- "webSurfaces": [{ "host": "status.", "dir": "public" }], // host-routed static web surfaces (BV1.R84)
102
+ "webSurfaces": [{ "host": "status.", "dir": "public" }], // static web surfaces: a Host PREFIX (BV1.R84)…
103
+ // …or { "apexRoot": true, "dir": "public" } for the
104
+ // apex root (ADR 0218). One or the other, never both.
103
105
  "migrations": true // true → modules/<key>/migrations/*.sql applied if enabled
104
106
  },
105
107
  "provides": ["box.hasEverConnected"], // OPTIONAL. Seam PORTS this module registers a provider for.
@@ -152,7 +154,11 @@ At boot the loader (called from `src/modules.js` and the route mounter) runs:
152
154
  4. **Enablement filter** — check `isModuleEnabled(key)` (env override → `config/modules.json` → `config/modules.neutral.json` → `manifest.default`); disabled modules are skipped.
153
155
  5. **Mount routes** — for each `contributes.routes` key, `require(`modules/<key>/routes/<routeKey>.js`)` and call the factory. Audit is already composed at the kernel level (routes.js runs `auditMiddleware` before the loader mounts anything); each route self-gates at the appropriate rank via `api.requireBuilder` / `api.requireRank`. The fitness check (`BV1.R44`) ensures every write route is rank-gated.
154
156
  6. **Start pollers** — call each `contributes.pollers` file's `start()` on successful mount.
155
- 7. **Serve web surfaces** — for each `contributes.webSurfaces` entry `{ host, dir }`, `serve-internal.js` (via `loader.moduleWebSurfaces`) serves `modules/<key>/<dir>/` on the matching Host prefix (the content-hash-stamped index + branding injection the status page always used). This is how the status dashboard (`status-ui`) reaches `status.<apex>` with no core edit (BV1.R84). A disabled module's surface is never built, so its host routes nowhere.
157
+ 7. **Serve web surfaces** — a `contributes.webSurfaces` entry says WHERE the surface answers in exactly one of two ways, never both and never neither ([ADR 0218](adr/<redacted>.md)):
158
+ - `{ host: "status.", dir: "public" }` — a **Host-header prefix**. `serve-internal.js` (via `loader.moduleWebSurfaces`) serves `modules/<key>/<dir>/` on the matching host, with the content-hash-stamped index + branding injection the status page always used. This is how the status dashboard (`status-ui`) reaches `status.<apex>` with no core edit (BV1.R84).
159
+ - `{ apexRoot: true, dir: "public" }` — the **apex root**: whatever host is left once the subdomains are taken (`isApexHost` = `!isStatusHost && !isBuildersHost`). Declared by `public-landing`, the front door, and served by `platform-server.js`'s dedicated block. **`host: ""` is rejected, not read as "the root"** — the routers match with `host.startsWith(s.host)` and every string starts with `""`, so an empty prefix would answer on `builders.`/`status.` too and make `isModuleSurfaceHost()` true for every request, silently un-serving the hall.
160
+
161
+ A disabled module's surface is never built, so its host routes nowhere — and for the apex root that means the front door is gone and the 404 tail answers.
156
162
  8. **Apply migrations** — enabled-gated; `migrate.sh` discovers `modules/<key>/migrations/*.sql` only when the module is enabled.
157
163
 
158
164
  The loader is safe-by-construction: with no `modules/` dir it returns empty and all functions are no-ops — the instance behaves identically to before the module move.
@@ -246,6 +252,7 @@ Rules (enforced by the `BV1.R45` fitness check):
246
252
  | **`autonomy`** *(core-domain, default-on; R83)* | routes: `autonomy` (the `/autonomy/precheck`); pollers: `routine-timers` | — (registers NO port; reaches the lifecycle `tallyPeerVotes` via the doorway) | `^1.11.0` |
247
253
  | **`status-ui`** *(core-domain web surface, default-on; R84)* | webSurfaces: `{ host: "status.", dir: "public" }` (the status dashboard at `status.<apex>`) | — (registers NO port, NO routes; pure host-routed static surface) | `^1.11.0` |
248
254
  | **`hall-ui`** *(core-domain web surface, default-on; R85)* | webSurfaces: `{ host: "builders.", dir: "public" }` (the authenticated builders' hall) | — (registers NO port; keeps a DEDICATED serving block in `serve-internal.js`, unlike `status-ui`) | `^1.11.0` |
255
+ | **`public-landing`** *(core-domain web surface, default-on; task 1003322 / ADR 0218)* | webSurfaces: `{ apexRoot: true, dir: "public" }` (the front door at the apex root: `/`, `/projects`, `/create`, `/privacy`, `/terms`, `/contact`) | — (registers NO port; the first surface that is not a subdomain, and like `hall-ui` it keeps a DEDICATED serving block — in `platform-server.js`) | `^1.19.0` |
249
256
  | **`lifecycle`** *(core-domain, default-on; R86)* | routes: `tasks`, `claims`, `versions`, `done-when`, `goals`, `dependencies`, `gate-approvals`, `analytics` | provides `lifecycle` (createTask, classifyTaskKind, tallyPeerVotes, work-tracking reads); resolves `reward`, `onboarding` | `^1.12.0` |
250
257
  | **`provisioning`** *(default-off; [ADR 0111](adr/<redacted>.md))* | routes: `provisioning` (own+Archon rank-gated) | provides `provisioning.instanceState` | `^1.14.0` |
251
258
  | **`ui-design`** *(core-domain, default-on; [ADR 0197](adr/<redacted>.md))* | skills: `design`, `design-sync`, `figma-design-sync` (the /design playbook + the two tool round-trips); the ADR 0081 adapters, sync CLIs and validator live in the module dir | — (registers NO port, NO routes; declaration-only — disabling it withdraws the skills and touches no served surface) | `^1.19.0` |
@@ -15,7 +15,7 @@ Edge or Chrome must be installed. If neither launches, every kit command prints
15
15
  ## 1. Stub — serve the surface the way the instance would
16
16
 
17
17
  ```
18
- node modules/ui-design/kit/serve.js # public-landing at http://127.0.0.1:3412/
18
+ node modules/ui-design/kit/serve.js # the front door at http://127.0.0.1:3412/
19
19
  AUTH=1 STUB_PORT=3413 node modules/ui-design/kit/serve.js # the same, signed in (/me answers { builder })
20
20
  SURFACE=hall-ui PREFIX=/builders/ node modules/ui-design/kit/serve.js
21
21
  CHILD=1 node modules/ui-design/kit/serve.js # the child-instance shape (apex-only regions stripped)
@@ -25,7 +25,7 @@ FAIL=featured,progress node modules/ui-design/kit/serve.js # those feeds answe
25
25
 
26
26
  The stub runs the page through the **instance's real transforms** — the apex-only strip, the brand-token stamp, the pack's theme injection, run by the core-side command `scripts/gds/ui-kit-transform.js` (a module may not require core, so the stub spawns the command and memoises the page) — then the content-hash `?v=` stamp, with the instance's own branding pack, and answers the public feeds from `kit/fixtures/`. It also serves `docs/` raw, so a mock under `docs/design/mocks/` renders with its relative links: `http://127.0.0.1:3412/docs/design/mocks/hub/v2.html`.
27
27
 
28
- `SURFACE` is a checkout directory (`public-landing`, `modules/hall-ui/public`) or a module key whose manifest declares a `webSurfaces` dir. `PREFIX` is the URL prefix the surface's pages and assets live under (the hall's is `/builders/`).
28
+ `SURFACE` is a checkout directory (`modules/hall-ui/public`) or a module key whose manifest declares a `webSurfaces` dir (`public-landing`, `hall-ui`). `PREFIX` is the URL prefix the surface's pages and assets live under (the hall's is `/builders/`).
29
29
 
30
30
  ## 2. Render — every state, every width, both modes, audited
31
31
 
@@ -74,7 +74,7 @@ Then a state's own `expect` (a band open, a dialog present, a field's value, a c
74
74
 
75
75
  Actions: `click`, `focus`, `press`, `fill`, `wait`, `clickAt x y`, `clickIfVisible`, `dispatchClick`, `check`, `back`, `forward`. Expectations: `expanded`, `dialog`, `visible[]`, `hidden[]`, `open`, `closed`, `activeId`, `activeText`, `expandedIds[]`, `param{}`, `attr[[sel,name,value]]`, `text[[sel,value]]`, `href[[sel,value]]`, `count[[sel,n]]`, `value[[sel,v]]`, `hasClass[[sel,class,bool]]`, `checked`, `noOverflow`, `top[[sel,px]]` (an element's viewport top — assert it closed, open a band, assert it again: the proof an overlay did not push the page). The kit validates the file before it opens a browser and names every problem.
76
76
 
77
- The worked examples: `public-landing/projects.states.json` (the hub's thirteen), `public-landing/index.states.json` (the landing's four), `modules/hall-ui/public/ranks.states.json` (a second surface under its own prefix — it renders **red**, deliberately: the hall predates the 24px floor and Ranks has no `<h1>`, and the states file declares the shell's un-fixtured feeds rather than hiding the findings; idea 1000863 carries them).
77
+ The worked examples: `modules/public-landing/public/projects.states.json` (the hub's thirteen), `modules/public-landing/public/index.states.json` (the landing's four), `modules/hall-ui/public/ranks.states.json` (a second surface under its own prefix — it renders **red**, deliberately: the hall predates the 24px floor and Ranks has no `<h1>`, and the states file declares the shell's un-fixtured feeds rather than hiding the findings; idea 1000863 carries them).
78
78
 
79
79
  ## 3. Probe — the interaction contract, as PASS/FAIL lines
80
80
 
@@ -83,7 +83,7 @@ node modules/ui-design/kit/probe.js --page /projects
83
83
  node modules/ui-design/kit/probe.js --page / --only "Escape"
84
84
  ```
85
85
 
86
- A **probes file** (`<surface>/<page>.probes.json`) is a sequence: each probe opens the page (or continues the previous probe's page with `"continue": true`), drives steps from the same action vocabulary, and states what must be true with the same expectations. An uncaught page error during a probe fails it. The disclosure contract ships first — `public-landing/projects.probes.json` (24 probes: Enter opens on the first item, arrows cycle and skip hidden cells, Escape returns focus, Tab out closes, a click outside closes, one band closes the other, the views, the card yields Escape, the fold under 480, signed out nothing throws) and `index.probes.json` (10, the landing).
86
+ A **probes file** (`<surface>/<page>.probes.json`) is a sequence: each probe opens the page (or continues the previous probe's page with `"continue": true`), drives steps from the same action vocabulary, and states what must be true with the same expectations. An uncaught page error during a probe fails it. The disclosure contract ships first — `modules/public-landing/public/projects.probes.json` (24 probes: Enter opens on the first item, arrows cycle and skip hidden cells, Escape returns focus, Tab out closes, a click outside closes, one band closes the other, the views, the card yields Escape, the fold under 480, signed out nothing throws) and `index.probes.json` (10, the landing).
87
87
 
88
88
  ## 4. Read the shots, fix in one batch, re-run once
89
89
 
@@ -32,7 +32,7 @@ const FAKE = {
32
32
  counts: { strings: 3, unique_ids: 2, certain: 3, heuristic: 0, duplicate_ids: 1 },
33
33
  surfaces: {
34
34
  'builders-hall': { at: 'modules/hall-ui/public', files: 2, strings: 2 },
35
- landing: { at: 'public-landing', files: 1, strings: 1 },
35
+ landing: { at: 'modules/public-landing/public', files: 1, strings: 1 },
36
36
  },
37
37
  duplicates: [
38
38
  { id: 'dup1', surface: 'builders-hall', text: 'Could not save.', occurrences: 2,
@@ -41,7 +41,7 @@ const FAKE = {
41
41
  entries: [
42
42
  { id: 'dup1', surface: 'builders-hall', text: 'Could not save.', file: 'modules/hall-ui/public/a.js', line: 10, origin: 'js-notice', confidence: 'certain' },
43
43
  { id: 'dup1', surface: 'builders-hall', text: 'Could not save.', file: 'modules/hall-ui/public/b.js', line: 20, origin: 'js-notice', confidence: 'certain' },
44
- { id: 'solo', surface: 'landing', text: 'Enter the future.', file: 'public-landing/index.html', line: 4, origin: 'html-text', confidence: 'certain' },
44
+ { id: 'solo', surface: 'landing', text: 'Enter the future.', file: 'modules/public-landing/public/index.html', line: 4, origin: 'html-text', confidence: 'certain' },
45
45
  ],
46
46
  };
47
47
  const INDEX = registry.indexRegistry(FAKE);
@@ -137,7 +137,7 @@ await test('the snapshot is taken from the registry', () => {
137
137
  const r = ok({ scope: 'string', surface: 'landing', string_id: 'solo', reason: GOOD_REASON });
138
138
  assert.equal(r.ok, true);
139
139
  assert.equal(r.value.text_at_flag, 'Enter the future.');
140
- assert.equal(r.value.file_at_flag, 'public-landing/index.html');
140
+ assert.equal(r.value.file_at_flag, 'modules/public-landing/public/index.html');
141
141
  assert.equal(r.value.line_at_flag, 4);
142
142
  assert.equal(r.value.registry_schema, 1);
143
143
  });
@@ -153,7 +153,7 @@ await test('a caller-supplied snapshot is IGNORED', () => {
153
153
  });
154
154
  assert.equal(r.ok, true);
155
155
  assert.equal(r.value.text_at_flag, 'Enter the future.');
156
- assert.equal(r.value.file_at_flag, 'public-landing/index.html');
156
+ assert.equal(r.value.file_at_flag, 'modules/public-landing/public/index.html');
157
157
  assert.equal(r.value.line_at_flag, 4);
158
158
  });
159
159
 
@@ -0,0 +1,15 @@
1
+ # @bongos/core — installed platform dependency (not your project's CLAUDE.md)
2
+
3
+ This file is a placeholder shipped inside the **@bongos/core** package. The core's own
4
+ internal agent notes are intentionally omitted from the published artifact so they cannot
5
+ load into your instance's context.
6
+
7
+ **It does not govern this repository.** Your own root `CLAUDE.md`, your `.claude/`
8
+ directory, and the live Bongos database are the source of truth for how work happens here
9
+ and who may do what.
10
+
11
+ You are seeing this only because an agent opened a file under `node_modules/@bongos/core/`.
12
+ Nothing in here needs to be read to use the platform — run `bongos help` for commands.
13
+
14
+ _To work ON the platform core itself, use the standalone @bongos/core source repository,
15
+ not this vendored copy._
@@ -0,0 +1,15 @@
1
+ {
2
+ "key": "public-landing",
3
+ "title": "The front door",
4
+ "description": "The instance's public front door served at the APEX ROOT — the landing page (/), the projects hub (/projects, and the /create redirect into its ?view=new wizard), the three footer doors (/privacy, /terms, /contact) and every asset behind them. The third WEB-SURFACE core-domain module after status-ui (BV1.R84) and hall-ui (BV1.R85), carved in task 1003322 (ADR 0218; named in ADR 0197 §8 — the front door keeps its own key, because a customer of the ui-design capability is not part of it). default-on: an instance ships its front door like it ships its hall. Registers no port and contributes no routes — it declares a webSurface, and where hall-ui and status-ui name a Host PREFIX this one declares apexRoot:true, since the apex is whatever host is left once the subdomains are taken (ADR 0218 §2; host:\"\" is rejected, because every host string startsWith \"\"). Like the hall, the declaration is the discovery + scope-map + window.__MODULES__ record: the bytes are served by platform-server.js's dedicated landing block, which keeps the apex-only sentinel strip, the branding-token stamp and the ?v= content stamp and only re-points its root at this module's public/ dir. Disabling the module removes the front door outright — the apex then answers the game-less 404 tail. The world it renders (DESIGN.md, the token contract, the direction records) is the INSTANCE's; the method for building one stays in modules/ui-design/.",
5
+ "coreVersion": "^1.19.0",
6
+ "default": true,
7
+ "maintenance": { "status": "core-maintained" },
8
+ "contributes": {
9
+ "webSurfaces": [
10
+ { "apexRoot": true, "dir": "public" }
11
+ ]
12
+ },
13
+ "provides": [],
14
+ "consumes": []
15
+ }
@@ -53,7 +53,7 @@ function normalizePageArg(page) {
53
53
  if (typeof page === 'string' && /^[A-Za-z]:[\\/]/.test(page) && /[\\/]$/.test(page)) return '/';
54
54
  return page;
55
55
  }
56
- // A surface is a directory of the checkout: 'public-landing', 'modules/<key>/public',
56
+ // A surface is a directory of the checkout ('modules/<key>/public') or a module KEY
57
57
  // or a module KEY whose manifest declares a webSurfaces dir. Nothing is hardcoded.
58
58
  function resolveSurfaceDir(surface, root = REPO_ROOT) {
59
59
  if (!surface) return null;
@@ -234,7 +234,7 @@ function reducedMotionProblems({ running = [], frames = 0 } = {}) {
234
234
  }
235
235
 
236
236
  // ── the states file ───────────────────────────────────────────────────────────
237
- // { "page": "/projects", "surface"?: "public-landing", "stub"?: { prefix?, child? },
237
+ // { "page": "/projects", "surface"?: "public-landing" (a module key), "stub"?: { prefix?, child? },
238
238
  // "modes"?: ["dark" | "light", …] (the modes the page renders; default both — a page that pins
239
239
  // one mode declares it here), "modeQuery"?: "mode" | false, "ignoreRequests"?: [regex strings], "ignoreConsole"?: [...],
240
240
  // stub.fixtures?: { "<fixture name>": "<other fixture file>" } (serve another file under a name — an empty list, a
@@ -8,7 +8,7 @@
8
8
  // through two stubs this file starts itself (signed out, signed in), then a
9
9
  // reduced-motion pass per mode. Writes the shots + a JSON report; exits non-zero on any problem.
10
10
  //
11
- // node modules/ui-design/kit/render.js --page /projects (public-landing/projects.states.json)
11
+ // node modules/ui-design/kit/render.js --page /projects (surface defaults to the public-landing module key)
12
12
  // node modules/ui-design/kit/render.js --page /builders/ranks --surface hall-ui
13
13
  // node modules/ui-design/kit/render.js --states <file> (explicit file)
14
14
  // --modes dark,light --sizes 1440,390,320 --only a,b --out <dir>
@@ -10,9 +10,9 @@
10
10
  // fixtures/ so a page boots with real-shaped data and no database. Serves docs/
11
11
  // raw so a mock under docs/design/mocks/ renders with its relative links.
12
12
  //
13
- // node modules/ui-design/kit/serve.js -> http://127.0.0.1:3412/ (public-landing)
14
- // SURFACE=<dir or module key> a checkout dir ("public-landing", "modules/hall-ui/public") or a
15
- // module key whose manifest declares a webSurfaces dir
13
+ // node modules/ui-design/kit/serve.js -> http://127.0.0.1:3412/ (the public-landing module)
14
+ // SURFACE=<dir or module key> a checkout dir ("modules/hall-ui/public") or a module
15
+ // key ("public-landing") whose manifest declares a webSurfaces dir
16
16
  // PREFIX=/builders/ the URL prefix the surface's pages + assets are served under
17
17
  // STUB_REPO=<checkout> the checkout to serve (default: the one this file sits in)
18
18
  // STUB_PORT=<n> default 3412 (0 = any free port; the port is printed)
package/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.19.442",
3
+ "version": "1.19.444",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@bongos/core",
9
- "version": "1.19.442",
9
+ "version": "1.19.444",
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.442",
3
+ "version": "1.19.444",
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",
@@ -54,12 +54,12 @@ const REPORT_REL = 'docs/copy-inventory.md';
54
54
  const SURFACES = [
55
55
  { id: 'builders-hall', kind: 'dir', at: 'modules/hall-ui/public', exts: ['.html', '.js'] },
56
56
  { id: 'status-dashboard', kind: 'dir', at: 'modules/status-ui/public', exts: ['.html', '.js'] },
57
- // THE LANDING SURFACE IS public-landing/, NOT src/platform-server.js. The first
57
+ // THE LANDING SURFACE IS modules/public-landing/public/, NOT src/platform-server.js. The first
58
58
  // cut pointed here at the server file, which only fs.readFileSync's these
59
59
  // templates — so its JS patterns matched a handful of incidental literals and the
60
60
  // page's ACTUAL copy (hero, meta/og text, every section) was silently absent
61
61
  // while the registry reported a number. Caught by the grader on task 1003112.
62
- { id: 'landing', kind: 'dir', at: 'public-landing', exts: ['.html'] },
62
+ { id: 'landing', kind: 'dir', at: 'modules/public-landing/public', exts: ['.html'] },
63
63
  ];
64
64
 
65
65
  // Attributes whose value is COPY a person reads (not wiring). The matchers are
@@ -70,7 +70,7 @@ const COPY_ATTR_RES = COPY_ATTRS.map((attr) => ({ attr, re: new RegExp(`\\b${att
70
70
  // What this tool knowingly does not see. Printed in the report — an inventory that
71
71
  // implies completeness it does not have is worse than a short one.
72
72
  const BLIND_SPOTS = [
73
- 'Landing-page transforms: `public-landing/*.html` is scanned as authored, but the server rewrites it before a visitor sees it — `{{token}}` placeholders are filled from the branding pack, and `<!--apex-only:start--> … <!--apex-only:end-->` sections are STRIPPED on a child instance (src/platform-server.js `landingPage()`). So a row here may be copy that this instance never renders, and a rendered sentence may differ from its authored form.',
73
+ 'Landing-page transforms: `modules/public-landing/public/*.html` is scanned as authored, but the server rewrites it before a visitor sees it — `{{token}}` placeholders are filled from the branding pack, and `<!--apex-only:start--> … <!--apex-only:end-->` sections are STRIPPED on a child instance (src/platform-server.js `landingPage()`). So a row here may be copy that this instance never renders, and a rendered sentence may differ from its authored form.',
74
74
  'Server-side messages: route failures (`res.fail` reasons), validation text and API error copy live in server JS and are not walked here. A person reads them, so widening to them is a deliberate later step, not an oversight to quietly fix.',
75
75
  'Skill and playbook prose: `.claude/skills/**/SKILL.md` is read by agents and by builders and is arguably the largest body of project voice. Out of scope on purpose — it is not UI, and mixing it in would drown the UI signal.',
76
76
  'Discord copy: outbound broadcast text is composed in `modules/discord/*.js` at send time. User-facing, but not part of any UI surface.',
@@ -141,11 +141,27 @@ const IDENTITY_SCAN_SKIP_DIRS = new Set(['node_modules', '.git', 'generated', 'i
141
141
  // silently hid ~330 provision.js lines from this gate). Re-exported for the tests.
142
142
  const { stripCommentsForIdentity } = require('./identity-strip');
143
143
 
144
+ // An APEX-ONLY region is content the server DELETES on every instance that is not
145
+ // the hub (`stripApexOnly`, src/platform-server.js — ADR 0152; the front door became
146
+ // a module in ADR 0218, which is what first brought these pages under this gate).
147
+ // This check exists so "a non-OTB instance renders ITS OWN brand"; text inside these
148
+ // sentinels never reaches a non-hub instance at all, so it cannot produce that
149
+ // failure. The hub's own landing legitimately NAMES the projects hosted on it, and
150
+ // that catalog is exactly what the sentinels wrap.
151
+ //
152
+ // BLANKED, not removed, so a violation's reported line number still points at the
153
+ // real line. Applied BEFORE the comment strip, which would otherwise eat the
154
+ // sentinels (they are HTML comments) and take the region's boundaries with them.
155
+ const APEX_ONLY_REGION = /<!--apex-only:start-->[\s\S]*?<!--apex-only:end-->/g;
156
+ function blankApexOnly(text) {
157
+ return String(text).replace(APEX_ONLY_REGION, (m) => m.replace(/[^\n]/g, ' '));
158
+ }
159
+
144
160
  // Pure: scan one file's comment-stripped source for a hardcoded host-brand literal.
145
161
  // Returns violation strings. Exported for the "actually catches a re-hardcode" test.
146
162
  function scanPromptIdentity(relFile, text, ext = path.extname(relFile)) {
147
163
  const violations = [];
148
- stripCommentsForIdentity(text, ext).split('\n').forEach((raw, i) => {
164
+ stripCommentsForIdentity(blankApexOnly(text), ext).split('\n').forEach((raw, i) => {
149
165
  if (!raw.trim()) return;
150
166
  for (const re of PROMPT_IDENTITY_LITERALS) {
151
167
  const m = raw.match(re);
@@ -318,4 +334,5 @@ module.exports = {
318
334
  collectIdentityFiles,
319
335
  scanPromptIdentity,
320
336
  stripCommentsForIdentity,
337
+ blankApexOnly, // ADR 0218 — apex-only regions never reach a child instance (tested)
321
338
  };
@@ -66,6 +66,7 @@ const PUBLISH_ALLOWLIST = [
66
66
  'modules/ui-design/', // the design contract + its adapters/CLIs + the /design playbook (task 1003324, ADR 0197). default:true, so it MUST be here: a released core without it would materialize skills (design, design-sync, figma-design-sync) whose CLIs and adapters do not exist.
67
67
  'modules/hall-ui/',
68
68
  'modules/status-ui/',
69
+ 'modules/public-landing/', // the front door (task 1003322, ADR 0218) — the repo-root public-landing/ entry this replaces was always here, and for the same reason: default:true, and it is the only thing an instance serves at its apex root. Omit it and a released core answers the game-less 404 tail on its own home page.
69
70
  'modules/dev-box/',
70
71
  'modules/discord/',
71
72
  'modules/provisioning/', // instance-hosting control plane — CORE like its sibling dev-box (same do-api/cf-tunnel toolchain, all core). Reclassified IN so the core CLI scripts/gds/provision.js resolves it from the core package post-split, not a MODULE_NOT_FOUND (task 2135). default:false — shipped ≠ enabled.
@@ -137,7 +138,6 @@ const PUBLISH_ALLOWLIST = [
137
138
  '.gitattributes',
138
139
  'package.json',
139
140
  'package-lock.json',
140
- 'public-landing/',
141
141
  // --- served-at-runtime app assets a standalone MUST carry (task 2078) ---
142
142
  // The generated typed API client is served at /lib/bongos-client.js as
143
143
  // window.BongosClient; shell.js + builders.js call it at the TOP of every hall