@shykaruu/jarvis-brain 0.4.0

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.
Files changed (330) hide show
  1. package/LICENSE +153 -0
  2. package/README.md +428 -0
  3. package/bin/jarvis.ts +449 -0
  4. package/package.json +79 -0
  5. package/roles/activity-observer.yaml +60 -0
  6. package/roles/ceo-founder.yaml +144 -0
  7. package/roles/chief-of-staff.yaml +158 -0
  8. package/roles/dev-lead.yaml +182 -0
  9. package/roles/executive-assistant.yaml +77 -0
  10. package/roles/marketing-director.yaml +168 -0
  11. package/roles/personal-assistant.yaml +266 -0
  12. package/roles/research-specialist.yaml +60 -0
  13. package/roles/specialists/content-writer.yaml +53 -0
  14. package/roles/specialists/customer-support.yaml +57 -0
  15. package/roles/specialists/data-analyst.yaml +57 -0
  16. package/roles/specialists/financial-analyst.yaml +56 -0
  17. package/roles/specialists/hr-specialist.yaml +55 -0
  18. package/roles/specialists/legal-advisor.yaml +58 -0
  19. package/roles/specialists/marketing-strategist.yaml +56 -0
  20. package/roles/specialists/project-coordinator.yaml +55 -0
  21. package/roles/specialists/research-analyst.yaml +58 -0
  22. package/roles/specialists/software-engineer.yaml +57 -0
  23. package/roles/specialists/system-administrator.yaml +57 -0
  24. package/roles/system-admin.yaml +76 -0
  25. package/scripts/ensure-bun.cjs +16 -0
  26. package/src/actions/README.md +421 -0
  27. package/src/actions/app-control/desktop-controller.test.ts +26 -0
  28. package/src/actions/app-control/desktop-controller.ts +438 -0
  29. package/src/actions/app-control/interface.ts +64 -0
  30. package/src/actions/app-control/linux.ts +273 -0
  31. package/src/actions/app-control/macos.ts +54 -0
  32. package/src/actions/app-control/sidecar-launcher.test.ts +23 -0
  33. package/src/actions/app-control/sidecar-launcher.ts +286 -0
  34. package/src/actions/app-control/windows.ts +44 -0
  35. package/src/actions/browser/cdp.ts +138 -0
  36. package/src/actions/browser/chrome-launcher.ts +261 -0
  37. package/src/actions/browser/session.ts +506 -0
  38. package/src/actions/browser/stealth.ts +49 -0
  39. package/src/actions/index.ts +20 -0
  40. package/src/actions/terminal/executor.ts +157 -0
  41. package/src/actions/terminal/wsl-bridge.ts +126 -0
  42. package/src/actions/test.ts +93 -0
  43. package/src/actions/tools/agents.ts +363 -0
  44. package/src/actions/tools/builtin.ts +950 -0
  45. package/src/actions/tools/commitments.ts +192 -0
  46. package/src/actions/tools/content.ts +217 -0
  47. package/src/actions/tools/delegate.ts +147 -0
  48. package/src/actions/tools/desktop.test.ts +55 -0
  49. package/src/actions/tools/desktop.ts +305 -0
  50. package/src/actions/tools/documents.ts +169 -0
  51. package/src/actions/tools/goals.ts +376 -0
  52. package/src/actions/tools/local-tools-guard.ts +31 -0
  53. package/src/actions/tools/registry.ts +173 -0
  54. package/src/actions/tools/research.ts +111 -0
  55. package/src/actions/tools/sidecar-list.ts +57 -0
  56. package/src/actions/tools/sidecar-route.ts +105 -0
  57. package/src/actions/tools/workflows.ts +216 -0
  58. package/src/agents/agent.ts +132 -0
  59. package/src/agents/delegation.ts +107 -0
  60. package/src/agents/hierarchy.ts +113 -0
  61. package/src/agents/index.ts +19 -0
  62. package/src/agents/messaging.ts +125 -0
  63. package/src/agents/orchestrator.ts +592 -0
  64. package/src/agents/role-discovery.ts +61 -0
  65. package/src/agents/sub-agent-runner.ts +309 -0
  66. package/src/agents/task-manager.ts +151 -0
  67. package/src/authority/approval-delivery.ts +59 -0
  68. package/src/authority/approval.ts +196 -0
  69. package/src/authority/audit.ts +158 -0
  70. package/src/authority/authority.test.ts +519 -0
  71. package/src/authority/deferred-executor.ts +103 -0
  72. package/src/authority/emergency.ts +66 -0
  73. package/src/authority/engine.ts +301 -0
  74. package/src/authority/index.ts +12 -0
  75. package/src/authority/learning.ts +111 -0
  76. package/src/authority/tool-action-map.ts +74 -0
  77. package/src/awareness/analytics.ts +466 -0
  78. package/src/awareness/awareness.test.ts +332 -0
  79. package/src/awareness/capture-engine.ts +305 -0
  80. package/src/awareness/context-graph.ts +130 -0
  81. package/src/awareness/context-tracker.ts +349 -0
  82. package/src/awareness/index.ts +25 -0
  83. package/src/awareness/intelligence.ts +321 -0
  84. package/src/awareness/ocr-engine.ts +88 -0
  85. package/src/awareness/service.ts +528 -0
  86. package/src/awareness/struggle-detector.ts +342 -0
  87. package/src/awareness/suggestion-engine.ts +476 -0
  88. package/src/awareness/types.ts +201 -0
  89. package/src/cli/autostart.ts +417 -0
  90. package/src/cli/deps.ts +449 -0
  91. package/src/cli/doctor.ts +238 -0
  92. package/src/cli/helpers.ts +401 -0
  93. package/src/cli/onboard.ts +827 -0
  94. package/src/cli/uninstall.test.ts +37 -0
  95. package/src/cli/uninstall.ts +202 -0
  96. package/src/comms/README.md +329 -0
  97. package/src/comms/auth-error.html +48 -0
  98. package/src/comms/channels/discord.ts +228 -0
  99. package/src/comms/channels/signal.ts +56 -0
  100. package/src/comms/channels/telegram.ts +316 -0
  101. package/src/comms/channels/whatsapp.ts +60 -0
  102. package/src/comms/channels.test.ts +173 -0
  103. package/src/comms/dashboard-auth.ts +75 -0
  104. package/src/comms/desktop-notify.ts +114 -0
  105. package/src/comms/example.ts +129 -0
  106. package/src/comms/index.ts +129 -0
  107. package/src/comms/streaming.ts +149 -0
  108. package/src/comms/voice.test.ts +504 -0
  109. package/src/comms/voice.ts +341 -0
  110. package/src/comms/websocket.test.ts +409 -0
  111. package/src/comms/websocket.ts +669 -0
  112. package/src/config/README.md +389 -0
  113. package/src/config/index.ts +6 -0
  114. package/src/config/loader.test.ts +183 -0
  115. package/src/config/loader.ts +148 -0
  116. package/src/config/types.ts +293 -0
  117. package/src/daemon/README.md +232 -0
  118. package/src/daemon/agent-service-interface.ts +9 -0
  119. package/src/daemon/agent-service.ts +667 -0
  120. package/src/daemon/api-routes.ts +3067 -0
  121. package/src/daemon/background-agent-service.ts +396 -0
  122. package/src/daemon/background-agent.test.ts +78 -0
  123. package/src/daemon/channel-service.ts +201 -0
  124. package/src/daemon/commitment-executor.ts +297 -0
  125. package/src/daemon/dashboard-auth.test.ts +170 -0
  126. package/src/daemon/event-classifier.ts +239 -0
  127. package/src/daemon/event-coalescer.ts +123 -0
  128. package/src/daemon/event-reactor.ts +214 -0
  129. package/src/daemon/flock.c +7 -0
  130. package/src/daemon/health.ts +220 -0
  131. package/src/daemon/index.ts +1070 -0
  132. package/src/daemon/llm-settings.test.ts +78 -0
  133. package/src/daemon/llm-settings.ts +450 -0
  134. package/src/daemon/observer-service.ts +150 -0
  135. package/src/daemon/pid.test.ts +283 -0
  136. package/src/daemon/pid.ts +224 -0
  137. package/src/daemon/research-queue.ts +155 -0
  138. package/src/daemon/services.ts +175 -0
  139. package/src/daemon/ws-service.ts +926 -0
  140. package/src/global.d.ts +4 -0
  141. package/src/goals/accountability.ts +240 -0
  142. package/src/goals/awareness-bridge.ts +185 -0
  143. package/src/goals/estimator.ts +185 -0
  144. package/src/goals/events.ts +28 -0
  145. package/src/goals/goals.test.ts +400 -0
  146. package/src/goals/integration.test.ts +329 -0
  147. package/src/goals/nl-builder.test.ts +220 -0
  148. package/src/goals/nl-builder.ts +256 -0
  149. package/src/goals/rhythm.test.ts +177 -0
  150. package/src/goals/rhythm.ts +275 -0
  151. package/src/goals/service.test.ts +135 -0
  152. package/src/goals/service.ts +407 -0
  153. package/src/goals/types.ts +106 -0
  154. package/src/goals/workflow-bridge.ts +96 -0
  155. package/src/integrations/google-api.ts +134 -0
  156. package/src/integrations/google-auth.ts +175 -0
  157. package/src/llm/README.md +291 -0
  158. package/src/llm/anthropic.ts +400 -0
  159. package/src/llm/gemini.ts +380 -0
  160. package/src/llm/groq.ts +406 -0
  161. package/src/llm/history.ts +147 -0
  162. package/src/llm/index.ts +21 -0
  163. package/src/llm/manager.ts +226 -0
  164. package/src/llm/ollama.ts +316 -0
  165. package/src/llm/openai.ts +411 -0
  166. package/src/llm/openrouter.ts +390 -0
  167. package/src/llm/provider.test.ts +487 -0
  168. package/src/llm/provider.ts +61 -0
  169. package/src/llm/test.ts +88 -0
  170. package/src/observers/README.md +278 -0
  171. package/src/observers/calendar.ts +113 -0
  172. package/src/observers/clipboard.ts +136 -0
  173. package/src/observers/email.ts +109 -0
  174. package/src/observers/example.ts +58 -0
  175. package/src/observers/file-watcher.ts +124 -0
  176. package/src/observers/index.ts +159 -0
  177. package/src/observers/notifications.ts +197 -0
  178. package/src/observers/observers.test.ts +203 -0
  179. package/src/observers/processes.ts +225 -0
  180. package/src/personality/README.md +61 -0
  181. package/src/personality/adapter.ts +196 -0
  182. package/src/personality/index.ts +20 -0
  183. package/src/personality/learner.ts +209 -0
  184. package/src/personality/model.ts +132 -0
  185. package/src/personality/personality.test.ts +236 -0
  186. package/src/roles/README.md +252 -0
  187. package/src/roles/authority.ts +120 -0
  188. package/src/roles/example-usage.ts +198 -0
  189. package/src/roles/index.ts +42 -0
  190. package/src/roles/loader.ts +143 -0
  191. package/src/roles/prompt-builder.ts +218 -0
  192. package/src/roles/test-multi.ts +102 -0
  193. package/src/roles/test-role.yaml +77 -0
  194. package/src/roles/test-utils.ts +93 -0
  195. package/src/roles/test.ts +106 -0
  196. package/src/roles/tool-guide.ts +195 -0
  197. package/src/roles/types.ts +36 -0
  198. package/src/roles/utils.ts +200 -0
  199. package/src/scripts/google-setup.ts +168 -0
  200. package/src/sidecar/connection.ts +179 -0
  201. package/src/sidecar/index.ts +6 -0
  202. package/src/sidecar/manager.ts +542 -0
  203. package/src/sidecar/protocol.ts +85 -0
  204. package/src/sidecar/rpc.ts +161 -0
  205. package/src/sidecar/scheduler.ts +136 -0
  206. package/src/sidecar/types.ts +112 -0
  207. package/src/sidecar/validator.ts +144 -0
  208. package/src/sites/builder-tools.ts +215 -0
  209. package/src/sites/dev-server-manager.ts +286 -0
  210. package/src/sites/fixtures/security-test-site/.jarvis-project.json +6 -0
  211. package/src/sites/fixtures/security-test-site/Makefile +15 -0
  212. package/src/sites/fixtures/security-test-site/README.md +18 -0
  213. package/src/sites/fixtures/security-test-site/index.html +12 -0
  214. package/src/sites/fixtures/security-test-site/index.ts +16 -0
  215. package/src/sites/fixtures/security-test-site/package.json +13 -0
  216. package/src/sites/fixtures/security-test-site/src/app.tsx +780 -0
  217. package/src/sites/fixtures/security-test-site/tsconfig.json +10 -0
  218. package/src/sites/git-manager.ts +240 -0
  219. package/src/sites/github-manager.ts +355 -0
  220. package/src/sites/index.ts +25 -0
  221. package/src/sites/project-manager.ts +389 -0
  222. package/src/sites/proxy.ts +133 -0
  223. package/src/sites/service.ts +136 -0
  224. package/src/sites/templates.ts +169 -0
  225. package/src/sites/types.ts +89 -0
  226. package/src/user/profile-followup.test.ts +84 -0
  227. package/src/user/profile-followup.ts +185 -0
  228. package/src/user/profile.ts +224 -0
  229. package/src/vault/README.md +110 -0
  230. package/src/vault/awareness.ts +341 -0
  231. package/src/vault/commitments.ts +299 -0
  232. package/src/vault/content-pipeline.ts +270 -0
  233. package/src/vault/conversations.ts +173 -0
  234. package/src/vault/dashboard-sessions.ts +44 -0
  235. package/src/vault/documents.ts +130 -0
  236. package/src/vault/entities.ts +185 -0
  237. package/src/vault/extractor.test.ts +356 -0
  238. package/src/vault/extractor.ts +345 -0
  239. package/src/vault/facts.ts +190 -0
  240. package/src/vault/goals.ts +477 -0
  241. package/src/vault/index.ts +87 -0
  242. package/src/vault/keychain.ts +99 -0
  243. package/src/vault/observations.ts +115 -0
  244. package/src/vault/relationships.ts +178 -0
  245. package/src/vault/retrieval.test.ts +139 -0
  246. package/src/vault/retrieval.ts +258 -0
  247. package/src/vault/schema.ts +709 -0
  248. package/src/vault/settings.ts +38 -0
  249. package/src/vault/user-profile.test.ts +113 -0
  250. package/src/vault/user-profile.ts +176 -0
  251. package/src/vault/vectors.ts +92 -0
  252. package/src/vault/webapp-template-seeds.ts +116 -0
  253. package/src/vault/webapp-templates.ts +244 -0
  254. package/src/vault/workflows.ts +403 -0
  255. package/src/workflows/auto-suggest.ts +290 -0
  256. package/src/workflows/engine.ts +366 -0
  257. package/src/workflows/events.ts +24 -0
  258. package/src/workflows/executor.ts +207 -0
  259. package/src/workflows/nl-builder.ts +198 -0
  260. package/src/workflows/nodes/actions/agent-task.ts +73 -0
  261. package/src/workflows/nodes/actions/calendar-action.ts +85 -0
  262. package/src/workflows/nodes/actions/code-execution.ts +73 -0
  263. package/src/workflows/nodes/actions/discord.ts +77 -0
  264. package/src/workflows/nodes/actions/file-write.ts +73 -0
  265. package/src/workflows/nodes/actions/gmail.ts +69 -0
  266. package/src/workflows/nodes/actions/http-request.ts +117 -0
  267. package/src/workflows/nodes/actions/notification.ts +85 -0
  268. package/src/workflows/nodes/actions/run-tool.ts +55 -0
  269. package/src/workflows/nodes/actions/send-message.ts +82 -0
  270. package/src/workflows/nodes/actions/shell-command.ts +76 -0
  271. package/src/workflows/nodes/actions/telegram.ts +60 -0
  272. package/src/workflows/nodes/builtin.ts +119 -0
  273. package/src/workflows/nodes/error/error-handler.ts +37 -0
  274. package/src/workflows/nodes/error/fallback.ts +47 -0
  275. package/src/workflows/nodes/error/retry.ts +82 -0
  276. package/src/workflows/nodes/logic/delay.ts +42 -0
  277. package/src/workflows/nodes/logic/if-else.ts +41 -0
  278. package/src/workflows/nodes/logic/loop.ts +90 -0
  279. package/src/workflows/nodes/logic/merge.ts +38 -0
  280. package/src/workflows/nodes/logic/race.ts +40 -0
  281. package/src/workflows/nodes/logic/switch.ts +59 -0
  282. package/src/workflows/nodes/logic/template-render.ts +53 -0
  283. package/src/workflows/nodes/logic/variable-get.ts +37 -0
  284. package/src/workflows/nodes/logic/variable-set.ts +59 -0
  285. package/src/workflows/nodes/registry.ts +99 -0
  286. package/src/workflows/nodes/transform/aggregate.ts +99 -0
  287. package/src/workflows/nodes/transform/csv-parse.ts +70 -0
  288. package/src/workflows/nodes/transform/json-parse.ts +63 -0
  289. package/src/workflows/nodes/transform/map-filter.ts +84 -0
  290. package/src/workflows/nodes/transform/regex-match.ts +89 -0
  291. package/src/workflows/nodes/triggers/calendar.ts +33 -0
  292. package/src/workflows/nodes/triggers/clipboard.ts +32 -0
  293. package/src/workflows/nodes/triggers/cron.ts +40 -0
  294. package/src/workflows/nodes/triggers/email.ts +40 -0
  295. package/src/workflows/nodes/triggers/file-change.ts +45 -0
  296. package/src/workflows/nodes/triggers/git.ts +46 -0
  297. package/src/workflows/nodes/triggers/manual.ts +23 -0
  298. package/src/workflows/nodes/triggers/poll.ts +81 -0
  299. package/src/workflows/nodes/triggers/process.ts +44 -0
  300. package/src/workflows/nodes/triggers/screen-event.ts +37 -0
  301. package/src/workflows/nodes/triggers/webhook.ts +39 -0
  302. package/src/workflows/safe-eval.ts +139 -0
  303. package/src/workflows/template.ts +118 -0
  304. package/src/workflows/triggers/cron.ts +311 -0
  305. package/src/workflows/triggers/manager.ts +285 -0
  306. package/src/workflows/triggers/observer-bridge.ts +172 -0
  307. package/src/workflows/triggers/poller.ts +201 -0
  308. package/src/workflows/triggers/screen-condition.ts +218 -0
  309. package/src/workflows/triggers/triggers.test.ts +740 -0
  310. package/src/workflows/triggers/webhook.ts +191 -0
  311. package/src/workflows/types.ts +133 -0
  312. package/src/workflows/variables.ts +72 -0
  313. package/src/workflows/workflows.test.ts +383 -0
  314. package/src/workflows/yaml.ts +104 -0
  315. package/ui/dist/index-3gr23jt9.js +112614 -0
  316. package/ui/dist/index-9vmj8127.css +14239 -0
  317. package/ui/dist/index-hy9pc1gm.js +112873 -0
  318. package/ui/dist/index-j2ep5d1w.js +112374 -0
  319. package/ui/dist/index-jt00vjqs.js +112858 -0
  320. package/ui/dist/index-k9ymx5qb.js +112374 -0
  321. package/ui/dist/index.html +16 -0
  322. package/ui/public/audio/pcm-capture-processor.js +11 -0
  323. package/ui/public/openwakeword/models/embedding_model.onnx +0 -0
  324. package/ui/public/openwakeword/models/hey_jarvis_v0.1.onnx +0 -0
  325. package/ui/public/openwakeword/models/melspectrogram.onnx +0 -0
  326. package/ui/public/openwakeword/models/silero_vad.onnx +0 -0
  327. package/ui/public/ort/ort-wasm-simd-threaded.jsep.mjs +106 -0
  328. package/ui/public/ort/ort-wasm-simd-threaded.jsep.wasm +0 -0
  329. package/ui/public/ort/ort-wasm-simd-threaded.mjs +59 -0
  330. package/ui/public/ort/ort-wasm-simd-threaded.wasm +0 -0
