nexo-brain 5.3.19 → 5.3.21
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/.claude-plugin/plugin.json +1 -1
- package/bin/nexo-brain.js +52 -10
- package/package.json +1 -1
- package/src/auto_update.py +11 -8
- package/src/dashboard/static/favicon 2.svg +32 -0
- package/src/dashboard/static/nexo-logo 2.png +0 -0
- package/src/dashboard/static/nexo-logo 2.svg +40 -0
- package/src/dashboard/static/style 2.css +2458 -0
- package/src/dashboard/templates/adaptive 2.html +118 -0
- package/src/dashboard/templates/artifacts 2.html +133 -0
- package/src/dashboard/templates/backups 2.html +136 -0
- package/src/dashboard/templates/base 2.html +417 -0
- package/src/dashboard/templates/calendar 2.html +591 -0
- package/src/dashboard/templates/chat 2.html +356 -0
- package/src/dashboard/templates/claims 2.html +259 -0
- package/src/dashboard/templates/cortex 2.html +321 -0
- package/src/dashboard/templates/credentials 2.html +128 -0
- package/src/dashboard/templates/crons 2.html +370 -0
- package/src/dashboard/templates/dashboard 2.html +494 -0
- package/src/dashboard/templates/dreams 2.html +252 -0
- package/src/dashboard/templates/email 2.html +160 -0
- package/src/dashboard/templates/evolution 2.html +189 -0
- package/src/dashboard/templates/feed 2.html +249 -0
- package/src/dashboard/templates/followup_health 2.html +170 -0
- package/src/dashboard/templates/graph 2.html +201 -0
- package/src/dashboard/templates/guard 2.html +259 -0
- package/src/dashboard/templates/inbox 2.html +251 -0
- package/src/dashboard/templates/memory 2.html +420 -0
- package/src/dashboard/templates/operations 2.html +608 -0
- package/src/dashboard/templates/plugins 2.html +185 -0
- package/src/dashboard/templates/protocol 2.html +199 -0
- package/src/dashboard/templates/rules 2.html +246 -0
- package/src/dashboard/templates/sentiment 2.html +247 -0
- package/src/dashboard/templates/sessions 2.html +218 -0
- package/src/dashboard/templates/skills 2.html +329 -0
- package/src/dashboard/templates/somatic 2.html +73 -0
- package/src/dashboard/templates/triggers 2.html +133 -0
- package/src/dashboard/templates/trust 2.html +360 -0
- package/src/db/__init__ 2.py +259 -0
- package/src/db/_core 2.py +437 -0
- package/src/db/_credentials 2.py +124 -0
- package/src/db/_episodic 2.py +762 -0
- package/src/db/_evolution 2.py +54 -0
- package/src/db/_fts 2.py +406 -0
- package/src/db/_goal_profiles 2.py +376 -0
- package/src/db/_hot_context 2.py +660 -0
- package/src/db/_outcomes 2.py +800 -0
- package/src/db/_personal_scripts 2.py +582 -0
- package/src/db/_sessions 2.py +330 -0
- package/src/db/_tasks 2.py +91 -0
- package/src/db/_watchers 2.py +173 -0
- package/src/doctor/formatters 2.py +52 -0
- package/src/doctor/models 2.py +69 -0
- package/src/doctor/planes 2.py +87 -0
- package/src/doctor/providers/__init__ 2.py +1 -0
- package/src/doctor/providers/deep 2.py +367 -0
- package/src/evolution_cycle 2.py +519 -0
- package/src/hooks/auto_capture 2.py +208 -0
- package/src/hooks/caffeinate-guard 2.sh +8 -0
- package/src/hooks/capture-session 2.sh +21 -0
- package/src/hooks/capture-tool-logs 2.sh +158 -0
- package/src/hooks/daily-briefing-check 2.sh +33 -0
- package/src/hooks/heartbeat-enforcement 2.py +90 -0
- package/src/hooks/heartbeat-posttool 2.sh +18 -0
- package/src/hooks/inbox-hook 2.sh +76 -0
- package/src/hooks/post-compact 2.sh +152 -0
- package/src/hooks/pre-compact 2.sh +169 -0
- package/src/hooks/protocol-guardrail 2.sh +10 -0
- package/src/hooks/protocol-pretool-guardrail 2.sh +9 -0
- package/src/hooks/session-stop 2.sh +52 -0
- package/src/kg_populate 2.py +292 -0
- package/src/maintenance 2.py +53 -0
- package/src/memory_backends 2.py +71 -0
- package/src/migrate_embeddings 2.py +124 -0
- package/src/nexo_sdk 2.py +103 -0
- package/src/observability 2.py +199 -0
- package/src/plugin_loader 2.py +217 -0
- package/src/plugins/__init__ 2.py +0 -0
- package/src/plugins/artifact_registry 2.py +450 -0
- package/src/plugins/backup 2.py +127 -0
- package/src/plugins/claims_tools 2.py +119 -0
- package/src/plugins/cognitive_memory 2.py +609 -0
- package/src/plugins/core_rules 2.py +252 -0
- package/src/plugins/cortex 2.py +1155 -0
- package/src/plugins/entities 2.py +67 -0
- package/src/plugins/episodic_memory 2.py +560 -0
- package/src/plugins/evolution 2.py +167 -0
- package/src/plugins/goal_engine 2.py +142 -0
- package/src/plugins/guard 2.py +862 -0
- package/src/plugins/impact 2.py +29 -0
- package/src/plugins/knowledge_graph_tools 2.py +137 -0
- package/src/plugins/media_memory_tools 2.py +98 -0
- package/src/plugins/memory_export 2.py +196 -0
- package/src/plugins/outcomes 2.py +130 -0
- package/src/plugins/personal_scripts 2.py +117 -0
- package/src/plugins/preferences 2.py +47 -0
- package/src/plugins/protocol 2.py +1449 -0
- package/src/plugins/simple_api 2.py +106 -0
- package/src/plugins/skills 2.py +341 -0
- package/src/plugins/state_watchers 2.py +79 -0
- package/src/plugins/update 2.py +986 -0
- package/src/plugins/user_state_tools 2.py +43 -0
- package/src/plugins/workflow 2.py +588 -0
- package/src/protocol_settings 2.py +59 -0
- package/src/public_contribution 2.py +466 -0
- package/src/public_evolution_queue 2.py +241 -0
- package/src/requirements 2.txt +14 -0
- package/src/retroactive_learnings 2.py +373 -0
- package/src/rules/__init__ 2.py +0 -0
- package/src/rules/core-rules 2.json +331 -0
- package/src/rules/migrate 2.py +207 -0
- package/src/runtime_power 2.py +874 -0
- package/src/script_registry 2.py +1559 -0
- package/src/scripts/check-context 2.py +272 -0
- package/src/scripts/deep-sleep/apply_findings 2.py +2327 -0
- package/src/scripts/deep-sleep/collect 2.py +928 -0
- package/src/scripts/deep-sleep/extract 2.py +330 -0
- package/src/scripts/deep-sleep/extract-prompt 2.md +285 -0
- package/src/scripts/deep-sleep/synthesize 2.py +312 -0
- package/src/scripts/deep-sleep/synthesize-prompt 2.md +336 -0
- package/src/scripts/nexo-agent-run 2.py +75 -0
- package/src/scripts/nexo-auto-update 2.py +6 -0
- package/src/scripts/nexo-backup 2.sh +25 -0
- package/src/scripts/nexo-brain-activation 2.sh +140 -0
- package/src/scripts/nexo-catchup 2.py +300 -0
- package/src/scripts/nexo-cognitive-decay 2.py +257 -0
- package/src/scripts/nexo-cortex-cycle 2.py +293 -0
- package/src/scripts/nexo-cron-wrapper 2.sh +53 -0
- package/src/scripts/nexo-daily-self-audit 2.py +2161 -0
- package/src/scripts/nexo-dashboard 2.sh +29 -0
- package/src/scripts/nexo-deep-sleep 2.sh +86 -0
- package/src/scripts/nexo-evolution-run 2.py +1664 -0
- package/src/scripts/nexo-followup-hygiene 2.py +139 -0
- package/src/scripts/nexo-hook-record 2.py +42 -0
- package/src/scripts/nexo-immune 2.py +936 -0
- package/src/scripts/nexo-impact-scorer 2.py +117 -0
- package/src/scripts/nexo-inbox-hook 2.sh +74 -0
- package/src/scripts/nexo-install 2.py +6 -0
- package/src/scripts/nexo-learning-housekeep 2.py +401 -0
- package/src/scripts/nexo-learning-validator 2.py +266 -0
- package/src/scripts/nexo-migrate 2.py +260 -0
- package/src/scripts/nexo-outcome-checker 2.py +127 -0
- package/src/scripts/nexo-postmortem-consolidator 2.py +456 -0
- package/src/scripts/nexo-pre-commit 2.py +120 -0
- package/src/scripts/nexo-prevent-sleep 2.sh +35 -0
- package/src/scripts/nexo-proactive-dashboard 2.py +354 -0
- package/src/scripts/nexo-reflection 2.py +256 -0
- package/src/scripts/nexo-runtime-preflight 2.py +274 -0
- package/src/scripts/nexo-sleep 2.py +631 -0
- package/src/scripts/nexo-snapshot-restore 2.sh +35 -0
- package/src/scripts/nexo-sync-clients 2.py +16 -0
- package/src/scripts/nexo-synthesis 2.py +475 -0
- package/src/scripts/nexo-tcc-approve 2.sh +79 -0
- package/src/scripts/nexo-update 2.sh +306 -0
- package/src/scripts/nexo-watchdog 2.sh +1207 -0
- package/src/scripts/nexo-watchdog-smoke 2.py +119 -0
- package/src/scripts/rehydrate_learnings_from_archive 2.py +245 -0
- package/src/server 2.py +1296 -0
- package/src/skills/run-nexo-audit-phase/guide 2.md +43 -0
- package/src/skills/run-nexo-audit-phase/skill 2.json +59 -0
- package/src/skills/run-nexo-core-fix-cycle/guide 2.md +17 -0
- package/src/skills/run-nexo-core-fix-cycle/script 2.py +276 -0
- package/src/skills/run-nexo-core-fix-cycle/skill 2.json +58 -0
- package/src/skills/run-release-final-audit/guide 2.md +16 -0
- package/src/skills/run-release-final-audit/script 2.py +259 -0
- package/src/skills/run-release-final-audit/skill 2.json +77 -0
- package/src/skills/run-runtime-doctor/guide 2.md +12 -0
- package/src/skills/run-runtime-doctor/script 2.py +21 -0
- package/src/skills/run-runtime-doctor/skill 2.json +25 -0
- package/src/skills_runtime 2.py +932 -0
- package/src/state_watchers_runtime 2.py +475 -0
- package/src/storage_router 2.py +32 -0
- package/src/system_catalog 2.py +786 -0
- package/src/tools_coordination 2.py +103 -0
- package/src/tools_credentials 2.py +68 -0
- package/src/tools_drive 2.py +487 -0
- package/src/tools_hot_context 2.py +163 -0
- package/src/tools_learnings 2.py +612 -0
- package/src/tools_menu 2.py +229 -0
- package/src/tools_reminders 2.py +88 -0
- package/src/tools_reminders_crud 2.py +363 -0
- package/src/tools_sessions 2.py +1054 -0
- package/src/tools_system_catalog 2.py +19 -0
- package/src/tools_task_history 2.py +57 -0
- package/src/tools_transcripts 2.py +98 -0
- package/src/transcript_utils 2.py +412 -0
- package/src/user_context 2.py +46 -0
- package/src/user_data_portability 2.py +328 -0
- package/src/user_state_model 2.py +170 -0
- package/templates/CLAUDE.md 2.template +108 -0
- package/templates/CODEX.AGENTS.md 2.template +66 -0
- package/templates/launchagents/README 2.md +132 -0
- package/templates/launchagents/com.nexo.auto-close-sessions 2.plist +39 -0
- package/templates/launchagents/com.nexo.catchup 2.plist +39 -0
- package/templates/launchagents/com.nexo.cognitive-decay 2.plist +40 -0
- package/templates/launchagents/com.nexo.dashboard 2.plist +43 -0
- package/templates/launchagents/com.nexo.deep-sleep 2.plist +43 -0
- package/templates/launchagents/com.nexo.evolution 2.plist +44 -0
- package/templates/launchagents/com.nexo.followup-hygiene 2.plist +45 -0
- package/templates/launchagents/com.nexo.immune 2.plist +41 -0
- package/templates/launchagents/com.nexo.postmortem 2.plist +45 -0
- package/templates/launchagents/com.nexo.self-audit 2.plist +47 -0
- package/templates/launchagents/com.nexo.synthesis 2.plist +45 -0
- package/templates/launchagents/com.nexo.watchdog 2.plist +37 -0
- package/templates/nexo_helper 2.py +301 -0
- package/templates/openclaw 2.json +13 -0
- package/templates/plugin-template 2.py +40 -0
- package/templates/script-template 2.py +59 -0
- package/templates/script-template 2.sh +13 -0
- package/templates/skill-script-template 2.py +48 -0
- package/templates/skill-template 2.md +33 -0
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
{% extends "base.html" %}
|
|
2
|
+
|
|
3
|
+
{% block title %}Trust Deep-Dive{% endblock %}
|
|
4
|
+
{% block page_title %}Trust Deep-Dive{% endblock %}
|
|
5
|
+
|
|
6
|
+
{% block head %}
|
|
7
|
+
<style>
|
|
8
|
+
.gauge-ring {
|
|
9
|
+
transition: stroke-dashoffset 1.2s cubic-bezier(0.22, 1, 0.36, 1);
|
|
10
|
+
}
|
|
11
|
+
.score-value {
|
|
12
|
+
transition: all 0.8s ease;
|
|
13
|
+
}
|
|
14
|
+
@keyframes pulseGlow {
|
|
15
|
+
0%, 100% { filter: drop-shadow(0 0 8px rgba(124, 58, 237, 0.3)); }
|
|
16
|
+
50% { filter: drop-shadow(0 0 20px rgba(124, 58, 237, 0.6)); }
|
|
17
|
+
}
|
|
18
|
+
.gauge-container {
|
|
19
|
+
animation: pulseGlow 3s ease-in-out infinite;
|
|
20
|
+
}
|
|
21
|
+
.event-card {
|
|
22
|
+
transition: all 0.2s ease;
|
|
23
|
+
animation: slideIn 0.3s ease-out forwards;
|
|
24
|
+
opacity: 0;
|
|
25
|
+
}
|
|
26
|
+
.event-card:hover {
|
|
27
|
+
border-color: rgba(124, 58, 237, 0.3);
|
|
28
|
+
transform: translateX(2px);
|
|
29
|
+
}
|
|
30
|
+
.chart-container {
|
|
31
|
+
position: relative;
|
|
32
|
+
}
|
|
33
|
+
.delta-positive { color: #34d399; }
|
|
34
|
+
.delta-negative { color: #f87171; }
|
|
35
|
+
.delta-badge-positive { background: rgba(52, 211, 153, 0.1); border-color: rgba(52, 211, 153, 0.2); color: #34d399; }
|
|
36
|
+
.delta-badge-negative { background: rgba(248, 113, 113, 0.1); border-color: rgba(248, 113, 113, 0.2); color: #f87171; }
|
|
37
|
+
@keyframes slideIn {
|
|
38
|
+
from { opacity: 0; transform: translateX(-8px); }
|
|
39
|
+
to { opacity: 1; transform: translateX(0); }
|
|
40
|
+
}
|
|
41
|
+
.filter-btn.active {
|
|
42
|
+
background: rgba(124, 58, 237, 0.2);
|
|
43
|
+
color: #a78bfa;
|
|
44
|
+
border-color: rgba(124, 58, 237, 0.3);
|
|
45
|
+
}
|
|
46
|
+
</style>
|
|
47
|
+
{% endblock %}
|
|
48
|
+
|
|
49
|
+
{% block header_actions %}
|
|
50
|
+
<div class="flex items-center gap-1">
|
|
51
|
+
<button class="filter-btn active text-[10px] px-2 py-1 rounded border border-slate-700 text-slate-400 hover:text-slate-200 transition-colors" data-filter="all" onclick="setFilter('all')">All</button>
|
|
52
|
+
<button class="filter-btn text-[10px] px-2 py-1 rounded border border-slate-700 text-slate-400 hover:text-slate-200 transition-colors" data-filter="positive" onclick="setFilter('positive')">Positive</button>
|
|
53
|
+
<button class="filter-btn text-[10px] px-2 py-1 rounded border border-slate-700 text-slate-400 hover:text-slate-200 transition-colors" data-filter="negative" onclick="setFilter('negative')">Negative</button>
|
|
54
|
+
</div>
|
|
55
|
+
{% endblock %}
|
|
56
|
+
|
|
57
|
+
{% block content %}
|
|
58
|
+
<!-- Gauge + Stats Row -->
|
|
59
|
+
<div class="grid grid-cols-1 lg:grid-cols-3 gap-5 mb-6">
|
|
60
|
+
<!-- Trust Gauge -->
|
|
61
|
+
<div class="bg-slate-900/50 border border-slate-800/50 rounded-xl p-6 flex flex-col items-center justify-center">
|
|
62
|
+
<div class="text-xs uppercase tracking-wider text-slate-500 font-semibold mb-4">Current Trust Score</div>
|
|
63
|
+
<div class="gauge-container relative" style="width: 200px; height: 200px;">
|
|
64
|
+
<svg viewBox="0 0 200 200" class="w-full h-full">
|
|
65
|
+
<!-- Background ring -->
|
|
66
|
+
<circle cx="100" cy="100" r="85" fill="none" stroke="rgba(51,65,85,0.3)" stroke-width="10"
|
|
67
|
+
stroke-dasharray="534" stroke-dashoffset="0" stroke-linecap="round"
|
|
68
|
+
transform="rotate(-90 100 100)"/>
|
|
69
|
+
<!-- Score ring -->
|
|
70
|
+
<circle id="gauge-ring" cx="100" cy="100" r="85" fill="none" stroke="url(#gaugeGradient)" stroke-width="10"
|
|
71
|
+
stroke-dasharray="534" stroke-dashoffset="534" stroke-linecap="round"
|
|
72
|
+
transform="rotate(-90 100 100)" class="gauge-ring"/>
|
|
73
|
+
<!-- Gradient -->
|
|
74
|
+
<defs>
|
|
75
|
+
<linearGradient id="gaugeGradient" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
76
|
+
<stop offset="0%" stop-color="#7C3AED"/>
|
|
77
|
+
<stop offset="50%" stop-color="#a78bfa"/>
|
|
78
|
+
<stop offset="100%" stop-color="#34d399"/>
|
|
79
|
+
</linearGradient>
|
|
80
|
+
</defs>
|
|
81
|
+
</svg>
|
|
82
|
+
<div class="absolute inset-0 flex flex-col items-center justify-center">
|
|
83
|
+
<span id="gauge-score" class="text-5xl font-display font-bold text-white score-value">--</span>
|
|
84
|
+
<span class="text-xs text-slate-500 mt-1">/ 100</span>
|
|
85
|
+
</div>
|
|
86
|
+
</div>
|
|
87
|
+
</div>
|
|
88
|
+
|
|
89
|
+
<!-- Weekly Stats -->
|
|
90
|
+
<div class="bg-slate-900/50 border border-slate-800/50 rounded-xl p-5 flex flex-col justify-center">
|
|
91
|
+
<div class="text-xs uppercase tracking-wider text-slate-500 font-semibold mb-4">This Week</div>
|
|
92
|
+
<div class="space-y-4">
|
|
93
|
+
<div>
|
|
94
|
+
<div class="flex items-center justify-between mb-1">
|
|
95
|
+
<span class="text-xs text-slate-400">Average Score</span>
|
|
96
|
+
<span class="text-sm font-mono font-semibold text-slate-200" id="stat-avg">--</span>
|
|
97
|
+
</div>
|
|
98
|
+
<div class="h-1 bg-slate-800 rounded-full overflow-hidden">
|
|
99
|
+
<div class="h-full bg-violet-500 rounded-full transition-all duration-700" id="stat-avg-bar" style="width:0%"></div>
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
<div class="flex items-center justify-between">
|
|
103
|
+
<span class="text-xs text-slate-400">Biggest Gain</span>
|
|
104
|
+
<span class="text-sm font-mono font-semibold delta-positive" id="stat-gain">--</span>
|
|
105
|
+
</div>
|
|
106
|
+
<div class="flex items-center justify-between">
|
|
107
|
+
<span class="text-xs text-slate-400">Biggest Drop</span>
|
|
108
|
+
<span class="text-sm font-mono font-semibold delta-negative" id="stat-drop">--</span>
|
|
109
|
+
</div>
|
|
110
|
+
<div class="flex items-center justify-between">
|
|
111
|
+
<span class="text-xs text-slate-400">Total Events</span>
|
|
112
|
+
<span class="text-sm font-mono font-semibold text-slate-200" id="stat-events">--</span>
|
|
113
|
+
</div>
|
|
114
|
+
</div>
|
|
115
|
+
</div>
|
|
116
|
+
|
|
117
|
+
<!-- Score History Chart -->
|
|
118
|
+
<div class="bg-slate-900/50 border border-slate-800/50 rounded-xl p-5">
|
|
119
|
+
<div class="text-xs uppercase tracking-wider text-slate-500 font-semibold mb-3">Score History</div>
|
|
120
|
+
<div class="chart-container" style="height: 180px;">
|
|
121
|
+
<canvas id="history-chart" width="400" height="180"></canvas>
|
|
122
|
+
</div>
|
|
123
|
+
</div>
|
|
124
|
+
</div>
|
|
125
|
+
|
|
126
|
+
<!-- Event Timeline -->
|
|
127
|
+
<div>
|
|
128
|
+
<h2 class="text-xs uppercase tracking-wider text-slate-500 font-semibold mb-3 flex items-center gap-2">
|
|
129
|
+
<svg class="w-4 h-4 text-violet-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13 10V3L4 14h7v7l9-11h-7z"/></svg>
|
|
130
|
+
Trust Events
|
|
131
|
+
<span class="text-slate-600 font-mono" id="event-count"></span>
|
|
132
|
+
</h2>
|
|
133
|
+
<div class="space-y-2" id="event-timeline">
|
|
134
|
+
<div class="text-xs text-slate-600 text-center py-8">Loading trust events...</div>
|
|
135
|
+
</div>
|
|
136
|
+
</div>
|
|
137
|
+
{% endblock %}
|
|
138
|
+
|
|
139
|
+
{% block scripts %}
|
|
140
|
+
<script>
|
|
141
|
+
const REFRESH_MS = 60000;
|
|
142
|
+
let allEvents = [];
|
|
143
|
+
let currentFilter = 'all';
|
|
144
|
+
|
|
145
|
+
function setFilter(filter) {
|
|
146
|
+
currentFilter = filter;
|
|
147
|
+
document.querySelectorAll('.filter-btn').forEach(b => {
|
|
148
|
+
b.classList.toggle('active', b.dataset.filter === filter);
|
|
149
|
+
});
|
|
150
|
+
renderEvents();
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function updateGauge(score) {
|
|
154
|
+
const ring = document.getElementById('gauge-ring');
|
|
155
|
+
const scoreEl = document.getElementById('gauge-score');
|
|
156
|
+
const circumference = 534; // 2 * PI * 85
|
|
157
|
+
const offset = circumference - (score / 100) * circumference;
|
|
158
|
+
ring.style.strokeDashoffset = offset;
|
|
159
|
+
scoreEl.textContent = Math.round(score);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function drawChart(history) {
|
|
163
|
+
const canvas = document.getElementById('history-chart');
|
|
164
|
+
const ctx = canvas.getContext('2d');
|
|
165
|
+
const dpr = window.devicePixelRatio || 1;
|
|
166
|
+
const rect = canvas.getBoundingClientRect();
|
|
167
|
+
canvas.width = rect.width * dpr;
|
|
168
|
+
canvas.height = rect.height * dpr;
|
|
169
|
+
ctx.scale(dpr, dpr);
|
|
170
|
+
const w = rect.width;
|
|
171
|
+
const h = rect.height;
|
|
172
|
+
|
|
173
|
+
ctx.clearRect(0, 0, w, h);
|
|
174
|
+
|
|
175
|
+
if (!history || history.length < 2) {
|
|
176
|
+
ctx.fillStyle = '#475569';
|
|
177
|
+
ctx.font = '12px "Space Grotesk"';
|
|
178
|
+
ctx.textAlign = 'center';
|
|
179
|
+
ctx.fillText('Not enough data for chart', w / 2, h / 2);
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const scores = history.map(h => h.score);
|
|
184
|
+
const minScore = Math.max(0, Math.min(...scores) - 5);
|
|
185
|
+
const maxScore = Math.min(100, Math.max(...scores) + 5);
|
|
186
|
+
const range = maxScore - minScore || 1;
|
|
187
|
+
|
|
188
|
+
const padX = 10, padY = 15;
|
|
189
|
+
const chartW = w - padX * 2;
|
|
190
|
+
const chartH = h - padY * 2;
|
|
191
|
+
|
|
192
|
+
// Grid lines
|
|
193
|
+
ctx.strokeStyle = 'rgba(51, 65, 85, 0.3)';
|
|
194
|
+
ctx.lineWidth = 1;
|
|
195
|
+
for (let i = 0; i <= 4; i++) {
|
|
196
|
+
const y = padY + (chartH / 4) * i;
|
|
197
|
+
ctx.beginPath();
|
|
198
|
+
ctx.moveTo(padX, y);
|
|
199
|
+
ctx.lineTo(w - padX, y);
|
|
200
|
+
ctx.stroke();
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Gradient fill
|
|
204
|
+
const gradient = ctx.createLinearGradient(0, padY, 0, h - padY);
|
|
205
|
+
gradient.addColorStop(0, 'rgba(124, 58, 237, 0.15)');
|
|
206
|
+
gradient.addColorStop(1, 'rgba(124, 58, 237, 0)');
|
|
207
|
+
|
|
208
|
+
// Line path
|
|
209
|
+
const points = history.map((item, i) => ({
|
|
210
|
+
x: padX + (i / (history.length - 1)) * chartW,
|
|
211
|
+
y: padY + chartH - ((item.score - minScore) / range) * chartH
|
|
212
|
+
}));
|
|
213
|
+
|
|
214
|
+
// Fill area
|
|
215
|
+
ctx.beginPath();
|
|
216
|
+
ctx.moveTo(points[0].x, h - padY);
|
|
217
|
+
points.forEach(p => ctx.lineTo(p.x, p.y));
|
|
218
|
+
ctx.lineTo(points[points.length - 1].x, h - padY);
|
|
219
|
+
ctx.closePath();
|
|
220
|
+
ctx.fillStyle = gradient;
|
|
221
|
+
ctx.fill();
|
|
222
|
+
|
|
223
|
+
// Line
|
|
224
|
+
ctx.beginPath();
|
|
225
|
+
ctx.moveTo(points[0].x, points[0].y);
|
|
226
|
+
for (let i = 1; i < points.length; i++) {
|
|
227
|
+
const prev = points[i - 1];
|
|
228
|
+
const curr = points[i];
|
|
229
|
+
const cpx = (prev.x + curr.x) / 2;
|
|
230
|
+
ctx.bezierCurveTo(cpx, prev.y, cpx, curr.y, curr.x, curr.y);
|
|
231
|
+
}
|
|
232
|
+
ctx.strokeStyle = '#7C3AED';
|
|
233
|
+
ctx.lineWidth = 2;
|
|
234
|
+
ctx.stroke();
|
|
235
|
+
|
|
236
|
+
// Dots
|
|
237
|
+
points.forEach((p, i) => {
|
|
238
|
+
if (i === points.length - 1 || history.length <= 20 || i % Math.ceil(history.length / 15) === 0) {
|
|
239
|
+
ctx.beginPath();
|
|
240
|
+
ctx.arc(p.x, p.y, 3, 0, Math.PI * 2);
|
|
241
|
+
ctx.fillStyle = '#7C3AED';
|
|
242
|
+
ctx.fill();
|
|
243
|
+
ctx.strokeStyle = '#030712';
|
|
244
|
+
ctx.lineWidth = 1.5;
|
|
245
|
+
ctx.stroke();
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
// Last point highlight
|
|
250
|
+
const last = points[points.length - 1];
|
|
251
|
+
ctx.beginPath();
|
|
252
|
+
ctx.arc(last.x, last.y, 5, 0, Math.PI * 2);
|
|
253
|
+
ctx.fillStyle = '#a78bfa';
|
|
254
|
+
ctx.fill();
|
|
255
|
+
ctx.strokeStyle = '#030712';
|
|
256
|
+
ctx.lineWidth = 2;
|
|
257
|
+
ctx.stroke();
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function renderEvents() {
|
|
261
|
+
const container = document.getElementById('event-timeline');
|
|
262
|
+
const countEl = document.getElementById('event-count');
|
|
263
|
+
|
|
264
|
+
let filtered = allEvents;
|
|
265
|
+
if (currentFilter === 'positive') filtered = allEvents.filter(e => (e.delta || 0) > 0);
|
|
266
|
+
else if (currentFilter === 'negative') filtered = allEvents.filter(e => (e.delta || 0) < 0);
|
|
267
|
+
|
|
268
|
+
countEl.textContent = `(${filtered.length})`;
|
|
269
|
+
|
|
270
|
+
if (filtered.length === 0) {
|
|
271
|
+
container.innerHTML = '<div class="text-xs text-slate-600 text-center py-8">No events match filter</div>';
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
container.innerHTML = filtered.slice(0, 50).map((e, idx) => {
|
|
276
|
+
const delta = e.delta || 0;
|
|
277
|
+
const isPositive = delta >= 0;
|
|
278
|
+
const deltaStr = (isPositive ? '+' : '') + delta.toFixed(2);
|
|
279
|
+
const badgeClass = isPositive ? 'delta-badge-positive' : 'delta-badge-negative';
|
|
280
|
+
const event = e.event || e.description || 'Trust event';
|
|
281
|
+
const context = e.context || '';
|
|
282
|
+
const when = e.created_at ? relativeTime(e.created_at) : '';
|
|
283
|
+
const score = e.score != null ? e.score.toFixed(1) : '';
|
|
284
|
+
const delay = Math.min(idx * 0.05, 1);
|
|
285
|
+
|
|
286
|
+
return `<div class="event-card flex items-start gap-3 bg-slate-900/50 border border-slate-800/50 rounded-xl p-4" style="animation-delay:${delay}s">
|
|
287
|
+
<div class="flex-shrink-0 mt-0.5">
|
|
288
|
+
<span class="inline-flex items-center justify-center w-8 h-8 rounded-lg border text-xs font-mono font-bold ${badgeClass}">
|
|
289
|
+
${deltaStr}
|
|
290
|
+
</span>
|
|
291
|
+
</div>
|
|
292
|
+
<div class="flex-1 min-w-0">
|
|
293
|
+
<div class="flex items-center gap-2 mb-1">
|
|
294
|
+
<span class="text-sm text-slate-200 font-medium">${escapeHtml(event)}</span>
|
|
295
|
+
${score ? `<span class="text-[10px] font-mono text-slate-500 ml-auto flex-shrink-0">${score}</span>` : ''}
|
|
296
|
+
</div>
|
|
297
|
+
${context ? `<p class="text-xs text-slate-500 leading-relaxed">${escapeHtml(context)}</p>` : ''}
|
|
298
|
+
<span class="text-[10px] text-slate-600 font-mono mt-1 inline-block">${escapeHtml(when)}</span>
|
|
299
|
+
</div>
|
|
300
|
+
</div>`;
|
|
301
|
+
}).join('');
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
async function loadTrust() {
|
|
305
|
+
const [trustData, eventsData] = await Promise.all([
|
|
306
|
+
fetchJSON('/api/trust'),
|
|
307
|
+
fetchJSON('/api/trust/events?limit=50')
|
|
308
|
+
]);
|
|
309
|
+
|
|
310
|
+
if (trustData) {
|
|
311
|
+
const score = trustData.current_score != null ? trustData.current_score : 0;
|
|
312
|
+
updateGauge(score);
|
|
313
|
+
|
|
314
|
+
const history = trustData.history || [];
|
|
315
|
+
drawChart(history);
|
|
316
|
+
|
|
317
|
+
// Weekly stats
|
|
318
|
+
const now = new Date();
|
|
319
|
+
const weekAgo = new Date(now - 7 * 86400000);
|
|
320
|
+
const weekEvents = history.filter(h => new Date(h.created_at) >= weekAgo);
|
|
321
|
+
const weekScores = weekEvents.map(h => h.score).filter(s => s != null);
|
|
322
|
+
const weekDeltas = weekEvents.map(h => h.delta).filter(d => d != null);
|
|
323
|
+
|
|
324
|
+
if (weekScores.length > 0) {
|
|
325
|
+
const avg = weekScores.reduce((a, b) => a + b, 0) / weekScores.length;
|
|
326
|
+
document.getElementById('stat-avg').textContent = avg.toFixed(1);
|
|
327
|
+
document.getElementById('stat-avg-bar').style.width = avg + '%';
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
if (weekDeltas.length > 0) {
|
|
331
|
+
const maxGain = Math.max(...weekDeltas);
|
|
332
|
+
const maxDrop = Math.min(...weekDeltas);
|
|
333
|
+
document.getElementById('stat-gain').textContent = maxGain > 0 ? '+' + maxGain.toFixed(2) : '0';
|
|
334
|
+
document.getElementById('stat-drop').textContent = maxDrop < 0 ? maxDrop.toFixed(2) : '0';
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
document.getElementById('stat-events').textContent = formatNumber(history.length);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
if (eventsData) {
|
|
341
|
+
allEvents = eventsData.events || eventsData || [];
|
|
342
|
+
renderEvents();
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// Handle resize for chart
|
|
347
|
+
let resizeTimer;
|
|
348
|
+
window.addEventListener('resize', () => {
|
|
349
|
+
clearTimeout(resizeTimer);
|
|
350
|
+
resizeTimer = setTimeout(() => {
|
|
351
|
+
// Re-fetch to redraw chart
|
|
352
|
+
loadTrust();
|
|
353
|
+
}, 250);
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
// Init
|
|
357
|
+
loadTrust();
|
|
358
|
+
setInterval(loadTrust, REFRESH_MS);
|
|
359
|
+
</script>
|
|
360
|
+
{% endblock %}
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
"""NEXO DB — Modular SQLite database layer.
|
|
2
|
+
|
|
3
|
+
This package replaces the monolithic db.py. All public functions are
|
|
4
|
+
re-exported here for full backwards compatibility:
|
|
5
|
+
from db import get_db, create_learning, ...
|
|
6
|
+
|
|
7
|
+
Important:
|
|
8
|
+
`importlib.reload(db)` must also refresh the concrete submodules. The test
|
|
9
|
+
suite and several runtime repair flows rely on switching database paths or
|
|
10
|
+
runtime roots mid-process. If the package only re-exported functions from
|
|
11
|
+
already-imported submodules, those callables would keep pointing at stale
|
|
12
|
+
module state (especially old `db._core` connection globals).
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
import importlib
|
|
18
|
+
import sys
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _load_submodule(name: str):
|
|
22
|
+
"""Import or reload a db submodule and expose it on the package."""
|
|
23
|
+
module = sys.modules.get(name)
|
|
24
|
+
if module is None:
|
|
25
|
+
return importlib.import_module(name)
|
|
26
|
+
return importlib.reload(module)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _module(name: str):
|
|
30
|
+
module = sys.modules.get(name)
|
|
31
|
+
if module is None:
|
|
32
|
+
module = importlib.import_module(name)
|
|
33
|
+
return module
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
_core = _load_submodule("db._core")
|
|
37
|
+
_fts = _load_submodule("db._fts")
|
|
38
|
+
_schema = _load_submodule("db._schema")
|
|
39
|
+
_sessions = _load_submodule("db._sessions")
|
|
40
|
+
_reminders = _load_submodule("db._reminders")
|
|
41
|
+
_learnings = _load_submodule("db._learnings")
|
|
42
|
+
_credentials = _load_submodule("db._credentials")
|
|
43
|
+
_tasks = _load_submodule("db._tasks")
|
|
44
|
+
_entities = _load_submodule("db._entities")
|
|
45
|
+
_episodic = _load_submodule("db._episodic")
|
|
46
|
+
_evolution = _load_submodule("db._evolution")
|
|
47
|
+
_cron_runs = _load_submodule("db._cron_runs")
|
|
48
|
+
_protocol = _load_submodule("db._protocol")
|
|
49
|
+
_workflow = _load_submodule("db._workflow")
|
|
50
|
+
_watchers = _load_submodule("db._watchers")
|
|
51
|
+
_personal_scripts = _load_submodule("db._personal_scripts")
|
|
52
|
+
_skills = _load_submodule("db._skills")
|
|
53
|
+
_hot_context = _load_submodule("db._hot_context")
|
|
54
|
+
_drive = _load_submodule("db._drive")
|
|
55
|
+
_outcomes = _load_submodule("db._outcomes")
|
|
56
|
+
_goal_profiles = _load_submodule("db._goal_profiles")
|
|
57
|
+
|
|
58
|
+
# Core: connection, constants, init, utils
|
|
59
|
+
from db._core import (
|
|
60
|
+
DB_PATH, SESSION_STALE_SECONDS, MESSAGE_TTL_SECONDS, QUESTION_TTL_SECONDS,
|
|
61
|
+
get_db, close_db, _get_raw_conn, _SerializedConnection,
|
|
62
|
+
_shared_conn, _write_lock,
|
|
63
|
+
init_db, _gen_id, now_epoch, local_time_str, _multi_word_like,
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
# FTS5 search
|
|
67
|
+
from db._fts import (
|
|
68
|
+
fts_add_dir, fts_remove_dir, fts_list_dirs,
|
|
69
|
+
rebuild_fts_index, fts_search, fts_upsert,
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
# Schema migrations
|
|
73
|
+
from db._schema import (
|
|
74
|
+
run_migrations, get_schema_version,
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
# Sessions, file tracking, messages, questions
|
|
78
|
+
from db._sessions import (
|
|
79
|
+
register_session, update_session, complete_session,
|
|
80
|
+
get_active_sessions, clean_stale_sessions, search_sessions,
|
|
81
|
+
track_files, untrack_files, get_all_tracked_files,
|
|
82
|
+
send_message, get_inbox,
|
|
83
|
+
ask_question, answer_question, get_pending_questions, check_answer,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
# Reminders and followups
|
|
87
|
+
from db._reminders import (
|
|
88
|
+
create_reminder, update_reminder, complete_reminder, delete_reminder,
|
|
89
|
+
restore_reminder, add_reminder_note, get_reminders, get_reminder, get_reminder_history,
|
|
90
|
+
create_followup, update_followup, complete_followup, delete_followup,
|
|
91
|
+
restore_followup, add_followup_note, get_followups, get_followup, get_followup_history,
|
|
92
|
+
find_similar_followups,
|
|
93
|
+
compute_followup_impact, score_followup, score_active_followups,
|
|
94
|
+
add_item_history, get_item_history, validate_item_read_token,
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
# Learnings
|
|
98
|
+
from db._learnings import (
|
|
99
|
+
create_learning, update_learning, supersede_learning, delete_learning,
|
|
100
|
+
search_learnings, list_learnings,
|
|
101
|
+
extract_keywords, find_similar_learnings,
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
# Credentials
|
|
105
|
+
from db._credentials import (
|
|
106
|
+
create_credential, update_credential, delete_credential,
|
|
107
|
+
get_credential, list_credentials,
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
# Task history
|
|
111
|
+
from db._tasks import (
|
|
112
|
+
log_task, list_task_history, set_task_frequency,
|
|
113
|
+
get_overdue_tasks, get_task_frequencies,
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
# Entities, preferences, agents
|
|
117
|
+
from db._entities import (
|
|
118
|
+
create_entity, search_entities, list_entities, update_entity, delete_entity,
|
|
119
|
+
set_preference, get_preference, list_preferences, delete_preference,
|
|
120
|
+
create_agent, get_agent, list_agents, update_agent, delete_agent,
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
# Episodic memory
|
|
124
|
+
from db._episodic import (
|
|
125
|
+
cleanup_old_changes, log_change, search_changes, update_change_commit, auto_resolve_followups,
|
|
126
|
+
cleanup_old_decisions, log_decision, update_decision_outcome,
|
|
127
|
+
get_memory_review_queue, find_decisions_by_context_ref, search_decisions,
|
|
128
|
+
cleanup_old_diaries, write_session_diary,
|
|
129
|
+
diary_archive_search, diary_archive_read, diary_archive_stats,
|
|
130
|
+
check_session_has_diary,
|
|
131
|
+
upsert_diary_draft, get_diary_draft, delete_diary_draft,
|
|
132
|
+
save_checkpoint, read_checkpoint, increment_compaction_count,
|
|
133
|
+
get_orphan_sessions, read_session_diary,
|
|
134
|
+
recall,
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
# Evolution
|
|
138
|
+
from db._evolution import (
|
|
139
|
+
insert_evolution_metric, get_latest_metrics,
|
|
140
|
+
insert_evolution_log, get_evolution_history, update_evolution_log_status,
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
# Cron execution history
|
|
144
|
+
from db._cron_runs import (
|
|
145
|
+
cron_run_start, cron_run_end, cron_runs_recent, cron_runs_summary,
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
# Protocol discipline runtime
|
|
149
|
+
from db._protocol import (
|
|
150
|
+
VALID_IMPACT_LEVELS,
|
|
151
|
+
VALID_TASK_TYPES,
|
|
152
|
+
VALID_CLOSE_OUTCOMES,
|
|
153
|
+
create_protocol_task, get_protocol_task, close_protocol_task,
|
|
154
|
+
create_protocol_debt, resolve_protocol_debts, list_protocol_debts,
|
|
155
|
+
protocol_compliance_summary,
|
|
156
|
+
create_cortex_evaluation, get_cortex_evaluation, list_cortex_evaluations,
|
|
157
|
+
cortex_evaluation_summary,
|
|
158
|
+
latest_cortex_evaluation_for_task, task_has_cortex_evaluation,
|
|
159
|
+
override_cortex_evaluation, validate_close_outcome, validate_impact_level, validate_task_type,
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
# Durable workflow runtime
|
|
163
|
+
from db._workflow import (
|
|
164
|
+
create_workflow_run, get_workflow_run, list_workflow_runs,
|
|
165
|
+
list_workflow_steps, record_workflow_transition,
|
|
166
|
+
get_workflow_replay, get_workflow_resume_state,
|
|
167
|
+
create_workflow_goal, get_workflow_goal, list_workflow_goals,
|
|
168
|
+
update_workflow_goal,
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
# State watchers
|
|
172
|
+
from db._watchers import (
|
|
173
|
+
create_state_watcher, get_state_watcher, list_state_watchers,
|
|
174
|
+
update_state_watcher, update_state_watcher_result,
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
# Personal scripts registry
|
|
178
|
+
from db._personal_scripts import (
|
|
179
|
+
upsert_personal_script, list_personal_scripts, get_personal_script,
|
|
180
|
+
delete_missing_personal_scripts, register_personal_script_schedule,
|
|
181
|
+
delete_missing_personal_schedules, list_personal_script_schedules,
|
|
182
|
+
get_personal_script_schedule, delete_personal_script_schedule,
|
|
183
|
+
delete_personal_script,
|
|
184
|
+
record_personal_script_run, sync_personal_scripts_registry,
|
|
185
|
+
get_personal_script_health_report,
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
# Skills
|
|
189
|
+
from db._skills import (
|
|
190
|
+
create_skill, get_skill, list_skills, search_skills,
|
|
191
|
+
update_skill, delete_skill,
|
|
192
|
+
record_usage as record_skill_usage,
|
|
193
|
+
match_skills, merge_skills, get_skill_stats, decay_unused_skills,
|
|
194
|
+
get_featured_skills, get_skill_execution_spec, resolve_skill_paths,
|
|
195
|
+
validate_skill_params, render_command_template, sync_skill_directories,
|
|
196
|
+
import_skill_from_directory, approve_skill, collect_scriptable_skill_candidates,
|
|
197
|
+
collect_skill_improvement_candidates, materialize_personal_skill_definition,
|
|
198
|
+
get_skill_outcome_evidence, list_skill_outcome_reviews,
|
|
199
|
+
get_skill_health_report,
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
# Drive / Curiosity signals
|
|
203
|
+
from db._drive import (
|
|
204
|
+
create_drive_signal, reinforce_drive_signal, get_drive_signals,
|
|
205
|
+
get_drive_signal, update_drive_signal_status, decay_drive_signals,
|
|
206
|
+
find_similar_drive_signal, drive_signal_stats,
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
# Hot context / recent continuity
|
|
210
|
+
from db._hot_context import (
|
|
211
|
+
DEFAULT_CONTEXT_TTL_HOURS,
|
|
212
|
+
derive_context_key, clamp_ttl_hours,
|
|
213
|
+
cleanup_expired_hot_context,
|
|
214
|
+
remember_hot_context, record_recent_event, capture_context_event,
|
|
215
|
+
get_hot_context, search_hot_context, search_recent_events,
|
|
216
|
+
build_pre_action_context, format_pre_action_context_bundle,
|
|
217
|
+
resolve_hot_context,
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
# Outcomes
|
|
221
|
+
from db._outcomes import (
|
|
222
|
+
VALID_METRIC_SOURCES as OUTCOME_METRIC_SOURCES,
|
|
223
|
+
VALID_TARGET_OPERATORS as OUTCOME_TARGET_OPERATORS,
|
|
224
|
+
create_outcome, get_outcome, list_outcomes,
|
|
225
|
+
cancel_outcome, evaluate_outcome, pending_outcomes_due,
|
|
226
|
+
find_pending_outcomes_by_action, set_linked_outcomes_met,
|
|
227
|
+
list_outcome_pattern_candidates, capture_outcome_pattern,
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
# Goal Engine v1
|
|
231
|
+
from db._goal_profiles import (
|
|
232
|
+
DEFAULT_GOAL_PROFILES,
|
|
233
|
+
ensure_default_goal_profiles, get_goal_profile, list_goal_profiles,
|
|
234
|
+
upsert_goal_profile, resolve_goal_profile,
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
def get_db():
|
|
239
|
+
return _module("db._core").get_db()
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def close_db():
|
|
243
|
+
return _module("db._core").close_db()
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
def init_db():
|
|
247
|
+
return _module("db._core").init_db()
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def now_epoch():
|
|
251
|
+
return _module("db._core").now_epoch()
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
def run_migrations():
|
|
255
|
+
return _module("db._schema").run_migrations()
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
def get_schema_version():
|
|
259
|
+
return _module("db._schema").get_schema_version()
|