diff --git a/docs/devteam/dashboard/index.html b/docs/devteam/dashboard/index.html index 70b9b1d..ce35ac9 100644 --- a/docs/devteam/dashboard/index.html +++ b/docs/devteam/dashboard/index.html @@ -95,6 +95,14 @@ .stat b { display: block; font-size: 20px; font-weight: 600; letter-spacing: -.02em; margin-top: 2px; font-variant-numeric: tabular-nums; } .card { background: var(--surface); border: 1px solid var(--line); border-radius: 8px; padding: 14px 16px; margin-bottom: 8px; box-shadow: var(--shadow); } .card.small { padding: 10px 12px; } + .card[data-open] { cursor: pointer; } + .card[data-open]:hover { background: var(--hover); } + .place { font-size: 12px; color: var(--fg-2); margin-top: 3px; } + .lineage .diagram svg { max-width: 100%; height: auto; } + .lineage a.lineage-node { cursor: pointer; } + .lineage a.lineage-node:focus-visible { outline: 2px solid var(--blue-fg); outline-offset: 2px; } + .lineage-list h4 { margin: 8px 0 2px; font-size: 12px; color: var(--fg-2); } + .lineage-list ul { margin: 0 0 4px; } .card p { margin: 6px 0; } .two { display: grid; gap: 16px; grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr)); } @@ -640,6 +648,9 @@
What the signal adds up to. Things noticed more than once become recurring signals; real or likely trouble becomes a problem; lessons, facts and your preferences become knowledge, which goes into every agent's instructions once accepted.
+Recurring signals nothing has explained for more than a day: each wants a lesson, a problem, or a ruling that it is noise.
+${esc(id.slice(0, 22))}…`;
if (k === 'g' && goalOf(id)) return glink(id);
return `${esc(id.slice(0, 22))}…`;
@@ -2090,18 +2101,21 @@ ${cand.length} proposed lesson${cand.length > 1 ? 's are' : ' is'} waiting for you in the Inbox.
` : '') + - (acc.length ? acc.map((k) => `sensors), and polls them while it runs.');
for (const m of ms.filter((x) => x.kind === 'http')) loadSensorSeries(m.name);
$('incidents').innerHTML = incidentBoard(d.incidents || []);
- for (const b of $('incidents').querySelectorAll('[data-open]')) b.onclick = () => { location.hash = b.dataset.open; };
const feed = d.sensor_feed || [];
$('sensor-exceptions').innerHTML = feed.length ? `${v.detail}
` : ''} + ${lineageBlock(p)} ${d ? `It carried out a decision: correct the decision if the call was wrong (Loop → Decide). If the call was sound and the act went wrong, that is a problem, not a trust drop.
' : 'To correct it, use Correct on it in Loop → Act.
'} @@ -2935,6 +2951,7 @@Nothing yet.
'}` : ''} ${r.correction ? '' : 'To correct it, use Correct on it in Loop → Decide.
'} @@ -2997,10 +3014,163 @@Keep or retire it in the Inbox
' : ''} + ${lineageBlock(p)} ${obs.length ? `Only the nearest steps are shown: it goes on further.
' : ''}`; +} +const clip = (x, n) => { const t = String(x ?? ''); return t.length > n ? `${t.slice(0, n)}…` : t; }; +const hoursWords = (h) => (h < 48 ? `${h} hour${h === 1 ? '' : 's'}` : `${Math.floor(h / 24)} days`); +function openObservation(id) { + drawerFor('observation', id); + const p = peekOf('observation', id); + const card = (DATA.ooda.observations || []).find((x) => x.id === id); + const o = card || (p?.record ? { ...p.record.fields, id, created_by: p.record.created_by, created_at: p.record.created_at } : null); + if (!o) return notFound('observation', id, p, p?.error ? 'No such observation.' : ''); + const pv = card?.provenance ?? p?.provenance; + const place = p && p.place !== undefined ? p.place : card?.place; + showDrawer(`${fromWords(pv, o)}
` : ''} + ${attrs({ id, peek: p, type: 'observation', computed: [ + ['Where it sits', loopPlace(place), 'Where it is in the loop: not oriented yet, part of a recurring signal, explained, ruled noise, set aside, or carried on to a decision, an act or an outcome.'], + ['Stage', esc(words(card?.stage ?? p?.stage ?? '')), 'Which stage of the loop it is in: observe, orient, decide, act or learn.'], + ] })} +${linkify(o.detail)}
+ ${lineageBlock(p)} + ${citedBlock(p, o)} + ${historySection(p, id)}`); +} +// A recurring signal is computed, not stored: what nothing explains yet on one key. +const signalTitle = (key) => `${words(key.split(':')[0])} ${key.split(':').slice(1).join(':')}`.trim(); +function openSignal(key) { + drawerFor('signal', key); + const p = peekOf('signal', key); + const c = (DATA.ooda.clusters || []).find((x) => x.key === key); + const s = p?.signal; + if (!s && !c) return notFound('signal', key, p, p?.error ? 'Nothing recurs on this key now: it was explained, or never recurred.' : '', { noRecord: true }); + const items = s?.items ?? []; + showDrawer(`${linkify(c.latest)}
` : ''} +Loading…
' : empty('None unexplained.')} + ${lineageBlock(p)} + ${s?.explain?.length ? `With what it teaches, or a ruling that it is noise; you can correct either.
${s.explain.map((x) => `${esc(x)}`).join('')}${linkify(f.detail)}
` : ''} + ${lineageBlock(p)} + ${historySection(p, id)}`); +} // An incident's part of the problem drawer: its stage and authority, its fingerprints, the fix // ticket, and (folded, framed as untrusted) the latest event of each fingerprint. function incidentSection(inc, p) { @@ -3029,6 +3199,7 @@