nexus-prime 7.9.14 → 7.9.15
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/agents/adapters/mcp.d.ts +2 -0
- package/dist/agents/adapters/mcp.js +58 -6
- package/dist/cli/install-wizard.js +19 -0
- package/dist/cli.js +28 -1
- package/dist/dashboard/app/index.html +8 -0
- package/dist/dashboard/app/main.js +7 -0
- package/dist/dashboard/app/state.js +5 -0
- package/dist/dashboard/app/styles/board.css +163 -2
- package/dist/dashboard/app/styles/context-log.css +167 -0
- package/dist/dashboard/app/styles/memory.css +63 -0
- package/dist/dashboard/app/styles/workforce.css +21 -0
- package/dist/dashboard/app/views/board.js +145 -7
- package/dist/dashboard/app/views/context-log.js +158 -0
- package/dist/dashboard/app/views/memory.js +87 -3
- package/dist/dashboard/app/views/workforce.js +22 -6
- package/dist/dashboard/routes/events.js +80 -3
- package/dist/dashboard/stream/sse-broker.js +25 -13
- package/dist/engines/client-bootstrap.js +66 -20
- package/dist/engines/code-review-graph-client.d.ts +11 -3
- package/dist/engines/code-review-graph-client.js +151 -24
- package/dist/engines/instruction-gateway.js +6 -0
- package/dist/engines/mcp-entrypoint.js +3 -1
- package/dist/engines/orchestrator/decision-spine.d.ts +170 -0
- package/dist/engines/orchestrator/decision-spine.js +424 -0
- package/dist/engines/orchestrator/selection-policy.d.ts +39 -0
- package/dist/engines/orchestrator/selection-policy.js +32 -0
- package/dist/engines/orchestrator.js +19 -33
- package/dist/phantom/runtime.d.ts +16 -0
- package/dist/phantom/runtime.js +158 -20
- package/package.json +2 -2
|
@@ -20,6 +20,7 @@ export declare class MCPAdapter implements Adapter {
|
|
|
20
20
|
private currentTask;
|
|
21
21
|
private middlewarePipeline;
|
|
22
22
|
private scanCache;
|
|
23
|
+
private sessionLifecycleFinalized;
|
|
23
24
|
private sciFiMatrixLog;
|
|
24
25
|
private classifyToolCategory;
|
|
25
26
|
private sciFiToolHeader;
|
|
@@ -83,6 +84,7 @@ export declare class MCPAdapter implements Adapter {
|
|
|
83
84
|
private extractFileRefsFromArgs;
|
|
84
85
|
scanSourceFiles(cwd: string): Promise<string[]>;
|
|
85
86
|
connect(): Promise<void>;
|
|
87
|
+
private finalizeSessionLifecycle;
|
|
86
88
|
disconnect(): Promise<void>;
|
|
87
89
|
send(message: NetworkMessage): Promise<void>;
|
|
88
90
|
receive(message: NetworkMessage): void;
|
|
@@ -160,6 +160,7 @@ export class MCPAdapter {
|
|
|
160
160
|
currentTask = '';
|
|
161
161
|
middlewarePipeline;
|
|
162
162
|
scanCache = new Map();
|
|
163
|
+
sessionLifecycleFinalized = false;
|
|
163
164
|
sciFiMatrixLog(title, metrics, intent) {
|
|
164
165
|
const width = 76;
|
|
165
166
|
console.error(`\n\x1b[36m╔═══ [ \x1b[37m\x1b[1mNEXUS PRIME · ORCHESTRATION MATRIX\x1b[0m\x1b[36m ] ${'═'.repeat(Math.max(0, width - 48))}╗\x1b[0m`);
|
|
@@ -876,6 +877,9 @@ export class MCPAdapter {
|
|
|
876
877
|
}
|
|
877
878
|
else {
|
|
878
879
|
this.telemetry.observeSuccessfulToolCall(toolName, args);
|
|
880
|
+
if (toolName === 'nexus_session_dna' && String(args.action ?? 'load') === 'generate') {
|
|
881
|
+
this.sessionLifecycleFinalized = true;
|
|
882
|
+
}
|
|
879
883
|
}
|
|
880
884
|
}
|
|
881
885
|
// Surface meaningful tool calls on the SSE feed; persist only high-signal outcomes.
|
|
@@ -1159,22 +1163,70 @@ export class MCPAdapter {
|
|
|
1159
1163
|
startWatchdog();
|
|
1160
1164
|
console.error('[MCP Adapter] Connected — runtime tools active');
|
|
1161
1165
|
}
|
|
1162
|
-
async
|
|
1163
|
-
|
|
1166
|
+
async finalizeSessionLifecycle(reason) {
|
|
1167
|
+
if (this.sessionLifecycleFinalized && reason !== 'explicit')
|
|
1168
|
+
return;
|
|
1169
|
+
const telemetry = this.telemetry.snapshot();
|
|
1170
|
+
try {
|
|
1171
|
+
const promoted = this.nexusRef?.runTierPromotion?.();
|
|
1172
|
+
if (promoted)
|
|
1173
|
+
nexusEventBus.emit('memory.tier.promoted', promoted);
|
|
1174
|
+
}
|
|
1175
|
+
catch (e) {
|
|
1176
|
+
nexusEventBus.emit('mcp.handler.failed', {
|
|
1177
|
+
toolName: 'nexus_session_dna.disconnect.tierPromotion',
|
|
1178
|
+
code: 'internal',
|
|
1179
|
+
attempts: 1,
|
|
1180
|
+
durationMs: 0,
|
|
1181
|
+
});
|
|
1182
|
+
console.error('[MCP Adapter] Failed to run Session DNA tier promotion:', e);
|
|
1183
|
+
}
|
|
1164
1184
|
try {
|
|
1165
|
-
const telemetry = this.telemetry.snapshot();
|
|
1166
1185
|
this.sessionDNA.syncFromTelemetry({
|
|
1167
1186
|
callCount: telemetry.callCount,
|
|
1168
1187
|
memoriesStored: telemetry.memoriesStored,
|
|
1169
1188
|
memoriesRecalled: telemetry.memoriesRecalled,
|
|
1170
1189
|
tokensOptimized: telemetry.tokensOptimized,
|
|
1171
1190
|
});
|
|
1172
|
-
this.sessionDNA.flush();
|
|
1173
|
-
|
|
1191
|
+
const dna = this.sessionDNA.flush();
|
|
1192
|
+
this.sessionLifecycleFinalized = true;
|
|
1193
|
+
try {
|
|
1194
|
+
const runtimeTokens = this.runtime?.getUsageSnapshot().tokens?.grossInputTokens ?? 0;
|
|
1195
|
+
this.getOrchestrator({}).persistSessionSummary(telemetry.tokensOptimized || runtimeTokens || 0);
|
|
1196
|
+
}
|
|
1197
|
+
catch (e) {
|
|
1198
|
+
nexusEventBus.emit('mcp.handler.failed', {
|
|
1199
|
+
toolName: 'nexus_session_dna.disconnect.persistSessionSummary',
|
|
1200
|
+
code: 'internal',
|
|
1201
|
+
attempts: 1,
|
|
1202
|
+
durationMs: 0,
|
|
1203
|
+
});
|
|
1204
|
+
console.error('[MCP Adapter] Failed to persist Session DNA summary:', e);
|
|
1205
|
+
}
|
|
1206
|
+
await getSharedTelemetry().trackSessionEnd(this.telemetry.elapsedMs(), {
|
|
1207
|
+
projectId: this.nexusRef?.getWorkspaceContext?.()?.repoRoot ?? '',
|
|
1208
|
+
tokensSaved: telemetry.tokensOptimized,
|
|
1209
|
+
memoriesCreated: telemetry.memoriesStored,
|
|
1210
|
+
memoriesRecalled: telemetry.memoriesRecalled,
|
|
1211
|
+
toolsUsed: telemetry.callCount,
|
|
1212
|
+
sessionId: dna.sessionId,
|
|
1213
|
+
}).catch((e) => {
|
|
1214
|
+
nexusEventBus.emit('mcp.handler.failed', {
|
|
1215
|
+
toolName: 'nexus_session_dna.disconnect.trackSessionEnd',
|
|
1216
|
+
code: 'internal',
|
|
1217
|
+
attempts: 1,
|
|
1218
|
+
durationMs: 0,
|
|
1219
|
+
});
|
|
1220
|
+
console.error('[MCP Adapter] Failed to track Session DNA session end:', e);
|
|
1221
|
+
});
|
|
1222
|
+
console.error(`[MCP Adapter] Session DNA finalized on ${reason}`);
|
|
1174
1223
|
}
|
|
1175
1224
|
catch (e) {
|
|
1176
|
-
console.error('[MCP Adapter] Failed to
|
|
1225
|
+
console.error('[MCP Adapter] Failed to finalize Session DNA:', e);
|
|
1177
1226
|
}
|
|
1227
|
+
}
|
|
1228
|
+
async disconnect() {
|
|
1229
|
+
await this.finalizeSessionLifecycle('disconnect');
|
|
1178
1230
|
await this.server.close();
|
|
1179
1231
|
this.connected = false;
|
|
1180
1232
|
console.error('[MCP Adapter] Disconnected');
|
|
@@ -159,6 +159,21 @@ function _writeClaudeCodeHooks(workspaceRoot) {
|
|
|
159
159
|
});
|
|
160
160
|
});
|
|
161
161
|
}
|
|
162
|
+
function _isManagedGraphPeer(server) {
|
|
163
|
+
if (!server || typeof server !== 'object' || Array.isArray(server))
|
|
164
|
+
return false;
|
|
165
|
+
const record = server;
|
|
166
|
+
const args = Array.isArray(record.args) ? record.args.map(String) : [];
|
|
167
|
+
return record.command === 'goatlas' && args.length === 1 && args[0] === 'mcp';
|
|
168
|
+
}
|
|
169
|
+
function _stripInternalGraphPeers(mcpServers) {
|
|
170
|
+
if (!mcpServers)
|
|
171
|
+
return;
|
|
172
|
+
delete mcpServers['code-review-graph'];
|
|
173
|
+
if (_isManagedGraphPeer(mcpServers['atlas'])) {
|
|
174
|
+
delete mcpServers['atlas'];
|
|
175
|
+
}
|
|
176
|
+
}
|
|
162
177
|
/**
|
|
163
178
|
* Write workspace-local MCP config files for IDEs whose workspace directories
|
|
164
179
|
* already exist (`.vscode/`, `.cursor/`). Non-fatal; errors are swallowed.
|
|
@@ -181,6 +196,7 @@ function _writeWorkspaceLocalConfigs(callerIde, workspaceRoot) {
|
|
|
181
196
|
? settings.mcpServers
|
|
182
197
|
: {};
|
|
183
198
|
servers['nexus-prime'] = entry;
|
|
199
|
+
_stripInternalGraphPeers(servers);
|
|
184
200
|
settings.mcpServers = servers;
|
|
185
201
|
writeFileSync(settingsPath, JSON.stringify(settings, null, 2), 'utf8');
|
|
186
202
|
appendToManifest((m) => {
|
|
@@ -212,6 +228,7 @@ function _writeWorkspaceLocalConfigs(callerIde, workspaceRoot) {
|
|
|
212
228
|
? mcp.mcpServers
|
|
213
229
|
: {};
|
|
214
230
|
servers['nexus-prime'] = entry;
|
|
231
|
+
_stripInternalGraphPeers(servers);
|
|
215
232
|
mcp.mcpServers = servers;
|
|
216
233
|
writeFileSync(mcpPath, JSON.stringify(mcp, null, 2), 'utf8');
|
|
217
234
|
appendToManifest((m) => {
|
|
@@ -347,6 +364,7 @@ function mergeIntoExistingConfig(configPath, newContent, ide) {
|
|
|
347
364
|
...(existing.mcpServers ?? {}),
|
|
348
365
|
...(incoming.mcpServers ?? {}),
|
|
349
366
|
};
|
|
367
|
+
_stripInternalGraphPeers(existing.mcpServers);
|
|
350
368
|
return JSON.stringify(existing, null, 2);
|
|
351
369
|
}
|
|
352
370
|
if (ide === 'claude-code') {
|
|
@@ -362,6 +380,7 @@ function mergeIntoExistingConfig(configPath, newContent, ide) {
|
|
|
362
380
|
...(existing.mcpServers ?? {}),
|
|
363
381
|
...(incoming.mcpServers ?? {}),
|
|
364
382
|
};
|
|
383
|
+
_stripInternalGraphPeers(existing.mcpServers);
|
|
365
384
|
}
|
|
366
385
|
return JSON.stringify(existing, null, 2);
|
|
367
386
|
}
|
package/dist/cli.js
CHANGED
|
@@ -197,9 +197,25 @@ function writeStandardMcpConfig(targetPath, workspaceRoot) {
|
|
|
197
197
|
const existing = readJson(targetPath);
|
|
198
198
|
existing.mcpServers = existing.mcpServers ?? {};
|
|
199
199
|
existing.mcpServers['nexus-prime'] = buildStandardMcpServerConfig(workspaceRoot);
|
|
200
|
+
delete existing.mcpServers['code-review-graph'];
|
|
201
|
+
if (isNexusManagedGraphPeer(existing.mcpServers['atlas'])) {
|
|
202
|
+
delete existing.mcpServers['atlas'];
|
|
203
|
+
}
|
|
200
204
|
ensureParentDir(targetPath);
|
|
201
205
|
writeFileSync(targetPath, JSON.stringify(existing, null, 2));
|
|
202
206
|
}
|
|
207
|
+
function isNexusManagedGraphPeer(server) {
|
|
208
|
+
if (!server || typeof server !== 'object' || Array.isArray(server))
|
|
209
|
+
return false;
|
|
210
|
+
const record = server;
|
|
211
|
+
const args = Array.isArray(record['args']) ? record['args'].map(String) : [];
|
|
212
|
+
return record['command'] === 'goatlas' && args.length === 1 && args[0] === 'mcp';
|
|
213
|
+
}
|
|
214
|
+
function jsonExposesInternalGraphPeer(parsed) {
|
|
215
|
+
const servers = parsed?.mcpServers ?? parsed?.mcp ?? {};
|
|
216
|
+
return Boolean(servers?.['code-review-graph']
|
|
217
|
+
|| isNexusManagedGraphPeer(servers?.['atlas']));
|
|
218
|
+
}
|
|
203
219
|
function writeOpencodeConfig(targetPath, workspaceRoot) {
|
|
204
220
|
const existing = readJson(targetPath);
|
|
205
221
|
const mcpConfig = buildStandardMcpServerConfig(workspaceRoot);
|
|
@@ -428,6 +444,15 @@ function buildInstructionFiles(clientId) {
|
|
|
428
444
|
content: artifact.content,
|
|
429
445
|
}));
|
|
430
446
|
}
|
|
447
|
+
function resolveClaudeDesktopConfigPath() {
|
|
448
|
+
if (process.platform === 'darwin') {
|
|
449
|
+
return join(homedir(), 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json');
|
|
450
|
+
}
|
|
451
|
+
if (process.platform === 'win32') {
|
|
452
|
+
return join(process.env.APPDATA || join(homedir(), 'AppData', 'Roaming'), 'Claude', 'claude_desktop_config.json');
|
|
453
|
+
}
|
|
454
|
+
return join(homedir(), '.claude', 'claude_desktop_config.json');
|
|
455
|
+
}
|
|
431
456
|
function getSetupDefinition(clientId) {
|
|
432
457
|
const instructionFiles = buildInstructionFiles(clientId);
|
|
433
458
|
if (clientId === 'codex') {
|
|
@@ -458,7 +483,7 @@ function getSetupDefinition(clientId) {
|
|
|
458
483
|
return {
|
|
459
484
|
id: clientId,
|
|
460
485
|
label: 'Claude Desktop',
|
|
461
|
-
configPath:
|
|
486
|
+
configPath: resolveClaudeDesktopConfigPath(),
|
|
462
487
|
instructionFiles,
|
|
463
488
|
};
|
|
464
489
|
}
|
|
@@ -583,6 +608,8 @@ function hasExpectedConfig(definition) {
|
|
|
583
608
|
}
|
|
584
609
|
try {
|
|
585
610
|
const parsed = JSON.parse(readFileSync(definition.configPath, 'utf8'));
|
|
611
|
+
if (jsonExposesInternalGraphPeer(parsed))
|
|
612
|
+
return false;
|
|
586
613
|
if (definition.id === 'opencode') {
|
|
587
614
|
const server = parsed?.mcp?.['nexus-prime'];
|
|
588
615
|
return Boolean(server && isStableNexusMcpServerConfig(server, 'environment'));
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
<link rel="stylesheet" href="./styles/board.css">
|
|
12
12
|
<link rel="stylesheet" href="./styles/workforce.css">
|
|
13
13
|
<link rel="stylesheet" href="./styles/memory.css">
|
|
14
|
+
<link rel="stylesheet" href="./styles/context-log.css">
|
|
14
15
|
<link rel="stylesheet" href="./styles/governance.css">
|
|
15
16
|
<link rel="stylesheet" href="./styles/trust.css">
|
|
16
17
|
<link rel="stylesheet" href="./styles/animation.css">
|
|
@@ -55,6 +56,7 @@ if(location.protocol==='file:'){
|
|
|
55
56
|
<a class="nav-item" data-nav="runtime" href="#runtime">⚡ Runtime</a>
|
|
56
57
|
<a class="nav-item" data-nav="workforce" href="#workforce">Workforce</a>
|
|
57
58
|
<a class="nav-item" data-nav="memory" href="#memory">Memory</a>
|
|
59
|
+
<a class="nav-item" data-nav="context-log" href="#context-log">Context Log</a>
|
|
58
60
|
<a class="nav-item" data-nav="repo" href="#repo">Repo</a>
|
|
59
61
|
<a class="nav-item" data-nav="knowledge" href="#knowledge">Knowledge</a>
|
|
60
62
|
<a class="nav-item" data-nav="governance" href="#governance">Governance</a>
|
|
@@ -214,12 +216,18 @@ if(location.protocol==='file:'){
|
|
|
214
216
|
<input id="mem-search" type="text" placeholder="Search memories…" aria-label="Search memories">
|
|
215
217
|
<button class="btn btn-sm" id="mem-list-browse-btn">Browse</button>
|
|
216
218
|
</div>
|
|
219
|
+
<div id="memory-selection-panel" class="memory-selection-panel"></div>
|
|
217
220
|
<div id="mem-list"></div>
|
|
218
221
|
</div>
|
|
219
222
|
<div class="card"><div id="mem-stats"></div></div>
|
|
220
223
|
</div>
|
|
221
224
|
</section>
|
|
222
225
|
|
|
226
|
+
<!-- CONTEXT LOG ────────────────────────────────────────────── -->
|
|
227
|
+
<section class="view-panel" data-view="context-log" aria-label="Context log">
|
|
228
|
+
<div id="context-log-view"></div>
|
|
229
|
+
</section>
|
|
230
|
+
|
|
223
231
|
<!-- REPO ───────────────────────────────────────────────────── -->
|
|
224
232
|
<section class="view-panel" data-view="repo" aria-label="Repo graph">
|
|
225
233
|
<div class="shd">Repo knowledge graph</div>
|
|
@@ -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 ContextLog from './views/context-log.js';
|
|
18
19
|
import * as Knowledge from './views/knowledge.js';
|
|
19
20
|
import * as Repo from './views/repo.js';
|
|
20
21
|
import * as Governance from './views/governance.js';
|
|
@@ -53,6 +54,7 @@ navRegister('board', Board.load);
|
|
|
53
54
|
navRegister('runtime', Runtime.load);
|
|
54
55
|
navRegister('workforce', Workforce.load);
|
|
55
56
|
navRegister('memory', Memory.load);
|
|
57
|
+
navRegister('context-log', ContextLog.load);
|
|
56
58
|
navRegister('repo', Repo.load);
|
|
57
59
|
navRegister('knowledge', Knowledge.load);
|
|
58
60
|
navRegister('governance', Governance.load);
|
|
@@ -113,10 +115,14 @@ setOnEvent(evt => {
|
|
|
113
115
|
// here we just refresh the surface payload so kanban + KPIs reflect the new run.
|
|
114
116
|
if (String(evt.type||'').startsWith('orchestration.')) {
|
|
115
117
|
bustCache('/api/dashboard/surface/operate');
|
|
118
|
+
bustCache('/api/runs');
|
|
116
119
|
if (tab === 'board') {
|
|
117
120
|
Board.handleOrchestrationEvent?.(evt);
|
|
118
121
|
Board.render();
|
|
119
122
|
}
|
|
123
|
+
if (tab === 'context-log') {
|
|
124
|
+
ContextLog.load();
|
|
125
|
+
}
|
|
120
126
|
}
|
|
121
127
|
// Workspace root promoted (e.g. from bootstrap hint) — refresh header immediately.
|
|
122
128
|
if (String(evt.type||'') === 'workspace.changed') {
|
|
@@ -300,6 +306,7 @@ function _reloadTab(tab) {
|
|
|
300
306
|
if (tab === 'board') Board.load();
|
|
301
307
|
if (tab === 'workforce') Workforce.load();
|
|
302
308
|
if (tab === 'memory') Memory.load();
|
|
309
|
+
if (tab === 'context-log') ContextLog.load();
|
|
303
310
|
if (tab === 'knowledge') Knowledge.load();
|
|
304
311
|
}
|
|
305
312
|
|
|
@@ -65,6 +65,7 @@ export const S = {
|
|
|
65
65
|
memQuery: '',
|
|
66
66
|
graphSim: null,
|
|
67
67
|
memLane: 'all',
|
|
68
|
+
selectedMemoryIds: [],
|
|
68
69
|
memorySurface: null,
|
|
69
70
|
topology: null,
|
|
70
71
|
|
|
@@ -81,6 +82,10 @@ export const S = {
|
|
|
81
82
|
// Orchestration pipeline (live decomposition + completion from SSE)
|
|
82
83
|
lastDecomposition: null,
|
|
83
84
|
lastCompletion: null,
|
|
85
|
+
lastDecisionSpine: null,
|
|
86
|
+
contextLogRuns: [],
|
|
87
|
+
contextLogSelectedRunId: null,
|
|
88
|
+
contextLogSpine: null,
|
|
84
89
|
|
|
85
90
|
// Neural Stream HUD ring buffer (latest SSE events, restored from v3.8.0)
|
|
86
91
|
neuralStream: [],
|
|
@@ -30,9 +30,11 @@
|
|
|
30
30
|
.kb-body { display: flex; flex-direction: column; gap: 6px; min-height: 100px; }
|
|
31
31
|
.kb-empty {
|
|
32
32
|
height: 80px; border: 1px dashed var(--border); border-radius: var(--radius);
|
|
33
|
-
display: flex; align-items: center; justify-content: center;
|
|
33
|
+
display: flex; flex-direction: column; align-items: center; justify-content: center;
|
|
34
|
+
gap: 4px; padding: 0 14px; text-align: center;
|
|
34
35
|
}
|
|
35
|
-
.kb-empty-
|
|
36
|
+
.kb-empty-title { font-family: var(--font-mono); font-size: 0.78rem; color: var(--text-dim); }
|
|
37
|
+
.kb-empty-sub { font-size: 0.72rem; line-height: 1.35; color: var(--text-dim); opacity: 0.75; }
|
|
36
38
|
.kcard {
|
|
37
39
|
padding: 9px 11px; background: var(--bg-elevated); border: 1px solid var(--border);
|
|
38
40
|
border-radius: var(--radius); cursor: pointer;
|
|
@@ -168,6 +170,165 @@
|
|
|
168
170
|
.ledger-n { font-family: var(--font-mono); font-size: 0.78rem; color: var(--accent); flex-shrink: 0; min-width: 18px; }
|
|
169
171
|
.ledger-txt { color: var(--text-muted); }
|
|
170
172
|
|
|
173
|
+
/* ── Decision Spine ── */
|
|
174
|
+
.decision-spine-prompt {
|
|
175
|
+
padding: 9px 11px;
|
|
176
|
+
margin-bottom: 10px;
|
|
177
|
+
border: 1px solid var(--border);
|
|
178
|
+
border-radius: var(--radius);
|
|
179
|
+
background: var(--bg-panel);
|
|
180
|
+
color: var(--text-main);
|
|
181
|
+
font-size: 0.78rem;
|
|
182
|
+
line-height: 1.45;
|
|
183
|
+
}
|
|
184
|
+
.decision-spine-grid {
|
|
185
|
+
display: grid;
|
|
186
|
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
187
|
+
gap: 8px;
|
|
188
|
+
margin-bottom: 10px;
|
|
189
|
+
}
|
|
190
|
+
.decision-spine-card {
|
|
191
|
+
min-width: 0;
|
|
192
|
+
padding: 8px 10px;
|
|
193
|
+
border: 1px solid var(--border);
|
|
194
|
+
border-radius: var(--radius);
|
|
195
|
+
background: var(--bg-elevated);
|
|
196
|
+
}
|
|
197
|
+
.decision-spine-k {
|
|
198
|
+
font-family: var(--font-mono);
|
|
199
|
+
font-size: 0.68rem;
|
|
200
|
+
letter-spacing: 0.08em;
|
|
201
|
+
text-transform: uppercase;
|
|
202
|
+
color: var(--text-dim);
|
|
203
|
+
margin-bottom: 4px;
|
|
204
|
+
}
|
|
205
|
+
.decision-spine-v {
|
|
206
|
+
font-family: var(--font-mono);
|
|
207
|
+
font-size: 0.9rem;
|
|
208
|
+
color: var(--accent);
|
|
209
|
+
white-space: nowrap;
|
|
210
|
+
overflow: hidden;
|
|
211
|
+
text-overflow: ellipsis;
|
|
212
|
+
}
|
|
213
|
+
.decision-spine-sub {
|
|
214
|
+
margin-top: 3px;
|
|
215
|
+
color: var(--text-dim);
|
|
216
|
+
font-size: 0.72rem;
|
|
217
|
+
white-space: nowrap;
|
|
218
|
+
overflow: hidden;
|
|
219
|
+
text-overflow: ellipsis;
|
|
220
|
+
}
|
|
221
|
+
.decision-spine-block {
|
|
222
|
+
display: grid;
|
|
223
|
+
grid-template-columns: 68px 1fr;
|
|
224
|
+
gap: 8px;
|
|
225
|
+
align-items: start;
|
|
226
|
+
padding: 6px 0;
|
|
227
|
+
border-top: 1px solid var(--border);
|
|
228
|
+
font-size: 0.78rem;
|
|
229
|
+
}
|
|
230
|
+
.decision-spine-block > span {
|
|
231
|
+
font-family: var(--font-mono);
|
|
232
|
+
color: var(--text-dim);
|
|
233
|
+
text-transform: uppercase;
|
|
234
|
+
letter-spacing: 0.06em;
|
|
235
|
+
font-size: 0.68rem;
|
|
236
|
+
padding-top: 2px;
|
|
237
|
+
}
|
|
238
|
+
.decision-spine-list {
|
|
239
|
+
display: flex;
|
|
240
|
+
flex-wrap: wrap;
|
|
241
|
+
gap: 4px;
|
|
242
|
+
min-width: 0;
|
|
243
|
+
}
|
|
244
|
+
.decision-spine-latest {
|
|
245
|
+
margin-top: 10px;
|
|
246
|
+
padding: 7px 9px;
|
|
247
|
+
border-left: 2px solid var(--accent);
|
|
248
|
+
background: var(--bg-panel);
|
|
249
|
+
color: var(--text-muted);
|
|
250
|
+
font-size: 0.78rem;
|
|
251
|
+
line-height: 1.4;
|
|
252
|
+
}
|
|
253
|
+
.decision-spine-full-link {
|
|
254
|
+
float: right;
|
|
255
|
+
color: var(--accent);
|
|
256
|
+
font-family: var(--font-mono);
|
|
257
|
+
font-size: 0.68rem;
|
|
258
|
+
text-decoration: none;
|
|
259
|
+
}
|
|
260
|
+
.decision-spine-full-link:hover { text-decoration: underline; }
|
|
261
|
+
.decision-spine-mini {
|
|
262
|
+
margin-top: 8px;
|
|
263
|
+
padding: 8px 12px;
|
|
264
|
+
border-left: 3px solid var(--secondary);
|
|
265
|
+
background: var(--bg-panel);
|
|
266
|
+
}
|
|
267
|
+
.decision-spine-mini-head {
|
|
268
|
+
font-size: 0.78rem;
|
|
269
|
+
font-weight: 600;
|
|
270
|
+
margin-bottom: 5px;
|
|
271
|
+
}
|
|
272
|
+
.decision-spine-mini-row,
|
|
273
|
+
.decision-spine-mini-lists {
|
|
274
|
+
display: flex;
|
|
275
|
+
flex-wrap: wrap;
|
|
276
|
+
gap: 6px;
|
|
277
|
+
color: var(--text-dim);
|
|
278
|
+
font-family: var(--font-mono);
|
|
279
|
+
font-size: 0.72rem;
|
|
280
|
+
}
|
|
281
|
+
.decision-spine-mini-lists { margin-top: 6px; }
|
|
282
|
+
.decision-spine-browser {
|
|
283
|
+
display: grid;
|
|
284
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
285
|
+
gap: 10px;
|
|
286
|
+
margin-top: 10px;
|
|
287
|
+
padding-top: 10px;
|
|
288
|
+
border-top: 1px solid var(--border);
|
|
289
|
+
}
|
|
290
|
+
.decision-spine-browser-col {
|
|
291
|
+
min-width: 0;
|
|
292
|
+
}
|
|
293
|
+
.decision-spine-browser-title {
|
|
294
|
+
font-family: var(--font-mono);
|
|
295
|
+
font-size: 0.68rem;
|
|
296
|
+
letter-spacing: 0.06em;
|
|
297
|
+
text-transform: uppercase;
|
|
298
|
+
color: var(--text-dim);
|
|
299
|
+
margin-bottom: 6px;
|
|
300
|
+
}
|
|
301
|
+
.decision-spine-log-row {
|
|
302
|
+
min-width: 0;
|
|
303
|
+
padding: 7px 8px;
|
|
304
|
+
border: 1px solid var(--border);
|
|
305
|
+
border-radius: var(--radius);
|
|
306
|
+
background: var(--bg-panel);
|
|
307
|
+
margin-bottom: 6px;
|
|
308
|
+
}
|
|
309
|
+
.decision-spine-log-head {
|
|
310
|
+
display: flex;
|
|
311
|
+
align-items: center;
|
|
312
|
+
justify-content: space-between;
|
|
313
|
+
gap: 8px;
|
|
314
|
+
color: var(--accent);
|
|
315
|
+
font-family: var(--font-mono);
|
|
316
|
+
font-size: 0.72rem;
|
|
317
|
+
margin-bottom: 4px;
|
|
318
|
+
}
|
|
319
|
+
.decision-spine-log-reason {
|
|
320
|
+
color: var(--text-muted);
|
|
321
|
+
font-size: 0.76rem;
|
|
322
|
+
line-height: 1.35;
|
|
323
|
+
margin-bottom: 5px;
|
|
324
|
+
}
|
|
325
|
+
.decision-spine-log-ref,
|
|
326
|
+
.decision-spine-empty {
|
|
327
|
+
color: var(--text-dim);
|
|
328
|
+
font-size: 0.72rem;
|
|
329
|
+
line-height: 1.35;
|
|
330
|
+
}
|
|
331
|
+
|
|
171
332
|
/* ── Tasks Tab ── */
|
|
172
333
|
.task-toolbar { display: flex; align-items: center; gap: 8px; margin-bottom: 14px; flex-wrap: wrap; }
|
|
173
334
|
.filter-grp { display: flex; gap: 2px; }
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
.context-log-shell {
|
|
2
|
+
display: grid;
|
|
3
|
+
grid-template-columns: 260px minmax(0, 1fr);
|
|
4
|
+
gap: 14px;
|
|
5
|
+
align-items: start;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.context-log-rail,
|
|
9
|
+
.context-log-summary,
|
|
10
|
+
.context-log-row,
|
|
11
|
+
.context-log-decision {
|
|
12
|
+
background: var(--bg-elevated);
|
|
13
|
+
border: 1px solid var(--border);
|
|
14
|
+
border-radius: var(--radius);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.context-log-rail {
|
|
18
|
+
padding: 10px;
|
|
19
|
+
max-height: calc(100vh - 150px);
|
|
20
|
+
overflow-y: auto;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.context-log-rail-head {
|
|
24
|
+
display: flex;
|
|
25
|
+
align-items: center;
|
|
26
|
+
justify-content: space-between;
|
|
27
|
+
gap: 8px;
|
|
28
|
+
margin-bottom: 8px;
|
|
29
|
+
color: var(--text-muted);
|
|
30
|
+
font-family: var(--font-mono);
|
|
31
|
+
font-size: 0.78rem;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.context-log-run {
|
|
35
|
+
width: 100%;
|
|
36
|
+
display: flex;
|
|
37
|
+
flex-direction: column;
|
|
38
|
+
gap: 3px;
|
|
39
|
+
padding: 8px 9px;
|
|
40
|
+
margin-bottom: 6px;
|
|
41
|
+
border: 1px solid var(--border);
|
|
42
|
+
border-radius: var(--radius);
|
|
43
|
+
background: var(--bg-panel);
|
|
44
|
+
color: var(--text-muted);
|
|
45
|
+
text-align: left;
|
|
46
|
+
cursor: pointer;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.context-log-run.active {
|
|
50
|
+
border-color: rgba(0,255,136,0.38);
|
|
51
|
+
background: rgba(0,255,136,0.06);
|
|
52
|
+
color: var(--text-main);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.context-log-run span,
|
|
56
|
+
.context-log-row-head span {
|
|
57
|
+
font-family: var(--font-mono);
|
|
58
|
+
font-size: 0.78rem;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.context-log-run small {
|
|
62
|
+
color: var(--text-dim);
|
|
63
|
+
font-size: 0.72rem;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.context-log-main {
|
|
67
|
+
min-width: 0;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.context-log-summary {
|
|
71
|
+
display: grid;
|
|
72
|
+
grid-template-columns: repeat(5, minmax(90px, 1fr));
|
|
73
|
+
gap: 10px;
|
|
74
|
+
padding: 14px;
|
|
75
|
+
margin-bottom: 14px;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.context-log-kpi span,
|
|
79
|
+
.context-log-selection span {
|
|
80
|
+
display: block;
|
|
81
|
+
margin-bottom: 4px;
|
|
82
|
+
color: var(--text-dim);
|
|
83
|
+
font-family: var(--font-mono);
|
|
84
|
+
font-size: 0.68rem;
|
|
85
|
+
text-transform: uppercase;
|
|
86
|
+
letter-spacing: 0.05em;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.context-log-kpi strong {
|
|
90
|
+
color: var(--text-main);
|
|
91
|
+
font-size: 1rem;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.context-log-selection {
|
|
95
|
+
grid-column: 1 / -1;
|
|
96
|
+
display: grid;
|
|
97
|
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
98
|
+
gap: 10px;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.context-log-selection > div,
|
|
102
|
+
.context-log-refs {
|
|
103
|
+
display: flex;
|
|
104
|
+
flex-wrap: wrap;
|
|
105
|
+
gap: 4px;
|
|
106
|
+
min-width: 0;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.context-log-grid {
|
|
110
|
+
display: grid;
|
|
111
|
+
grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
|
|
112
|
+
gap: 14px;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.context-log-row,
|
|
116
|
+
.context-log-decision {
|
|
117
|
+
padding: 10px 12px;
|
|
118
|
+
margin-bottom: 8px;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.context-log-row-head {
|
|
122
|
+
display: grid;
|
|
123
|
+
grid-template-columns: auto auto minmax(0, 1fr);
|
|
124
|
+
gap: 8px;
|
|
125
|
+
align-items: center;
|
|
126
|
+
margin-bottom: 7px;
|
|
127
|
+
color: var(--accent);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.context-log-row-head time {
|
|
131
|
+
justify-self: end;
|
|
132
|
+
color: var(--text-dim);
|
|
133
|
+
font-family: var(--font-mono);
|
|
134
|
+
font-size: 0.7rem;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.context-log-row p,
|
|
138
|
+
.context-log-decision p {
|
|
139
|
+
margin: 0 0 8px;
|
|
140
|
+
color: var(--text-muted);
|
|
141
|
+
font-size: 0.78rem;
|
|
142
|
+
line-height: 1.45;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.context-log-decision strong {
|
|
146
|
+
display: block;
|
|
147
|
+
margin-bottom: 6px;
|
|
148
|
+
color: var(--text-main);
|
|
149
|
+
font-size: 0.82rem;
|
|
150
|
+
line-height: 1.35;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.context-log-empty {
|
|
154
|
+
color: var(--text-dim);
|
|
155
|
+
font-size: 0.72rem;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
@media (max-width: 980px) {
|
|
159
|
+
.context-log-shell,
|
|
160
|
+
.context-log-grid,
|
|
161
|
+
.context-log-selection {
|
|
162
|
+
grid-template-columns: 1fr;
|
|
163
|
+
}
|
|
164
|
+
.context-log-summary {
|
|
165
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
166
|
+
}
|
|
167
|
+
}
|