@bongos/core 1.21.145 → 1.21.147
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 +98 -68
- package/clients/bongos-client/README.md +1 -1
- package/clients/bongos-client/bongos-client.global.js +2 -0
- package/clients/bongos-client/index.cjs +2 -0
- package/clients/bongos-client/index.d.ts +6 -2
- package/clients/bongos-client/index.mjs +2 -0
- package/docs/api/openapi.json +90 -7
- package/docs/api-reference.md +3 -2
- package/docs/copy-inventory.md +17 -15
- package/docs/copy-registry.json +37 -19
- package/docs/module-api-changelog.md +4 -0
- package/docs/page-readings.json +85 -85
- package/modules/builder-settings/core-move-seen.js +41 -0
- package/modules/builder-settings/routes/settings.js +22 -0
- package/modules/builder-settings/settings.js +5 -0
- package/modules/hall-ui/public/atlas.html +1 -1
- package/modules/hall-ui/public/blockers.html +1 -1
- package/modules/hall-ui/public/board-room.html +1 -1
- package/modules/hall-ui/public/city.html +1 -1
- package/modules/hall-ui/public/collab.html +1 -1
- package/modules/hall-ui/public/commands.html +1 -1
- package/modules/hall-ui/public/copy-desk.html +1 -1
- package/modules/hall-ui/public/core-move-notice.js +70 -0
- package/modules/hall-ui/public/deploy.html +1 -1
- package/modules/hall-ui/public/diagrams.html +1 -1
- package/modules/hall-ui/public/drachmae.html +1 -1
- package/modules/hall-ui/public/fleet.html +1 -1
- package/modules/hall-ui/public/gate.html +1 -1
- package/modules/hall-ui/public/goal-map.html +1 -1
- package/modules/hall-ui/public/goals.html +1 -1
- package/modules/hall-ui/public/government.html +1 -1
- package/modules/hall-ui/public/idea.html +1 -1
- package/modules/hall-ui/public/ideas.html +1 -1
- package/modules/hall-ui/public/index.html +1 -1
- package/modules/hall-ui/public/modules.html +1 -1
- package/modules/hall-ui/public/my-agents.html +1 -1
- package/modules/hall-ui/public/primer.html +1 -1
- package/modules/hall-ui/public/profile.html +1 -1
- package/modules/hall-ui/public/project-settings.html +1 -1
- package/modules/hall-ui/public/ranks.html +1 -1
- package/modules/hall-ui/public/roadmap.html +1 -1
- package/modules/hall-ui/public/roster.html +1 -1
- package/modules/hall-ui/public/sessions.html +1 -1
- package/modules/hall-ui/public/settings-software-update.js +38 -5
- package/modules/hall-ui/public/settings.html +2 -2
- package/modules/hall-ui/public/shell.js +18 -6
- package/modules/hall-ui/public/street.html +1 -1
- package/modules/hall-ui/public/studio.html +1 -1
- package/modules/hall-ui/public/style.css +11 -0
- package/modules/hall-ui/public/task.html +1 -1
- package/modules/hall-ui/public/thinking.html +1 -1
- package/modules/hall-ui/public/tweak-editor.html +1 -1
- package/modules/hall-ui/public/watch.html +1 -1
- package/modules/hall-ui/public/work.html +1 -1
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/release-notes.json +12 -0
- package/scripts/gds/provision-auto-upgrade.js +30 -7
- package/scripts/gds/provision-core-upgrade.js +9 -3
- package/src/bongos/core-moves.js +155 -0
- package/src/bongos/routes/core-update.js +55 -3
- package/src/bongos/upgrade-hold.js +96 -0
- package/src/module-api.js +1 -1
- package/tests/core_auto_upgrade.mjs +64 -3
- package/tests/core_move_notice.mjs +356 -0
- package/tests/core_upgrade_owner_door.mjs +25 -2
- package/tests/nav_permission_atoms.mjs +4 -2
- package/tests/upgrade_hold.mjs +207 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// modules/builder-settings/core-move-seen.js — which core move a builder has already been
|
|
2
|
+
// told about (task 1004731).
|
|
3
|
+
//
|
|
4
|
+
// After the project's core moves, its hall shows a one-time notice ("Upgraded to core X on
|
|
5
|
+
// <date>", and what changed). One-time has to mean once per PERSON, across devices: an owner
|
|
6
|
+
// who read it on their laptop should not be told again on their phone. So, like the profile
|
|
7
|
+
// nudge's dismissal (profile-nudge-prefs.js), it is stored SERVER-side, in one reserved key
|
|
8
|
+
// of the `behavior_prefs` jsonb on `builders` (migration 119), and adds no migration.
|
|
9
|
+
//
|
|
10
|
+
// The value is the id of the core_upgrades ledger row the builder acknowledged. Only the
|
|
11
|
+
// newest row can be a notice, so remembering one id is enough: the next move writes a new
|
|
12
|
+
// row with a new id, and is news again. Core (src/bongos/core-moves.js) never reads this key
|
|
13
|
+
// itself; it asks the `builder-settings` port's `coreMoveSeen`.
|
|
14
|
+
|
|
15
|
+
const RESERVED_KEY = 'core_move_seen';
|
|
16
|
+
const ID_RE = /^\d{1,19}$/;
|
|
17
|
+
|
|
18
|
+
/** The ledger row id this builder has acknowledged, or null. PURE. */
|
|
19
|
+
function seenId(behaviorPrefs) {
|
|
20
|
+
const raw = behaviorPrefs && behaviorPrefs[RESERVED_KEY];
|
|
21
|
+
return typeof raw === 'string' && ID_RE.test(raw) ? raw : null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Validate a PATCH body `{ id: "<ledger row id>" }`. PURE. */
|
|
25
|
+
function validatePatch(body) {
|
|
26
|
+
if (body == null || typeof body !== 'object' || Array.isArray(body)) {
|
|
27
|
+
return { ok: false, errors: [{ error: 'body_must_be_object' }] };
|
|
28
|
+
}
|
|
29
|
+
const id = body.id == null ? '' : String(body.id);
|
|
30
|
+
if (!ID_RE.test(id)) return { ok: false, errors: [{ key: 'id', error: 'invalid_value', allowed: 'a core_upgrades row id' }] };
|
|
31
|
+
const extra = Object.keys(body).filter((k) => k !== 'id');
|
|
32
|
+
if (extra.length) return { ok: false, errors: extra.map((key) => ({ key, error: 'unknown_key', allowed: ['id'] })) };
|
|
33
|
+
return { ok: true, id };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** The builder's behavior_prefs with the acknowledged id set; sibling keys untouched. PURE. */
|
|
37
|
+
function applySeen(existing, id) {
|
|
38
|
+
return { ...(existing || {}), [RESERVED_KEY]: id };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
module.exports = { seenId, validatePatch, applySeen };
|
|
@@ -30,6 +30,7 @@ const modelAllocPrefs = require('../model-alloc-prefs');
|
|
|
30
30
|
const lawLocks = require('../law-locks');
|
|
31
31
|
const renderPrefs = require('../render-prefs');
|
|
32
32
|
const profileNudgePrefs = require('../profile-nudge-prefs');
|
|
33
|
+
const coreMoveSeen = require('../core-move-seen');
|
|
33
34
|
const displayName = require('../display-name');
|
|
34
35
|
const filterViews = require('../filter-views');
|
|
35
36
|
// task 1003208: structured logging (pino via the doorway) — was console.*.
|
|
@@ -495,6 +496,27 @@ module.exports = function buildBuilderSettingsRouter() {
|
|
|
495
496
|
}
|
|
496
497
|
});
|
|
497
498
|
|
|
499
|
+
// The core move this builder has been told about (task 1004731, core-move-seen.js):
|
|
500
|
+
// closing the hall's "Upgraded to core X" notice stores that move's ledger id here, so
|
|
501
|
+
// it is not shown to them again on any device. Body: { id: "<core_upgrades row id>" }.
|
|
502
|
+
//
|
|
503
|
+
// rank: any-builder — own acknowledgement; same posture as /me/profile-nudge.
|
|
504
|
+
router.patch('/me/core-move-seen', api.requireBuilder, async (req, res) => {
|
|
505
|
+
if (api.validateOrRespond(req, res, {
|
|
506
|
+
id: { required: true, type: 'string', maxLength: 19 },
|
|
507
|
+
}, { strict: true })) return undefined;
|
|
508
|
+
try {
|
|
509
|
+
const v = coreMoveSeen.validatePatch(req.body || {});
|
|
510
|
+
if (!v.ok) return res.fail('invalid_patch', 422, { errors: v.errors });
|
|
511
|
+
const existing = await db.getBuilderBehaviorPrefs(req.builder.id);
|
|
512
|
+
const saved = await db.setBuilderBehaviorPrefs(req.builder.id, coreMoveSeen.applySeen(existing, v.id));
|
|
513
|
+
res.json({ ok: true, seen: coreMoveSeen.seenId(saved) });
|
|
514
|
+
} catch (err) {
|
|
515
|
+
log.error('PATCH /me/core-move-seen', err);
|
|
516
|
+
res.fail('write_failed', { status: 500, message: 'internal error' });
|
|
517
|
+
}
|
|
518
|
+
});
|
|
519
|
+
|
|
498
520
|
// Per-builder SAVED FILTER VIEWS (task 1004553; shares the behavior_prefs jsonb /
|
|
499
521
|
// migration 119). A view is a named set of filter values for one hall page. They
|
|
500
522
|
// are PERSONAL: every route reads and writes only req.builder.id's own prefs, so
|
|
@@ -33,6 +33,7 @@ const modelAllocPrefs = require('./model-alloc-prefs');
|
|
|
33
33
|
const renderPrefs = require('./render-prefs');
|
|
34
34
|
const builderNeeds = require('./builder-needs');
|
|
35
35
|
const lawLocks = require('./law-locks');
|
|
36
|
+
const coreMoveSeen = require('./core-move-seen');
|
|
36
37
|
|
|
37
38
|
module.exports = {
|
|
38
39
|
// --- the raw behavior_prefs blob read (GET /me resolves this once, then shapes
|
|
@@ -53,6 +54,10 @@ module.exports = {
|
|
|
53
54
|
// values, not the builder's own.
|
|
54
55
|
describeWithLaws: (...a) => lawLocks.describe(...a),
|
|
55
56
|
|
|
57
|
+
// task 1004731: the core_upgrades row id this builder has acknowledged (the hall's
|
|
58
|
+
// one-time "Upgraded to core X" notice), from the behavior_prefs blob; null if none.
|
|
59
|
+
coreMoveSeen: (behaviorPrefs) => coreMoveSeen.seenId(behaviorPrefs),
|
|
60
|
+
|
|
56
61
|
// --- the per-builder model ceiling for a skill (cascade-dispatch clamps to it;
|
|
57
62
|
// never exceeds it). Mirrors the former `skillPrefs.getForBuilder` call.
|
|
58
63
|
skillCeiling: (builderPrefs, skillName) => skillPrefs.getForBuilder(builderPrefs, skillName),
|
|
@@ -93,7 +93,7 @@
|
|
|
93
93
|
|
|
94
94
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
95
95
|
<script src="/builders/craft-mode.js?v=2026-10-09-living3"></script>
|
|
96
|
-
<script src="/builders/shell.js?v=2026-10-
|
|
96
|
+
<script src="/builders/shell.js?v=2026-10-18-core-move1"></script>
|
|
97
97
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
98
98
|
<script src="/builders/palette.js" defer></script>
|
|
99
99
|
<script src="/builders/atlas.js?v=2026-09-02-index" defer></script>
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
chrome exists before the page script runs. -->
|
|
53
53
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
54
54
|
<script src="/builders/craft-mode.js?v=2026-10-09-living3"></script>
|
|
55
|
-
<script src="/builders/shell.js?v=2026-10-
|
|
55
|
+
<script src="/builders/shell.js?v=2026-10-18-core-move1"></script>
|
|
56
56
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
57
57
|
<script src="/builders/palette.js" defer></script>
|
|
58
58
|
<!-- shared frontend toolkit (window.OTB — rank labels, number formats) + the
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
|
|
63
63
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
64
64
|
<script src="/builders/craft-mode.js?v=2026-10-09-living3"></script>
|
|
65
|
-
<script src="/builders/shell.js?v=2026-10-
|
|
65
|
+
<script src="/builders/shell.js?v=2026-10-18-core-move1"></script>
|
|
66
66
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
67
67
|
<script src="/builders/palette.js" defer></script>
|
|
68
68
|
<script src="/builders/dom-utils.js?v=2026-06-16-board"></script>
|
|
@@ -105,7 +105,7 @@
|
|
|
105
105
|
|
|
106
106
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
107
107
|
<script src="/builders/craft-mode.js?v=2026-10-09-living3"></script>
|
|
108
|
-
<script src="/builders/shell.js?v=2026-10-
|
|
108
|
+
<script src="/builders/shell.js?v=2026-10-18-core-move1"></script>
|
|
109
109
|
<script src="/builders/palette.js" defer></script>
|
|
110
110
|
<script src="/builders/gov-living.js?v=2026-10-09-positions1"></script>
|
|
111
111
|
<script src="/builders/gov-feeds.js?v=2026-10-09-living3"></script>
|
|
@@ -150,7 +150,7 @@
|
|
|
150
150
|
|
|
151
151
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
152
152
|
<script src="/builders/craft-mode.js?v=2026-10-09-living3"></script>
|
|
153
|
-
<script src="/builders/shell.js?v=2026-10-
|
|
153
|
+
<script src="/builders/shell.js?v=2026-10-18-core-move1"></script>
|
|
154
154
|
<script src="/builders/palette.js" defer></script>
|
|
155
155
|
<script src="/builders/dom-utils.js?v=2026-06-23-contrib"></script>
|
|
156
156
|
<script src="/builders/collab-lib.js?v=2026-09-24-archive"></script>
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
|
|
57
57
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
58
58
|
<script src="/builders/craft-mode.js?v=2026-10-09-living3"></script>
|
|
59
|
-
<script src="/builders/shell.js?v=2026-10-
|
|
59
|
+
<script src="/builders/shell.js?v=2026-10-18-core-move1"></script>
|
|
60
60
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
61
61
|
<script src="/builders/palette.js" defer></script>
|
|
62
62
|
<script src="/builders/dom-utils.js?v=2026-06-14-domutils"></script>
|
|
@@ -179,7 +179,7 @@
|
|
|
179
179
|
|
|
180
180
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
181
181
|
<script src="/builders/craft-mode.js?v=2026-10-09-living3"></script>
|
|
182
|
-
<script src="/builders/shell.js?v=2026-10-
|
|
182
|
+
<script src="/builders/shell.js?v=2026-10-18-core-move1"></script>
|
|
183
183
|
<script src="/builders/palette.js" defer></script>
|
|
184
184
|
<script src="/builders/dom-utils.js?v=2026-06-23-contrib"></script>
|
|
185
185
|
<script src="/builders/hall-kit.js"></script>
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// modules/hall-ui/public/core-move-notice.js — "Upgraded to core X on <date>", once, after
|
|
2
|
+
// this project's core moved, with the release-note entries between the old and the new
|
|
3
|
+
// version (task 1004731).
|
|
4
|
+
//
|
|
5
|
+
// THE SERVER DECIDES, THIS ONLY DRAWS. GET /core-update carries `moved` only when there is
|
|
6
|
+
// one for THIS builder (src/bongos/core-moves.js: the newest ledger row is a move to the core
|
|
7
|
+
// this server runs, recent, and not yet seen by them), with the sentence already worded.
|
|
8
|
+
//
|
|
9
|
+
// SEEN IS PER BUILDER. Closing it, or following it to Settings → Software update, marks that
|
|
10
|
+
// move seen: on the server (`remember: 'server'` → PATCH /me/core-move-seen, the
|
|
11
|
+
// builder-settings module's behavior_prefs, so no other device shows it again), or in this
|
|
12
|
+
// browser when the server has nowhere to keep it (`remember: 'browser'`).
|
|
13
|
+
//
|
|
14
|
+
// Its own file, loaded by shell.js only when there is a notice to draw (the gov-positions.js
|
|
15
|
+
// way): shell.js sits at the 1500-line ratchet, and most page loads have nothing to say here.
|
|
16
|
+
|
|
17
|
+
(function () {
|
|
18
|
+
'use strict';
|
|
19
|
+
|
|
20
|
+
var SEEN_KEY = 'bongos.coreMove.seen';
|
|
21
|
+
function esc(s) {
|
|
22
|
+
return String(s == null ? '' : s).replace(/[&<>"']/g, function (c) {
|
|
23
|
+
return { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c];
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Draw the notice under the top bar. `opts.api` is shell.js's client; `opts.href` Settings. */
|
|
28
|
+
function render(moved, opts) {
|
|
29
|
+
if (!moved || !moved.id || !moved.message) return;
|
|
30
|
+
var api = opts && opts.api;
|
|
31
|
+
var onServer = moved.remember === 'server' && !!api;
|
|
32
|
+
if (!onServer) {
|
|
33
|
+
try {
|
|
34
|
+
if (window.localStorage && window.localStorage.getItem(SEEN_KEY) === String(moved.id)) return;
|
|
35
|
+
} catch (e) { /* no storage: show it */ }
|
|
36
|
+
}
|
|
37
|
+
var topbar = document.getElementById('app-topbar');
|
|
38
|
+
if (!topbar) return;
|
|
39
|
+
var el = document.createElement('div');
|
|
40
|
+
el.className = 'core-update-notice core-move-notice';
|
|
41
|
+
el.id = 'core-move-notice';
|
|
42
|
+
el.setAttribute('role', 'status');
|
|
43
|
+
var entries = Array.isArray(moved.entries) ? moved.entries : [];
|
|
44
|
+
var list = entries.length
|
|
45
|
+
? '<ul class="core-move-notice__list">' + entries.map(function (e) { return '<li>' + esc(e && e.text) + '</li>'; }).join('') +
|
|
46
|
+
(moved.more > 0 ? '<li>…and ' + esc(String(moved.more)) + ' more.</li>' : '') + '</ul>'
|
|
47
|
+
: '';
|
|
48
|
+
el.innerHTML = '<div class="core-move-notice__body"><span>' + esc(moved.message) +
|
|
49
|
+
(entries.length ? ' What changed:' : '') + '</span>' + list + '</div>' +
|
|
50
|
+
'<a class="core-update-notice__action core-move-notice__more" href="' + esc((opts && opts.href) || '/settings#software-update') + '">Update history</a>' +
|
|
51
|
+
'<button type="button" class="core-update-notice__close core-move-notice__close" aria-label="Dismiss">×</button>';
|
|
52
|
+
function markSeen() {
|
|
53
|
+
try {
|
|
54
|
+
if (window.localStorage) window.localStorage.setItem(SEEN_KEY, String(moved.id));
|
|
55
|
+
} catch (e) { /* best-effort */ }
|
|
56
|
+
if (onServer) {
|
|
57
|
+
api.request('PATCH', '/api/bongos/me/core-move-seen', { body: { id: String(moved.id) } })
|
|
58
|
+
.then(null, function () { /* seen is best-effort; it shows once more at worst */ });
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
el.querySelector('.core-move-notice__more').addEventListener('click', markSeen);
|
|
62
|
+
el.querySelector('.core-move-notice__close').addEventListener('click', function () {
|
|
63
|
+
markSeen();
|
|
64
|
+
el.remove();
|
|
65
|
+
});
|
|
66
|
+
topbar.insertAdjacentElement('afterend', el);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
window.CoreMoveNotice = { render: render };
|
|
70
|
+
})();
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
|
|
77
77
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
78
78
|
<script src="/builders/craft-mode.js?v=2026-10-09-living3"></script>
|
|
79
|
-
<script src="/builders/shell.js?v=2026-10-
|
|
79
|
+
<script src="/builders/shell.js?v=2026-10-18-core-move1"></script>
|
|
80
80
|
<script src="/builders/palette.js" defer></script>
|
|
81
81
|
<script src="/builders/dom-utils.js?v=2026-06-16-gate"></script>
|
|
82
82
|
<script src="/builders/hall-kit.js"></script>
|
|
@@ -99,7 +99,7 @@
|
|
|
99
99
|
time so the chrome exists before the deferred page scripts execute. -->
|
|
100
100
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
101
101
|
<script src="/builders/craft-mode.js?v=2026-10-09-living3"></script>
|
|
102
|
-
<script src="/builders/shell.js?v=2026-10-
|
|
102
|
+
<script src="/builders/shell.js?v=2026-10-18-core-move1"></script>
|
|
103
103
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
104
104
|
<script src="/builders/palette.js" defer></script>
|
|
105
105
|
<script src="/builders/diagram-viewer.js?v=2026-06-14-diagviewer-1" defer></script>
|
|
@@ -100,7 +100,7 @@
|
|
|
100
100
|
|
|
101
101
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
102
102
|
<script src="/builders/craft-mode.js?v=2026-10-09-living3"></script>
|
|
103
|
-
<script src="/builders/shell.js?v=2026-10-
|
|
103
|
+
<script src="/builders/shell.js?v=2026-10-18-core-move1"></script>
|
|
104
104
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
105
105
|
<script src="/builders/palette.js" defer></script>
|
|
106
106
|
<script src="/builders/md-reader.js?v=2026-09-02-mdreader-2"></script>
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
|
|
57
57
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
58
58
|
<script src="/builders/craft-mode.js?v=2026-10-09-living3"></script>
|
|
59
|
-
<script src="/builders/shell.js?v=2026-10-
|
|
59
|
+
<script src="/builders/shell.js?v=2026-10-18-core-move1"></script>
|
|
60
60
|
<script src="/builders/palette.js" defer></script>
|
|
61
61
|
<script src="/builders/dom-utils.js?v=2026-06-16-gate"></script>
|
|
62
62
|
<script src="/builders/hall-kit.js"></script>
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
|
|
80
80
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
81
81
|
<script src="/builders/craft-mode.js?v=2026-10-09-living3"></script>
|
|
82
|
-
<script src="/builders/shell.js?v=2026-10-
|
|
82
|
+
<script src="/builders/shell.js?v=2026-10-18-core-move1"></script>
|
|
83
83
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
84
84
|
<script src="/builders/palette.js" defer></script>
|
|
85
85
|
<script src="/builders/dom-utils.js?v=2026-06-16-gate"></script>
|
|
@@ -139,7 +139,7 @@
|
|
|
139
139
|
|
|
140
140
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
141
141
|
<script src="/builders/craft-mode.js?v=2026-10-09-living3"></script>
|
|
142
|
-
<script src="/builders/shell.js?v=2026-10-
|
|
142
|
+
<script src="/builders/shell.js?v=2026-10-18-core-move1"></script>
|
|
143
143
|
<script src="/builders/palette.js" defer></script>
|
|
144
144
|
|
|
145
145
|
<script src="/builders/idea-objects.js?v=2026-09-27-split"></script>
|
|
@@ -232,7 +232,7 @@
|
|
|
232
232
|
|
|
233
233
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
234
234
|
<script src="/builders/craft-mode.js?v=2026-10-09-living3"></script>
|
|
235
|
-
<script src="/builders/shell.js?v=2026-10-
|
|
235
|
+
<script src="/builders/shell.js?v=2026-10-18-core-move1"></script>
|
|
236
236
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
237
237
|
<script src="/builders/palette.js" defer></script>
|
|
238
238
|
<script src="/builders/dom-utils.js?v=2026-06-14-domutils"></script>
|
|
@@ -136,7 +136,7 @@
|
|
|
136
136
|
|
|
137
137
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
138
138
|
<script src="/builders/craft-mode.js?v=2026-10-09-living3"></script>
|
|
139
|
-
<script src="/builders/shell.js?v=2026-10-
|
|
139
|
+
<script src="/builders/shell.js?v=2026-10-18-core-move1"></script>
|
|
140
140
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
141
141
|
<script src="/builders/palette.js" defer></script>
|
|
142
142
|
<script src="/builders/dom-utils.js?v=2026-06-16-gate"></script>
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
|
|
53
53
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
54
54
|
<script src="/builders/craft-mode.js?v=2026-10-09-living3"></script>
|
|
55
|
-
<script src="/builders/shell.js?v=2026-10-
|
|
55
|
+
<script src="/builders/shell.js?v=2026-10-18-core-move1"></script>
|
|
56
56
|
<script src="/builders/palette.js" defer></script>
|
|
57
57
|
<script src="/builders/dom-utils.js?v=2026-06-23-contrib" defer></script>
|
|
58
58
|
<!-- task-detail.js still owns the #/idea/N and #/blocker/N overlay, so a ref
|
|
@@ -227,7 +227,7 @@
|
|
|
227
227
|
|
|
228
228
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
229
229
|
<script src="/builders/craft-mode.js?v=2026-10-09-living3"></script>
|
|
230
|
-
<script src="/builders/shell.js?v=2026-10-
|
|
230
|
+
<script src="/builders/shell.js?v=2026-10-18-core-move1"></script>
|
|
231
231
|
<script src="/builders/palette.js" defer></script>
|
|
232
232
|
<script src="/builders/dom-utils.js?v=2026-06-23-contrib"></script>
|
|
233
233
|
<!-- task 1003069 (R08) — the quick-filing form's routed result links a task
|
|
@@ -108,7 +108,7 @@
|
|
|
108
108
|
BEFORE builders.js so the chrome ids exist when events are wired. -->
|
|
109
109
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab" defer></script>
|
|
110
110
|
<script src="/builders/craft-mode.js?v=2026-10-09-living3" defer></script>
|
|
111
|
-
<script src="/builders/shell.js?v=2026-10-
|
|
111
|
+
<script src="/builders/shell.js?v=2026-10-18-core-move1" defer></script>
|
|
112
112
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
113
113
|
<script src="/builders/palette.js" defer></script>
|
|
114
114
|
<!-- task 2166: the shared component kit (window.OTBKit) — pager/ledger/rail.
|
|
@@ -103,7 +103,7 @@
|
|
|
103
103
|
|
|
104
104
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
105
105
|
<script src="/builders/craft-mode.js?v=2026-10-09-living3"></script>
|
|
106
|
-
<script src="/builders/shell.js?v=2026-10-
|
|
106
|
+
<script src="/builders/shell.js?v=2026-10-18-core-move1"></script>
|
|
107
107
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
108
108
|
<script src="/builders/palette.js" defer></script>
|
|
109
109
|
<script src="/builders/dom-utils.js?v=2026-06-23-contrib"></script>
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
|
|
62
62
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
63
63
|
<script src="/builders/craft-mode.js?v=2026-10-09-living3"></script>
|
|
64
|
-
<script src="/builders/shell.js?v=2026-10-
|
|
64
|
+
<script src="/builders/shell.js?v=2026-10-18-core-move1"></script>
|
|
65
65
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
66
66
|
<script src="/builders/palette.js" defer></script>
|
|
67
67
|
<script src="/builders/dom-utils.js?v=2026-06-14-domutils"></script>
|
|
@@ -117,7 +117,7 @@
|
|
|
117
117
|
|
|
118
118
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
119
119
|
<script src="/builders/craft-mode.js?v=2026-10-09-living3"></script>
|
|
120
|
-
<script src="/builders/shell.js?v=2026-10-
|
|
120
|
+
<script src="/builders/shell.js?v=2026-10-18-core-move1"></script>
|
|
121
121
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
122
122
|
<script src="/builders/palette.js" defer></script>
|
|
123
123
|
<!-- the shared markdown reader (window.OTBMdReader) — primer.js renders through
|
|
@@ -209,7 +209,7 @@
|
|
|
209
209
|
chrome exists before the page script runs. -->
|
|
210
210
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
211
211
|
<script src="/builders/craft-mode.js?v=2026-10-09-living3"></script>
|
|
212
|
-
<script src="/builders/shell.js?v=2026-10-
|
|
212
|
+
<script src="/builders/shell.js?v=2026-10-18-core-move1"></script>
|
|
213
213
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
214
214
|
<script src="/builders/palette.js" defer></script>
|
|
215
215
|
<!-- shared frontend toolkit (window.OTB) — loaded before profile.js, which pulls from it. -->
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
|
|
73
73
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
74
74
|
<script src="/builders/craft-mode.js?v=2026-10-09-living3"></script>
|
|
75
|
-
<script src="/builders/shell.js?v=2026-10-
|
|
75
|
+
<script src="/builders/shell.js?v=2026-10-18-core-move1"></script>
|
|
76
76
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
77
77
|
<script src="/builders/palette.js" defer></script>
|
|
78
78
|
<script src="/builders/dom-utils.js?v=2026-06-16-gate"></script>
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
chrome exists before the page script runs. -->
|
|
80
80
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
81
81
|
<script src="/builders/craft-mode.js?v=2026-10-09-living3"></script>
|
|
82
|
-
<script src="/builders/shell.js?v=2026-10-
|
|
82
|
+
<script src="/builders/shell.js?v=2026-10-18-core-move1"></script>
|
|
83
83
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
84
84
|
<script src="/builders/palette.js" defer></script>
|
|
85
85
|
<!-- shared frontend toolkit (window.OTB) — loaded before ranks.js, which pulls from it. -->
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
|
|
44
44
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
45
45
|
<script src="/builders/craft-mode.js?v=2026-10-09-living3"></script>
|
|
46
|
-
<script src="/builders/shell.js?v=2026-10-
|
|
46
|
+
<script src="/builders/shell.js?v=2026-10-18-core-move1"></script>
|
|
47
47
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
48
48
|
<script src="/builders/palette.js" defer></script>
|
|
49
49
|
<script src="/builders/dom-utils.js?v=2026-06-14-domutils"></script>
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
chrome exists before the page script runs. -->
|
|
56
56
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
57
57
|
<script src="/builders/craft-mode.js?v=2026-10-09-living3"></script>
|
|
58
|
-
<script src="/builders/shell.js?v=2026-10-
|
|
58
|
+
<script src="/builders/shell.js?v=2026-10-18-core-move1"></script>
|
|
59
59
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
60
60
|
<script src="/builders/palette.js" defer></script>
|
|
61
61
|
<!-- shared frontend toolkit (window.OTB — rank labels, number formats) + the
|
|
@@ -113,7 +113,7 @@
|
|
|
113
113
|
chrome exists before the page script runs. -->
|
|
114
114
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
115
115
|
<script src="/builders/craft-mode.js?v=2026-10-09-living3"></script>
|
|
116
|
-
<script src="/builders/shell.js?v=2026-10-
|
|
116
|
+
<script src="/builders/shell.js?v=2026-10-18-core-move1"></script>
|
|
117
117
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
118
118
|
<script src="/builders/palette.js" defer></script>
|
|
119
119
|
<!-- shared frontend toolkit (window.OTB) — loaded BEFORE sessions.js so it can pull from it. -->
|
|
@@ -166,6 +166,35 @@
|
|
|
166
166
|
return `${head}${warn}<ol class="su-versions" aria-labelledby="su-new-h">${items.join('')}</ol>${more ? `<div class="row-end">${more}</div>` : ''}${beyond}`;
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
+
// A move this project's own ledger says was rolled back (task 1004730): the server's plain
|
|
170
|
+
// sentence, said as it is. It names the version tried, that it was rolled back, and that
|
|
171
|
+
// the project is still on its old version and working; nothing here re-derives it.
|
|
172
|
+
function heldHtml(held) {
|
|
173
|
+
if (!held || !held.message) return '';
|
|
174
|
+
return `<p class="panel-status" role="status">${escapeHtml(held.message)}</p>`;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// The short history of moves (task 1004731, src/bongos/core-moves.js): each core this
|
|
178
|
+
// project moved to, when, how it was started, and whether it went in. Only for the people
|
|
179
|
+
// allowed to upgrade (the server sends `history: null` to anyone else). The words for
|
|
180
|
+
// "how" are only as precise as the ledger: a move run on the server by neither the Update
|
|
181
|
+
// button nor an automatic rule is said as exactly that.
|
|
182
|
+
const HOW_WORDS = { automatic: 'Automatic', by_hand: 'By hand, from the Update button', on_server: 'Run on the server' };
|
|
183
|
+
const OUTCOME_WORDS = { upgraded: 'Installed', moved_back: 'Moved back to it', rolled_back: 'Rolled back' };
|
|
184
|
+
function historyHtml(history) {
|
|
185
|
+
if (!Array.isArray(history) || !history.length) return '';
|
|
186
|
+
const items = history.map((m) => {
|
|
187
|
+
const when = m.at ? longDate(m.at) : null;
|
|
188
|
+
const outcome = OUTCOME_WORDS[m.outcome] || OUTCOME_WORDS.upgraded;
|
|
189
|
+
const pill = m.outcome === 'rolled_back' ? 'su-pill' : 'su-pill su-pill--ok';
|
|
190
|
+
return `<li class="su-version">
|
|
191
|
+
<span class="prow__label">${mono(m.version)}${when ? `<span class="prow__tag">${escapeHtml(when)}</span>` : ''}</span>
|
|
192
|
+
<p class="prow__desc">${escapeHtml(HOW_WORDS[m.how] || HOW_WORDS.on_server)}${m.from ? `, from ${mono(m.from)}` : ''}. <span class="${pill}">${escapeHtml(outcome)}</span></p>
|
|
193
|
+
</li>`;
|
|
194
|
+
}).join('');
|
|
195
|
+
return `<h3 class="su-h" id="su-history-h">Recent updates</h3><ol class="su-versions" aria-labelledby="su-history-h">${items}</ol>`;
|
|
196
|
+
}
|
|
197
|
+
|
|
169
198
|
function render(data) {
|
|
170
199
|
const body = byId('su-body');
|
|
171
200
|
const note = byId('su-note');
|
|
@@ -177,19 +206,23 @@
|
|
|
177
206
|
|
|
178
207
|
if (u.reading !== 'ok') {
|
|
179
208
|
body.innerHTML = row('This project runs', u.running ? mono(u.running) : 'a version it could not name')
|
|
180
|
-
+
|
|
209
|
+
+ heldHtml(data.held)
|
|
210
|
+
+ `<p class="panel-status panel-status--danger" role="status">Could not check for a newer version: ${escapeHtml(u.error || 'no answer')}.</p>`
|
|
211
|
+
+ historyHtml(data.history);
|
|
181
212
|
if (note) note.textContent = notes.join(' ');
|
|
182
213
|
return;
|
|
183
214
|
}
|
|
184
215
|
|
|
185
|
-
let html = row('This project runs', mono(u.running));
|
|
216
|
+
let html = row('This project runs', mono(u.running)) + heldHtml(data.held);
|
|
217
|
+
const onHold = !!(data.held && u.offered && data.held.version === u.offered);
|
|
186
218
|
if (!u.offered) {
|
|
187
219
|
html += row('Newest for this project', `${mono(u.running)} — this project is up to date.`, '<span class="su-pill su-pill--ok">Up to date</span>');
|
|
188
220
|
} else {
|
|
189
221
|
const when = ago(u.offered_published_at);
|
|
190
222
|
const pending = data.can_update && data.ask && data.ask.available && askPending(data.ask, u.offered);
|
|
191
|
-
html += row('Newest for this project', `${mono(u.offered)}${when ? ` — published ${escapeHtml(when)}` : ''}`, `<span class="su-pill">${pending ? 'Requested' : 'Update ready'}</span>`);
|
|
192
|
-
|
|
223
|
+
html += row('Newest for this project', `${mono(u.offered)}${when ? ` — published ${escapeHtml(when)}` : ''}`, `<span class="su-pill">${onHold ? 'On hold' : pending ? 'Requested' : 'Update ready'}</span>`);
|
|
224
|
+
// No button to take again the very version that was just rolled back here (task 1004730).
|
|
225
|
+
if (!onHold) html += doorHtml(data, u.offered);
|
|
193
226
|
html += whatsNewHtml(u.whats_new, (data.door || {}).kind === 'local');
|
|
194
227
|
}
|
|
195
228
|
// A newer line this project's channel does not take is a fact worth one sentence — it
|
|
@@ -197,7 +230,7 @@
|
|
|
197
230
|
if (u.newest && u.newest !== (u.offered || u.running) && String(u.newest).split('.')[1] !== String(u.running).split('.')[1]) {
|
|
198
231
|
notes.push(`${u.newest} is also published; it starts a new line, and this project takes updates within ${String(u.running).split('.').slice(0, 2).join('.')} on its own.`);
|
|
199
232
|
}
|
|
200
|
-
body.innerHTML = html;
|
|
233
|
+
body.innerHTML = html + historyHtml(data.history);
|
|
201
234
|
if (note) note.textContent = notes.join(' ');
|
|
202
235
|
|
|
203
236
|
const askBtn = byId('su-ask');
|
|
@@ -472,7 +472,7 @@
|
|
|
472
472
|
chrome exists before the page scripts run. -->
|
|
473
473
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
474
474
|
<script src="/builders/craft-mode.js?v=2026-10-09-living3"></script>
|
|
475
|
-
<script src="/builders/shell.js?v=2026-10-
|
|
475
|
+
<script src="/builders/shell.js?v=2026-10-18-core-move1"></script>
|
|
476
476
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
477
477
|
<script src="/builders/palette.js" defer></script>
|
|
478
478
|
<!-- shared frontend toolkit (window.OTB) — loaded before consuming IIFEs. -->
|
|
@@ -498,7 +498,7 @@
|
|
|
498
498
|
settings.js is against the 1500-line ratchet. -->
|
|
499
499
|
<script src="/builders/settings-render.js?v=2026-09-16-render-levels"></script>
|
|
500
500
|
<!-- task 1004296: Settings → Software update. Own file on the same precedent. -->
|
|
501
|
-
<script src="/builders/settings-software-update.js?v=2026-10-
|
|
501
|
+
<script src="/builders/settings-software-update.js?v=2026-10-18-history"></script>
|
|
502
502
|
<!-- task 1004501: Settings → Your Autobongos runner. Own file on the same precedent. -->
|
|
503
503
|
<script src="/builders/settings-autobongos.js?v=2026-10-01-autobongos"></script>
|
|
504
504
|
<!-- task 1003793: Settings → Module install reports. Own file on the same precedent. -->
|
|
@@ -774,9 +774,17 @@
|
|
|
774
774
|
coreUpdateAsked = true;
|
|
775
775
|
api.request('GET', '/api/bongos/core-update').then(function (res) {
|
|
776
776
|
if (!res || res.status !== 200 || !res.data) return;
|
|
777
|
-
if (res.data.update) renderCoreUpdateBanner(res.data.update);
|
|
777
|
+
if (res.data.update) renderCoreUpdateBanner(res.data.update, res.data.held);
|
|
778
|
+
if (res.data.moved) renderCoreMoveNotice(res.data.moved); // task 1004731: loads core-move-notice.js, which draws it
|
|
778
779
|
}, function () { /* fail-soft: no banner is the correct answer to no answer */ });
|
|
779
780
|
}
|
|
781
|
+
function renderCoreMoveNotice(moved) {
|
|
782
|
+
if (!document.head || !document.head.appendChild) return;
|
|
783
|
+
var tag = document.createElement('script');
|
|
784
|
+
tag.src = '/builders/core-move-notice.js' + (SHELL_V ? '?v=' + SHELL_V : '');
|
|
785
|
+
tag.onload = function () { if (window.CoreMoveNotice) window.CoreMoveNotice.render(moved, { api: api, href: SOFTWARE_UPDATE_HREF }); };
|
|
786
|
+
document.head.appendChild(tag);
|
|
787
|
+
}
|
|
780
788
|
|
|
781
789
|
// Where the banner's Upgrade goes (task 1004296). The platform's hall runs the deploy
|
|
782
790
|
// door itself, so there it is /deploy. Every other hall — a hosted project, a
|
|
@@ -789,7 +797,7 @@
|
|
|
789
797
|
// is current AND when the registry could not be read; `reading` separates them,
|
|
790
798
|
// and neither renders. A banner is a claim about being out of date, and a wrong
|
|
791
799
|
// one on a project that is actually current is worse than silence.
|
|
792
|
-
function renderCoreUpdateBanner(update) {
|
|
800
|
+
function renderCoreUpdateBanner(update, held) {
|
|
793
801
|
if (!update || update.reading !== 'ok' || !update.behind || !update.latest) return;
|
|
794
802
|
// A dismissal is remembered PER VERSION, not forever: the next release is new
|
|
795
803
|
// news and must re-announce itself, or the surface is dead after one click.
|
|
@@ -826,10 +834,14 @@
|
|
|
826
834
|
: (onUpdatePanel
|
|
827
835
|
? '<span class="core-update-notice__hint">Its details are below.</span>'
|
|
828
836
|
: '<a class="core-update-notice__action" href="' + SOFTWARE_UPDATE_HREF + '">Upgrade</a>');
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
837
|
+
// task 1004730: the newest version already failed here and was rolled back. Say so, never
|
|
838
|
+
// "available" with a button to take it again; Software update carries the full sentence.
|
|
839
|
+
var hold = held && held.version === update.latest ? held : null;
|
|
840
|
+
el.innerHTML = (hold
|
|
841
|
+
? '<span>Core <strong>' + esc(hold.version) + '</strong> was tried on this project and rolled back. It is still on ' +
|
|
842
|
+
esc(hold.still_on) + ' and working.</span><a class="core-update-notice__action" href="' + SOFTWARE_UPDATE_HREF + '">Details</a>'
|
|
843
|
+
: '<span>Core <strong>' + esc(update.latest) + '</strong> is available — this project runs ' +
|
|
844
|
+
esc(update.running || 'an unknown version') + '.</span>' + action) +
|
|
833
845
|
'<button type="button" class="core-update-notice__close" aria-label="Dismiss">×</button>';
|
|
834
846
|
el.querySelector('.core-update-notice__close').addEventListener('click', function () {
|
|
835
847
|
try {
|
|
@@ -230,7 +230,7 @@
|
|
|
230
230
|
|
|
231
231
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
232
232
|
<script src="/builders/craft-mode.js?v=2026-10-09-living3"></script>
|
|
233
|
-
<script src="/builders/shell.js?v=2026-10-
|
|
233
|
+
<script src="/builders/shell.js?v=2026-10-18-core-move1"></script>
|
|
234
234
|
<script src="/builders/palette.js" defer></script>
|
|
235
235
|
<script src="/builders/gov-living.js?v=2026-10-09-positions1"></script>
|
|
236
236
|
<script src="/builders/gov-feeds.js?v=2026-10-09-living3"></script>
|