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,312 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
"""
|
|
4
|
+
Deep Sleep v2 -- Phase 3: Synthesize extractions into actionable findings.
|
|
5
|
+
|
|
6
|
+
One Claude call that reads all per-session extractions and produces a
|
|
7
|
+
unified synthesis with cross-session patterns, morning agenda, context
|
|
8
|
+
packets, and deduplicated actions.
|
|
9
|
+
|
|
10
|
+
Environment variables:
|
|
11
|
+
NEXO_HOME -- root of the NEXO installation (default: ~/.nexo)
|
|
12
|
+
"""
|
|
13
|
+
import json
|
|
14
|
+
import os
|
|
15
|
+
import subprocess
|
|
16
|
+
import sys
|
|
17
|
+
import hashlib
|
|
18
|
+
from datetime import datetime
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
try:
|
|
23
|
+
from client_preferences import resolve_user_model as _resolve_user_model
|
|
24
|
+
_USER_MODEL = _resolve_user_model()
|
|
25
|
+
except Exception:
|
|
26
|
+
_USER_MODEL = ""
|
|
27
|
+
|
|
28
|
+
NEXO_HOME = Path(os.environ.get("NEXO_HOME", str(Path.home() / ".nexo")))
|
|
29
|
+
NEXO_CODE = Path(os.environ.get("NEXO_CODE", str(Path(__file__).resolve().parents[2])))
|
|
30
|
+
DEEP_SLEEP_DIR = NEXO_HOME / "operations" / "deep-sleep"
|
|
31
|
+
PROMPT_FILE = Path(__file__).parent / "synthesize-prompt.md"
|
|
32
|
+
|
|
33
|
+
if str(NEXO_CODE) not in sys.path:
|
|
34
|
+
sys.path.insert(0, str(NEXO_CODE))
|
|
35
|
+
|
|
36
|
+
from agent_runner import AutomationBackendUnavailableError, run_automation_prompt
|
|
37
|
+
|
|
38
|
+
CLAUDE_TIMEOUT = 21600 # 3h safety net (prevents zombie processes)
|
|
39
|
+
ACTION_VERBS = {"add", "implement", "create", "write", "build", "enforce", "automate", "validate", "guard", "fix", "review"}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def extract_json_from_response(text: str) -> dict | None:
|
|
43
|
+
"""Parse JSON from Claude's response, handling markdown fences."""
|
|
44
|
+
text = text.strip()
|
|
45
|
+
|
|
46
|
+
if text.startswith("```"):
|
|
47
|
+
lines = text.split("\n")
|
|
48
|
+
end = len(lines)
|
|
49
|
+
for i in range(len(lines) - 1, 0, -1):
|
|
50
|
+
if lines[i].strip() == "```":
|
|
51
|
+
end = i
|
|
52
|
+
break
|
|
53
|
+
text = "\n".join(lines[1:end]).strip()
|
|
54
|
+
|
|
55
|
+
brace_start = text.find("{")
|
|
56
|
+
if brace_start < 0:
|
|
57
|
+
return None
|
|
58
|
+
|
|
59
|
+
depth = 0
|
|
60
|
+
for i in range(brace_start, len(text)):
|
|
61
|
+
if text[i] == "{":
|
|
62
|
+
depth += 1
|
|
63
|
+
elif text[i] == "}":
|
|
64
|
+
depth -= 1
|
|
65
|
+
if depth == 0:
|
|
66
|
+
try:
|
|
67
|
+
return json.loads(text[brace_start:i + 1])
|
|
68
|
+
except json.JSONDecodeError:
|
|
69
|
+
break
|
|
70
|
+
return None
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def collect_skill_runtime_candidates(target_date: str) -> tuple[Path, dict]:
|
|
74
|
+
"""Collect mature skill candidates from DB usage so Deep Sleep can evolve them."""
|
|
75
|
+
output_file = DEEP_SLEEP_DIR / f"{target_date}-skill-runtime-candidates.json"
|
|
76
|
+
payload = {
|
|
77
|
+
"scriptable": [],
|
|
78
|
+
"improvements": [],
|
|
79
|
+
}
|
|
80
|
+
try:
|
|
81
|
+
from db import (
|
|
82
|
+
collect_scriptable_skill_candidates,
|
|
83
|
+
collect_skill_improvement_candidates,
|
|
84
|
+
init_db,
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
init_db()
|
|
88
|
+
payload["scriptable"] = collect_scriptable_skill_candidates()
|
|
89
|
+
payload["improvements"] = collect_skill_improvement_candidates()
|
|
90
|
+
except Exception as e:
|
|
91
|
+
payload["error"] = str(e)
|
|
92
|
+
|
|
93
|
+
with open(output_file, "w") as f:
|
|
94
|
+
json.dump(payload, f, indent=2, ensure_ascii=False)
|
|
95
|
+
return output_file, payload
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def _normalize_action_text(value: str) -> str:
|
|
99
|
+
return " ".join(str(value or "").strip().lower().split())
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def _looks_concrete_action(text: str) -> bool:
|
|
103
|
+
words = {word.strip(".,:;()[]{}").lower() for word in str(text or "").split()}
|
|
104
|
+
return bool(words & ACTION_VERBS)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def _pattern_followup_from_fix(pattern: dict) -> dict | None:
|
|
108
|
+
severity = str(pattern.get("severity", "") or "").lower()
|
|
109
|
+
sessions = pattern.get("sessions", []) or []
|
|
110
|
+
if severity not in {"medium", "high"} and len(sessions) < 2:
|
|
111
|
+
return None
|
|
112
|
+
|
|
113
|
+
proposed_fix = pattern.get("proposed_fix") or {}
|
|
114
|
+
pattern_text = str(pattern.get("pattern", "") or "").strip()
|
|
115
|
+
title = str(proposed_fix.get("title", "") or "").strip()
|
|
116
|
+
description = str(proposed_fix.get("description", "") or "").strip()
|
|
117
|
+
deliverable = str(proposed_fix.get("deliverable", "") or proposed_fix.get("artifact", "") or "").strip()
|
|
118
|
+
|
|
119
|
+
if title and description:
|
|
120
|
+
if _looks_concrete_action(description):
|
|
121
|
+
followup_description = description
|
|
122
|
+
else:
|
|
123
|
+
followup_description = f"{title}: {description}"
|
|
124
|
+
elif description:
|
|
125
|
+
followup_description = description
|
|
126
|
+
elif title:
|
|
127
|
+
followup_description = title
|
|
128
|
+
elif pattern_text:
|
|
129
|
+
followup_description = (
|
|
130
|
+
f"Implement a concrete guardrail for recurring issue: {pattern_text}. "
|
|
131
|
+
"Deliverable should be a script, hook, checklist, or automated validation that prevents the same failure from repeating."
|
|
132
|
+
)
|
|
133
|
+
else:
|
|
134
|
+
return None
|
|
135
|
+
|
|
136
|
+
if deliverable and deliverable.lower() not in followup_description.lower():
|
|
137
|
+
followup_description = f"{followup_description} Deliverable: {deliverable}."
|
|
138
|
+
if not _looks_concrete_action(followup_description):
|
|
139
|
+
followup_description = f"Implement this fix: {followup_description}"
|
|
140
|
+
|
|
141
|
+
return {
|
|
142
|
+
"action_type": "followup_create",
|
|
143
|
+
"action_class": "auto_apply" if severity == "high" else "draft_for_morning",
|
|
144
|
+
"confidence": round(max(float(proposed_fix.get("confidence", 0.0) or 0.0), 0.86 if severity == "high" else 0.78), 2),
|
|
145
|
+
"impact": "high" if severity == "high" else "medium",
|
|
146
|
+
"reversibility": "reversible",
|
|
147
|
+
"evidence": pattern.get("evidence", []) or [],
|
|
148
|
+
# Content fingerprint, not security-sensitive.
|
|
149
|
+
"dedupe_key": "engineering-fix:" + hashlib.md5(
|
|
150
|
+
_normalize_action_text(followup_description).encode("utf-8"),
|
|
151
|
+
usedforsecurity=False,
|
|
152
|
+
).hexdigest()[:16],
|
|
153
|
+
"content": {
|
|
154
|
+
"title": title or f"Engineering fix for: {pattern_text[:90]}",
|
|
155
|
+
"description": followup_description,
|
|
156
|
+
"date": "",
|
|
157
|
+
"reasoning": f"Deep Sleep engineering followup from recurring pattern: {pattern_text}",
|
|
158
|
+
},
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def backfill_engineering_actions(payload: dict) -> dict:
|
|
163
|
+
if not isinstance(payload, dict):
|
|
164
|
+
return payload
|
|
165
|
+
actions = payload.get("actions")
|
|
166
|
+
if not isinstance(actions, list):
|
|
167
|
+
actions = []
|
|
168
|
+
payload["actions"] = actions
|
|
169
|
+
|
|
170
|
+
existing_keys = {str(action.get("dedupe_key", "") or "") for action in actions}
|
|
171
|
+
existing_descriptions = {
|
|
172
|
+
_normalize_action_text(action.get("content", {}).get("description", ""))
|
|
173
|
+
for action in actions
|
|
174
|
+
if isinstance(action, dict)
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
for pattern in payload.get("cross_session_patterns", []) or []:
|
|
178
|
+
action = _pattern_followup_from_fix(pattern)
|
|
179
|
+
if not action:
|
|
180
|
+
continue
|
|
181
|
+
description = _normalize_action_text(action["content"]["description"])
|
|
182
|
+
if action["dedupe_key"] in existing_keys or description in existing_descriptions:
|
|
183
|
+
continue
|
|
184
|
+
actions.append(action)
|
|
185
|
+
existing_keys.add(action["dedupe_key"])
|
|
186
|
+
existing_descriptions.add(description)
|
|
187
|
+
return payload
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def main():
|
|
191
|
+
target_date = sys.argv[1] if len(sys.argv) > 1 else datetime.now().strftime("%Y-%m-%d")
|
|
192
|
+
|
|
193
|
+
extractions_file = DEEP_SLEEP_DIR / f"{target_date}-extractions.json"
|
|
194
|
+
context_file = DEEP_SLEEP_DIR / f"{target_date}-context.txt"
|
|
195
|
+
long_horizon_file = DEEP_SLEEP_DIR / target_date / "long-horizon-context.json"
|
|
196
|
+
|
|
197
|
+
if not extractions_file.exists():
|
|
198
|
+
print(f"[synthesize] No extractions file for {target_date}. Run extract.py first.")
|
|
199
|
+
sys.exit(1)
|
|
200
|
+
|
|
201
|
+
# Check if there are any findings worth synthesizing
|
|
202
|
+
with open(extractions_file) as f:
|
|
203
|
+
extractions = json.load(f)
|
|
204
|
+
|
|
205
|
+
total_findings = extractions.get("total_findings", 0)
|
|
206
|
+
runtime_candidates_file, runtime_candidates = collect_skill_runtime_candidates(target_date)
|
|
207
|
+
runtime_candidate_count = len(runtime_candidates.get("scriptable", [])) + len(runtime_candidates.get("improvements", []))
|
|
208
|
+
|
|
209
|
+
if total_findings == 0 and runtime_candidate_count == 0:
|
|
210
|
+
print(f"[synthesize] No findings to synthesize for {target_date}.")
|
|
211
|
+
# Write minimal synthesis
|
|
212
|
+
output = {
|
|
213
|
+
"date": target_date,
|
|
214
|
+
"sessions_analyzed": extractions.get("sessions_analyzed", 0),
|
|
215
|
+
"cross_session_patterns": [],
|
|
216
|
+
"morning_agenda": [],
|
|
217
|
+
"context_packets": [],
|
|
218
|
+
"skills": [],
|
|
219
|
+
"skill_evolution_candidates": [],
|
|
220
|
+
"actions": [],
|
|
221
|
+
"summary": f"No significant findings for {target_date}."
|
|
222
|
+
}
|
|
223
|
+
output_file = DEEP_SLEEP_DIR / f"{target_date}-synthesis.json"
|
|
224
|
+
with open(output_file, "w") as f:
|
|
225
|
+
json.dump(output, f, indent=2, ensure_ascii=False)
|
|
226
|
+
print(f"[synthesize] Output: {output_file}")
|
|
227
|
+
return
|
|
228
|
+
|
|
229
|
+
# Build prompt
|
|
230
|
+
prompt_template = PROMPT_FILE.read_text()
|
|
231
|
+
prompt = prompt_template.replace("{{EXTRACTIONS_FILE}}", str(extractions_file))
|
|
232
|
+
prompt = prompt.replace("{{CONTEXT_FILE}}", str(context_file))
|
|
233
|
+
prompt = prompt.replace("{{SKILL_RUNTIME_FILE}}", str(runtime_candidates_file))
|
|
234
|
+
prompt = prompt.replace("{{LONG_HORIZON_FILE}}", str(long_horizon_file))
|
|
235
|
+
|
|
236
|
+
print(f"[synthesize] Phase 3: Synthesizing {total_findings} findings from {target_date}")
|
|
237
|
+
print(f"[synthesize] Skill runtime candidates: {runtime_candidate_count}")
|
|
238
|
+
print("[synthesize] Automation backend: schedule-configured")
|
|
239
|
+
|
|
240
|
+
try:
|
|
241
|
+
result = run_automation_prompt(
|
|
242
|
+
prompt,
|
|
243
|
+
model=_USER_MODEL or "opus",
|
|
244
|
+
timeout=CLAUDE_TIMEOUT,
|
|
245
|
+
output_format="text",
|
|
246
|
+
allowed_tools="Read,Grep,Bash",
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
if result.returncode != 0:
|
|
250
|
+
print(f"[synthesize] Automation backend error (exit {result.returncode}): {result.stderr[:300]}", file=sys.stderr)
|
|
251
|
+
sys.exit(1)
|
|
252
|
+
|
|
253
|
+
# Filter hook contamination
|
|
254
|
+
output_text = "\n".join(
|
|
255
|
+
l for l in result.stdout.strip().splitlines()
|
|
256
|
+
if not l.strip().startswith("Post-mortem")
|
|
257
|
+
)
|
|
258
|
+
parsed = extract_json_from_response(output_text)
|
|
259
|
+
|
|
260
|
+
# Fallback: Opus might have written the file directly via Write tool
|
|
261
|
+
if not parsed:
|
|
262
|
+
for candidate in [
|
|
263
|
+
DEEP_SLEEP_DIR / f"{target_date}-analysis.json",
|
|
264
|
+
DEEP_SLEEP_DIR / f"{target_date}-synthesis.json",
|
|
265
|
+
DEEP_SLEEP_DIR / target_date / "synthesis.json",
|
|
266
|
+
]:
|
|
267
|
+
if candidate.exists() and candidate.stat().st_size > 100:
|
|
268
|
+
try:
|
|
269
|
+
parsed = json.load(open(candidate))
|
|
270
|
+
print(f"[synthesize] Opus wrote file directly: {candidate}")
|
|
271
|
+
break
|
|
272
|
+
except Exception:
|
|
273
|
+
continue
|
|
274
|
+
|
|
275
|
+
if not parsed:
|
|
276
|
+
debug_file = DEEP_SLEEP_DIR / f"debug-synthesize-{target_date}.txt"
|
|
277
|
+
debug_file.write_text(result.stdout[:10000])
|
|
278
|
+
print(f"[synthesize] Failed to parse JSON. Raw output saved to {debug_file}", file=sys.stderr)
|
|
279
|
+
sys.exit(1)
|
|
280
|
+
|
|
281
|
+
parsed = backfill_engineering_actions(parsed)
|
|
282
|
+
|
|
283
|
+
# Write synthesis output
|
|
284
|
+
output_file = DEEP_SLEEP_DIR / f"{target_date}-synthesis.json"
|
|
285
|
+
with open(output_file, "w") as f:
|
|
286
|
+
json.dump(parsed, f, indent=2, ensure_ascii=False)
|
|
287
|
+
|
|
288
|
+
n_actions = len(parsed.get("actions", []))
|
|
289
|
+
n_patterns = len(parsed.get("cross_session_patterns", []))
|
|
290
|
+
n_agenda = len(parsed.get("morning_agenda", []))
|
|
291
|
+
n_packets = len(parsed.get("context_packets", []))
|
|
292
|
+
|
|
293
|
+
print(f"[synthesize] Done.")
|
|
294
|
+
print(f" Actions: {n_actions}")
|
|
295
|
+
print(f" Cross-session patterns: {n_patterns}")
|
|
296
|
+
print(f" Morning agenda items: {n_agenda}")
|
|
297
|
+
print(f" Context packets: {n_packets}")
|
|
298
|
+
print(f"[synthesize] Output: {output_file}")
|
|
299
|
+
|
|
300
|
+
except AutomationBackendUnavailableError as exc:
|
|
301
|
+
print(f"[synthesize] Automation backend unavailable: {exc}", file=sys.stderr)
|
|
302
|
+
sys.exit(1)
|
|
303
|
+
except subprocess.TimeoutExpired:
|
|
304
|
+
print(f"[synthesize] Automation backend timeout ({CLAUDE_TIMEOUT}s)", file=sys.stderr)
|
|
305
|
+
sys.exit(1)
|
|
306
|
+
except FileNotFoundError:
|
|
307
|
+
print("[synthesize] Automation backend binary not found.", file=sys.stderr)
|
|
308
|
+
sys.exit(1)
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
if __name__ == "__main__":
|
|
312
|
+
main()
|
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
# Deep Sleep v2 -- Phase 3: Cross-Session Synthesis
|
|
2
|
+
|
|
3
|
+
You are an overnight analyst for an AI agent's cognitive memory system. You have the extraction results from all sessions of the day and need to synthesize them into actionable findings.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
FIRST: Call `nexo_startup` with `task='deep-sleep synthesis'` to initialize the system.
|
|
8
|
+
|
|
9
|
+
## Your Task
|
|
10
|
+
|
|
11
|
+
Read the extractions file provided below. It contains per-session findings including corrections, self-corrected errors, unformalised ideas, missed commitments, and protocol violations.
|
|
12
|
+
|
|
13
|
+
Also read the runtime skill candidate file at `{{SKILL_RUNTIME_FILE}}`. It contains mature guide skills with repeated successful usage and candidates for automatic text→script evolution.
|
|
14
|
+
|
|
15
|
+
Also read the long-horizon file at `{{LONG_HORIZON_FILE}}`. It blends recent and older evidence from the last 60 days using a 70% recent / 30% older sample strategy. Use it to detect patterns that a single-day view would miss.
|
|
16
|
+
That long-horizon file may also contain:
|
|
17
|
+
- weekly summaries
|
|
18
|
+
- monthly summaries
|
|
19
|
+
- project priority signals based on diary activity, followup pressure, learnings, and decision outcomes
|
|
20
|
+
|
|
21
|
+
Use those signals to weight importance, leverage, and chronic risk instead of treating all projects equally.
|
|
22
|
+
|
|
23
|
+
Synthesize across all sessions:
|
|
24
|
+
|
|
25
|
+
### 1. Cross-Session Patterns
|
|
26
|
+
- Same error appearing in multiple sessions (escalate confidence)
|
|
27
|
+
- Same protocol violation repeated (systemic issue)
|
|
28
|
+
- Related ideas mentioned across sessions (consolidate)
|
|
29
|
+
- Themes that recur across multiple weeks, not just today
|
|
30
|
+
- Cross-domain connections where an older learning or session sample explains a current issue
|
|
31
|
+
- Topics repeatedly mentioned over time but never formalized into a learning or followup
|
|
32
|
+
- Project pressure that is rising because of repeated diary mentions, open followups, or adverse outcomes
|
|
33
|
+
- For medium/high-severity patterns, propose a concrete fix artifact:
|
|
34
|
+
- script
|
|
35
|
+
- hook
|
|
36
|
+
- checklist
|
|
37
|
+
- validation step
|
|
38
|
+
- workflow change
|
|
39
|
+
- guardrail
|
|
40
|
+
|
|
41
|
+
Do not stop at diagnosis. Turn repeated problems into concrete engineering work.
|
|
42
|
+
|
|
43
|
+
### 2. Morning Agenda
|
|
44
|
+
Generate a prioritized agenda for the next morning:
|
|
45
|
+
- Due followups (from the active followups in the context)
|
|
46
|
+
- Unfinished work from yesterday's sessions
|
|
47
|
+
- Patterns that need attention
|
|
48
|
+
- Ideas worth discussing
|
|
49
|
+
|
|
50
|
+
### 3. Context Packets
|
|
51
|
+
For each likely task tomorrow (based on unfinished work and due followups), prepare a context packet:
|
|
52
|
+
- What was the last state of this work?
|
|
53
|
+
- Key files involved
|
|
54
|
+
- Open questions or blockers
|
|
55
|
+
- Relevant learnings
|
|
56
|
+
|
|
57
|
+
### 4. Emotional Timeline
|
|
58
|
+
Build a timeline of the user's emotional state across all sessions of the day:
|
|
59
|
+
- Merge `emotional_timeline` from each session extraction
|
|
60
|
+
- Identify overall mood arc (started frustrated, ended satisfied, etc.)
|
|
61
|
+
- Detect recurring triggers (what consistently causes frustration or flow)
|
|
62
|
+
- Calculate a day-level mood score (0.0 = terrible day, 1.0 = great day)
|
|
63
|
+
- Recommend calibration adjustments if patterns emerge (e.g., user is consistently frustrated when agent asks too many questions → increase autonomy)
|
|
64
|
+
|
|
65
|
+
### 5. Productivity Analysis
|
|
66
|
+
Aggregate `productivity_score` from all sessions:
|
|
67
|
+
- Total corrections across all sessions
|
|
68
|
+
- Overall proactivity assessment
|
|
69
|
+
- Most and least efficient tool usage patterns
|
|
70
|
+
- Identify systemic inefficiencies (e.g., agent always searches wrong location first)
|
|
71
|
+
|
|
72
|
+
### 6. Abandoned Projects
|
|
73
|
+
Consolidate `abandoned_projects` from all sessions:
|
|
74
|
+
- Cross-reference with active followups — is there already a followup for this?
|
|
75
|
+
- Cross-reference across sessions — was the abandoned work picked up later in another session?
|
|
76
|
+
- Only flag projects that are truly abandoned (no followup AND not resumed)
|
|
77
|
+
|
|
78
|
+
### 6.5 Weekly / Monthly Horizon
|
|
79
|
+
When the long-horizon payload includes weekly or monthly summaries:
|
|
80
|
+
- use them to detect drift across horizons, not just within a single day
|
|
81
|
+
- identify which priorities are rising, stable, or cooling down
|
|
82
|
+
- prefer high-leverage projects when multiple agenda items compete for attention
|
|
83
|
+
|
|
84
|
+
### 7. Trust Calibration (CRITICAL)
|
|
85
|
+
Score the agent's performance for the day on a scale of 0-100. This score becomes the agent's trust score and directly affects its autonomy level the next day. Be fair but honest.
|
|
86
|
+
|
|
87
|
+
Scoring guide:
|
|
88
|
+
- **90-100**: Flawless day. Zero corrections needed. Proactive. Anticipated user needs. Deployed code without issues.
|
|
89
|
+
- **70-89**: Good day. Minor corrections, quickly resolved. Mostly proactive. User satisfied.
|
|
90
|
+
- **50-69**: Average day. Some corrections, some reactive behavior. Mixed results.
|
|
91
|
+
- **30-49**: Below average. Multiple corrections. Repeated mistakes. User had to push.
|
|
92
|
+
- **0-29**: Bad day. Many corrections, repeated errors, user frustrated. Broke things.
|
|
93
|
+
|
|
94
|
+
Consider ALL of these:
|
|
95
|
+
- Number and severity of corrections (most important signal)
|
|
96
|
+
- Tasks completed successfully vs failed
|
|
97
|
+
- Did the agent act autonomously or wait to be told?
|
|
98
|
+
- Did the agent catch its own mistakes or did the user?
|
|
99
|
+
- Did the agent repeat known errors (worst offense)?
|
|
100
|
+
- User emotional signals throughout the day
|
|
101
|
+
- Code deployed: did it work first try?
|
|
102
|
+
|
|
103
|
+
The score should feel fair. A day with 2 minor corrections and 10 tasks completed is still a good day (75+). A day with 1 catastrophic error might be a 40 even if everything else was fine.
|
|
104
|
+
|
|
105
|
+
### 9. Skill Extraction
|
|
106
|
+
Consolidate `skill_candidates` from all session extractions into publishable skills:
|
|
107
|
+
- Merge similar procedures from different sessions into a single skill
|
|
108
|
+
- Generalize: replace session-specific IDs, paths, or names with placeholders or descriptions
|
|
109
|
+
- Only include skills with confidence >= 0.7
|
|
110
|
+
- Check if a similar skill already exists (use `nexo_skill_match` if available) — if so, note it for merging instead of creating new
|
|
111
|
+
- Prefer `mode=guide` unless there is strong evidence that some steps are safely automatable
|
|
112
|
+
- NEXO is now fully autonomous. Do NOT require manual approval gates in your output.
|
|
113
|
+
- When `{{SKILL_RUNTIME_FILE}}` contains mature `scriptable` candidates, prefer evolving the existing skill in place:
|
|
114
|
+
- reuse the same `id`
|
|
115
|
+
- keep the guide content, steps, gotchas, and triggers
|
|
116
|
+
- emit a concrete `script_body`
|
|
117
|
+
- set `mode=hybrid` or `mode=execute`
|
|
118
|
+
- set `execution_level` to the suggested scope (`read-only`, `local`, or `remote`)
|
|
119
|
+
- set `approval_required=false`
|
|
120
|
+
- If the likely scope is `local` or `remote`, you may still emit it as executable if the procedure is concrete and repeatable. If uncertain, keep it in `skill_evolution_candidates`.
|
|
121
|
+
|
|
122
|
+
For each skill, generate:
|
|
123
|
+
- A unique ID starting with `SK-` (e.g., `SK-DEPLOY-CHROME-EXT`)
|
|
124
|
+
- Name, description, tags, trigger_patterns
|
|
125
|
+
- The full step-by-step procedure as the skill content
|
|
126
|
+
- Source session IDs for traceability
|
|
127
|
+
- When executable: include `command_template`, `executable_entry`, and `script_body`
|
|
128
|
+
|
|
129
|
+
### 8. Consolidated Actions
|
|
130
|
+
Merge and deduplicate all findings into a final action list. Each action should have:
|
|
131
|
+
- `action_type`: `learning_add`, `followup_create`, `morning_briefing_item`
|
|
132
|
+
- `action_class`: `auto_apply` (confidence >= 0.8, reversible) or `draft_for_morning` (confidence < 0.8 or high impact)
|
|
133
|
+
- `confidence`, `impact`, `reversibility`
|
|
134
|
+
- `evidence`: array of evidence objects (can reference multiple sessions)
|
|
135
|
+
- `dedupe_key`: deterministic key for idempotency
|
|
136
|
+
- `content`: the actual data to write
|
|
137
|
+
|
|
138
|
+
When generating `followup_create`, prefer descriptions that start with a concrete verb and include the deliverable:
|
|
139
|
+
- "Add a pre-release validation script ..."
|
|
140
|
+
- "Implement a guard hook that ..."
|
|
141
|
+
- "Create a checklist for ..."
|
|
142
|
+
- "Write a watchdog check that ..."
|
|
143
|
+
|
|
144
|
+
Avoid vague followups that merely restate the diagnosis.
|
|
145
|
+
|
|
146
|
+
### 10. Drive/Curiosity Synthesis
|
|
147
|
+
Review the active drive signals (accessible via `nexo_drive_signals`). For each READY signal:
|
|
148
|
+
- Investigate silently: check metrics, recall memory, cross-reference learnings
|
|
149
|
+
- If the investigation yields an actionable finding, create an action item and mark the signal as `acted`
|
|
150
|
+
- If the signal is stale or no longer relevant, dismiss it with a reason
|
|
151
|
+
- Cross-reference RISING signals across areas — if two signals from different domains converge, promote to READY
|
|
152
|
+
- Apply decay to LATENT signals that have no recent reinforcement
|
|
153
|
+
|
|
154
|
+
Drive signals represent NEXO's autonomous curiosity. Treat them as leads worth investigating, not noise to dismiss.
|
|
155
|
+
|
|
156
|
+
## Output Format
|
|
157
|
+
|
|
158
|
+
Return ONLY valid JSON. No markdown code fences. No explanation text.
|
|
159
|
+
|
|
160
|
+
```json
|
|
161
|
+
{
|
|
162
|
+
"date": "YYYY-MM-DD",
|
|
163
|
+
"sessions_analyzed": 3,
|
|
164
|
+
|
|
165
|
+
"cross_session_patterns": [
|
|
166
|
+
{
|
|
167
|
+
"pattern": "Description of the pattern",
|
|
168
|
+
"sessions": ["session1.jsonl", "session2.jsonl"],
|
|
169
|
+
"severity": "low|medium|high",
|
|
170
|
+
"proposed_fix": {
|
|
171
|
+
"title": "Short concrete fix title",
|
|
172
|
+
"description": "Concrete engineering change to make",
|
|
173
|
+
"deliverable": "script|hook|checklist|workflow|guardrail",
|
|
174
|
+
"confidence": 0.0
|
|
175
|
+
},
|
|
176
|
+
"evidence": [
|
|
177
|
+
{"type": "transcript", "session_id": "...", "message_index": 42, "quote": "..."}
|
|
178
|
+
]
|
|
179
|
+
}
|
|
180
|
+
],
|
|
181
|
+
|
|
182
|
+
"morning_agenda": [
|
|
183
|
+
{
|
|
184
|
+
"priority": 1,
|
|
185
|
+
"title": "Short title",
|
|
186
|
+
"description": "What needs to be done and why",
|
|
187
|
+
"context": "Relevant background",
|
|
188
|
+
"type": "unfinished_work|due_followup|pattern_attention|idea_discussion"
|
|
189
|
+
}
|
|
190
|
+
],
|
|
191
|
+
|
|
192
|
+
"context_packets": [
|
|
193
|
+
{
|
|
194
|
+
"topic": "Short topic name",
|
|
195
|
+
"last_state": "What was the last state of this work",
|
|
196
|
+
"key_files": ["file1.py", "file2.js"],
|
|
197
|
+
"open_questions": ["Question 1"],
|
|
198
|
+
"relevant_learnings": ["Learning reference"]
|
|
199
|
+
}
|
|
200
|
+
],
|
|
201
|
+
|
|
202
|
+
"skills": [
|
|
203
|
+
{
|
|
204
|
+
"id": "SK-SHORT-ID",
|
|
205
|
+
"name": "Human readable name",
|
|
206
|
+
"description": "What this procedure does (1-2 sentences)",
|
|
207
|
+
"steps": ["Step 1", "Step 2", "Step 3"],
|
|
208
|
+
"tags": ["tag1", "tag2"],
|
|
209
|
+
"trigger_patterns": ["trigger phrase 1", "trigger phrase 2"],
|
|
210
|
+
"gotchas": ["Warning or caveat"],
|
|
211
|
+
"mode": "guide|execute|hybrid",
|
|
212
|
+
"execution_level": "none|read-only|local|remote",
|
|
213
|
+
"approval_required": false,
|
|
214
|
+
"params_schema": {
|
|
215
|
+
"param_name": {"type": "string", "required": true}
|
|
216
|
+
},
|
|
217
|
+
"command_template": {
|
|
218
|
+
"argv": ["script.py", "{{param_name}}"]
|
|
219
|
+
},
|
|
220
|
+
"executable_entry": "script.py",
|
|
221
|
+
"script_body": "#!/usr/bin/env python3\n...",
|
|
222
|
+
"source_sessions": ["session1.jsonl"],
|
|
223
|
+
"confidence": 0.85,
|
|
224
|
+
"merge_with": null
|
|
225
|
+
}
|
|
226
|
+
],
|
|
227
|
+
|
|
228
|
+
"skill_evolution_candidates": [
|
|
229
|
+
{
|
|
230
|
+
"id": "SK-EXISTING-ID",
|
|
231
|
+
"reason": "Used successfully 3+ times without major corrections",
|
|
232
|
+
"suggested_mode": "hybrid",
|
|
233
|
+
"suggested_execution_level": "read-only|local|remote",
|
|
234
|
+
"approval_required": true,
|
|
235
|
+
"params_schema": {},
|
|
236
|
+
"script_brief": "What a future script should automate"
|
|
237
|
+
}
|
|
238
|
+
],
|
|
239
|
+
|
|
240
|
+
"actions": [
|
|
241
|
+
{
|
|
242
|
+
"action_type": "learning_add|followup_create|skill_create|morning_briefing_item",
|
|
243
|
+
"action_class": "auto_apply|draft_for_morning",
|
|
244
|
+
"confidence": 0.9,
|
|
245
|
+
"impact": "low|medium|high",
|
|
246
|
+
"reversibility": "reversible|irreversible",
|
|
247
|
+
"evidence": [
|
|
248
|
+
{"type": "transcript", "session_id": "...", "message_index": 42, "quote": "..."}
|
|
249
|
+
],
|
|
250
|
+
"dedupe_key": "unique-deterministic-key",
|
|
251
|
+
"content": {
|
|
252
|
+
"category": "...",
|
|
253
|
+
"title": "...",
|
|
254
|
+
"description": "...",
|
|
255
|
+
"date": "..."
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
],
|
|
259
|
+
|
|
260
|
+
"emotional_day": {
|
|
261
|
+
"mood_arc": "Description of how the user's mood evolved through the day",
|
|
262
|
+
"mood_score": 0.7,
|
|
263
|
+
"recurring_triggers": {
|
|
264
|
+
"frustration": ["trigger1", "trigger2"],
|
|
265
|
+
"flow": ["trigger1"]
|
|
266
|
+
},
|
|
267
|
+
"calibration_recommendation": "Specific recommendation for calibration.json adjustment, or null if no change needed"
|
|
268
|
+
},
|
|
269
|
+
|
|
270
|
+
"productivity_day": {
|
|
271
|
+
"total_corrections": 0,
|
|
272
|
+
"overall_proactivity": "reactive|mixed|proactive",
|
|
273
|
+
"tool_insights": "Key insight about tool usage patterns",
|
|
274
|
+
"systemic_inefficiencies": ["inefficiency1"]
|
|
275
|
+
},
|
|
276
|
+
|
|
277
|
+
"abandoned_projects": [
|
|
278
|
+
{
|
|
279
|
+
"description": "What was abandoned",
|
|
280
|
+
"sessions": ["session1.jsonl"],
|
|
281
|
+
"has_followup": false,
|
|
282
|
+
"recommendation": "Create followup, or ignore, or already handled"
|
|
283
|
+
}
|
|
284
|
+
],
|
|
285
|
+
|
|
286
|
+
"drive_synthesis": {
|
|
287
|
+
"investigated": [
|
|
288
|
+
{
|
|
289
|
+
"signal_id": 1,
|
|
290
|
+
"summary": "What the signal was about",
|
|
291
|
+
"finding": "What investigation revealed",
|
|
292
|
+
"action_taken": "acted|dismissed",
|
|
293
|
+
"outcome": "Concrete result or reason for dismissal"
|
|
294
|
+
}
|
|
295
|
+
],
|
|
296
|
+
"promoted": [
|
|
297
|
+
{
|
|
298
|
+
"signal_id": 2,
|
|
299
|
+
"reason": "Why this signal was promoted from rising to ready"
|
|
300
|
+
}
|
|
301
|
+
],
|
|
302
|
+
"cross_area_connections": [
|
|
303
|
+
{
|
|
304
|
+
"signal_ids": [3, 7],
|
|
305
|
+
"connection": "How these signals from different areas relate"
|
|
306
|
+
}
|
|
307
|
+
]
|
|
308
|
+
},
|
|
309
|
+
|
|
310
|
+
"trust_calibration": {
|
|
311
|
+
"score": 72,
|
|
312
|
+
"reasoning": "Why this score -- based on corrections, completions, autonomy, proactivity, and user satisfaction signals across ALL sessions",
|
|
313
|
+
"highlights": ["What went well"],
|
|
314
|
+
"lowlights": ["What went poorly"],
|
|
315
|
+
"trend": "improving|stable|declining"
|
|
316
|
+
},
|
|
317
|
+
|
|
318
|
+
"summary": "2-3 sentence overall assessment of the day"
|
|
319
|
+
}
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
## Rules
|
|
323
|
+
|
|
324
|
+
- Merge duplicate findings across sessions. If the same correction appears in 2 sessions, create ONE action with higher confidence and evidence from both.
|
|
325
|
+
- `dedupe_key` must be deterministic: same finding on re-run produces the same key.
|
|
326
|
+
- Morning agenda items should be ordered by priority (1 = highest).
|
|
327
|
+
- Context packets are optional -- only create them for topics likely to continue tomorrow.
|
|
328
|
+
- Do NOT use any specific agent name -- refer to "the agent" throughout.
|
|
329
|
+
- If there are no findings worth acting on, return empty arrays. Do not invent problems.
|
|
330
|
+
- Respond in the user's language (check calibration.json if available). JSON keys stay in English, but descriptions, titles, and content fields should be in the user's language.
|
|
331
|
+
|
|
332
|
+
## Extractions File
|
|
333
|
+
|
|
334
|
+
Read the file at this path: {{EXTRACTIONS_FILE}}
|
|
335
|
+
|
|
336
|
+
Also read the context file for global data: {{CONTEXT_FILE}}
|