nexus-prime 7.9.28 → 7.9.30
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/dist/dashboard/app/api.js +30 -11
- package/dist/dashboard/app/index.html +28 -3
- package/dist/dashboard/app/main.js +34 -20
- package/dist/dashboard/app/state.js +4 -0
- package/dist/dashboard/app/styles/board.css +75 -0
- package/dist/dashboard/app/styles/context-log.css +154 -3
- package/dist/dashboard/app/styles/learning.css +204 -0
- package/dist/dashboard/app/styles/memory.css +169 -1
- package/dist/dashboard/app/styles/tokens.css +5 -0
- package/dist/dashboard/app/styles/workforce.css +51 -1
- package/dist/dashboard/app/views/board.js +96 -25
- package/dist/dashboard/app/views/context-log.js +130 -7
- package/dist/dashboard/app/views/learning.js +200 -0
- package/dist/dashboard/app/views/memory.js +139 -26
- package/dist/dashboard/app/views/repo.js +168 -5
- package/dist/dashboard/app/views/workforce.js +51 -8
- package/dist/dashboard/routes/events.js +71 -3
- package/dist/dashboard/routes/governance.js +16 -3
- package/dist/dashboard/routes/graph.js +50 -0
- package/dist/dashboard/routes/learning.d.ts +2 -0
- package/dist/dashboard/routes/learning.js +213 -0
- package/dist/dashboard/routes/run-artifacts.d.ts +5 -0
- package/dist/dashboard/routes/run-artifacts.js +107 -0
- package/dist/dashboard/routes/runtime.js +98 -38
- package/dist/dashboard/routes/surfaces.js +2 -1
- package/dist/dashboard/routes/workforce.js +47 -1
- package/dist/dashboard/selectors/operate-selector.js +105 -12
- package/dist/dashboard/server.js +2 -0
- package/dist/dashboard/types.d.ts +4 -1
- package/dist/engines/index.d.ts +2 -0
- package/dist/engines/index.js +1 -0
- package/dist/engines/learning/index.d.ts +1 -0
- package/dist/engines/learning/index.js +1 -0
- package/dist/engines/learning-network.d.ts +150 -0
- package/dist/engines/learning-network.js +452 -0
- package/dist/engines/orchestrator/decision-spine.d.ts +30 -3
- package/dist/engines/orchestrator/decision-spine.js +195 -23
- package/dist/phantom/runtime.d.ts +14 -0
- package/dist/phantom/runtime.js +144 -4
- package/dist/workforce/db/schema.d.ts +1 -1
- package/dist/workforce/db/schema.js +4 -2
- package/dist/workforce/index.d.ts +3 -2
- package/dist/workforce/index.js +3 -2
- package/dist/workforce/jobs.d.ts +1 -0
- package/dist/workforce/jobs.js +7 -0
- package/dist/workforce/kanban-view.js +15 -0
- package/dist/workforce/types.d.ts +2 -0
- package/package.json +1 -1
|
@@ -8,6 +8,18 @@
|
|
|
8
8
|
import { CACHE_TTL, S, bus } from './state.js';
|
|
9
9
|
|
|
10
10
|
const _cache = new Map();
|
|
11
|
+
const DEFAULT_TIMEOUT_MS = 5_000;
|
|
12
|
+
|
|
13
|
+
function _timeoutFor(url, override) {
|
|
14
|
+
if (Number.isFinite(Number(override))) return Number(override);
|
|
15
|
+
if (url.includes('/api/tokens/')) return 1_800;
|
|
16
|
+
if (url.includes('/api/license')) return 2_500;
|
|
17
|
+
if (url.includes('/api/runtimes')) return 3_000;
|
|
18
|
+
if (url.includes('/api/dashboard/surface/')) return 4_000;
|
|
19
|
+
if (url.includes('/api/dashboard/summary')) return 4_500;
|
|
20
|
+
if (url.includes('/api/knowledge-topology')) return 7_000;
|
|
21
|
+
return DEFAULT_TIMEOUT_MS;
|
|
22
|
+
}
|
|
11
23
|
|
|
12
24
|
function _scopedUrl(url) {
|
|
13
25
|
if (typeof url !== 'string' || !url.startsWith('/api/')) return url;
|
|
@@ -27,32 +39,39 @@ function _scopedUrl(url) {
|
|
|
27
39
|
* then kick off a background refresh. Callers get the fast synchronous hit
|
|
28
40
|
* for p50 <5ms; the next render cycle gets the fresh value.
|
|
29
41
|
*/
|
|
30
|
-
export async function api(url, ttl = CACHE_TTL) {
|
|
42
|
+
export async function api(url, ttl = CACHE_TTL, opts = {}) {
|
|
31
43
|
const requestUrl = _scopedUrl(url);
|
|
32
44
|
const hit = _cache.get(requestUrl);
|
|
33
45
|
const fresh = !hit || (Date.now() - hit.ts >= ttl);
|
|
34
46
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
47
|
+
if (hit) {
|
|
48
|
+
if (fresh) {
|
|
49
|
+
_fetch(requestUrl, opts).catch(() => {});
|
|
50
|
+
bus.emit('api:stale', { url: requestUrl, ageMs: Date.now() - hit.ts });
|
|
51
|
+
} else {
|
|
52
|
+
_fetch(requestUrl, opts).catch(() => {});
|
|
53
|
+
}
|
|
54
|
+
return hit.data;
|
|
41
55
|
}
|
|
42
56
|
|
|
43
|
-
return
|
|
57
|
+
return _fetch(requestUrl, opts);
|
|
44
58
|
}
|
|
45
59
|
|
|
46
|
-
async function _fetch(url) {
|
|
60
|
+
async function _fetch(url, opts = {}) {
|
|
61
|
+
const controller = new AbortController();
|
|
62
|
+
const timeout = setTimeout(() => controller.abort(), _timeoutFor(url, opts.timeoutMs));
|
|
47
63
|
try {
|
|
48
|
-
const r = await fetch(url);
|
|
64
|
+
const r = await fetch(url, { signal: controller.signal });
|
|
49
65
|
if (!r.ok) return null;
|
|
50
66
|
const d = await r.json();
|
|
51
67
|
_cache.set(url, { data: d, ts: Date.now() });
|
|
52
68
|
bus.emit('cache:updated', url);
|
|
53
69
|
return d;
|
|
54
|
-
} catch {
|
|
70
|
+
} catch (err) {
|
|
71
|
+
bus.emit('api:timeout', { url, error: err?.name === 'AbortError' ? 'timeout' : String(err?.message || err) });
|
|
55
72
|
return null;
|
|
73
|
+
} finally {
|
|
74
|
+
clearTimeout(timeout);
|
|
56
75
|
}
|
|
57
76
|
}
|
|
58
77
|
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
<link rel="stylesheet" href="./styles/workforce.css">
|
|
13
13
|
<link rel="stylesheet" href="./styles/memory.css">
|
|
14
14
|
<link rel="stylesheet" href="./styles/context-log.css">
|
|
15
|
+
<link rel="stylesheet" href="./styles/learning.css">
|
|
15
16
|
<link rel="stylesheet" href="./styles/governance.css">
|
|
16
17
|
<link rel="stylesheet" href="./styles/trust.css">
|
|
17
18
|
<link rel="stylesheet" href="./styles/animation.css">
|
|
@@ -56,6 +57,7 @@ if(location.protocol==='file:'){
|
|
|
56
57
|
<a class="nav-item" data-nav="runtime" href="#runtime">⚡ Runtime</a>
|
|
57
58
|
<a class="nav-item" data-nav="workforce" href="#workforce">Workforce</a>
|
|
58
59
|
<a class="nav-item" data-nav="memory" href="#memory">Memory</a>
|
|
60
|
+
<a class="nav-item" data-nav="learning" href="#learning">Learning</a>
|
|
59
61
|
<a class="nav-item" data-nav="context-log" href="#context-log">Context Log</a>
|
|
60
62
|
<a class="nav-item" data-nav="repo" href="#repo">Repo</a>
|
|
61
63
|
<a class="nav-item" data-nav="knowledge" href="#knowledge">Knowledge</a>
|
|
@@ -111,6 +113,8 @@ if(location.protocol==='file:'){
|
|
|
111
113
|
<div class="hero-stat"><div class="metric-val" id="m-ops">—</div><div class="metric-lbl">Operatives</div><canvas id="spark-ops" class="sparkline" width="80" height="24" aria-hidden="true"></canvas></div>
|
|
112
114
|
</div>
|
|
113
115
|
|
|
116
|
+
<div id="model-router-panel" class="model-router-panel card" aria-label="Model and context router"></div>
|
|
117
|
+
|
|
114
118
|
<!-- Live strip + kanban -->
|
|
115
119
|
<div id="agents-live-strip"></div>
|
|
116
120
|
<div id="kanban-board">
|
|
@@ -189,6 +193,7 @@ if(location.protocol==='file:'){
|
|
|
189
193
|
|
|
190
194
|
<div class="memory-toolbar">
|
|
191
195
|
<button class="btn btn-sm" id="mem-graph-max-btn">Maximize graph</button>
|
|
196
|
+
<button class="btn btn-sm" id="mem-graph-focus-btn">Focus selected</button>
|
|
192
197
|
<button class="btn btn-sm" id="mem-browse-btn">Browse memories</button>
|
|
193
198
|
</div>
|
|
194
199
|
<div id="graph-container" class="card">
|
|
@@ -228,13 +233,33 @@ if(location.protocol==='file:'){
|
|
|
228
233
|
<div id="context-log-view"></div>
|
|
229
234
|
</section>
|
|
230
235
|
|
|
236
|
+
<!-- LEARNING ───────────────────────────────────────────────── -->
|
|
237
|
+
<section class="view-panel" data-view="learning" aria-label="Learning network">
|
|
238
|
+
<div id="learning-view"></div>
|
|
239
|
+
</section>
|
|
240
|
+
|
|
231
241
|
<!-- REPO ───────────────────────────────────────────────────── -->
|
|
232
242
|
<section class="view-panel" data-view="repo" aria-label="Repo graph">
|
|
233
243
|
<div class="shd">Repo knowledge graph</div>
|
|
234
|
-
<div id="repo-graph-header"
|
|
244
|
+
<div id="repo-graph-header" class="repo-graph-header">
|
|
235
245
|
<span id="repo-graph-meta">—</span>
|
|
236
|
-
<
|
|
237
|
-
|
|
246
|
+
<div class="repo-graph-actions">
|
|
247
|
+
<button id="repo-build-btn" class="btn btn-sm">Build graph</button>
|
|
248
|
+
<button id="repo-memory-focus-btn" class="btn btn-sm">Memory overlay</button>
|
|
249
|
+
<input id="repo-search-input" class="repo-graph-search" type="text" placeholder="Search nodes…" autocomplete="off">
|
|
250
|
+
<div class="repo-graph-controls" aria-label="Repo graph navigation controls">
|
|
251
|
+
<button id="repo-zoom-out-btn" class="repo-graph-control" title="Zoom out">-</button>
|
|
252
|
+
<button id="repo-zoom-in-btn" class="repo-graph-control" title="Zoom in">+</button>
|
|
253
|
+
<button id="repo-fit-btn" class="repo-graph-control repo-graph-control-wide" title="Fit graph">Fit</button>
|
|
254
|
+
<button id="repo-reset-btn" class="repo-graph-control repo-graph-control-wide" title="Reset view">Reset</button>
|
|
255
|
+
<button id="repo-pan-left-btn" class="repo-graph-control" title="Pan left"><</button>
|
|
256
|
+
<button id="repo-pan-right-btn" class="repo-graph-control" title="Pan right">></button>
|
|
257
|
+
<button id="repo-pan-up-btn" class="repo-graph-control" title="Pan up">^</button>
|
|
258
|
+
<button id="repo-pan-down-btn" class="repo-graph-control" title="Pan down">v</button>
|
|
259
|
+
<button id="repo-graph-max-btn" class="repo-graph-control repo-graph-control-wide" title="Maximize graph">Max</button>
|
|
260
|
+
<span id="repo-viewport-badge" class="repo-viewport-badge">100%</span>
|
|
261
|
+
</div>
|
|
262
|
+
</div>
|
|
238
263
|
</div>
|
|
239
264
|
<div class="card" style="position:relative;overflow:hidden">
|
|
240
265
|
<div id="repo-graph-container" style="width:100%;height:480px;position:relative">
|
|
@@ -15,6 +15,7 @@ import { init as initCmdBar } from './widgets/command-bar.js';
|
|
|
15
15
|
import * as Board from './views/board.js';
|
|
16
16
|
import * as Workforce from './views/workforce.js';
|
|
17
17
|
import * as Memory from './views/memory.js';
|
|
18
|
+
import * as Learning from './views/learning.js';
|
|
18
19
|
import * as ContextLog from './views/context-log.js';
|
|
19
20
|
import * as Knowledge from './views/knowledge.js';
|
|
20
21
|
import * as Repo from './views/repo.js';
|
|
@@ -54,6 +55,7 @@ navRegister('board', Board.load);
|
|
|
54
55
|
navRegister('runtime', Runtime.load);
|
|
55
56
|
navRegister('workforce', Workforce.load);
|
|
56
57
|
navRegister('memory', Memory.load);
|
|
58
|
+
navRegister('learning', Learning.load);
|
|
57
59
|
navRegister('context-log', ContextLog.load);
|
|
58
60
|
navRegister('repo', Repo.load);
|
|
59
61
|
navRegister('knowledge', Knowledge.load);
|
|
@@ -89,6 +91,10 @@ setOnEvent(evt => {
|
|
|
89
91
|
if (tab === 'memory' && evt.category === 'memory') {
|
|
90
92
|
_refreshMemorySoon();
|
|
91
93
|
}
|
|
94
|
+
if (tab === 'learning' && (evt.category === 'memory' || String(evt.type||'').startsWith('orchestration.'))) {
|
|
95
|
+
bustCache('/api/learning/packets?limit=24');
|
|
96
|
+
Learning.load();
|
|
97
|
+
}
|
|
92
98
|
if (tab === 'governance' && evt.category === 'darwin') {
|
|
93
99
|
Governance.load();
|
|
94
100
|
}
|
|
@@ -123,6 +129,9 @@ setOnEvent(evt => {
|
|
|
123
129
|
if (tab === 'context-log') {
|
|
124
130
|
ContextLog.load();
|
|
125
131
|
}
|
|
132
|
+
if (tab === 'learning') {
|
|
133
|
+
Learning.load();
|
|
134
|
+
}
|
|
126
135
|
}
|
|
127
136
|
// Workspace root promoted (e.g. from bootstrap hint) — refresh header immediately.
|
|
128
137
|
if (String(evt.type||'') === 'workspace.changed') {
|
|
@@ -184,8 +193,9 @@ async function loadProjects() {
|
|
|
184
193
|
]);
|
|
185
194
|
S.projects = Array.isArray(projectsD) ? projectsD : (projectsD?.projects||[]);
|
|
186
195
|
S.runtimes = Array.isArray(runtimesD) ? runtimesD : (runtimesD?.runtimes||[]);
|
|
187
|
-
_selectDefaultRuntime();
|
|
196
|
+
const scopeChanged = _selectDefaultRuntime();
|
|
188
197
|
_renderProjectSelectors();
|
|
198
|
+
return scopeChanged;
|
|
189
199
|
}
|
|
190
200
|
|
|
191
201
|
async function loadCompanies() {
|
|
@@ -210,7 +220,7 @@ function _renderProjectSelectors() {
|
|
|
210
220
|
}
|
|
211
221
|
|
|
212
222
|
function _selectDefaultRuntime() {
|
|
213
|
-
if (S.scope.runtimeId || !(S.runtimes||[]).length) return;
|
|
223
|
+
if (S.scope.runtimeId || !(S.runtimes||[]).length) return false;
|
|
214
224
|
const current = S.workspace?.repoRoot || S.workspace?.workspaceRoot || '';
|
|
215
225
|
const candidates = (S.runtimes||[]).filter(r => r?.runtimeId);
|
|
216
226
|
const exact = current ? candidates.find(r => r.repoIdentity?.repoRoot === current) : null;
|
|
@@ -228,7 +238,10 @@ function _selectDefaultRuntime() {
|
|
|
228
238
|
return root && root !== '/';
|
|
229
239
|
});
|
|
230
240
|
const selected = (exact && !currentLooksLikeHome ? exact : null) || remoteRepo || deepestRepo || candidates[0];
|
|
231
|
-
|
|
241
|
+
const nextRuntimeId = selected?.runtimeId || null;
|
|
242
|
+
const changed = nextRuntimeId !== S.scope.runtimeId;
|
|
243
|
+
S.scope.runtimeId = nextRuntimeId;
|
|
244
|
+
return changed;
|
|
232
245
|
}
|
|
233
246
|
|
|
234
247
|
/* ─────────────────── Header / ticker ─────────────────── */
|
|
@@ -344,29 +357,30 @@ async function bootstrap() {
|
|
|
344
357
|
_renderHeader(false);
|
|
345
358
|
|
|
346
359
|
await loadWorkspace();
|
|
347
|
-
await loadProjects();
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
loadCompanies(),
|
|
353
|
-
loadRepoTree(),
|
|
354
|
-
api('/api/license', 60000),
|
|
355
|
-
]);
|
|
356
|
-
S.license = lic;
|
|
357
|
-
|
|
358
|
-
// Populate agent selector
|
|
359
|
-
const agentSel = $('ctx-agent');
|
|
360
|
-
if (agentSel && S.synapseHealth.length) {
|
|
361
|
-
agentSel.innerHTML = '<option value="">All agents</option>' +
|
|
362
|
-
S.synapseHealth.map(o=>`<option value="${esc(o.id||o.operativeId)}">${esc(o.role||o.name||o.id||'agent')}</option>`).join('');
|
|
360
|
+
const scopeChanged = await loadProjects();
|
|
361
|
+
if (scopeChanged) {
|
|
362
|
+
bustCache('/api/workspace');
|
|
363
|
+
bustCache('/api/repo-tree');
|
|
364
|
+
await loadWorkspace();
|
|
363
365
|
}
|
|
364
366
|
|
|
365
|
-
// Wire router
|
|
367
|
+
// Wire router before slow side panels. Each view owns progressive loading.
|
|
366
368
|
routerStart();
|
|
367
369
|
|
|
368
370
|
// Connect SSE stream — SSE drives all live updates; no polling needed.
|
|
369
371
|
connectSSE();
|
|
372
|
+
|
|
373
|
+
Promise.allSettled([
|
|
374
|
+
loadCompanies(),
|
|
375
|
+
loadRepoTree(),
|
|
376
|
+
api('/api/license', 60000, { timeoutMs: 2500 }).then(lic => { S.license = lic; }),
|
|
377
|
+
]).then(() => {
|
|
378
|
+
const agentSel = $('ctx-agent');
|
|
379
|
+
if (agentSel && S.synapseHealth.length) {
|
|
380
|
+
agentSel.innerHTML = '<option value="">All agents</option>' +
|
|
381
|
+
S.synapseHealth.map(o=>`<option value="${esc(o.id||o.operativeId)}">${esc(o.role||o.name||o.id||'agent')}</option>`).join('');
|
|
382
|
+
}
|
|
383
|
+
});
|
|
370
384
|
}
|
|
371
385
|
|
|
372
386
|
// Start when DOM is ready
|
|
@@ -86,6 +86,10 @@ export const S = {
|
|
|
86
86
|
contextLogRuns: [],
|
|
87
87
|
contextLogSelectedRunId: null,
|
|
88
88
|
contextLogSpine: null,
|
|
89
|
+
contextLogLearning: null,
|
|
90
|
+
learningSurface: null,
|
|
91
|
+
learningGraph: null,
|
|
92
|
+
learningSelectedPacketId: null,
|
|
89
93
|
|
|
90
94
|
// Neural Stream HUD ring buffer (latest SSE events, restored from v3.8.0)
|
|
91
95
|
neuralStream: [],
|
|
@@ -13,6 +13,81 @@
|
|
|
13
13
|
.hero-stat { padding: 18px 22px; background: var(--bg-elevated); transition: background 0.15s; }
|
|
14
14
|
.hero-stat:hover { background: var(--bg-panel); }
|
|
15
15
|
|
|
16
|
+
.model-router-panel {
|
|
17
|
+
margin: 0 0 16px;
|
|
18
|
+
padding: 14px;
|
|
19
|
+
background:
|
|
20
|
+
radial-gradient(circle at 18% 0%, rgba(0,212,255,0.12), transparent 30%),
|
|
21
|
+
radial-gradient(circle at 80% 10%, rgba(0,255,136,0.10), transparent 26%),
|
|
22
|
+
var(--bg-elevated);
|
|
23
|
+
overflow: hidden;
|
|
24
|
+
}
|
|
25
|
+
.model-router-head {
|
|
26
|
+
display: flex; justify-content: space-between; align-items: flex-start; gap: 12px;
|
|
27
|
+
margin-bottom: 10px;
|
|
28
|
+
}
|
|
29
|
+
.model-router-head span,
|
|
30
|
+
.model-lane-client {
|
|
31
|
+
display: block;
|
|
32
|
+
color: var(--text-dim);
|
|
33
|
+
font-family: var(--font-mono);
|
|
34
|
+
font-size: 0.68rem;
|
|
35
|
+
text-transform: uppercase;
|
|
36
|
+
letter-spacing: 0.06em;
|
|
37
|
+
}
|
|
38
|
+
.model-router-head strong {
|
|
39
|
+
display: block;
|
|
40
|
+
margin-top: 3px;
|
|
41
|
+
color: var(--text-main);
|
|
42
|
+
font: var(--title);
|
|
43
|
+
}
|
|
44
|
+
.model-router-lanes {
|
|
45
|
+
display: grid;
|
|
46
|
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
47
|
+
gap: 10px;
|
|
48
|
+
}
|
|
49
|
+
.model-lane {
|
|
50
|
+
min-height: 92px;
|
|
51
|
+
padding: 12px;
|
|
52
|
+
text-align: left;
|
|
53
|
+
color: var(--text-muted);
|
|
54
|
+
background: rgba(0,0,0,0.2);
|
|
55
|
+
border: 1px solid var(--border);
|
|
56
|
+
border-radius: var(--radius);
|
|
57
|
+
cursor: pointer;
|
|
58
|
+
transition: transform .24s var(--ease), border-color .24s var(--ease), background .24s var(--ease);
|
|
59
|
+
}
|
|
60
|
+
.model-lane:hover,
|
|
61
|
+
.model-lane.selected {
|
|
62
|
+
transform: translateY(-2px);
|
|
63
|
+
border-color: rgba(0,255,136,0.36);
|
|
64
|
+
background: rgba(0,255,136,0.06);
|
|
65
|
+
}
|
|
66
|
+
.model-lane strong {
|
|
67
|
+
display: block;
|
|
68
|
+
margin: 6px 0 2px;
|
|
69
|
+
color: var(--text-main);
|
|
70
|
+
font-family: var(--font-mono);
|
|
71
|
+
font-size: 1rem;
|
|
72
|
+
}
|
|
73
|
+
.model-lane small {
|
|
74
|
+
color: var(--text-dim);
|
|
75
|
+
font-family: var(--font-mono);
|
|
76
|
+
}
|
|
77
|
+
.model-router-reason {
|
|
78
|
+
margin-top: 10px;
|
|
79
|
+
color: var(--text-muted);
|
|
80
|
+
font-size: 0.78rem;
|
|
81
|
+
line-height: 1.45;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
@media (max-width: 900px) {
|
|
85
|
+
#hero-stats,
|
|
86
|
+
.model-router-lanes {
|
|
87
|
+
grid-template-columns: 1fr;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
16
91
|
/* ── Kanban ── */
|
|
17
92
|
#kanban-board {
|
|
18
93
|
display: grid; grid-template-columns: repeat(5, 1fr); gap: 10px;
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
.context-log-rail,
|
|
9
9
|
.context-log-summary,
|
|
10
|
+
.context-router-card,
|
|
10
11
|
.context-log-row,
|
|
11
12
|
.context-log-decision {
|
|
12
13
|
background: var(--bg-elevated);
|
|
@@ -69,7 +70,7 @@
|
|
|
69
70
|
|
|
70
71
|
.context-log-summary {
|
|
71
72
|
display: grid;
|
|
72
|
-
grid-template-columns: repeat(
|
|
73
|
+
grid-template-columns: repeat(7, minmax(82px, 1fr));
|
|
73
74
|
gap: 10px;
|
|
74
75
|
padding: 14px;
|
|
75
76
|
margin-bottom: 14px;
|
|
@@ -99,13 +100,91 @@
|
|
|
99
100
|
}
|
|
100
101
|
|
|
101
102
|
.context-log-selection > div,
|
|
102
|
-
.context-log-refs
|
|
103
|
+
.context-log-refs,
|
|
104
|
+
.context-log-changed {
|
|
103
105
|
display: flex;
|
|
104
106
|
flex-wrap: wrap;
|
|
105
107
|
gap: 4px;
|
|
106
108
|
min-width: 0;
|
|
107
109
|
}
|
|
108
110
|
|
|
111
|
+
.context-router-card {
|
|
112
|
+
padding: 13px 14px;
|
|
113
|
+
margin-bottom: 14px;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.context-router-card.context-router-advisory {
|
|
117
|
+
border-color: rgba(255,209,77,0.3);
|
|
118
|
+
background: linear-gradient(180deg, rgba(255,209,77,0.055), var(--bg-elevated));
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.context-router-card.context-router-changed {
|
|
122
|
+
border-color: rgba(0,255,136,0.3);
|
|
123
|
+
background: linear-gradient(180deg, rgba(0,255,136,0.055), var(--bg-elevated));
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.context-router-head {
|
|
127
|
+
display: flex;
|
|
128
|
+
justify-content: space-between;
|
|
129
|
+
align-items: flex-start;
|
|
130
|
+
gap: 14px;
|
|
131
|
+
margin-bottom: 8px;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.context-router-head span,
|
|
135
|
+
.context-router-grid span,
|
|
136
|
+
.context-log-changed > span {
|
|
137
|
+
display: block;
|
|
138
|
+
color: var(--text-dim);
|
|
139
|
+
font-family: var(--font-mono);
|
|
140
|
+
font-size: 0.68rem;
|
|
141
|
+
letter-spacing: 0.05em;
|
|
142
|
+
text-transform: uppercase;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.context-router-head strong {
|
|
146
|
+
display: block;
|
|
147
|
+
margin-top: 3px;
|
|
148
|
+
color: var(--text-main);
|
|
149
|
+
font-family: var(--font-mono);
|
|
150
|
+
font-size: 1rem;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.context-router-metrics {
|
|
154
|
+
display: flex;
|
|
155
|
+
flex-wrap: wrap;
|
|
156
|
+
justify-content: flex-end;
|
|
157
|
+
gap: 6px;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.context-router-metrics span {
|
|
161
|
+
padding: 4px 7px;
|
|
162
|
+
border: 1px solid var(--border);
|
|
163
|
+
border-radius: var(--radius);
|
|
164
|
+
background: rgba(0,0,0,0.18);
|
|
165
|
+
color: var(--text-muted);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.context-router-card p {
|
|
169
|
+
margin: 0 0 11px;
|
|
170
|
+
color: var(--text-muted);
|
|
171
|
+
font-size: 0.8rem;
|
|
172
|
+
line-height: 1.45;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.context-router-grid {
|
|
176
|
+
display: grid;
|
|
177
|
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
178
|
+
gap: 10px;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.context-router-grid > div {
|
|
182
|
+
display: flex;
|
|
183
|
+
flex-wrap: wrap;
|
|
184
|
+
gap: 5px;
|
|
185
|
+
min-width: 0;
|
|
186
|
+
}
|
|
187
|
+
|
|
109
188
|
.context-log-grid {
|
|
110
189
|
display: grid;
|
|
111
190
|
grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
|
|
@@ -142,6 +221,15 @@
|
|
|
142
221
|
line-height: 1.45;
|
|
143
222
|
}
|
|
144
223
|
|
|
224
|
+
.context-log-changed {
|
|
225
|
+
margin-top: 7px;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
.context-log-changed > span {
|
|
229
|
+
width: 100%;
|
|
230
|
+
margin-bottom: 2px;
|
|
231
|
+
}
|
|
232
|
+
|
|
145
233
|
.context-log-decision strong {
|
|
146
234
|
display: block;
|
|
147
235
|
margin-bottom: 6px;
|
|
@@ -150,6 +238,68 @@
|
|
|
150
238
|
line-height: 1.35;
|
|
151
239
|
}
|
|
152
240
|
|
|
241
|
+
.context-link-chip {
|
|
242
|
+
cursor: pointer;
|
|
243
|
+
font: var(--caption-role);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
.context-link-chip[data-context-target] {
|
|
247
|
+
border-color: rgba(0,212,255,0.28);
|
|
248
|
+
background: rgba(0,212,255,0.06);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
.context-link-chip[data-context-target]:hover {
|
|
252
|
+
color: var(--text-main);
|
|
253
|
+
border-color: rgba(0,255,136,0.36);
|
|
254
|
+
background: rgba(0,255,136,0.08);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
.context-learning-card {
|
|
258
|
+
padding: 12px;
|
|
259
|
+
margin-bottom: 14px;
|
|
260
|
+
border: 1px solid rgba(0,255,136,0.16);
|
|
261
|
+
border-radius: var(--radius);
|
|
262
|
+
background: linear-gradient(180deg, rgba(0,255,136,0.05), rgba(0,212,255,0.025));
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
.context-learning-list {
|
|
266
|
+
display: grid;
|
|
267
|
+
gap: 8px;
|
|
268
|
+
margin-top: 10px;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
.context-learning-item {
|
|
272
|
+
padding: 9px 10px;
|
|
273
|
+
border: 1px solid var(--border);
|
|
274
|
+
border-radius: var(--radius);
|
|
275
|
+
background: rgba(0,0,0,0.18);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
.context-learning-item span {
|
|
279
|
+
color: var(--secondary);
|
|
280
|
+
font-family: var(--font-mono);
|
|
281
|
+
font-size: 0.68rem;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
.context-learning-item strong,
|
|
285
|
+
.context-learning-item em {
|
|
286
|
+
display: block;
|
|
287
|
+
margin-top: 4px;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
.context-learning-item strong {
|
|
291
|
+
color: var(--text-main);
|
|
292
|
+
font-size: 0.8rem;
|
|
293
|
+
line-height: 1.35;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
.context-learning-item em {
|
|
297
|
+
color: var(--text-muted);
|
|
298
|
+
font-size: 0.74rem;
|
|
299
|
+
font-style: normal;
|
|
300
|
+
line-height: 1.45;
|
|
301
|
+
}
|
|
302
|
+
|
|
153
303
|
.context-log-empty {
|
|
154
304
|
color: var(--text-dim);
|
|
155
305
|
font-size: 0.72rem;
|
|
@@ -158,7 +308,8 @@
|
|
|
158
308
|
@media (max-width: 980px) {
|
|
159
309
|
.context-log-shell,
|
|
160
310
|
.context-log-grid,
|
|
161
|
-
.context-log-selection
|
|
311
|
+
.context-log-selection,
|
|
312
|
+
.context-router-grid {
|
|
162
313
|
grid-template-columns: 1fr;
|
|
163
314
|
}
|
|
164
315
|
.context-log-summary {
|