@bongos/core 1.24.11 → 1.24.13
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 +160 -85
- package/clients/bongos-client/README.md +1 -1
- package/clients/bongos-client/bongos-client.global.js +6 -0
- package/clients/bongos-client/index.cjs +6 -0
- package/clients/bongos-client/index.d.ts +8 -0
- package/clients/bongos-client/index.mjs +6 -0
- package/docs/adr/0371-auto-pickup-applies-a-submitted-tweak-on-the-runner.md +1 -0
- package/docs/api/openapi.json +175 -3
- package/docs/api-reference.md +5 -2
- package/docs/copy-inventory.md +92 -20
- package/docs/copy-registry.json +777 -33
- package/docs/module-api-changelog.md +4 -0
- package/docs/page-inventory.json +68 -4
- package/docs/page-readings.json +856 -802
- package/migrations/core_288_credit_log_idea_unique.sql +51 -0
- package/modules/economy/credits.js +6 -5
- package/modules/hall-ui/public/ai-studio.html +1 -1
- 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/craft-mode.js +2 -2
- 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/market-watch-item.html +83 -0
- package/modules/hall-ui/public/market-watch-item.js +150 -0
- package/modules/hall-ui/public/market-watch-item.states.json +143 -0
- package/modules/hall-ui/public/market-watch-lib.js +243 -0
- package/modules/hall-ui/public/market-watch-rules.html +1 -1
- package/modules/hall-ui/public/market-watch-settings.html +1 -1
- package/modules/hall-ui/public/market-watch.css +169 -0
- package/modules/hall-ui/public/market-watch.html +111 -0
- package/modules/hall-ui/public/market-watch.js +129 -0
- package/modules/hall-ui/public/market-watch.states.json +14 -0
- 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/project-settings.js +2 -2
- 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.html +1 -1
- package/modules/hall-ui/public/shell.js +3 -2
- package/modules/hall-ui/public/street.html +1 -1
- package/modules/hall-ui/public/studio.html +1 -1
- 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/modules/hall-ui/records/market-watch.md +40 -0
- package/modules/lifecycle/autopickup.js +46 -24
- package/modules/lifecycle/db-claims.js +1 -1
- package/modules/lifecycle/routes/project-settings.js +24 -16
- package/modules/market-watch/db.js +15 -10
- package/modules/market-watch/module.json +2 -1
- package/modules/market-watch/pages.js +323 -0
- package/modules/market-watch/proposals.js +66 -4
- package/modules/market-watch/research.js +27 -0
- package/modules/market-watch/routes/pages.js +116 -0
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/release-notes.json +20 -0
- package/scripts/bongos/run-unit-tests.js +4 -0
- package/src/bongos/module-scope-map.js +1 -0
- package/src/bongos/project-settings.js +2 -2
- package/src/module-api.js +1 -1
- package/tests/autopickup_cap.mjs +122 -60
- package/tests/credit_log_idea_unique_db.mjs +98 -0
- package/tests/fixtures/market-watch-seed-rows.cjs +60 -0
- package/tests/hall_nav.mjs +4 -1
- package/tests/hall_page_gate_map.mjs +4 -0
- package/tests/market_watch_data_db.mjs +1 -0
- package/tests/market_watch_module.mjs +2 -1
- package/tests/market_watch_pages.mjs +356 -0
- package/tests/market_watch_rules.mjs +63 -3
- package/tests/market_watch_run.mjs +44 -0
- package/tests/nav_permission_atoms.mjs +1 -1
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
+
<title>Market Watch — {{worldName}}</title>
|
|
7
|
+
<meta name="description" content="The project's scouts on its competitors, partners and topics: the landscape, the next sweep, the budget left and this week's reports.">
|
|
8
|
+
<link rel="icon" href="data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'><text x='16' y='24' font-size='24' text-anchor='middle' font-family='sans-serif'>⌂</text></svg>">
|
|
9
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
10
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
11
|
+
<link rel="stylesheet" href="/builders/style.css?v=2026-07-02-shell1">
|
|
12
|
+
<link rel="stylesheet" href="/builders/market-watch.css">
|
|
13
|
+
</head>
|
|
14
|
+
<body data-page="market-watch" data-page-title="Market Watch">
|
|
15
|
+
|
|
16
|
+
<div class="app">
|
|
17
|
+
<aside class="app-sidebar" id="app-sidebar" aria-label="Primary"></aside>
|
|
18
|
+
<div class="app-scrim" id="app-scrim" hidden></div>
|
|
19
|
+
<div class="app-body">
|
|
20
|
+
<header class="app-topbar" id="app-topbar"></header>
|
|
21
|
+
<div class="app-content">
|
|
22
|
+
<!-- The page's one h1, for screen readers: no page shows its head (task 1004836). -->
|
|
23
|
+
<div class="page-head page-head--room">
|
|
24
|
+
<h1 class="page-head__h">Market Watch</h1>
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
<main id="hall-main">
|
|
28
|
+
<p class="mw-quiet" id="mw-loading">Loading the watch…</p>
|
|
29
|
+
|
|
30
|
+
<!-- Market Watch is off on this project: a quiet line, never an error. -->
|
|
31
|
+
<section class="mw-panel mw-off" id="mw-off" hidden>
|
|
32
|
+
<span class="mw-label">market watch</span>
|
|
33
|
+
<p>Market Watch is off on this project.</p>
|
|
34
|
+
<p class="mw-quiet">An owner can turn it on from <a href="/modules">Modules</a>.</p>
|
|
35
|
+
</section>
|
|
36
|
+
|
|
37
|
+
<section class="mw-panel mw-off" id="mw-fail" hidden>
|
|
38
|
+
<p id="mw-fail-text">Could not read the watch. Try reloading the page.</p>
|
|
39
|
+
</section>
|
|
40
|
+
|
|
41
|
+
<div class="mw-desk" id="mw-desk" hidden>
|
|
42
|
+
<section class="mw-panel" aria-labelledby="mw-scouts-h">
|
|
43
|
+
<span class="mw-label" id="mw-scouts-h">your scouts</span>
|
|
44
|
+
<p class="mw-watched" id="mw-watched"></p>
|
|
45
|
+
<div id="mw-scouts"></div>
|
|
46
|
+
<button class="btn btn--ghost mw-send" type="button" id="mw-send">+ send a new scout</button>
|
|
47
|
+
<span class="mw-label" style="margin-top:16px">streak</span>
|
|
48
|
+
<div class="mw-streak" id="mw-streak"></div>
|
|
49
|
+
<a class="mw-rules-link" href="/market-watch-rules">the watch rules, and what members proposed →</a>
|
|
50
|
+
<div class="mw-pins" id="mw-pins" hidden>
|
|
51
|
+
<span class="mw-label">pinned</span>
|
|
52
|
+
<div id="mw-pin-list"></div>
|
|
53
|
+
</div>
|
|
54
|
+
</section>
|
|
55
|
+
|
|
56
|
+
<section class="mw-panel mw-scope-wrap" aria-label="The landscape">
|
|
57
|
+
<div class="mw-scope-tools">
|
|
58
|
+
<label for="mw-ax">across</label> <select id="mw-ax"></select>
|
|
59
|
+
<label for="mw-ay">up</label> <select id="mw-ay"></select>
|
|
60
|
+
<span class="mw-sp"></span>
|
|
61
|
+
<span class="mw-key"><i class="mw-dot" style="background:var(--accent)"></i> new signal</span>
|
|
62
|
+
<span class="mw-key"><i class="mw-dot" style="background:var(--ink)"></i> us</span>
|
|
63
|
+
</div>
|
|
64
|
+
<div class="mw-scope" id="mw-scope"></div>
|
|
65
|
+
<div class="mw-scope-tools mw-open">
|
|
66
|
+
<label for="mw-open">open a case file</label> <select id="mw-open"></select>
|
|
67
|
+
</div>
|
|
68
|
+
</section>
|
|
69
|
+
|
|
70
|
+
<div class="mw-side">
|
|
71
|
+
<section class="mw-panel" aria-labelledby="mw-sweep-h">
|
|
72
|
+
<span class="mw-label" id="mw-sweep-h">next sweep</span>
|
|
73
|
+
<div class="mw-fuel">
|
|
74
|
+
<div>
|
|
75
|
+
<div class="mw-count mw-num" id="mw-cd"></div>
|
|
76
|
+
<div class="mw-when" id="mw-when"></div>
|
|
77
|
+
</div>
|
|
78
|
+
<span class="mw-sp" style="flex:1"></span>
|
|
79
|
+
<div>
|
|
80
|
+
<div class="mw-tank" id="mw-tank"><i id="mw-tank-fill"></i></div>
|
|
81
|
+
<div class="mw-left mw-num" id="mw-left"></div>
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
</section>
|
|
85
|
+
<section class="mw-panel" aria-labelledby="mw-reps-h">
|
|
86
|
+
<span class="mw-label" id="mw-reps-h">reports in · this week</span>
|
|
87
|
+
<div class="mw-xp"><span class="mw-num" id="mw-xpn"></span><span class="mw-xp__b"><i id="mw-xpb" style="width:0"></i></span><span>read</span></div>
|
|
88
|
+
<div id="mw-reps"></div>
|
|
89
|
+
</section>
|
|
90
|
+
</div>
|
|
91
|
+
</div>
|
|
92
|
+
</main>
|
|
93
|
+
|
|
94
|
+
<footer class="app-foot" id="app-foot"></footer>
|
|
95
|
+
</div>
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
|
|
99
|
+
<dialog class="mw-dialog" id="mw-propose" aria-label="Propose a change"></dialog>
|
|
100
|
+
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
101
|
+
|
|
102
|
+
<script src="/builders/dom-utils.js?v=2026-10-25-escape"></script>
|
|
103
|
+
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
104
|
+
<script src="/builders/craft-mode.js?v=2026-10-09-living3"></script>
|
|
105
|
+
<script src="/builders/shell.js?v=2026-10-30-market-watch-pages"></script>
|
|
106
|
+
<script src="/builders/palette.js" defer></script>
|
|
107
|
+
<script src="/builders/hall-kit.js"></script>
|
|
108
|
+
<script src="/builders/market-watch-lib.js"></script>
|
|
109
|
+
<script src="/builders/market-watch.js"></script>
|
|
110
|
+
</body>
|
|
111
|
+
</html>
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
// market-watch.js — the Market Watch home, the watchtower desk (task 1004939; design of
|
|
2
|
+
// record docs/design/mocks/market-watch/home.html, option D). One read,
|
|
3
|
+
// GET /market-watch/home, which every signed-in member may make. Where the module is off
|
|
4
|
+
// its routes do not exist, so the page shows its quiet off state rather than an error.
|
|
5
|
+
(() => {
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const MW = window.OTBMarketWatch;
|
|
9
|
+
const esc = MW.esc;
|
|
10
|
+
const $ = (id) => document.getElementById(id);
|
|
11
|
+
const toast = (m) => (window.OTB && window.OTB.toast ? window.OTB.toast(m, { duration: 1800, clear: true }) : null);
|
|
12
|
+
let HOME = null;
|
|
13
|
+
|
|
14
|
+
function show(id) {
|
|
15
|
+
$('mw-loading').hidden = true;
|
|
16
|
+
for (const k of ['mw-off', 'mw-fail', 'mw-desk']) $(k).hidden = k !== id;
|
|
17
|
+
}
|
|
18
|
+
function moduleOff() {
|
|
19
|
+
const m = window.__MODULES__;
|
|
20
|
+
return !!(m && m.enabled && 'market-watch' in m.enabled && m.enabled['market-watch'] !== true);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function renderScouts(h) {
|
|
24
|
+
const weeks = h.weeks_watched;
|
|
25
|
+
$('mw-watched').innerHTML = `<i class="mw-dot" style="background:var(--accent)" aria-hidden="true"></i> <b>${weeks}</b> ${weeks === 1 ? 'week' : 'weeks'} watched`;
|
|
26
|
+
$('mw-scouts').innerHTML = h.scouts.map((s) => `<div class="mw-scout">
|
|
27
|
+
<span class="mw-scout__ic" aria-hidden="true">${MW.KIND_ICON[s.kind]}</span>
|
|
28
|
+
<span class="mw-scout__t">${MW.KIND_PLURAL[s.kind]}<br><span class="mw-scout__lv">${s.watched} watched${s.level ? ` · lvl ${s.level}` : ''}</span></span>
|
|
29
|
+
<span class="mw-badge${s.reports ? '' : ' mw-badge--none'}" title="${s.reports} with a report this week">${s.reports}</span></div>`).join('');
|
|
30
|
+
$('mw-streak').innerHTML = h.streak.length
|
|
31
|
+
? h.streak.map((r) => `<i class="${r.ran ? '' : 'no'}" title="${r.ran ? `run ${r.n} · ${MW.fmtDay(r.date)}` : `skipped · ${MW.fmtDay(r.date)}`}"></i>`).join('')
|
|
32
|
+
: '<span class="mw-quiet">no runs yet</span>';
|
|
33
|
+
const pins = MW.pins.all();
|
|
34
|
+
$('mw-pins').hidden = !pins.length;
|
|
35
|
+
$('mw-pin-list').innerHTML = pins.map((p) => `<div class="mw-pin-row"><span aria-hidden="true">${MW.KIND_ICON[p.kind] || ''}</span><a class="mw-one" href="${MW.itemHref(p.id)}">${esc(p.name)}</a></div>`).join('');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function renderScope() {
|
|
39
|
+
$('mw-scope').innerHTML = MW.scopeSvg(HOME, $('mw-ax').value, $('mw-ay').value);
|
|
40
|
+
}
|
|
41
|
+
function initAxes(h) {
|
|
42
|
+
const opts = h.axes.map((a) => `<option value="${esc(a.key)}">${esc(a.label)}</option>`).join('');
|
|
43
|
+
$('mw-ax').innerHTML = opts;
|
|
44
|
+
$('mw-ay').innerHTML = opts;
|
|
45
|
+
// The mockup opens on open-source ethos across, contributor economy up.
|
|
46
|
+
const has = (k) => h.axes.some((a) => a.key === k);
|
|
47
|
+
$('mw-ax').value = has('open_source_ethos') ? 'open_source_ethos' : h.axes[0].key;
|
|
48
|
+
$('mw-ay').value = has('contributor_economy') ? 'contributor_economy' : (h.axes[1] || h.axes[0]).key;
|
|
49
|
+
$('mw-ax').onchange = renderScope;
|
|
50
|
+
$('mw-ay').onchange = renderScope;
|
|
51
|
+
// A dot is a picture, not a control (36 of them would be 36 undersized links); a
|
|
52
|
+
// click on one opens its file, and the picker below reaches every item by name.
|
|
53
|
+
$('mw-scope').addEventListener('click', (ev) => {
|
|
54
|
+
const blip = ev.target.closest && ev.target.closest('[data-id]');
|
|
55
|
+
if (blip) window.location.assign(MW.itemHref(blip.getAttribute('data-id')));
|
|
56
|
+
});
|
|
57
|
+
const groups = ['competitor', 'partner', 'topic'].map((k) => {
|
|
58
|
+
const mine = (h.index || []).filter((i) => i.kind === k);
|
|
59
|
+
return mine.length ? `<optgroup label="${MW.KIND_PLURAL[k]}">${mine.map((i) => `<option value="${i.id}">${esc(i.name)}</option>`).join('')}</optgroup>` : '';
|
|
60
|
+
}).join('');
|
|
61
|
+
$('mw-open').innerHTML = `<option value="">pick one…</option>${groups}`;
|
|
62
|
+
$('mw-open').onchange = () => { if ($('mw-open').value) window.location.assign(MW.itemHref($('mw-open').value)); };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function renderSweep(h) {
|
|
66
|
+
const s = MW.nextSweep(h);
|
|
67
|
+
$('mw-cd').textContent = s.big;
|
|
68
|
+
$('mw-when').textContent = s.small;
|
|
69
|
+
const b = h.budget;
|
|
70
|
+
const used = b.cap_usd > 0 ? Math.min(100, Math.round((b.spent_usd / b.cap_usd) * 100)) : 0;
|
|
71
|
+
$('mw-tank-fill').style.height = `${used}%`;
|
|
72
|
+
$('mw-tank').title = `${MW.money(b.spent_usd)} of ${MW.money(b.cap_usd)} used this month`;
|
|
73
|
+
$('mw-left').textContent = `${MW.money(b.left_usd)} left`;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function renderReports(h) {
|
|
77
|
+
const read = new Set(MW.reads.get());
|
|
78
|
+
const total = h.reports.length;
|
|
79
|
+
const count = () => h.reports.filter((r) => read.has(String(r.id))).length;
|
|
80
|
+
const bar = () => {
|
|
81
|
+
const n = count();
|
|
82
|
+
$('mw-xpn').textContent = `${n}/${total}`;
|
|
83
|
+
$('mw-xpb').style.width = total ? `${(n / total) * 100}%` : '0';
|
|
84
|
+
};
|
|
85
|
+
$('mw-reps').innerHTML = total
|
|
86
|
+
? h.reports.map((r) => `<div class="mw-rep${read.has(String(r.id)) ? ' done' : ''}" data-id="${r.id}">
|
|
87
|
+
<span class="mw-rep__ic" aria-hidden="true">${MW.KIND_ICON[r.kind]}</span>
|
|
88
|
+
<a class="mw-rep__t" href="${MW.itemHref(r.item_id)}" title="${esc(r.takeaway)}"><b>${esc(r.item_name)}</b> · ${esc(r.takeaway)}</a>
|
|
89
|
+
<button type="button" aria-label="Mark the ${esc(r.item_name)} report read">ok</button></div>`).join('')
|
|
90
|
+
: '<p class="mw-quiet">No reports this week yet.</p>';
|
|
91
|
+
bar();
|
|
92
|
+
$('mw-reps').querySelectorAll('.mw-rep button').forEach((btn) => {
|
|
93
|
+
btn.addEventListener('click', () => {
|
|
94
|
+
const row = btn.closest('.mw-rep');
|
|
95
|
+
if (row.classList.contains('done')) return;
|
|
96
|
+
row.classList.add('done');
|
|
97
|
+
MW.reads.add(row.dataset.id);
|
|
98
|
+
read.add(row.dataset.id);
|
|
99
|
+
bar();
|
|
100
|
+
toast(count() === total ? 'All caught up — every report read' : '+1 report read');
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async function load() {
|
|
106
|
+
if (moduleOff()) return show('mw-off');
|
|
107
|
+
let res;
|
|
108
|
+
try {
|
|
109
|
+
res = await fetch('/api/bongos/market-watch/home', { credentials: 'same-origin' });
|
|
110
|
+
} catch (e) {
|
|
111
|
+
return show('mw-fail');
|
|
112
|
+
}
|
|
113
|
+
if (res.status === 401) { window.location.assign(`/api/bongos/auth/web/start?return=${encodeURIComponent(window.location.pathname)}`); return; }
|
|
114
|
+
if (res.status === 404) return show('mw-off'); // the module's routes are not mounted
|
|
115
|
+
if (!res.ok) return show('mw-fail');
|
|
116
|
+
HOME = await res.json();
|
|
117
|
+
show('mw-desk');
|
|
118
|
+
renderScouts(HOME);
|
|
119
|
+
initAxes(HOME);
|
|
120
|
+
renderScope();
|
|
121
|
+
renderSweep(HOME);
|
|
122
|
+
renderReports(HOME);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
$('mw-send').addEventListener('click', () => {
|
|
126
|
+
MW.openPropose('scout', {}, () => toast('Scout proposed — the government will decide'));
|
|
127
|
+
});
|
|
128
|
+
document.addEventListener('DOMContentLoaded', load);
|
|
129
|
+
})();
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_": "MARKET WATCH HOME, the watchtower desk (task 1004939; design of record docs/design/mocks/market-watch/home.html, option D). One read, GET /market-watch/home. Against the kit's own stub it 404s, which the page reads as the module being off, so the stub render is the quiet off state. The populated desk needs the hall-preview harness with the module reported on; its market-watch__home.json fixture was built from the committed 2026-10-28 seed through the real shapes (tests/fixtures/market-watch-seed-rows.cjs):\n\n node scripts/hall-preview/server.js --port 4639 --fixture-me --modules-on market-watch\n node modules/ui-design/kit/render.js --states modules/hall-ui/public/market-watch.states.json --base-in http://localhost:4639 --base-out http://localhost:4639",
|
|
3
|
+
"page": "/builders/market-watch",
|
|
4
|
+
"surface": "hall-ui",
|
|
5
|
+
"stub": { "prefix": "/builders/" },
|
|
6
|
+
"modeQuery": false,
|
|
7
|
+
"ignoreRequests": ["/api/(gds|bongos)/"],
|
|
8
|
+
"ignoreConsole": ["/api/(gds|bongos)/", "\\b401\\b", "\\b403\\b", "\\b404\\b", "Unauthorized", "Forbidden", "Not Found", "load failed"],
|
|
9
|
+
"states": {
|
|
10
|
+
"desk": { "auth": true, "actions": [["wait", 900], ["clickIfVisible", "[data-craft-close]"], ["wait", 200]], "expect": { "visible": ["#mw-desk", "#mw-scope svg"] } },
|
|
11
|
+
"out": { "auth": false, "actions": [["wait", 600], ["clickIfVisible", "[data-craft-close]"]] }
|
|
12
|
+
},
|
|
13
|
+
"reducedMotion": { "auth": true, "actions": [["wait", 900], ["clickIfVisible", "[data-craft-close]"], ["wait", 200]] }
|
|
14
|
+
}
|
|
@@ -128,7 +128,7 @@
|
|
|
128
128
|
<script src="/builders/dom-utils.js?v=2026-10-25-escape"></script>
|
|
129
129
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
130
130
|
<script src="/builders/craft-mode.js?v=2026-10-30-market-watch"></script>
|
|
131
|
-
<script src="/builders/shell.js?v=2026-10-30-market-watch"></script>
|
|
131
|
+
<script src="/builders/shell.js?v=2026-10-30-market-watch-pages"></script>
|
|
132
132
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
133
133
|
<script src="/builders/palette.js" defer></script>
|
|
134
134
|
<script src="/builders/brand-apply.js"></script>
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
<script src="/builders/dom-utils.js?v=2026-10-25-escape"></script>
|
|
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-30-market-watch"></script>
|
|
65
|
-
<script src="/builders/shell.js?v=2026-10-30-market-watch"></script>
|
|
65
|
+
<script src="/builders/shell.js?v=2026-10-30-market-watch-pages"></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/gov-living.js?v=2026-10-10-real1"></script>
|
|
@@ -113,7 +113,7 @@
|
|
|
113
113
|
<script src="/builders/dom-utils.js?v=2026-10-25-escape"></script>
|
|
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-30-market-watch"></script>
|
|
116
|
-
<script src="/builders/shell.js?v=2026-10-30-market-watch"></script>
|
|
116
|
+
<script src="/builders/shell.js?v=2026-10-30-market-watch-pages"></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
|
<!-- the shared markdown reader (window.OTBMdReader) — primer.js renders through
|
|
@@ -208,7 +208,7 @@
|
|
|
208
208
|
<script src="/builders/dom-utils.js?v=2026-10-25-escape"></script>
|
|
209
209
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
210
210
|
<script src="/builders/craft-mode.js?v=2026-10-30-market-watch"></script>
|
|
211
|
-
<script src="/builders/shell.js?v=2026-10-30-market-watch"></script>
|
|
211
|
+
<script src="/builders/shell.js?v=2026-10-30-market-watch-pages"></script>
|
|
212
212
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
213
213
|
<script src="/builders/palette.js" defer></script>
|
|
214
214
|
<!-- task 1004727: the ONE karma vote control every task/idea list renders -->
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
<script src="/builders/dom-utils.js?v=2026-10-25-escape"></script>
|
|
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-30-market-watch"></script>
|
|
75
|
-
<script src="/builders/shell.js?v=2026-10-30-market-watch"></script>
|
|
75
|
+
<script src="/builders/shell.js?v=2026-10-30-market-watch-pages"></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/hall-kit.js"></script>
|
|
@@ -168,9 +168,9 @@
|
|
|
168
168
|
</div>
|
|
169
169
|
${ranks.map((r) => `
|
|
170
170
|
<div class="ps-controls">
|
|
171
|
-
<label for="ps-tweak-rank-${escapeHtml(String(r.rank))}">${escapeHtml(String(r.rank))}</label>
|
|
171
|
+
<label for="ps-tweak-rank-${escapeHtml(String(r.rank))}">${escapeHtml(String(r.rank))}, per person</label>
|
|
172
172
|
<input type="number" class="ps-tweak-rank" id="ps-tweak-rank-${escapeHtml(String(r.rank))}" data-rank="${escapeHtml(String(r.rank))}"
|
|
173
|
-
min="1" max="${max}" step="1" value="${r.cap == null ? '' : escapeHtml(String(r.cap))}" placeholder="
|
|
173
|
+
min="1" max="${max}" step="1" value="${r.cap == null ? '' : escapeHtml(String(r.cap))}" placeholder="no limit of its own">
|
|
174
174
|
</div>`).join('')}
|
|
175
175
|
<div class="ps-controls">
|
|
176
176
|
<button type="button" class="btn" id="ps-tweak-save">Save</button>
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
<script src="/builders/dom-utils.js?v=2026-10-25-escape"></script>
|
|
75
75
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
76
76
|
<script src="/builders/craft-mode.js?v=2026-10-30-market-watch"></script>
|
|
77
|
-
<script src="/builders/shell.js?v=2026-10-30-market-watch"></script>
|
|
77
|
+
<script src="/builders/shell.js?v=2026-10-30-market-watch-pages"></script>
|
|
78
78
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
79
79
|
<script src="/builders/palette.js" defer></script>
|
|
80
80
|
<script src="/builders/founding-mark.js?v=2026-09-30-founding"></script>
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
<script src="/builders/dom-utils.js?v=2026-10-25-escape"></script>
|
|
45
45
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
46
46
|
<script src="/builders/craft-mode.js?v=2026-10-30-market-watch"></script>
|
|
47
|
-
<script src="/builders/shell.js?v=2026-10-30-market-watch"></script>
|
|
47
|
+
<script src="/builders/shell.js?v=2026-10-30-market-watch-pages"></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,7 +56,7 @@
|
|
|
56
56
|
<script src="/builders/dom-utils.js?v=2026-10-25-escape"></script>
|
|
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-30-market-watch"></script>
|
|
59
|
-
<script src="/builders/shell.js?v=2026-10-30-market-watch"></script>
|
|
59
|
+
<script src="/builders/shell.js?v=2026-10-30-market-watch-pages"></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
|
<!-- the branding pack's currency label, loaded BEFORE roster.js. -->
|
|
@@ -112,7 +112,7 @@
|
|
|
112
112
|
<script src="/builders/dom-utils.js?v=2026-10-25-escape"></script>
|
|
113
113
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
114
114
|
<script src="/builders/craft-mode.js?v=2026-10-30-market-watch"></script>
|
|
115
|
-
<script src="/builders/shell.js?v=2026-10-30-market-watch"></script>
|
|
115
|
+
<script src="/builders/shell.js?v=2026-10-30-market-watch-pages"></script>
|
|
116
116
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
117
117
|
<script src="/builders/palette.js" defer></script>
|
|
118
118
|
<script src="/builders/task-detail.js?v=2026-07-03-taskdetail"></script>
|
|
@@ -487,7 +487,7 @@
|
|
|
487
487
|
<script src="/builders/dom-utils.js?v=2026-10-25-escape"></script>
|
|
488
488
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
489
489
|
<script src="/builders/craft-mode.js?v=2026-10-30-market-watch"></script>
|
|
490
|
-
<script src="/builders/shell.js?v=2026-10-30-market-watch"></script>
|
|
490
|
+
<script src="/builders/shell.js?v=2026-10-30-market-watch-pages"></script>
|
|
491
491
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
492
492
|
<script src="/builders/palette.js" defer></script>
|
|
493
493
|
<!-- shared component kit (window.OTBKit) — section rail (task 2166). -->
|
|
@@ -101,6 +101,7 @@
|
|
|
101
101
|
// the zen-garden reading of "a place an artist wants to be", so it does not
|
|
102
102
|
// reuse a glyph that would read as one more docs/goals page.
|
|
103
103
|
studio: '<path d="M9 15.5V8.5"/><path d="M9 8.5C9 5.5 6.5 3.5 3.5 3.5c0 3 2.5 5 5.5 5Z"/><path d="M9 10C9 7.5 11.2 5.5 14 5.5c0 2.7-2.2 4.5-5 4.5Z"/>',
|
|
104
|
+
marketwatch: '<circle cx="9" cy="9" r="6.5"/><path d="M9 9 13.6 4.4"/><path d="M9 5.2a3.8 3.8 0 1 0 3.8 3.8"/><circle cx="11.6" cy="11.2" r="0.9" fill="currentColor"/>',
|
|
104
105
|
// You
|
|
105
106
|
accomplishments: '<path d="M6 2.5l1.6 4.2M12 2.5l-1.6 4.2"/><circle cx="9" cy="10.8" r="4.2"/><circle cx="9" cy="10.8" r="1.8"/>',
|
|
106
107
|
profile: '<rect x="2.5" y="4" width="13" height="10" rx="1.5"/><circle cx="6.3" cy="8" r="1.6"/><path d="M4.1 12c.3-1.1 1.1-1.7 2.2-1.7s1.9.6 2.2 1.7"/><path d="M10.4 7.5h3M10.4 10.3h3"/>',
|
|
@@ -280,6 +281,7 @@
|
|
|
280
281
|
// the artist. NO module gate: it degrades to reviews alone on an instance
|
|
281
282
|
// without copy-desk, rather than vanishing.
|
|
282
283
|
{ id: 'studio', label: 'Studio', icon: 'studio', href: '/studio', gate: 'signed' },
|
|
284
|
+
{ id: 'market-watch', label: 'Market Watch', icon: 'marketwatch', href: '/market-watch', gate: 'signed', module: 'market-watch' }, // task 1004939: 'signed' is its page floor; dropped where the module is off
|
|
283
285
|
] },
|
|
284
286
|
// Your own numbers. task 2174 folded Achievements into Standing and this task
|
|
285
287
|
// retires its nav entry; VIEW_ALIASES still routes #achievements here, so old
|
|
@@ -428,7 +430,6 @@
|
|
|
428
430
|
}
|
|
429
431
|
|
|
430
432
|
// ---------- render ----------
|
|
431
|
-
|
|
432
433
|
function renderSidebar() {
|
|
433
434
|
var el = document.getElementById('app-sidebar');
|
|
434
435
|
if (!el) return;
|
|
@@ -1472,7 +1473,7 @@
|
|
|
1472
1473
|
// task 1004430: someone else's profile belongs to Builders, not to your own
|
|
1473
1474
|
// Profile; probeMe hands the mark back if the id turns out to be yours.
|
|
1474
1475
|
var otherProfile = path === '/profile' && /(^|[?&])id=/.test(window.location.search || '');
|
|
1475
|
-
if (otherProfile) path = '/roster';
|
|
1476
|
+
if (otherProfile) path = '/roster'; else if (/^\/market-watch-(item|rules)$/.test(path)) path = '/market-watch'; // task 1004939
|
|
1476
1477
|
document.querySelectorAll('#app-sidebar .nav-item').forEach(function (a) {
|
|
1477
1478
|
var target = a.getAttribute('href');
|
|
1478
1479
|
if (target && !a.dataset.view && target === path) a.classList.add('nav-item--active');
|
|
@@ -231,7 +231,7 @@
|
|
|
231
231
|
<script src="/builders/dom-utils.js?v=2026-10-25-escape"></script>
|
|
232
232
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
233
233
|
<script src="/builders/craft-mode.js?v=2026-10-30-market-watch"></script>
|
|
234
|
-
<script src="/builders/shell.js?v=2026-10-30-market-watch"></script>
|
|
234
|
+
<script src="/builders/shell.js?v=2026-10-30-market-watch-pages"></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>
|
|
@@ -219,7 +219,7 @@
|
|
|
219
219
|
<script src="/builders/dom-utils.js?v=2026-10-25-escape"></script>
|
|
220
220
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
221
221
|
<script src="/builders/craft-mode.js?v=2026-10-30-market-watch"></script>
|
|
222
|
-
<script src="/builders/shell.js?v=2026-10-30-market-watch"></script>
|
|
222
|
+
<script src="/builders/shell.js?v=2026-10-30-market-watch-pages"></script>
|
|
223
223
|
<script src="/builders/palette.js" defer></script>
|
|
224
224
|
<!-- The kit, for its ONE renderer: the full-size ship-time visual figure
|
|
225
225
|
(task 1003829), which the older reviews still show. -->
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
<script src="/builders/dom-utils.js?v=2026-10-25-escape"></script>
|
|
60
60
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
61
61
|
<script src="/builders/craft-mode.js?v=2026-10-30-market-watch"></script>
|
|
62
|
-
<script src="/builders/shell.js?v=2026-10-30-market-watch"></script>
|
|
62
|
+
<script src="/builders/shell.js?v=2026-10-30-market-watch-pages"></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
|
|
@@ -141,7 +141,7 @@
|
|
|
141
141
|
<script src="/builders/dom-utils.js?v=2026-10-25-escape"></script>
|
|
142
142
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
143
143
|
<script src="/builders/craft-mode.js?v=2026-10-30-market-watch"></script>
|
|
144
|
-
<script src="/builders/shell.js?v=2026-10-30-market-watch"></script>
|
|
144
|
+
<script src="/builders/shell.js?v=2026-10-30-market-watch-pages"></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>
|
|
@@ -145,7 +145,7 @@
|
|
|
145
145
|
<script src="/builders/dom-utils.js?v=2026-10-25-escape"></script>
|
|
146
146
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
147
147
|
<script src="/builders/craft-mode.js?v=2026-10-30-market-watch"></script>
|
|
148
|
-
<script src="/builders/shell.js?v=2026-10-30-market-watch"></script>
|
|
148
|
+
<script src="/builders/shell.js?v=2026-10-30-market-watch-pages"></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>
|
|
@@ -166,7 +166,7 @@
|
|
|
166
166
|
<script src="/builders/dom-utils.js?v=2026-10-25-escape"></script>
|
|
167
167
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
168
168
|
<script src="/builders/craft-mode.js?v=2026-10-30-market-watch"></script>
|
|
169
|
-
<script src="/builders/shell.js?v=2026-10-30-market-watch"></script>
|
|
169
|
+
<script src="/builders/shell.js?v=2026-10-30-market-watch-pages"></script>
|
|
170
170
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
171
171
|
<script src="/builders/palette.js" defer></script>
|
|
172
172
|
<!-- shared component kit (window.OTBKit) — tabs, ledger, pager (task 2166). -->
|
|
@@ -174,7 +174,7 @@
|
|
|
174
174
|
<script src="/builders/dom-utils.js?v=2026-10-25-escape"></script>
|
|
175
175
|
<script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
|
|
176
176
|
<script src="/builders/craft-mode.js?v=2026-10-30-market-watch"></script>
|
|
177
|
-
<script src="/builders/shell.js?v=2026-10-30-market-watch"></script>
|
|
177
|
+
<script src="/builders/shell.js?v=2026-10-30-market-watch-pages"></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 -->
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Market Watch — the watchtower desk (/market-watch) and the dossier (/market-watch-item) (task 1004939)
|
|
2
|
+
|
|
3
|
+
Goal 1000137, "Run a business in Bongos". The designs of record are the owner's picks of 2026-10-29:
|
|
4
|
+
`docs/design/mocks/market-watch/home.html` (option D) and `item.html` (option B). Both pages ride
|
|
5
|
+
`market-watch.css` plus `market-watch-lib.js` (the drawing both share), and read the market-watch
|
|
6
|
+
module's one route file, `modules/market-watch/routes/pages.js`.
|
|
7
|
+
|
|
8
|
+
**What the desk holds.** A link to the rules page (`/market-watch-rules`, task 1004941) under the streak; three scouts (competitors, partners, topics) as levelled cards, each with the
|
|
9
|
+
number of its items reported this week as the badge; the run streak; the landscape, every competitor as a
|
|
10
|
+
dot on two dimensions the viewer picks from the rules' own rubric (open-source ethos across and
|
|
11
|
+
contributor economy up by default, as the mock opens); the next sweep with the budget left as a tank;
|
|
12
|
+
and this week's reports, one per item, competitors and partners taken in turn because they are scored on
|
|
13
|
+
different scales. A report row links to the item; "ok" marks it read for this viewer only.
|
|
14
|
+
|
|
15
|
+
**What the dossier holds.** The item as a card that levels up run by run (level and streak are derived in
|
|
16
|
+
`modules/market-watch/db.js`), the overall line and one sparkline per rubric dimension, why it is watched,
|
|
17
|
+
its known facts, and the sortable case file (found, run, type, takeaway, confidence, source), filtered by type through the kit filter bar (`?type=` in the URL). Sparklines and the dimension bars are the kit's (`OTBKit.sparklineHtml`, `barSeriesHtml`); only the landscape scope is drawn here, since the kit has no scatter plot.
|
|
18
|
+
|
|
19
|
+
**Decisions a later edit must keep.**
|
|
20
|
+
|
|
21
|
+
- **No page head, no ask card.** The topbar names the page. Nothing here asks the reader to decide
|
|
22
|
+
something about the project, so there is no OTBAsk; proposals go to the government, which decides on
|
|
23
|
+
the rules page (task 1004941).
|
|
24
|
+
- **A dot is a picture, not a control.** Thirty-six 6–14px links failed the 24px floor and would overlap
|
|
25
|
+
at phone width. A click on a dot opens its file; the "open a case file" picker under the landscape
|
|
26
|
+
reaches every item by name, partners and topics included.
|
|
27
|
+
- **Every button that changes what is watched files a proposal.** Propose a change (re-score, move
|
|
28
|
+
between partner and competitor, add a source, correct an entry), Stop tracking (a `remove_item`) and
|
|
29
|
+
"+ send a new scout" (an `add_item`), each with a one-line reason. Nothing on these pages changes an
|
|
30
|
+
item, a score or an entry. The direction of a move comes from the item on the server, never the client.
|
|
31
|
+
- **Pin and "read" are the viewer's own** (localStorage `mw-pins`, `mw-read`): conveniences, not the
|
|
32
|
+
record. Pinned items list under the scouts.
|
|
33
|
+
- **"sweep now" is not here.** A manual run spends the project's AI budget, so it is the settings page's
|
|
34
|
+
(task 1004938) to offer with the cap beside it.
|
|
35
|
+
- **Off is quiet.** Where the default-off module is not enabled the nav item is dropped, the page shows
|
|
36
|
+
one line pointing at Modules, and it asks the server nothing; a 404 from unmounted routes reads the same.
|
|
37
|
+
|
|
38
|
+
**Verified** through `modules/ui-design/kit/render.js` against the hall-preview harness
|
|
39
|
+
(`--fixture-me --modules-on market-watch`), whose `market-watch__*.json` fixtures were built from the
|
|
40
|
+
committed seed through the real shapes. Tests: `tests/market_watch_pages.mjs`.
|