@@ -0,0 +1,407 @@
1
+ /**
2
+ * GoalService — Core service for M16 Autonomous Goal Pursuit
3
+ *
4
+ * Manages goal lifecycle, daily rhythm (morning plan + evening review),
5
+ * accountability checks, health recalculation, and escalation.
6
+ * Implements the Service interface for daemon integration.
7
+ */
8
+
9
+ import type { Service, ServiceStatus } from '../daemon/services.ts';
10
+ import type { GoalEvent } from './events.ts';
11
+ import type { GoalConfig } from '../config/types.ts';
12
+ import type { Goal, GoalLevel, GoalStatus, GoalHealth } from './types.ts';
13
+ import type { DailyRhythm } from './rhythm.ts';
14
+ import * as vault from '../vault/goals.ts';
15
+
16
+ export class GoalService implements Service {
17
+ name = 'goals';
18
+ private _status: ServiceStatus = 'stopped';
19
+ private config: GoalConfig;
20
+ private eventCallback: ((event: GoalEvent) => void) | null = null;
21
+ private chatCallback: ((text: string) => void) | null = null;
22
+ private rhythm: DailyRhythm | null = null;
23
+
24
+ // Timers
25
+ private rhythmTimer: Timer | null = null; // daily rhythm check (60s)
26
+ private accountabilityTimer: Timer | null = null; // accountability check (5min)
27
+ private healthTimer: Timer | null = null; // health recalc (15min)
28
+
29
+ constructor(config: GoalConfig) {
30
+ this.config = config;
31
+ }
32
+
33
+ /**
34
+ * Set callback for broadcasting goal events via WebSocket.
35
+ */
36
+ setEventCallback(cb: (event: GoalEvent) => void): void {
37
+ this.eventCallback = cb;
38
+ }
39
+
40
+ /**
41
+ * Set callback for sending proactive messages to the user's chat.
42
+ */
43
+ setChatCallback(cb: (text: string) => void): void {
44
+ this.chatCallback = cb;
45
+ }
46
+
47
+ /**
48
+ * Set the DailyRhythm instance for morning/evening planning.
49
+ */
50
+ setRhythm(rhythm: DailyRhythm): void {
51
+ this.rhythm = rhythm;
52
+ }
53
+
54
+ private emit(event: GoalEvent): void {
55
+ if (this.eventCallback) {
56
+ this.eventCallback(event);
57
+ }
58
+ }
59
+
60
+ async start(): Promise<void> {
61
+ if (!this.config.enabled) {
62
+ this._status = 'stopped';
63
+ console.log('[GoalService] Disabled by config');
64
+ return;
65
+ }
66
+
67
+ this._status = 'starting';
68
+
69
+ // Daily rhythm check — runs every 60s to detect morning/evening windows
70
+ this.rhythmTimer = setInterval(() => {
71
+ this.checkDailyRhythm().catch(err =>
72
+ console.error('[GoalService] Rhythm check error:', err)
73
+ );
74
+ }, 60_000);
75
+
76
+ // Accountability check — runs every 5min for escalation monitoring
77
+ this.accountabilityTimer = setInterval(() => {
78
+ this.checkAccountability().catch(err =>
79
+ console.error('[GoalService] Accountability check error:', err)
80
+ );
81
+ }, 5 * 60_000);
82
+
83
+ // Health recalculation — runs every 15min
84
+ this.healthTimer = setInterval(() => {
85
+ this.recalculateAllHealth().catch(err =>
86
+ console.error('[GoalService] Health recalc error:', err)
87
+ );
88
+ }, 15 * 60_000);
89
+
90
+ this._status = 'running';
91
+ console.log('[GoalService] Started (rhythm=60s, accountability=5min, health=15min)');
92
+ }
93
+
94
+ async stop(): Promise<void> {
95
+ this._status = 'stopping';
96
+
97
+ if (this.rhythmTimer) { clearInterval(this.rhythmTimer); this.rhythmTimer = null; }
98
+ if (this.accountabilityTimer) { clearInterval(this.accountabilityTimer); this.accountabilityTimer = null; }
99
+ if (this.healthTimer) { clearInterval(this.healthTimer); this.healthTimer = null; }
100
+
101
+ this._status = 'stopped';
102
+ console.log('[GoalService] Stopped');
103
+ }
104
+
105
+ status(): ServiceStatus {
106
+ return this._status;
107
+ }
108
+
109
+ // ── Goal CRUD with events ─────────────────────────────────────────
110
+
111
+ createGoal(title: string, level: GoalLevel, opts?: Parameters<typeof vault.createGoal>[2]): Goal {
112
+ const goal = vault.createGoal(title, level, opts);
113
+ this.emit({
114
+ type: 'goal_created',
115
+ goalId: goal.id,
116
+ data: { title, level, parent_id: goal.parent_id },
117
+ timestamp: Date.now(),
118
+ });
119
+ return goal;
120
+ }
121
+
122
+ getGoal(id: string): Goal | null {
123
+ return vault.getGoal(id);
124
+ }
125
+
126
+ updateGoal(id: string, updates: Parameters<typeof vault.updateGoal>[1]): Goal | null {
127
+ const goal = vault.updateGoal(id, updates);
128
+ if (goal) {
129
+ this.emit({
130
+ type: 'goal_updated',
131
+ goalId: id,
132
+ data: { updates },
133
+ timestamp: Date.now(),
134
+ });
135
+ }
136
+ return goal;
137
+ }
138
+
139
+ scoreGoal(id: string, score: number, reason: string, source = 'user'): Goal | null {
140
+ const goal = vault.updateGoalScore(id, score, reason, source);
141
+ if (goal) {
142
+ this.emit({
143
+ type: 'goal_scored',
144
+ goalId: id,
145
+ data: { score: goal.score, reason, source },
146
+ timestamp: Date.now(),
147
+ });
148
+ }
149
+ return goal;
150
+ }
151
+
152
+ updateStatus(id: string, status: GoalStatus): Goal | null {
153
+ const goal = vault.updateGoalStatus(id, status);
154
+ if (!goal) return null;
155
+
156
+ const eventType = status === 'completed' ? 'goal_completed'
157
+ : status === 'failed' ? 'goal_failed'
158
+ : status === 'killed' ? 'goal_killed'
159
+ : 'goal_status_changed';
160
+
161
+ this.emit({
162
+ type: eventType,
163
+ goalId: id,
164
+ data: { status },
165
+ timestamp: Date.now(),
166
+ });
167
+
168
+ // Extract goal completion data for vault knowledge
169
+ if (status === 'completed' || status === 'failed' || status === 'killed') {
170
+ try {
171
+ const { extractGoalCompletion } = require('../vault/extractor.ts');
172
+ extractGoalCompletion(goal);
173
+ } catch {
174
+ // Extractor may not be available — ignore
175
+ }
176
+ }
177
+
178
+ return goal;
179
+ }
180
+
181
+ updateHealth(id: string, health: GoalHealth): Goal | null {
182
+ const goal = vault.updateGoalHealth(id, health);
183
+ if (goal) {
184
+ this.emit({
185
+ type: 'goal_health_changed',
186
+ goalId: id,
187
+ data: { health },
188
+ timestamp: Date.now(),
189
+ });
190
+ }
191
+ return goal;
192
+ }
193
+
194
+ deleteGoal(id: string): boolean {
195
+ const result = vault.deleteGoal(id);
196
+ if (result) {
197
+ this.emit({
198
+ type: 'goal_deleted',
199
+ goalId: id,
200
+ data: {},
201
+ timestamp: Date.now(),
202
+ });
203
+ }
204
+ return result;
205
+ }
206
+
207
+ // ── Daily Rhythm ──────────────────────────────────────────────────
208
+
209
+ /**
210
+ * Check if we're in a morning or evening window and trigger check-ins.
211
+ * Calls DailyRhythm to generate the plan/review and sends the message to chat.
212
+ */
213
+ private async checkDailyRhythm(): Promise<void> {
214
+ const now = new Date();
215
+ const hour = now.getHours();
216
+
217
+ const morningWindow = this.config.morning_window ?? { start: 7, end: 9 };
218
+ const eveningWindow = this.config.evening_window ?? { start: 20, end: 22 };
219
+
220
+ // Check morning window
221
+ if (hour >= morningWindow.start && hour < morningWindow.end) {
222
+ const existing = vault.getTodayCheckIn('morning_plan');
223
+ if (!existing) {
224
+ console.log('[GoalService] Morning plan window — running morning plan');
225
+ if (this.rhythm) {
226
+ try {
227
+ const result = await this.rhythm.runMorningPlan();
228
+ if (this.chatCallback) {
229
+ const parts: string[] = [];
230
+ parts.push(`**Morning Plan**\n`);
231
+ parts.push(result.message);
232
+ if (result.warnings.length > 0) {
233
+ parts.push(`\n\n**Warnings:**`);
234
+ for (const w of result.warnings) parts.push(`- ${w}`);
235
+ }
236
+ if (result.focusAreas.length > 0) {
237
+ parts.push(`\n\n**Focus Areas:**`);
238
+ for (const f of result.focusAreas) parts.push(`- ${f}`);
239
+ }
240
+ if (result.dailyActions.length > 0) {
241
+ parts.push(`\n\n**Today's Actions:**`);
242
+ for (const a of result.dailyActions) parts.push(`- ${a}`);
243
+ }
244
+ this.chatCallback(parts.join('\n'));
245
+ }
246
+ } catch (err) {
247
+ console.error('[GoalService] Morning plan failed:', err);
248
+ }
249
+ }
250
+ }
251
+ }
252
+
253
+ // Check evening window
254
+ if (hour >= eveningWindow.start && hour < eveningWindow.end) {
255
+ const existing = vault.getTodayCheckIn('evening_review');
256
+ if (!existing) {
257
+ console.log('[GoalService] Evening review window — running evening review');
258
+ if (this.rhythm) {
259
+ try {
260
+ const result = await this.rhythm.runEveningReview();
261
+ if (this.chatCallback) {
262
+ const parts: string[] = [];
263
+ parts.push(`**Evening Review**\n`);
264
+ parts.push(result.message);
265
+ parts.push(`\n\n${result.assessment}`);
266
+ if (result.scoreUpdates.length > 0) {
267
+ parts.push(`\n\n**Score Updates:**`);
268
+ for (const u of result.scoreUpdates) {
269
+ parts.push(`- ${u.reason} (${u.newScore.toFixed(1)})`);
270
+ }
271
+ }
272
+ this.chatCallback(parts.join('\n'));
273
+ }
274
+ } catch (err) {
275
+ console.error('[GoalService] Evening review failed:', err);
276
+ }
277
+ }
278
+ }
279
+ }
280
+ }
281
+
282
+ // ── Accountability ────────────────────────────────────────────────
283
+
284
+ /**
285
+ * Check active goals for escalation needs.
286
+ * Full drill-sergeant logic is in src/goals/accountability.ts (Phase 4).
287
+ */
288
+ private async checkAccountability(): Promise<void> {
289
+ const needingEscalation = vault.getGoalsNeedingEscalation();
290
+ const overdue = vault.getOverdueGoals();
291
+
292
+ for (const goal of needingEscalation) {
293
+ if (goal.escalation_stage === 'none') {
294
+ // Auto-escalate to 'pressure' stage
295
+ const escalationWeeks = this.config.escalation_weeks ?? { pressure: 1, root_cause: 3, suggest_kill: 4 };
296
+ const behindSince = goal.updated_at;
297
+ const weeksBehind = (Date.now() - behindSince) / (7 * 24 * 60 * 60 * 1000);
298
+
299
+ if (weeksBehind >= escalationWeeks.pressure) {
300
+ vault.updateGoalEscalation(goal.id, 'pressure');
301
+ this.emit({
302
+ type: 'goal_escalated',
303
+ goalId: goal.id,
304
+ data: { stage: 'pressure', weeksBehind },
305
+ timestamp: Date.now(),
306
+ });
307
+ }
308
+ } else if (goal.escalation_stage === 'pressure') {
309
+ const escalationWeeks = this.config.escalation_weeks ?? { pressure: 1, root_cause: 3, suggest_kill: 4 };
310
+ const startedAt = goal.escalation_started_at ?? goal.updated_at;
311
+ const weeksSinceEscalation = (Date.now() - startedAt) / (7 * 24 * 60 * 60 * 1000);
312
+
313
+ if (weeksSinceEscalation >= escalationWeeks.root_cause) {
314
+ vault.updateGoalEscalation(goal.id, 'root_cause');
315
+ this.emit({
316
+ type: 'goal_escalated',
317
+ goalId: goal.id,
318
+ data: { stage: 'root_cause', weeksSinceEscalation },
319
+ timestamp: Date.now(),
320
+ });
321
+ }
322
+ } else if (goal.escalation_stage === 'root_cause') {
323
+ const escalationWeeks = this.config.escalation_weeks ?? { pressure: 1, root_cause: 3, suggest_kill: 4 };
324
+ const startedAt = goal.escalation_started_at ?? goal.updated_at;
325
+ const weeksSinceEscalation = (Date.now() - startedAt) / (7 * 24 * 60 * 60 * 1000);
326
+
327
+ if (weeksSinceEscalation >= escalationWeeks.suggest_kill) {
328
+ vault.updateGoalEscalation(goal.id, 'suggest_kill');
329
+ this.emit({
330
+ type: 'goal_escalated',
331
+ goalId: goal.id,
332
+ data: { stage: 'suggest_kill', weeksSinceEscalation },
333
+ timestamp: Date.now(),
334
+ });
335
+ }
336
+ }
337
+ }
338
+
339
+ // Log overdue goals (Phase 4 will handle the drill-sergeant messaging)
340
+ if (overdue.length > 0) {
341
+ console.log(`[GoalService] ${overdue.length} overdue goal(s) detected`);
342
+ }
343
+ }
344
+
345
+ // ── Health Recalculation ──────────────────────────────────────────
346
+
347
+ /**
348
+ * Recalculate health for all active goals based on score and deadline.
349
+ */
350
+ private async recalculateAllHealth(): Promise<void> {
351
+ const activeGoals = vault.findGoals({ status: 'active' });
352
+ let changed = 0;
353
+
354
+ for (const goal of activeGoals) {
355
+ const newHealth = this.calculateHealth(goal);
356
+ if (newHealth !== goal.health) {
357
+ this.updateHealth(goal.id, newHealth);
358
+ changed++;
359
+ }
360
+ }
361
+
362
+ if (changed > 0) {
363
+ console.log(`[GoalService] Health recalculated: ${changed} goal(s) changed`);
364
+ }
365
+ }
366
+
367
+ /**
368
+ * Calculate health for a single goal based on score progress vs time elapsed.
369
+ */
370
+ private calculateHealth(goal: Goal): GoalHealth {
371
+ // If no deadline, base purely on score
372
+ if (!goal.deadline) {
373
+ if (goal.score >= 0.6) return 'on_track';
374
+ if (goal.score >= 0.3) return 'at_risk';
375
+ return 'behind';
376
+ }
377
+
378
+ const now = Date.now();
379
+ const startTime = goal.started_at ?? goal.created_at;
380
+ const totalDuration = goal.deadline - startTime;
381
+ const elapsed = now - startTime;
382
+
383
+ // If past deadline
384
+ if (now > goal.deadline) {
385
+ if (goal.score >= 0.7) return 'on_track'; // nearly done
386
+ if (goal.score >= 0.4) return 'behind';
387
+ return 'critical';
388
+ }
389
+
390
+ // Ratio: how far along are we in time vs score
391
+ const timeRatio = totalDuration > 0 ? elapsed / totalDuration : 0;
392
+ const expectedScore = timeRatio * 0.7; // expecting 0.7 = good at deadline
393
+
394
+ const gap = expectedScore - goal.score;
395
+
396
+ if (gap <= 0) return 'on_track'; // ahead of pace
397
+ if (gap <= 0.15) return 'at_risk'; // slightly behind
398
+ if (gap <= 0.3) return 'behind'; // significantly behind
399
+ return 'critical'; // way behind
400
+ }
401
+
402
+ // ── Metrics ───────────────────────────────────────────────────────
403
+
404
+ getMetrics() {
405
+ return vault.getGoalMetrics();
406
+ }
407
+ }
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Goal Pursuit Types for M16 — Autonomous Goal Pursuit & Long-Term Planning
3
+ *
4
+ * OKR-style hierarchical goal system with Google-style 0.0-1.0 scoring.
5
+ * Goals nest: objective → key_result → milestone → task → daily_action.
6
+ */
7
+
8
+ // ── Enums ───────────────────────────────────────────────────────────
9
+
10
+ export type GoalLevel = 'objective' | 'key_result' | 'milestone' | 'task' | 'daily_action';
11
+
12
+ export type GoalStatus = 'draft' | 'active' | 'paused' | 'completed' | 'failed' | 'killed';
13
+
14
+ export type GoalHealth = 'on_track' | 'at_risk' | 'behind' | 'critical';
15
+
16
+ export type TimeHorizon = 'life' | 'yearly' | 'quarterly' | 'monthly' | 'weekly' | 'daily';
17
+
18
+ export type EscalationStage = 'none' | 'pressure' | 'root_cause' | 'suggest_kill';
19
+
20
+ export type ProgressType = 'manual' | 'auto_detected' | 'review' | 'system';
21
+
22
+ export type CheckInType = 'morning_plan' | 'evening_review';
23
+
24
+ // ── Core Types ──────────────────────────────────────────────────────
25
+
26
+ export type Goal = {
27
+ id: string;
28
+ parent_id: string | null;
29
+ level: GoalLevel;
30
+ title: string;
31
+ description: string;
32
+ success_criteria: string;
33
+ time_horizon: TimeHorizon;
34
+ score: number; // 0.0-1.0 OKR score (0.7 = good)
35
+ score_reason: string | null;
36
+ status: GoalStatus;
37
+ health: GoalHealth;
38
+ deadline: number | null; // epoch ms
39
+ started_at: number | null;
40
+ estimated_hours: number | null;
41
+ actual_hours: number;
42
+ authority_level: number; // min authority for actions within this goal
43
+ tags: string[];
44
+ dependencies: string[]; // goal IDs that must complete first
45
+ escalation_stage: EscalationStage;
46
+ escalation_started_at: number | null;
47
+ sort_order: number;
48
+ created_at: number;
49
+ updated_at: number;
50
+ completed_at: number | null;
51
+ };
52
+
53
+ export type GoalProgressEntry = {
54
+ id: string;
55
+ goal_id: string;
56
+ type: ProgressType;
57
+ score_before: number;
58
+ score_after: number;
59
+ note: string;
60
+ source: string; // 'user', 'awareness', 'daily_review', etc.
61
+ created_at: number;
62
+ };
63
+
64
+ export type GoalCheckIn = {
65
+ id: string;
66
+ type: CheckInType;
67
+ summary: string;
68
+ goals_reviewed: string[]; // goal IDs
69
+ actions_planned: string[]; // for morning
70
+ actions_completed: string[]; // for evening
71
+ created_at: number;
72
+ };
73
+
74
+ export type GoalEstimate = {
75
+ llm_estimate_hours: number;
76
+ historical_estimate_hours: number | null;
77
+ final_estimate_hours: number;
78
+ confidence: number; // 0.0-1.0
79
+ reasoning: string;
80
+ similar_past_goals: string[]; // vault entity IDs
81
+ };
82
+
83
+ // ── Query Types ─────────────────────────────────────────────────────
84
+
85
+ export type GoalQuery = {
86
+ status?: GoalStatus;
87
+ level?: GoalLevel;
88
+ parent_id?: string | null;
89
+ health?: GoalHealth;
90
+ tag?: string;
91
+ time_horizon?: TimeHorizon;
92
+ limit?: number;
93
+ };
94
+
95
+ export type GoalUpdate = {
96
+ title?: string;
97
+ description?: string;
98
+ success_criteria?: string;
99
+ time_horizon?: TimeHorizon;
100
+ deadline?: number | null;
101
+ estimated_hours?: number | null;
102
+ authority_level?: number;
103
+ tags?: string[];
104
+ dependencies?: string[];
105
+ sort_order?: number;
106
+ };
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Goal → Workflow Bridge
3
+ *
4
+ * Auto-generates cron-triggered workflows for morning plan and evening review.
5
+ * Also supports creating recurring task workflows for goals with repeating work.
6
+ */
7
+
8
+ import type { GoalConfig } from '../config/types.ts';
9
+
10
+ /**
11
+ * Workflow definition for the goal system's daily rhythm.
12
+ * These can be registered with the TriggerManager when both
13
+ * the workflow engine and goal service are available.
14
+ */
15
+ export type GoalWorkflowDefinition = {
16
+ id: string;
17
+ name: string;
18
+ description: string;
19
+ triggerType: 'cron';
20
+ cronExpression: string;
21
+ action: 'morning_plan' | 'evening_review';
22
+ };
23
+
24
+ /**
25
+ * Generate workflow definitions for the daily rhythm check-ins.
26
+ * Returns cron-triggered workflow specs that can be registered with the engine.
27
+ */
28
+ export function generateRhythmWorkflows(config: GoalConfig): GoalWorkflowDefinition[] {
29
+ if (!config.enabled) return [];
30
+
31
+ const workflows: GoalWorkflowDefinition[] = [];
32
+
33
+ const morningWindow = config.morning_window ?? { start: 7, end: 9 };
34
+ const eveningWindow = config.evening_window ?? { start: 20, end: 22 };
35
+
36
+ // Morning plan: fire at the start of the morning window
37
+ workflows.push({
38
+ id: 'goal_morning_plan',
39
+ name: 'Morning Goal Plan',
40
+ description: 'Automated morning planning session — reviews active goals, generates daily actions, and sets focus areas.',
41
+ triggerType: 'cron',
42
+ cronExpression: `0 ${morningWindow.start} * * *`, // e.g., "0 7 * * *"
43
+ action: 'morning_plan',
44
+ });
45
+
46
+ // Evening review: fire at the start of the evening window
47
+ workflows.push({
48
+ id: 'goal_evening_review',
49
+ name: 'Evening Goal Review',
50
+ description: 'Automated evening review — scores daily progress, generates accountability assessment, and updates goal health.',
51
+ triggerType: 'cron',
52
+ cronExpression: `0 ${eveningWindow.start} * * *`, // e.g., "0 20 * * *"
53
+ action: 'evening_review',
54
+ });
55
+
56
+ return workflows;
57
+ }
58
+
59
+ /**
60
+ * Register goal rhythm workflows with the trigger manager.
61
+ * This bridges goal check-ins with the workflow execution system.
62
+ *
63
+ * When the workflow fires, it calls the goalService's daily rhythm methods.
64
+ */
65
+ export function registerGoalWorkflows(
66
+ goalWorkflows: GoalWorkflowDefinition[],
67
+ triggerManager: { fireTrigger: (workflowId: string, triggerType: string, data?: Record<string, unknown>) => void },
68
+ ): void {
69
+ // Note: The actual cron scheduling is handled by the GoalService's own timers
70
+ // (checkDailyRhythm runs every 60s and checks the time window).
71
+ // This function exists for future use when we want to create
72
+ // full workflow graph executions for morning/evening routines.
73
+ //
74
+ // For now, we just log the available workflows.
75
+ for (const wf of goalWorkflows) {
76
+ console.log(`[GoalWorkflowBridge] Registered: ${wf.name} (${wf.cronExpression})`);
77
+ }
78
+ }
79
+
80
+ /**
81
+ * Handle a goal workflow trigger firing.
82
+ * Called from the goal service when daily rhythm check-ins happen.
83
+ */
84
+ export async function handleGoalWorkflowTrigger(
85
+ action: 'morning_plan' | 'evening_review',
86
+ goalService: { getGoal: (id: string) => unknown },
87
+ onComplete?: (result: Record<string, unknown>) => void,
88
+ ): Promise<void> {
89
+ console.log(`[GoalWorkflowBridge] Executing ${action}`);
90
+
91
+ // The actual planning/review logic is in rhythm.ts
92
+ // This bridge just provides the workflow integration layer
93
+ if (onComplete) {
94
+ onComplete({ action, completedAt: Date.now() });
95
+ }
96
+ }