@bongos/core 1.24.42 → 1.24.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.bongos-core.json +93 -83
- package/docs/copy-inventory.md +86 -104
- package/docs/copy-registry.json +159 -351
- package/docs/module-api-changelog.md +2 -0
- package/docs/onboarding/primer.md +1 -1
- package/docs/page-inventory.json +3 -3
- package/docs/page-readings.json +386 -428
- package/modules/hall-ui/public/ai-studio.html +4 -4
- package/modules/hall-ui/public/atlas.html +4 -4
- package/modules/hall-ui/public/blockers.html +4 -4
- package/modules/hall-ui/public/board-room.html +4 -4
- package/modules/hall-ui/public/builders.js +22 -505
- package/modules/hall-ui/public/city.html +4 -4
- package/modules/hall-ui/public/collab.html +4 -4
- package/modules/hall-ui/public/commands.html +4 -4
- package/modules/hall-ui/public/copy-desk.html +4 -4
- package/modules/hall-ui/public/craft-mode.js +1 -1
- package/modules/hall-ui/public/deploy.html +4 -4
- package/modules/hall-ui/public/dom-utils.js +2 -1
- package/modules/hall-ui/public/goal-map.html +4 -4
- package/modules/hall-ui/public/goals.html +4 -4
- package/modules/hall-ui/public/government.html +4 -4
- package/modules/hall-ui/public/hall-render.js +23 -524
- package/modules/hall-ui/public/hall-widgets.js +11 -109
- package/modules/hall-ui/public/idea.html +4 -4
- package/modules/hall-ui/public/ideas.html +4 -4
- package/modules/hall-ui/public/index.html +6 -19
- package/modules/hall-ui/public/index.states.json +0 -33
- package/modules/hall-ui/public/market-watch-item.html +4 -4
- package/modules/hall-ui/public/market-watch-rules.html +4 -4
- package/modules/hall-ui/public/market-watch.html +4 -4
- package/modules/hall-ui/public/modules.html +4 -4
- package/modules/hall-ui/public/money.html +4 -4
- package/modules/hall-ui/public/my-agents.html +4 -4
- package/modules/hall-ui/public/palette.js +7 -6
- package/modules/hall-ui/public/primer.html +4 -4
- package/modules/hall-ui/public/profile-own.js +639 -0
- package/modules/hall-ui/public/profile.css +2 -1
- package/modules/hall-ui/public/profile.html +48 -5
- package/modules/hall-ui/public/profile.js +27 -2
- package/modules/hall-ui/public/profile.states.json +18 -0
- package/modules/hall-ui/public/project-settings.html +4 -4
- package/modules/hall-ui/public/roadmap.html +4 -4
- package/modules/hall-ui/public/roster.html +4 -4
- package/modules/hall-ui/public/settings.html +4 -4
- package/modules/hall-ui/public/shell-trail.js +2 -1
- package/modules/hall-ui/public/shell.js +28 -25
- package/modules/hall-ui/public/street.html +4 -4
- package/modules/hall-ui/public/studio.html +4 -4
- package/modules/hall-ui/public/task.html +4 -4
- package/modules/hall-ui/public/thinking.html +4 -4
- package/modules/hall-ui/public/tweak-editor.html +4 -4
- package/modules/hall-ui/public/watch.html +4 -4
- package/modules/hall-ui/public/work.html +4 -4
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/release-notes.json +6 -0
- package/src/module-api.js +1 -1
- package/tests/curve_controls_delegation.mjs +9 -8
- package/tests/curve_kind_overlay.mjs +5 -5
- package/tests/hall_acclaim_vote_control.mjs +5 -3
- package/tests/hall_audit.mjs +10 -6
- package/tests/hall_board_world.mjs +40 -26
- package/tests/hall_builders_page_pass.mjs +14 -5
- package/tests/hall_home_ships_bounded.mjs +10 -21
- package/tests/hall_kit_charts.mjs +3 -2
- package/tests/hall_loading.mjs +2 -1
- package/tests/hall_nav.mjs +36 -37
- package/tests/hall_numbers_page.mjs +100 -0
- package/tests/hall_palette.mjs +19 -24
- package/tests/hall_profile_world.mjs +7 -2
- package/tests/hall_reading_room.mjs +3 -2
- package/tests/helpers.mjs +8 -2
- package/tests/leaderboard_roles.mjs +1 -1
- package/tests/module_contributions.mjs +6 -4
- package/tests/nav_permission_atoms.mjs +3 -2
- package/tests/page_tweak_artist.mjs +2 -1
- package/tests/rank_tier_single_source.mjs +3 -0
- package/tests/task_visuals.mjs +3 -1
|
@@ -174,6 +174,47 @@
|
|
|
174
174
|
</div>
|
|
175
175
|
</section>
|
|
176
176
|
|
|
177
|
+
<!-- ============ yours: only on your own profile (task 1005050) ============ -->
|
|
178
|
+
|
|
179
|
+
<!-- Accomplishments folded into this page (owner decision 2026-11-03,
|
|
180
|
+
idea 1001315): what was only ever yours there lives here, and
|
|
181
|
+
profile-own.js draws it ONLY on the viewer's own profile. Every
|
|
182
|
+
section starts hidden, and so does the screen's rail key, so
|
|
183
|
+
someone else's profile never shows it. -->
|
|
184
|
+
<section class="scroll" id="rank-scroll" aria-labelledby="rank-standing-h" data-group="yours" hidden>
|
|
185
|
+
<h2 id="rank-standing-h" class="scroll__h">Where you stand</h2>
|
|
186
|
+
<div id="rank-standing-body"><div class="hall-loading" role="status">Loading…</div></div>
|
|
187
|
+
</section>
|
|
188
|
+
<section class="scroll" id="grades-scroll" aria-labelledby="marks-h" data-group="yours" hidden>
|
|
189
|
+
<h2 id="marks-h" class="scroll__h">Reviews</h2>
|
|
190
|
+
<table class="ledger" id="recent-grades"><thead><tr><th>№</th><th>Work</th><th>Score</th><th>Verdict</th><th>Reviewed</th></tr></thead>
|
|
191
|
+
<tbody><tr><td colspan="5" class="ledger__empty"><span class="hall-loading" role="status">Loading…</span></td></tr></tbody></table>
|
|
192
|
+
<p class="ledger__note" id="grades-rolling-note" hidden></p>
|
|
193
|
+
</section>
|
|
194
|
+
<section class="scroll" id="karma-scroll" aria-labelledby="karma-h" data-group="yours" hidden>
|
|
195
|
+
<h2 id="karma-h" class="scroll__h">Karma</h2>
|
|
196
|
+
<p class="scroll__lede">Ideas passed, peer votes and approvals earn karma. Shipped work earns <span data-currency-label>credits</span>.</p>
|
|
197
|
+
<table class="ledger" id="karma-feed"><thead><tr><th>When</th><th>Delta</th><th>Reason</th><th>Granted by</th></tr></thead>
|
|
198
|
+
<tbody><tr><td colspan="4" class="ledger__empty"><span class="hall-loading" role="status">Loading…</span></td></tr></tbody></table>
|
|
199
|
+
</section>
|
|
200
|
+
<section class="scroll" id="acclaim-scroll" aria-labelledby="acclaim-h" data-group="yours" hidden>
|
|
201
|
+
<h2 id="acclaim-h" class="scroll__h">Peer recognition</h2>
|
|
202
|
+
<p class="scroll__lede">Vote on others’ finished work. A vote counts toward their karma after a week.</p>
|
|
203
|
+
<table class="ledger" id="acclaim-feed"><thead><tr><th>Work</th><th>By</th><th>Votes</th></tr></thead>
|
|
204
|
+
<tbody><tr><td colspan="3" class="ledger__empty"><span class="hall-loading" role="status">Loading…</span></td></tr></tbody></table>
|
|
205
|
+
<div id="acclaim-pager-mount"></div>
|
|
206
|
+
</section>
|
|
207
|
+
<section class="scroll" id="analytics-scroll" aria-labelledby="curve-h" data-group="yours" hidden>
|
|
208
|
+
<h2 id="curve-h" class="scroll__h">Progress</h2>
|
|
209
|
+
<p class="scroll__lede">How your work has changed over time. <span id="curve-scope-note"></span></p>
|
|
210
|
+
<div class="curve" id="curve-body">
|
|
211
|
+
<div class="profile__placeholder" id="curve-empty" style="display:none;">Not enough shipped work yet to chart.</div>
|
|
212
|
+
<div class="curve__headline" id="curve-headline"></div>
|
|
213
|
+
<div class="curve__grid" id="curve-grid"></div>
|
|
214
|
+
<div class="curve__kinds" id="curve-kinds"></div>
|
|
215
|
+
</div>
|
|
216
|
+
</section>
|
|
217
|
+
|
|
177
218
|
<!-- ============ connections: hub-only ============ -->
|
|
178
219
|
|
|
179
220
|
<!-- Connections — section 6 of the profile-page spec (R20, task
|
|
@@ -205,10 +246,10 @@
|
|
|
205
246
|
|
|
206
247
|
<!-- The app shell (sidebar + top bar). Dependency-free; loaded FIRST so the
|
|
207
248
|
chrome exists before the page script runs. -->
|
|
208
|
-
<script src="/builders/dom-utils.js?v=2026-
|
|
209
|
-
<script src="/builders/shell-trail.js?v=2026-
|
|
210
|
-
<script src="/builders/craft-mode.js?v=2026-11-05-
|
|
211
|
-
<script src="/builders/shell.js?v=2026-11-05-
|
|
249
|
+
<script src="/builders/dom-utils.js?v=2026-11-05-numbers"></script>
|
|
250
|
+
<script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
|
|
251
|
+
<script src="/builders/craft-mode.js?v=2026-11-05-numbers"></script>
|
|
252
|
+
<script src="/builders/shell.js?v=2026-11-05-numbers"></script>
|
|
212
253
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
213
254
|
<script src="/builders/palette.js" defer></script>
|
|
214
255
|
<!-- task 1004727: the ONE karma vote control every task/idea list renders -->
|
|
@@ -237,6 +278,8 @@
|
|
|
237
278
|
what the tabs draw. Both loaded BEFORE profile.js. -->
|
|
238
279
|
<script src="/builders/idea-objects.js?v=2026-09-27-split"></script>
|
|
239
280
|
<script src="/builders/profile-crafts.js?v=2026-10-01-crafts"></script>
|
|
240
|
-
|
|
281
|
+
<!-- task 1005050: the "Just you" screen, drawn only on your own profile. -->
|
|
282
|
+
<script src="/builders/profile-own.js?v=2026-11-05-own"></script>
|
|
283
|
+
<script src="/builders/profile.js?v=2026-11-05-own"></script>
|
|
241
284
|
</body>
|
|
242
285
|
</html>
|
|
@@ -862,13 +862,21 @@
|
|
|
862
862
|
{ id: 'works', label: 'Works' },
|
|
863
863
|
{ id: 'activity', label: 'Activity' },
|
|
864
864
|
{ id: 'connections', label: 'Connections' },
|
|
865
|
+
// task 1005050: Accomplishments' private half, offered on your own profile only.
|
|
866
|
+
{ id: 'yours', label: 'Just you' },
|
|
865
867
|
];
|
|
866
868
|
const RAIL_GROUPS = RAIL_ITEMS.map((i) => i.id);
|
|
867
869
|
let rail = null;
|
|
868
870
|
|
|
871
|
+
// True once render() has drawn the "Just you" screen — the viewer's own profile.
|
|
872
|
+
let ownShown = false;
|
|
873
|
+
// Whether the profile asked for is the viewer's own: /profile with no id, or an
|
|
874
|
+
// ?id= equal to the viewer's. Settled in load() from the REQUEST, before any
|
|
875
|
+
// profile data is read, so someone else's profile can never count as yours.
|
|
876
|
+
let ownRequest = false;
|
|
869
877
|
function railItems() {
|
|
870
878
|
const conn = $('#conn-scroll');
|
|
871
|
-
return RAIL_ITEMS.filter((i) => i.id !== 'connections' || (conn && !conn.hidden));
|
|
879
|
+
return RAIL_ITEMS.filter((i) => (i.id !== 'connections' || (conn && !conn.hidden)) && (i.id !== 'yours' || ownShown));
|
|
872
880
|
}
|
|
873
881
|
|
|
874
882
|
function activateGroup(group, opts) {
|
|
@@ -877,6 +885,8 @@
|
|
|
877
885
|
if (!groups) return;
|
|
878
886
|
groups.dataset.active = group;
|
|
879
887
|
rail?.activate(group);
|
|
888
|
+
// task 1005050: the "Just you" screen's feeds load the first time it opens.
|
|
889
|
+
if (group === 'yours' && window.OTBProfileOwn && window.OTBProfileOwn.open) window.OTBProfileOwn.open();
|
|
880
890
|
if (!opts || opts.scroll !== false) window.scrollTo({ top: 0 });
|
|
881
891
|
}
|
|
882
892
|
|
|
@@ -963,6 +973,18 @@
|
|
|
963
973
|
// reveals its own section or leaves it hidden. Optional by design: a page
|
|
964
974
|
// that does not load it simply has no connections section.
|
|
965
975
|
if (window.OTBConnections) window.OTBConnections.render(data, selfId);
|
|
976
|
+
// task 1005050: what only you see (Accomplishments, folded in) — your own
|
|
977
|
+
// profile only. Someone else's profile never calls it, so its screen and
|
|
978
|
+
// rail key stay hidden. The data is the viewer's own /me and public feeds.
|
|
979
|
+
if (ownRequest && selfId != null && selfMe && window.OTBProfileOwn) {
|
|
980
|
+
window.OTBProfileOwn.render({ api, API, me: selfMe });
|
|
981
|
+
ownShown = true;
|
|
982
|
+
if (rail) {
|
|
983
|
+
rail.refresh(railItems());
|
|
984
|
+
rail.activate($('#profile-groups')?.dataset.active || 'overview');
|
|
985
|
+
}
|
|
986
|
+
applyHash(); // an old Accomplishments link lands here as #yours
|
|
987
|
+
}
|
|
966
988
|
}
|
|
967
989
|
|
|
968
990
|
// Render the friendly "no builder chosen" empty state for a signed-out visitor
|
|
@@ -1025,7 +1047,9 @@
|
|
|
1025
1047
|
const idParam = new URLSearchParams(location.search).get('id');
|
|
1026
1048
|
try {
|
|
1027
1049
|
if (idParam) {
|
|
1028
|
-
|
|
1050
|
+
const selfId = await resolveSelfId();
|
|
1051
|
+
ownRequest = selfId != null && String(idParam) === String(selfId);
|
|
1052
|
+
await fetchProfile(idParam, selfId);
|
|
1029
1053
|
return;
|
|
1030
1054
|
}
|
|
1031
1055
|
// No id — soft-resolve the viewer's OWN id from /me (no hard redirect; a
|
|
@@ -1043,6 +1067,7 @@
|
|
|
1043
1067
|
renderEmpty();
|
|
1044
1068
|
return;
|
|
1045
1069
|
}
|
|
1070
|
+
ownRequest = true;
|
|
1046
1071
|
await fetchProfile(selfId, selfId);
|
|
1047
1072
|
} catch (err) {
|
|
1048
1073
|
console.error('[profile] failed to load', err);
|
|
@@ -73,6 +73,24 @@
|
|
|
73
73
|
]
|
|
74
74
|
}
|
|
75
75
|
},
|
|
76
|
+
"yours": {
|
|
77
|
+
"_": "Your own profile's \"Just you\" screen (task 1005050): Accomplishments' private half — where you stand, reviews, karma, peer recognition, progress.",
|
|
78
|
+
"auth": true,
|
|
79
|
+
"url": "/profile#yours",
|
|
80
|
+
"actions": [
|
|
81
|
+
[
|
|
82
|
+
"wait",
|
|
83
|
+
1500
|
|
84
|
+
]
|
|
85
|
+
],
|
|
86
|
+
"expect": {
|
|
87
|
+
"visible": [
|
|
88
|
+
"#profile-rail",
|
|
89
|
+
"#rank-scroll",
|
|
90
|
+
"#grades-scroll"
|
|
91
|
+
]
|
|
92
|
+
}
|
|
93
|
+
},
|
|
76
94
|
"activity-artist": {
|
|
77
95
|
"_": "The artist's Activity tab (task 1004435): approved pages, each with its before/after. Fixtures builders__2001__profile + copy-desk__artists__2001__pages.",
|
|
78
96
|
"auth": true,
|
|
@@ -74,10 +74,10 @@
|
|
|
74
74
|
|
|
75
75
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
76
76
|
|
|
77
|
-
<script src="/builders/dom-utils.js?v=2026-
|
|
78
|
-
<script src="/builders/shell-trail.js?v=2026-
|
|
79
|
-
<script src="/builders/craft-mode.js?v=2026-11-05-
|
|
80
|
-
<script src="/builders/shell.js?v=2026-11-05-
|
|
77
|
+
<script src="/builders/dom-utils.js?v=2026-11-05-numbers"></script>
|
|
78
|
+
<script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
|
|
79
|
+
<script src="/builders/craft-mode.js?v=2026-11-05-numbers"></script>
|
|
80
|
+
<script src="/builders/shell.js?v=2026-11-05-numbers"></script>
|
|
81
81
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
82
82
|
<script src="/builders/palette.js" defer></script>
|
|
83
83
|
<script src="/builders/hall-kit.js"></script>
|
|
@@ -41,10 +41,10 @@
|
|
|
41
41
|
|
|
42
42
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
43
43
|
|
|
44
|
-
<script src="/builders/dom-utils.js?v=2026-
|
|
45
|
-
<script src="/builders/shell-trail.js?v=2026-
|
|
46
|
-
<script src="/builders/craft-mode.js?v=2026-11-05-
|
|
47
|
-
<script src="/builders/shell.js?v=2026-11-05-
|
|
44
|
+
<script src="/builders/dom-utils.js?v=2026-11-05-numbers"></script>
|
|
45
|
+
<script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
|
|
46
|
+
<script src="/builders/craft-mode.js?v=2026-11-05-numbers"></script>
|
|
47
|
+
<script src="/builders/shell.js?v=2026-11-05-numbers"></script>
|
|
48
48
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
49
49
|
<script src="/builders/palette.js" defer></script>
|
|
50
50
|
<!-- The chart kit and the timeline's series builders (task 1003447). Both MUST
|
|
@@ -56,10 +56,10 @@
|
|
|
56
56
|
|
|
57
57
|
<!-- The app shell (sidebar + top bar). Dependency-free; loaded FIRST so the
|
|
58
58
|
chrome exists before the page script runs. -->
|
|
59
|
-
<script src="/builders/dom-utils.js?v=2026-
|
|
60
|
-
<script src="/builders/shell-trail.js?v=2026-
|
|
61
|
-
<script src="/builders/craft-mode.js?v=2026-11-05-
|
|
62
|
-
<script src="/builders/shell.js?v=2026-11-05-
|
|
59
|
+
<script src="/builders/dom-utils.js?v=2026-11-05-numbers"></script>
|
|
60
|
+
<script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
|
|
61
|
+
<script src="/builders/craft-mode.js?v=2026-11-05-numbers"></script>
|
|
62
|
+
<script src="/builders/shell.js?v=2026-11-05-numbers"></script>
|
|
63
63
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
64
64
|
<script src="/builders/palette.js" defer></script>
|
|
65
65
|
<!-- the branding pack's currency label, loaded BEFORE roster.js. -->
|
|
@@ -391,10 +391,10 @@
|
|
|
391
391
|
|
|
392
392
|
<!-- The app shell (sidebar + top bar). Dependency-free; loaded FIRST so the
|
|
393
393
|
chrome exists before the page scripts run. -->
|
|
394
|
-
<script src="/builders/dom-utils.js?v=2026-
|
|
395
|
-
<script src="/builders/shell-trail.js?v=2026-
|
|
396
|
-
<script src="/builders/craft-mode.js?v=2026-11-05-
|
|
397
|
-
<script src="/builders/shell.js?v=2026-11-05-
|
|
394
|
+
<script src="/builders/dom-utils.js?v=2026-11-05-numbers"></script>
|
|
395
|
+
<script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
|
|
396
|
+
<script src="/builders/craft-mode.js?v=2026-11-05-numbers"></script>
|
|
397
|
+
<script src="/builders/shell.js?v=2026-11-05-numbers"></script>
|
|
398
398
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
399
399
|
<script src="/builders/palette.js" defer></script>
|
|
400
400
|
<!-- shared component kit (window.OTBKit) — section rail (task 2166). -->
|
|
@@ -78,7 +78,8 @@
|
|
|
78
78
|
function backLabel(path, hash) {
|
|
79
79
|
if (path === '/') {
|
|
80
80
|
var m = /^#\/(task|idea|blocker)\/(\d+)/.exec(hash || '');
|
|
81
|
-
|
|
81
|
+
// task 1005050: no Accomplishments view any more; its hashes redirect to /profile.
|
|
82
|
+
return m ? m[1] + ' ' + m[2] : 'Home';
|
|
82
83
|
}
|
|
83
84
|
var rec = /^\/(task|idea)\/(\d+)$/.exec(path);
|
|
84
85
|
if (rec) return rec[1] + ' ' + rec[2];
|
|
@@ -13,9 +13,9 @@
|
|
|
13
13
|
// (#app-sidebar / #app-topbar / #app-foot) every hall page carries;
|
|
14
14
|
// - rank-gate nav items COSMETICALLY (server-side page gates remain the real
|
|
15
15
|
// access control — serve-internal.js requireGovernmentPage etc.);
|
|
16
|
-
// - on the index (body[data-page="home"]) route the
|
|
17
|
-
// #
|
|
18
|
-
//
|
|
16
|
+
// - on the index (body[data-page="home"]) route the #home view, and REDIRECT
|
|
17
|
+
// retired hashes: #leaderboard to the /roster page (task 1003441), and the
|
|
18
|
+
// Accomplishments hashes to your own /profile (task 1005050). The
|
|
19
19
|
// `#/task|idea|blocker/N` deep-link hashes belong to builders.js and are
|
|
20
20
|
// deliberately ignored here;
|
|
21
21
|
// - expose window.OTBShell.applyAccess(...) so builders.js (index) or the
|
|
@@ -34,23 +34,12 @@
|
|
|
34
34
|
// task 1003441: 'leaderboard' left this list — the Roll is the /roster PAGE
|
|
35
35
|
// now. Its hash is not an alias (there is no host view to land on) but a
|
|
36
36
|
// REDIRECT, declared in VIEW_REDIRECTS below.
|
|
37
|
-
|
|
37
|
+
// task 1005050: 'standing' (Accomplishments) left too — it folded into /profile.
|
|
38
|
+
var VIEWS = ['home'];
|
|
38
39
|
// A hash that lands on a view, scrolled to a section (route() ignores any
|
|
39
|
-
// other).
|
|
40
|
-
//
|
|
41
|
-
|
|
42
|
-
var VIEW_ALIASES = {
|
|
43
|
-
accomplishments: { view: 'standing', anchor: null },
|
|
44
|
-
'accomplishments-work': { view: 'standing', anchor: 'standing-work' },
|
|
45
|
-
'accomplishments-karma': { view: 'standing', anchor: 'standing-karma' },
|
|
46
|
-
'accomplishments-progress': { view: 'standing', anchor: 'standing-progress' },
|
|
47
|
-
'accomplishments-achievements': { view: 'standing', anchor: 'standing-achievements' },
|
|
48
|
-
achievements: { view: 'standing', anchor: 'standing-achievements' },
|
|
49
|
-
'standing-work': { view: 'standing', anchor: 'standing-work' },
|
|
50
|
-
'standing-karma': { view: 'standing', anchor: 'standing-karma' },
|
|
51
|
-
'standing-progress': { view: 'standing', anchor: 'standing-progress' },
|
|
52
|
-
'standing-achievements': { view: 'standing', anchor: 'standing-achievements' },
|
|
53
|
-
};
|
|
40
|
+
// other). Empty since task 1005050: every alias named the 'standing' view,
|
|
41
|
+
// and those hashes are REDIRECTS now (below).
|
|
42
|
+
var VIEW_ALIASES = Object.create(null);
|
|
54
43
|
// A retired view whose content moved to its OWN PAGE, so there is no host
|
|
55
44
|
// view to alias onto. Every existing #leaderboard link — bookmarks, the
|
|
56
45
|
// Standing card's stat tiles, profile.js's prose link — lands on the roster
|
|
@@ -58,8 +47,24 @@
|
|
|
58
47
|
// Object.create(null): the key is an attacker-controlled hash string, so a
|
|
59
48
|
// plain object would answer for "constructor"/"toString" as well as the real
|
|
60
49
|
// entries. Harmless with one literal key, wrong to leave as the pattern.
|
|
50
|
+
// task 1005050 (owner decision 2026-11-03, idea 1001315): Accomplishments
|
|
51
|
+
// folded into the Profile page, so every #accomplishments / #standing /
|
|
52
|
+
// #achievements link lands on your OWN profile (/profile with no id is
|
|
53
|
+
// yours) — its "Just you" screen, its Works, or the overview with your
|
|
54
|
+
// achievements, whichever the old section was.
|
|
61
55
|
var VIEW_REDIRECTS = Object.assign(Object.create(null), {
|
|
62
56
|
leaderboard: '/roster',
|
|
57
|
+
accomplishments: '/profile#yours',
|
|
58
|
+
'accomplishments-work': '/profile#works',
|
|
59
|
+
'accomplishments-karma': '/profile#yours',
|
|
60
|
+
'accomplishments-progress': '/profile#yours',
|
|
61
|
+
'accomplishments-achievements': '/profile',
|
|
62
|
+
achievements: '/profile',
|
|
63
|
+
standing: '/profile#yours',
|
|
64
|
+
'standing-work': '/profile#works',
|
|
65
|
+
'standing-karma': '/profile#yours',
|
|
66
|
+
'standing-progress': '/profile#yours',
|
|
67
|
+
'standing-achievements': '/profile',
|
|
63
68
|
});
|
|
64
69
|
// builders.js owns these hashes (deep-link overlay) — never route them.
|
|
65
70
|
var DEEPLINK_RE = /^#\/(task|idea|blocker)\/(\d+)$/;
|
|
@@ -288,11 +293,9 @@
|
|
|
288
293
|
// call 2026-09-25, ADR 0337 D5). Cross-project discovery is the hub's, and
|
|
289
294
|
// /people redirects to /roster.
|
|
290
295
|
] },
|
|
291
|
-
// Your own numbers. task
|
|
292
|
-
//
|
|
293
|
-
// bookmarks and the stat tiles keep landing on the section.
|
|
296
|
+
// Your own numbers. task 1005050: Accomplishments folded into Profile — one
|
|
297
|
+
// page for your numbers — and its old links redirect there (VIEW_REDIRECTS).
|
|
294
298
|
{ group: 'You', gate: 'signed', items: [
|
|
295
|
-
{ id: 'standing', label: 'Accomplishments', icon: 'accomplishments', href: '/#accomplishments', view: 'standing', gate: 'signed' },
|
|
296
299
|
// task 1467: the viewable, shareable builder profile. The nav link points at
|
|
297
300
|
// the viewer's OWN profile (profile.js defaults to self when no ?id=). gate is
|
|
298
301
|
// cosmetic only — the /profile PAGE is public (a portfolio others can open via
|
|
@@ -1241,8 +1244,8 @@
|
|
|
1241
1244
|
}
|
|
1242
1245
|
|
|
1243
1246
|
function route(opts) {
|
|
1244
|
-
// The redirect runs BEFORE the view lookup: #leaderboard
|
|
1245
|
-
// view, so viewFromHash would return nothing and route() would leave the
|
|
1247
|
+
// The redirect runs BEFORE the view lookup: #leaderboard (and since task
|
|
1248
|
+
// 1005050 #accomplishments and #standing) is no longer a view, so viewFromHash would return nothing and route() would leave the
|
|
1246
1249
|
// page on Home — a dead link that looks like it worked. replace() rather
|
|
1247
1250
|
// than assign() so Back does not bounce the reader between the two.
|
|
1248
1251
|
var redirect = IS_INDEX && VIEW_REDIRECTS[String(window.location.hash || "").replace(/^#/, "")];
|
|
@@ -228,10 +228,10 @@
|
|
|
228
228
|
</div>
|
|
229
229
|
</div>
|
|
230
230
|
|
|
231
|
-
<script src="/builders/dom-utils.js?v=2026-
|
|
232
|
-
<script src="/builders/shell-trail.js?v=2026-
|
|
233
|
-
<script src="/builders/craft-mode.js?v=2026-11-05-
|
|
234
|
-
<script src="/builders/shell.js?v=2026-11-05-
|
|
231
|
+
<script src="/builders/dom-utils.js?v=2026-11-05-numbers"></script>
|
|
232
|
+
<script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
|
|
233
|
+
<script src="/builders/craft-mode.js?v=2026-11-05-numbers"></script>
|
|
234
|
+
<script src="/builders/shell.js?v=2026-11-05-numbers"></script>
|
|
235
235
|
<script src="/builders/palette.js" defer></script>
|
|
236
236
|
<script src="/builders/gov-living.js?v=2026-10-09-positions1"></script>
|
|
237
237
|
<script src="/builders/gov-feeds.js?v=2026-10-09-living3"></script>
|
|
@@ -222,10 +222,10 @@
|
|
|
222
222
|
|
|
223
223
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
224
224
|
|
|
225
|
-
<script src="/builders/dom-utils.js?v=2026-
|
|
226
|
-
<script src="/builders/shell-trail.js?v=2026-
|
|
227
|
-
<script src="/builders/craft-mode.js?v=2026-11-05-
|
|
228
|
-
<script src="/builders/shell.js?v=2026-11-05-
|
|
225
|
+
<script src="/builders/dom-utils.js?v=2026-11-05-numbers"></script>
|
|
226
|
+
<script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
|
|
227
|
+
<script src="/builders/craft-mode.js?v=2026-11-05-numbers"></script>
|
|
228
|
+
<script src="/builders/shell.js?v=2026-11-05-numbers"></script>
|
|
229
229
|
<script src="/builders/palette.js" defer></script>
|
|
230
230
|
<!-- The kit, for its ONE renderer: the full-size ship-time visual figure
|
|
231
231
|
(task 1003829), which the older reviews still show. -->
|
|
@@ -56,10 +56,10 @@
|
|
|
56
56
|
|
|
57
57
|
<!-- The app shell (sidebar + top bar + footer). Dependency-free; runs at parse
|
|
58
58
|
time so the chrome exists before the deferred page scripts execute. -->
|
|
59
|
-
<script src="/builders/dom-utils.js?v=2026-
|
|
60
|
-
<script src="/builders/shell-trail.js?v=2026-
|
|
61
|
-
<script src="/builders/craft-mode.js?v=2026-11-05-
|
|
62
|
-
<script src="/builders/shell.js?v=2026-11-05-
|
|
59
|
+
<script src="/builders/dom-utils.js?v=2026-11-05-numbers"></script>
|
|
60
|
+
<script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
|
|
61
|
+
<script src="/builders/craft-mode.js?v=2026-11-05-numbers"></script>
|
|
62
|
+
<script src="/builders/shell.js?v=2026-11-05-numbers"></script>
|
|
63
63
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
64
64
|
<script src="/builders/palette.js" defer></script>
|
|
65
65
|
<!-- task-detail.js still owns the #/idea/N and #/blocker/N deep-link overlay
|
|
@@ -138,10 +138,10 @@
|
|
|
138
138
|
</div>
|
|
139
139
|
</div>
|
|
140
140
|
|
|
141
|
-
<script src="/builders/dom-utils.js?v=2026-
|
|
142
|
-
<script src="/builders/shell-trail.js?v=2026-
|
|
143
|
-
<script src="/builders/craft-mode.js?v=2026-11-05-
|
|
144
|
-
<script src="/builders/shell.js?v=2026-11-05-
|
|
141
|
+
<script src="/builders/dom-utils.js?v=2026-11-05-numbers"></script>
|
|
142
|
+
<script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
|
|
143
|
+
<script src="/builders/craft-mode.js?v=2026-11-05-numbers"></script>
|
|
144
|
+
<script src="/builders/shell.js?v=2026-11-05-numbers"></script>
|
|
145
145
|
<script src="/builders/palette.js" defer></script>
|
|
146
146
|
|
|
147
147
|
<script src="/builders/idea-objects.js?v=2026-09-27-split"></script>
|
|
@@ -142,10 +142,10 @@
|
|
|
142
142
|
|
|
143
143
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
144
144
|
|
|
145
|
-
<script src="/builders/dom-utils.js?v=2026-
|
|
146
|
-
<script src="/builders/shell-trail.js?v=2026-
|
|
147
|
-
<script src="/builders/craft-mode.js?v=2026-11-05-
|
|
148
|
-
<script src="/builders/shell.js?v=2026-11-05-
|
|
145
|
+
<script src="/builders/dom-utils.js?v=2026-11-05-numbers"></script>
|
|
146
|
+
<script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
|
|
147
|
+
<script src="/builders/craft-mode.js?v=2026-11-05-numbers"></script>
|
|
148
|
+
<script src="/builders/shell.js?v=2026-11-05-numbers"></script>
|
|
149
149
|
<script src="/builders/palette.js" defer></script>
|
|
150
150
|
<script src="/builders/brand-holes.js?v=2026-09-29-aqfix"></script>
|
|
151
151
|
<script src="/builders/tweak-editor-lib.js?v=2026-09-29-tw27"></script>
|
|
@@ -268,10 +268,10 @@
|
|
|
268
268
|
|
|
269
269
|
<!-- The app shell (sidebar + top bar). Dependency-free; loaded FIRST so the
|
|
270
270
|
chrome exists before the page script runs. -->
|
|
271
|
-
<script src="/builders/dom-utils.js?v=2026-
|
|
272
|
-
<script src="/builders/shell-trail.js?v=2026-
|
|
273
|
-
<script src="/builders/craft-mode.js?v=2026-11-05-
|
|
274
|
-
<script src="/builders/shell.js?v=2026-11-05-
|
|
271
|
+
<script src="/builders/dom-utils.js?v=2026-11-05-numbers"></script>
|
|
272
|
+
<script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
|
|
273
|
+
<script src="/builders/craft-mode.js?v=2026-11-05-numbers"></script>
|
|
274
|
+
<script src="/builders/shell.js?v=2026-11-05-numbers"></script>
|
|
275
275
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
276
276
|
<script src="/builders/palette.js" defer></script>
|
|
277
277
|
<!-- shared component kit (window.OTBKit) — tabs, ledger, pager (task 2166). -->
|
|
@@ -171,10 +171,10 @@
|
|
|
171
171
|
|
|
172
172
|
<!-- The app shell (sidebar + top bar + footer). Dependency-free; runs at parse
|
|
173
173
|
time so the chrome exists before the deferred page scripts execute. -->
|
|
174
|
-
<script src="/builders/dom-utils.js?v=2026-
|
|
175
|
-
<script src="/builders/shell-trail.js?v=2026-
|
|
176
|
-
<script src="/builders/craft-mode.js?v=2026-11-05-
|
|
177
|
-
<script src="/builders/shell.js?v=2026-11-05-
|
|
174
|
+
<script src="/builders/dom-utils.js?v=2026-11-05-numbers"></script>
|
|
175
|
+
<script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
|
|
176
|
+
<script src="/builders/craft-mode.js?v=2026-11-05-numbers"></script>
|
|
177
|
+
<script src="/builders/shell.js?v=2026-11-05-numbers"></script>
|
|
178
178
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
179
179
|
<script src="/builders/palette.js" defer></script>
|
|
180
180
|
<!-- task 1004727: the ONE karma vote control every task/idea list renders -->
|
package/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.24.
|
|
3
|
+
"version": "1.24.43",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@bongos/core",
|
|
9
|
-
"version": "1.24.
|
|
9
|
+
"version": "1.24.43",
|
|
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.24.
|
|
3
|
+
"version": "1.24.43",
|
|
4
4
|
"description": "Cloud Bongos — the AI-first build platform core (GDS + platform surfaces + module system), installed as a versioned dependency (ADR 0108).",
|
|
5
5
|
"license": "AGPL-3.0-or-later",
|
|
6
6
|
"main": "src/platform-server.js",
|
package/release-notes.json
CHANGED
|
@@ -11215,5 +11215,11 @@
|
|
|
11215
11215
|
"id": "1005076",
|
|
11216
11216
|
"text": "New builders now get one clear setup screen they finish once, and everyone already set up no longer sees a setup banner across the top of Home."
|
|
11217
11217
|
}
|
|
11218
|
+
],
|
|
11219
|
+
"1.24.43": [
|
|
11220
|
+
{
|
|
11221
|
+
"id": "1005050",
|
|
11222
|
+
"text": "Your numbers are on one page now: your Profile. The separate Accomplishments page is gone from the sidebar. The parts only you should see — your rank and how to reach the next one, how your work was reviewed, your karma histor"
|
|
11223
|
+
}
|
|
11218
11224
|
]
|
|
11219
11225
|
}
|
package/src/module-api.js
CHANGED
|
@@ -81,7 +81,7 @@ const { sleep } = require('./sleep');
|
|
|
81
81
|
// MAJOR (see allowBoxScope below): passes the request through untouched.
|
|
82
82
|
function deprecatedNoopMiddleware(_req, _res, next) { next(); }
|
|
83
83
|
|
|
84
|
-
const CORE_VERSION = '1.24.
|
|
84
|
+
const CORE_VERSION = '1.24.43'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
|
|
85
85
|
|
|
86
86
|
// A namespaced logger so a module's log lines are attributable + consistent.
|
|
87
87
|
// Usage: const log = api.logger('discord'); log.info('mounted');
|
|
@@ -23,18 +23,19 @@ import { fileURLToPath } from 'node:url';
|
|
|
23
23
|
|
|
24
24
|
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
25
25
|
const PUB = path.join(ROOT, 'modules/hall-ui/public');
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
// task 1005050: the Progress section moved with Accomplishments to the Profile
|
|
27
|
+
// page's "Just you" screen — its markup is profile.html's, its wiring profile-own.js's.
|
|
28
|
+
const pageSrc = fs.readFileSync(path.join(PUB, 'profile.html'), 'utf8');
|
|
29
|
+
const buildersSrc = fs.readFileSync(path.join(PUB, 'profile-own.js'), 'utf8');
|
|
28
30
|
|
|
29
31
|
const SECTION_ID = 'analytics-scroll';
|
|
30
32
|
|
|
31
33
|
// The Progress widget's markup: the concatenated string literals of its w() call.
|
|
32
34
|
function progressMarkup() {
|
|
33
|
-
const start =
|
|
34
|
-
assert.ok(start >= 0, `
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
return [...call.matchAll(/'((?:[^'\\]|\\.)*)'/g)].map((m) => m[1]).slice(2).join('');
|
|
35
|
+
const start = pageSrc.indexOf(`id="${SECTION_ID}"`);
|
|
36
|
+
assert.ok(start >= 0, `profile.html no longer carries '${SECTION_ID}'`);
|
|
37
|
+
const open = pageSrc.lastIndexOf('<section', start);
|
|
38
|
+
return pageSrc.slice(open, pageSrc.indexOf('</section>', start) + '</section>'.length);
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
// True if the element with id=`outer` encloses the element with id=`inner`.
|
|
@@ -57,7 +58,7 @@ function encloses(html, outer, inner) {
|
|
|
57
58
|
// The selector each curve-control listener is attached to in builders.js.
|
|
58
59
|
function delegationTarget(marker) {
|
|
59
60
|
const at = buildersSrc.indexOf(marker);
|
|
60
|
-
assert.ok(at >= 0, `
|
|
61
|
+
assert.ok(at >= 0, `profile-own.js no longer handles ${marker}`);
|
|
61
62
|
const before = buildersSrc.slice(0, at);
|
|
62
63
|
const all = [...before.matchAll(/\$\('#([\w-]+)'\)\?\.addEventListener\('(click|change)'/g)];
|
|
63
64
|
assert.ok(all.length, `no delegated listener found before ${marker}`);
|
|
@@ -254,7 +254,7 @@ test('cost is WITHHELD under a kind filter, not faked', () => {
|
|
|
254
254
|
});
|
|
255
255
|
|
|
256
256
|
test('the client hides the cost chart and stat rather than printing $0.00', () => {
|
|
257
|
-
const render = fs.readFileSync(path.join(ROOT, 'modules/hall-ui/public/
|
|
257
|
+
const render = fs.readFileSync(path.join(ROOT, 'modules/hall-ui/public/profile-own.js'), 'utf8');
|
|
258
258
|
assert.match(render, /costUnavailable = Array\.isArray\(data\.unavailable\) && data\.unavailable\.includes\('cost_trend'\)/);
|
|
259
259
|
assert.match(render, /costUnavailable\s*\?\s*statCard\('Cost \/ work', '—'/,
|
|
260
260
|
'a withheld cost must render as —, never as a price');
|
|
@@ -264,7 +264,7 @@ test('the controls are written BEFORE every early return', () => {
|
|
|
264
264
|
// A kind with nothing shipped in the window takes the totalShipped === 0
|
|
265
265
|
// branch, which blanks the body. If the filter were drawn after that, the
|
|
266
266
|
// reader would be stranded at "no data" with no control to undo it.
|
|
267
|
-
const render = fs.readFileSync(path.join(ROOT, 'modules/hall-ui/public/
|
|
267
|
+
const render = fs.readFileSync(path.join(ROOT, 'modules/hall-ui/public/profile-own.js'), 'utf8');
|
|
268
268
|
const fn = render.slice(render.indexOf('function renderCurveBody()'));
|
|
269
269
|
const controls = fn.indexOf('kindFilterHtml()');
|
|
270
270
|
const firstReturn = fn.indexOf('if (!data) {');
|
|
@@ -275,8 +275,8 @@ test('the controls are written BEFORE every early return', () => {
|
|
|
275
275
|
});
|
|
276
276
|
|
|
277
277
|
test('the scope toggle is no longer rank-gated', () => {
|
|
278
|
-
const render = fs.readFileSync(path.join(ROOT, 'modules/hall-ui/public/
|
|
279
|
-
const builders = fs.readFileSync(path.join(ROOT, 'modules/hall-ui/public/
|
|
278
|
+
const render = fs.readFileSync(path.join(ROOT, 'modules/hall-ui/public/profile-own.js'), 'utf8');
|
|
279
|
+
const builders = fs.readFileSync(path.join(ROOT, 'modules/hall-ui/public/profile-own.js'), 'utf8');
|
|
280
280
|
assert.ok(!/analyticsState\.isArchon\s*&&/.test(render),
|
|
281
281
|
'the scope toggle is still gated on rank');
|
|
282
282
|
// The field is REMOVED, not merely unread — a write-only state flag is how a
|
|
@@ -288,7 +288,7 @@ test('the scope toggle is no longer rank-gated', () => {
|
|
|
288
288
|
});
|
|
289
289
|
|
|
290
290
|
test('a kind change re-fetches BOTH series, and the newest answer wins', () => {
|
|
291
|
-
const builders = fs.readFileSync(path.join(ROOT, 'modules/hall-ui/public/
|
|
291
|
+
const builders = fs.readFileSync(path.join(ROOT, 'modules/hall-ui/public/profile-own.js'), 'utf8');
|
|
292
292
|
const fn = builders.slice(builders.indexOf('async function reloadCurveForKind'));
|
|
293
293
|
const body = fn.slice(0, fn.indexOf('\n }') + 4);
|
|
294
294
|
assert.match(body, /analytics\/builder\/\$\{id\}\?days=90\$\{q\}/);
|
|
@@ -19,7 +19,9 @@ import { fileURLToPath } from 'node:url';
|
|
|
19
19
|
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
20
20
|
const HALL = path.join(ROOT, 'modules', 'hall-ui', 'public');
|
|
21
21
|
const read = (f) => fs.readFileSync(path.join(HALL, f), 'utf8').replace(/\r\n/g, '\n');
|
|
22
|
-
|
|
22
|
+
// task 1005050: the peer-recognition feed moved with Accomplishments to the
|
|
23
|
+
// Profile page's "Just you" screen (profile-own.js; its markup is profile.html's).
|
|
24
|
+
const builders = read('profile-own.js');
|
|
23
25
|
|
|
24
26
|
// A small DOM: enough for the control's cast() and event dispatch.
|
|
25
27
|
function el(attrs = {}) {
|
|
@@ -71,7 +73,7 @@ function bootControl(fetchImpl) {
|
|
|
71
73
|
// The feed's real handler, sliced from builders.js and run over a held list.
|
|
72
74
|
function feedHandler(tasks) {
|
|
73
75
|
const start = builders.indexOf('function onAcclaimVote(');
|
|
74
|
-
assert.ok(start > 0, '
|
|
76
|
+
assert.ok(start > 0, 'profile-own.js defines onAcclaimVote');
|
|
75
77
|
const end = builders.indexOf('\n }\n', start) + 4;
|
|
76
78
|
const ctx = { acclaimState: { tasks } };
|
|
77
79
|
vm.createContext(ctx);
|
|
@@ -109,5 +111,5 @@ test('a vote through the real control lands in the held, paged rows', async () =
|
|
|
109
111
|
test('the old vote markup, handler and CSS are gone', () => {
|
|
110
112
|
assert.doesNotMatch(builders, /acclaim__btn|acclaim__vote|data-vote-task|onAcclaimClick|data-acclaim-net/);
|
|
111
113
|
assert.doesNotMatch(read('style.css'), /\.acclaim__(btn|vote|readonly|net)/);
|
|
112
|
-
assert.match(read('
|
|
114
|
+
assert.match(read('profile.html'), /<th>Work<\/th><th>By<\/th><th>Votes<\/th><\/tr>/);
|
|
113
115
|
});
|