@mamdouh-aboammar/agentic-workflow 1.2.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 (118) hide show
  1. package/.claude-plugin/plugin.json +10 -0
  2. package/.codex-plugin/plugin.json +13 -0
  3. package/.skills.json +19 -0
  4. package/AGENTS.md +1344 -0
  5. package/CLAUDE.md +178 -0
  6. package/GEMINI.md +102 -0
  7. package/LICENSE +21 -0
  8. package/README.md +350 -0
  9. package/SKILL.md +132 -0
  10. package/bin/agentic-hooks.sh +79 -0
  11. package/bin/cli.js +1060 -0
  12. package/core/__init__.py +52 -0
  13. package/core/ai_evaluator.py +117 -0
  14. package/core/autopilot_engine.py +368 -0
  15. package/core/clean_code_guard.py +188 -0
  16. package/core/engine_py/__init__.py +29 -0
  17. package/core/engine_py/agent_worker.py +136 -0
  18. package/core/engine_py/decider.py +150 -0
  19. package/core/engine_py/energy.py +45 -0
  20. package/core/engine_py/event_bus.py +63 -0
  21. package/core/engine_py/executor.py +186 -0
  22. package/core/engine_py/models.py +193 -0
  23. package/core/engine_py/queue.py +314 -0
  24. package/core/engine_py/runner.py +116 -0
  25. package/core/engine_py/system_workers.py +70 -0
  26. package/core/engine_py/toon_adapter.py +586 -0
  27. package/core/engine_py/verification_controller.py +208 -0
  28. package/core/engine_py/worker.py +167 -0
  29. package/core/engine_spec/event_schema.json +65 -0
  30. package/core/engine_spec/example_workflow.yaml +73 -0
  31. package/core/engine_spec/workflow_schema.json +127 -0
  32. package/core/hooks/__init__.py +29 -0
  33. package/core/hooks/adapters/__init__.py +25 -0
  34. package/core/hooks/adapters/claude_adapter.py +83 -0
  35. package/core/hooks/adapters/cli_agent_adapter.py +82 -0
  36. package/core/hooks/adapters/codex_adapter.py +78 -0
  37. package/core/hooks/adapters/cursor_adapter.py +73 -0
  38. package/core/hooks/adapters/gemini_adapter.py +93 -0
  39. package/core/hooks/adapters/homebrew_adapter.py +69 -0
  40. package/core/hooks/adapters/mcp_proxy.py +133 -0
  41. package/core/hooks/adapters/shell_adapter.py +65 -0
  42. package/core/hooks/dispatcher.py +118 -0
  43. package/core/hooks/policy_engine.py +375 -0
  44. package/core/hooks/session_end.py +141 -0
  45. package/core/hooks/types.py +147 -0
  46. package/core/integrations/__init__.py +28 -0
  47. package/core/integrations/installer.py +225 -0
  48. package/core/integrations/lifecycle_director.py +175 -0
  49. package/core/integrations/registry.py +105 -0
  50. package/core/multi_agent_system.py +164 -0
  51. package/core/skills_indexer.py +742 -0
  52. package/core/system/__init__.py +25 -0
  53. package/core/system/announcements.py +72 -0
  54. package/core/system/dependencies.py +69 -0
  55. package/core/system/doctor.py +171 -0
  56. package/core/system/health.py +144 -0
  57. package/core/system/installer.py +137 -0
  58. package/core/system/notifications.py +97 -0
  59. package/core/system/refresher.py +110 -0
  60. package/core/system/updater.py +167 -0
  61. package/core/system/version_tracker.py +65 -0
  62. package/docs/architecture_plan.md +7 -0
  63. package/docs/guides/failure-recovery.md +714 -0
  64. package/docs/implementation_summary.md +10 -0
  65. package/docs/protocols/autopilot-execution.md +148 -0
  66. package/docs/protocols/code-change-protocol.md +49 -0
  67. package/docs/protocols/context-preservation-detail.md +114 -0
  68. package/docs/protocols/quality-gates.md +110 -0
  69. package/docs/protocols/ulw-mode.md +60 -0
  70. package/docs/research_findings.md +10 -0
  71. package/docs/solutions/autonomous-autopilot-engine-architecture.md +38 -0
  72. package/install.sh +111 -0
  73. package/marketplace.json +37 -0
  74. package/package.json +81 -0
  75. package/skills/agentic-workflow/SKILL.md +132 -0
  76. package/skills/agentic-workflow/skill-spec.json +100 -0
  77. package/soul.md +445 -0
  78. package/src/engine_ts/decider.ts +186 -0
  79. package/src/engine_ts/event-bus.ts +57 -0
  80. package/src/engine_ts/executor.ts +262 -0
  81. package/src/engine_ts/index.ts +12 -0
  82. package/src/engine_ts/queue.ts +93 -0
  83. package/src/engine_ts/runner.ts +108 -0
  84. package/src/engine_ts/skills-indexer.ts +264 -0
  85. package/src/engine_ts/toon-adapter.ts +91 -0
  86. package/src/engine_ts/types.ts +134 -0
  87. package/src/engine_ts/verification-controller.ts +204 -0
  88. package/src/engine_ts/worker.ts +280 -0
  89. package/src/hooks/adapters/claude-adapter.ts +54 -0
  90. package/src/hooks/adapters/cli-agent-adapter.ts +46 -0
  91. package/src/hooks/adapters/codex-adapter.ts +69 -0
  92. package/src/hooks/adapters/cursor-adapter.ts +60 -0
  93. package/src/hooks/adapters/gemini-adapter.ts +71 -0
  94. package/src/hooks/adapters/homebrew-adapter.ts +36 -0
  95. package/src/hooks/adapters/mcp-proxy.ts +66 -0
  96. package/src/hooks/adapters/shell-adapter.ts +42 -0
  97. package/src/hooks/dispatcher.ts +113 -0
  98. package/src/hooks/index.ts +16 -0
  99. package/src/hooks/policy-engine.ts +376 -0
  100. package/src/hooks/session-end.ts +125 -0
  101. package/src/hooks/types.ts +61 -0
  102. package/src/index.d.ts +34 -0
  103. package/src/index.ts +23 -0
  104. package/src/integrations/index.ts +7 -0
  105. package/src/integrations/installer.ts +208 -0
  106. package/src/integrations/lifecycle-director.ts +139 -0
  107. package/src/integrations/registry.ts +82 -0
  108. package/src/system/announcements.ts +143 -0
  109. package/src/system/dependencies.ts +176 -0
  110. package/src/system/doctor.ts +374 -0
  111. package/src/system/health.ts +270 -0
  112. package/src/system/index.ts +14 -0
  113. package/src/system/installer.ts +262 -0
  114. package/src/system/notifications.ts +180 -0
  115. package/src/system/refresher.ts +207 -0
  116. package/src/system/types.ts +268 -0
  117. package/src/system/updater.ts +219 -0
  118. package/src/system/version-tracker.ts +137 -0
@@ -0,0 +1,180 @@
1
+ /**
2
+ * src/system/notifications.ts — CLI/Terminal Banner & Desktop Notification Engine
3
+ */
4
+
5
+ import fs from 'node:fs';
6
+ import path from 'node:path';
7
+ import os from 'node:os';
8
+ import { execSync } from 'node:child_process';
9
+ import type { NotificationPayload, NotificationRecord, NotificationLevel } from './types.ts';
10
+
11
+ export class NotificationEngine {
12
+ private projectDir: string;
13
+ private historyFile: string;
14
+ private recentDispatches: Map<string, number> = new Map();
15
+
16
+ constructor(projectDir: string = '.') {
17
+ this.projectDir = path.resolve(projectDir);
18
+ this.historyFile = path.join(this.projectDir, '.notifications.json');
19
+ }
20
+
21
+ private isHeadless(): boolean {
22
+ return !!(process.env.CI || !process.stdout.isTTY);
23
+ }
24
+
25
+ public renderBanner(payload: NotificationPayload): string {
26
+ const level = payload.level || 'INFO';
27
+ const timestamp = new Date(payload.timestamp || Date.now()).toLocaleTimeString();
28
+ const source = payload.source ? ` [${payload.source}]` : '';
29
+
30
+ let color = '\x1b[36m'; // Cyan
31
+ let icon = 'ℹ️';
32
+ switch (level) {
33
+ case 'SUCCESS':
34
+ color = '\x1b[32m'; // Green
35
+ icon = '✅';
36
+ break;
37
+ case 'WARN':
38
+ color = '\x1b[33m'; // Yellow
39
+ icon = '⚠️';
40
+ break;
41
+ case 'ERROR':
42
+ case 'CRITICAL':
43
+ color = '\x1b[31m'; // Red
44
+ icon = '🛑';
45
+ break;
46
+ case 'ANNOUNCEMENT':
47
+ color = '\x1b[35m'; // Magenta
48
+ icon = '📢';
49
+ break;
50
+ }
51
+
52
+ const reset = '\x1b[0m';
53
+ const bold = '\x1b[1m';
54
+ const titleLine = `${icon} ${bold}${color}${level}${reset}${bold}: ${payload.title}${source} (${timestamp})${reset}`;
55
+ const lines = payload.message.split('\n');
56
+
57
+ const width = Math.min(80, Math.max(60, payload.title.length + 20, ...lines.map(l => l.length + 6)));
58
+ const border = '═'.repeat(width);
59
+
60
+ return `
61
+ ${color}╔${border}╗${reset}
62
+ ${titleLine}
63
+ ${color}╟${border}╢${reset}
64
+ ${lines.map(l => ` ${l}`).join('\n')}
65
+ ${color}╚${border}╝${reset}
66
+ `;
67
+ }
68
+
69
+ public sendDesktop(title: string, message: string, sound: boolean = true): boolean {
70
+ if (this.isHeadless()) return false;
71
+
72
+ const cleanTitle = title.replace(/"/g, '\\"');
73
+ const cleanMsg = message.replace(/"/g, '\\"');
74
+ const platform = os.platform();
75
+
76
+ try {
77
+ if (platform === 'darwin') {
78
+ const soundParam = sound ? 'sound name "Glass"' : '';
79
+ const script = `display notification "${cleanMsg}" with title "${cleanTitle}" ${soundParam}`;
80
+ execSync(`osascript -e '${script}'`, { stdio: 'ignore' });
81
+ return true;
82
+ } else if (platform === 'linux') {
83
+ execSync(`notify-send "${cleanTitle}" "${cleanMsg}"`, { stdio: 'ignore' });
84
+ return true;
85
+ }
86
+ } catch {
87
+ // Ignore desktop notification failures gracefully
88
+ }
89
+ return false;
90
+ }
91
+
92
+ public ringBell(): void {
93
+ if (!this.isHeadless()) {
94
+ process.stdout.write('\x07');
95
+ }
96
+ }
97
+
98
+ public send(payload: NotificationPayload): NotificationRecord {
99
+ const key = `${payload.level || 'INFO'}:${payload.title}:${payload.message.substring(0, 30)}`;
100
+ const now = Date.now();
101
+ const lastSent = this.recentDispatches.get(key) || 0;
102
+
103
+ // Rate-limiting deduplication: skip if identical within 3 seconds
104
+ if (now - lastSent < 3000) {
105
+ return {
106
+ id: payload.id || `notif_${now}`,
107
+ ...payload,
108
+ timestamp: now,
109
+ read: false
110
+ };
111
+ }
112
+ this.recentDispatches.set(key, now);
113
+
114
+ const record: NotificationRecord = {
115
+ id: payload.id || `notif_${now}_${Math.random().toString(36).substring(2, 6)}`,
116
+ title: payload.title,
117
+ message: payload.message,
118
+ level: payload.level || 'INFO',
119
+ source: payload.source || 'system',
120
+ timestamp: payload.timestamp || now,
121
+ sound: payload.sound !== false,
122
+ desktop: payload.desktop !== false,
123
+ terminal: payload.terminal !== false,
124
+ actionUrl: payload.actionUrl,
125
+ read: false
126
+ };
127
+
128
+ // 1. Terminal banner
129
+ if (record.terminal) {
130
+ console.log(this.renderBanner(record));
131
+ }
132
+
133
+ // 2. Audible bell
134
+ if (record.sound && (record.level === 'CRITICAL' || record.level === 'ERROR')) {
135
+ this.ringBell();
136
+ }
137
+
138
+ // 3. Desktop dispatch
139
+ if (record.desktop) {
140
+ this.sendDesktop(record.title, record.message, record.sound);
141
+ }
142
+
143
+ // 4. Save to history
144
+ this.saveToHistory(record);
145
+ return record;
146
+ }
147
+
148
+ public getHistory(): NotificationRecord[] {
149
+ try {
150
+ if (fs.existsSync(this.historyFile)) {
151
+ return JSON.parse(fs.readFileSync(this.historyFile, 'utf-8'));
152
+ }
153
+ } catch {
154
+ // Ignore
155
+ }
156
+ return [];
157
+ }
158
+
159
+ public clearHistory(): void {
160
+ try {
161
+ if (fs.existsSync(this.historyFile)) {
162
+ fs.unlinkSync(this.historyFile);
163
+ }
164
+ } catch {
165
+ // Ignore
166
+ }
167
+ }
168
+
169
+ private saveToHistory(record: NotificationRecord): void {
170
+ try {
171
+ const history = this.getHistory();
172
+ history.unshift(record);
173
+ // Keep at most 50
174
+ const trimmed = history.slice(0, 50);
175
+ fs.writeFileSync(this.historyFile, JSON.stringify(trimmed, null, 2));
176
+ } catch {
177
+ // Ignore write errors
178
+ }
179
+ }
180
+ }
@@ -0,0 +1,207 @@
1
+ /**
2
+ * src/system/refresher.ts — Refresher & Cache Invalidation Engine
3
+ */
4
+
5
+ import fs from 'node:fs';
6
+ import path from 'node:path';
7
+ import os from 'node:os';
8
+ import { execSync } from 'node:child_process';
9
+ import type { RefreshOptions, RefreshReport } from './types.ts';
10
+
11
+ export class Refresher {
12
+ private projectDir: string;
13
+ private homeDir: string;
14
+
15
+ constructor(projectDir: string = '.') {
16
+ this.projectDir = path.resolve(projectDir);
17
+ this.homeDir = os.homedir();
18
+ }
19
+
20
+ private removeDirRecursive(dirPath: string): { count: number; bytes: number } {
21
+ let count = 0;
22
+ let bytes = 0;
23
+ if (!fs.existsSync(dirPath)) return { count, bytes };
24
+
25
+ try {
26
+ const entries = fs.readdirSync(dirPath, { withFileTypes: true });
27
+ for (const entry of entries) {
28
+ const full = path.join(dirPath, entry.name);
29
+ if (entry.isDirectory()) {
30
+ const res = this.removeDirRecursive(full);
31
+ count += res.count;
32
+ bytes += res.bytes;
33
+ } else {
34
+ try {
35
+ const stat = fs.statSync(full);
36
+ bytes += stat.size;
37
+ fs.unlinkSync(full);
38
+ count++;
39
+ } catch {
40
+ // Ignore
41
+ }
42
+ }
43
+ }
44
+ fs.rmdirSync(dirPath);
45
+ } catch {
46
+ // Ignore
47
+ }
48
+ return { count, bytes };
49
+ }
50
+
51
+ private clearBytecodeCaches(): { items: string[]; bytes: number } {
52
+ const items: string[] = [];
53
+ let bytes = 0;
54
+
55
+ const findPycache = (dir: string) => {
56
+ if (!fs.existsSync(dir)) return;
57
+ try {
58
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
59
+ for (const entry of entries) {
60
+ const full = path.join(dir, entry.name);
61
+ if (entry.isDirectory()) {
62
+ if (entry.name === '__pycache__' || entry.name === '.pytest_cache') {
63
+ const res = this.removeDirRecursive(full);
64
+ items.push(path.relative(this.projectDir, full));
65
+ bytes += res.bytes;
66
+ } else if (!entry.name.startsWith('.') && entry.name !== 'node_modules') {
67
+ findPycache(full);
68
+ }
69
+ }
70
+ }
71
+ } catch {
72
+ // Ignore
73
+ }
74
+ };
75
+
76
+ findPycache(this.projectDir);
77
+ return { items, bytes };
78
+ }
79
+
80
+ private cleanStaleLocks(): string[] {
81
+ const cleared: string[] = [];
82
+ const lockFiles = [
83
+ path.join(this.projectDir, '.lock'),
84
+ path.join(this.projectDir, '.git', 'index.lock'),
85
+ path.join(this.projectDir, '.git', 'refs', 'heads', 'main.lock')
86
+ ];
87
+
88
+ for (const lf of lockFiles) {
89
+ if (fs.existsSync(lf)) {
90
+ try {
91
+ const stat = fs.statSync(lf);
92
+ // If older than 5 minutes, consider stale
93
+ if (Date.now() - stat.mtimeMs > 5 * 60 * 1000) {
94
+ fs.unlinkSync(lf);
95
+ cleared.push(path.relative(this.projectDir, lf));
96
+ }
97
+ } catch {
98
+ // Ignore
99
+ }
100
+ }
101
+ }
102
+ return cleared;
103
+ }
104
+
105
+ public refresh(options: RefreshOptions = {}): RefreshReport {
106
+ const startTime = Date.now();
107
+ const clearedItems: string[] = [];
108
+ let freedBytes = 0;
109
+ const messages: string[] = [];
110
+ const hostsSynced: string[] = [];
111
+
112
+ // 1. Clear Bytecode
113
+ if (options.clearBytecode !== false) {
114
+ const { items, bytes } = this.clearBytecodeCaches();
115
+ clearedItems.push(...items);
116
+ freedBytes += bytes;
117
+ if (items.length > 0) {
118
+ messages.push(`✓ Cleared ${items.length} Python bytecode cache directory(ies)`);
119
+ }
120
+ }
121
+
122
+ // 2. Clean Stale Lockfiles
123
+ if (options.cleanLockfiles !== false) {
124
+ const locks = this.cleanStaleLocks();
125
+ clearedItems.push(...locks);
126
+ if (locks.length > 0) {
127
+ messages.push(`✓ Removed ${locks.length} stale lockfile(s)`);
128
+ }
129
+ }
130
+
131
+ // 3. Reset Risk Scores
132
+ if (options.resetRiskScores) {
133
+ const riskPath = path.join(this.projectDir, 'risk-scores.json');
134
+ if (fs.existsSync(riskPath)) {
135
+ try {
136
+ fs.unlinkSync(riskPath);
137
+ clearedItems.push('risk-scores.json');
138
+ messages.push(`✓ Reset predictive debugging risk scores cache`);
139
+ } catch {
140
+ // Ignore
141
+ }
142
+ }
143
+ }
144
+
145
+ // 4. Rebuild Skills Index
146
+ let skillsReindexed = false;
147
+ if (options.rebuildSkillsIndex !== false) {
148
+ try {
149
+ execSync('python3 core/skills_indexer.py index', { cwd: this.projectDir, stdio: 'pipe' });
150
+ skillsReindexed = true;
151
+ messages.push(`✓ Rebuilt skills-index.json and skills-index.toon`);
152
+ } catch (err: any) {
153
+ messages.push(`! Skills re-indexing notice: ${err.message}`);
154
+ }
155
+ }
156
+
157
+ // 5. Sync Integrations
158
+ let integrationsSynced = false;
159
+ if (options.syncIntegrations !== false) {
160
+ try {
161
+ const script = `from core.integrations import IntegrationInstaller; IntegrationInstaller('${this.projectDir}').provision_all()`;
162
+ execSync(`python3 -c "${script}"`, { cwd: this.projectDir, stdio: 'pipe' });
163
+ integrationsSynced = true;
164
+ messages.push(`✓ Synchronized supportive integrations (Ponytail, TOON, Fable, Caveman)`);
165
+ } catch (err: any) {
166
+ messages.push(`! Integrations sync notice: ${err.message}`);
167
+ }
168
+ }
169
+
170
+ // 6. Sync Host Skills
171
+ if (options.syncHostSkills) {
172
+ const hostDirs = [
173
+ path.join(this.homeDir, '.claude', 'skills', 'agentic-workflow'),
174
+ path.join(this.homeDir, '.gemini', 'config', 'skills', 'agentic-workflow'),
175
+ path.join(this.homeDir, '.cursor', 'skills', 'agentic-workflow'),
176
+ path.join(this.homeDir, '.agents', 'skills', 'agentic-workflow')
177
+ ];
178
+
179
+ for (const hDir of hostDirs) {
180
+ if (fs.existsSync(hDir)) {
181
+ try {
182
+ // Update SKILL.md and marketplace.json
183
+ fs.copyFileSync(path.join(this.projectDir, 'SKILL.md'), path.join(hDir, 'SKILL.md'));
184
+ hostsSynced.push(hDir);
185
+ } catch {
186
+ // Ignore
187
+ }
188
+ }
189
+ }
190
+ if (hostsSynced.length > 0) {
191
+ messages.push(`✓ Updated skill definitions across ${hostsSynced.length} host environments`);
192
+ }
193
+ }
194
+
195
+ const durationMs = Date.now() - startTime;
196
+ return {
197
+ success: true,
198
+ clearedItems,
199
+ freedBytes,
200
+ skillsReindexed,
201
+ integrationsSynced,
202
+ hostsSynced,
203
+ durationMs,
204
+ messages
205
+ };
206
+ }
207
+ }
@@ -0,0 +1,268 @@
1
+ /**
2
+ * src/system/types.ts — Shared Type Definitions for AgenticWorkflow System Engines
3
+ */
4
+
5
+ // 1. Auto-Updater Types
6
+ export type UpdateStrategy = 'fast-forward' | 'stash-and-pull' | 'force-reset';
7
+
8
+ export interface UpdateCheckResult {
9
+ hasUpdate: boolean;
10
+ currentCommit: string;
11
+ currentVersion: string;
12
+ remoteCommit: string;
13
+ remoteVersion?: string;
14
+ branch: string;
15
+ behindCount: number;
16
+ commits: Array<{ hash: string; message: string; date: string }>;
17
+ channel: 'stable' | 'beta' | 'nightly';
18
+ }
19
+
20
+ export interface UpdateOptions {
21
+ strategy?: UpdateStrategy;
22
+ force?: boolean;
23
+ branch?: string;
24
+ autoReinstall?: boolean;
25
+ autoRefresh?: boolean;
26
+ }
27
+
28
+ export interface UpdateResult {
29
+ success: boolean;
30
+ previousCommit: string;
31
+ newCommit: string;
32
+ message: string;
33
+ stashed: boolean;
34
+ reinstalled: boolean;
35
+ refreshed: boolean;
36
+ }
37
+
38
+ export interface RollbackResult {
39
+ success: boolean;
40
+ rolledBackTo: string;
41
+ message: string;
42
+ }
43
+
44
+ // 2. Auto-Installer Types
45
+ export type HostPlatform = 'claude' | 'gemini' | 'cursor' | 'codex' | 'agents' | 'cli-symlink' | 'shell-profile';
46
+
47
+ export interface InstallTarget {
48
+ name: string;
49
+ platform: HostPlatform;
50
+ path: string;
51
+ installed: boolean;
52
+ }
53
+
54
+ export interface InstallOptions {
55
+ targets?: HostPlatform[];
56
+ globalBin?: boolean;
57
+ updateShellRc?: boolean;
58
+ provisionTools?: boolean;
59
+ dryRun?: boolean;
60
+ force?: boolean;
61
+ }
62
+
63
+ export interface InstallReport {
64
+ success: boolean;
65
+ installedTargets: InstallTarget[];
66
+ skippedTargets: InstallTarget[];
67
+ binLinked: string[];
68
+ shellConfigured: string[];
69
+ systemDeps: Array<{ name: string; available: boolean; version?: string }>;
70
+ messages: string[];
71
+ }
72
+
73
+ // 3. Refresher Types
74
+ export interface RefreshOptions {
75
+ clearBytecode?: boolean;
76
+ clearTemp?: boolean;
77
+ rebuildSkillsIndex?: boolean;
78
+ syncIntegrations?: boolean;
79
+ syncHostSkills?: boolean;
80
+ resetRiskScores?: boolean;
81
+ cleanLockfiles?: boolean;
82
+ }
83
+
84
+ export interface RefreshReport {
85
+ success: boolean;
86
+ clearedItems: string[];
87
+ freedBytes: number;
88
+ skillsReindexed: boolean;
89
+ integrationsSynced: boolean;
90
+ hostsSynced: string[];
91
+ durationMs: number;
92
+ messages: string[];
93
+ }
94
+
95
+ // 4. Doctor Types
96
+ export type DoctorSeverity = 'PASS' | 'WARN' | 'FAIL';
97
+
98
+ export interface DoctorCheckItem {
99
+ id: string;
100
+ category: 'runtime' | 'cli' | 'git' | 'dependencies' | 'state' | 'hooks' | 'skills' | 'integrations' | 'security';
101
+ title: string;
102
+ status: DoctorSeverity;
103
+ details: string;
104
+ recommendation?: string;
105
+ fixable: boolean;
106
+ }
107
+
108
+ export interface DoctorReport {
109
+ passed: number;
110
+ warned: number;
111
+ failed: number;
112
+ total: number;
113
+ checks: DoctorCheckItem[];
114
+ overallHealthy: boolean;
115
+ timestamp: string;
116
+ }
117
+
118
+ export interface FixResult {
119
+ checkId: string;
120
+ remediated: boolean;
121
+ message: string;
122
+ }
123
+
124
+ // 5. Health Engine Types
125
+ export type HealthGrade = 'A+' | 'A' | 'B' | 'C' | 'F';
126
+
127
+ export interface SystemVitals {
128
+ platform: string;
129
+ arch: string;
130
+ uptimeSeconds: number;
131
+ memory: {
132
+ totalBytes: number;
133
+ freeBytes: number;
134
+ rssBytes: number;
135
+ usedPercentage: number;
136
+ };
137
+ disk: {
138
+ freeBytes?: number;
139
+ totalBytes?: number;
140
+ };
141
+ nodeVersion: string;
142
+ bunVersion?: string;
143
+ pythonVersion?: string;
144
+ }
145
+
146
+ export interface WorkflowVitals {
147
+ hasActiveWorkflow: boolean;
148
+ currentStep?: string;
149
+ circuitBreakerStatus: 'CLOSED' | 'OPEN' | 'HALF_OPEN';
150
+ failureStreak: number;
151
+ retryCount: number;
152
+ traceSpansCount: number;
153
+ }
154
+
155
+ export interface HealthScore {
156
+ score: number; // 0 - 100
157
+ grade: HealthGrade;
158
+ breakdown: {
159
+ runtime: number; // max 20
160
+ workflow: number; // max 25
161
+ security: number; // max 20
162
+ dependencies: number;// max 15
163
+ integrity: number; // max 20
164
+ };
165
+ warnings: string[];
166
+ }
167
+
168
+ export interface HealthReport {
169
+ timestamp: string;
170
+ score: HealthScore;
171
+ vitals: SystemVitals;
172
+ workflow: WorkflowVitals;
173
+ services: Record<string, 'HEALTHY' | 'DEGRADED' | 'DOWN'>;
174
+ }
175
+
176
+ // 6. Dependencies Engine Types
177
+ export type DependencyType = 'bun-npm' | 'python' | 'supportive-tool' | 'system-binary';
178
+
179
+ export interface DependencyItem {
180
+ name: string;
181
+ type: DependencyType;
182
+ requiredVersion?: string;
183
+ installedVersion?: string;
184
+ status: 'SATISFIED' | 'OUTDATED' | 'MISSING' | 'INCOMPATIBLE';
185
+ description?: string;
186
+ location?: string;
187
+ }
188
+
189
+ export interface DependencyAuditReport {
190
+ total: number;
191
+ satisfied: number;
192
+ missing: number;
193
+ outdated: number;
194
+ incompatible: number;
195
+ dependencies: DependencyItem[];
196
+ allSatisfied: boolean;
197
+ }
198
+
199
+ // 7. Notifications Engine Types
200
+ export type NotificationLevel = 'INFO' | 'SUCCESS' | 'WARN' | 'ERROR' | 'CRITICAL' | 'ANNOUNCEMENT';
201
+
202
+ export interface NotificationPayload {
203
+ id?: string;
204
+ title: string;
205
+ message: string;
206
+ level?: NotificationLevel;
207
+ source?: string;
208
+ timestamp?: number;
209
+ sound?: boolean;
210
+ desktop?: boolean;
211
+ terminal?: boolean;
212
+ actionUrl?: string;
213
+ }
214
+
215
+ export interface NotificationRecord extends NotificationPayload {
216
+ id: string;
217
+ timestamp: number;
218
+ read: boolean;
219
+ }
220
+
221
+ // 8. Announcement Engine Types
222
+ export type AnnouncementCategory = 'SECURITY' | 'FEATURE' | 'UPDATE' | 'TIP' | 'MAINTENANCE';
223
+
224
+ export interface AnnouncementItem {
225
+ id: string;
226
+ title: string;
227
+ body: string;
228
+ category: AnnouncementCategory;
229
+ date: string;
230
+ version?: string;
231
+ priority: 'low' | 'normal' | 'high' | 'urgent';
232
+ url?: string;
233
+ }
234
+
235
+ export interface AnnouncementState {
236
+ seenIds: string[];
237
+ lastChecked: string;
238
+ }
239
+
240
+ // 9. Version Tracker Types
241
+ export interface ComponentVersion {
242
+ name: string;
243
+ version: string;
244
+ channel: string;
245
+ path?: string;
246
+ }
247
+
248
+ export interface VersionMatrix {
249
+ cliVersion: string;
250
+ tsEngineVersion: string;
251
+ pyEngineVersion: string;
252
+ toonProtocolVersion: string;
253
+ uahfHooksVersion: string;
254
+ gitCommit: string;
255
+ gitBranch: string;
256
+ gitClean: boolean;
257
+ buildDate: string;
258
+ components: ComponentVersion[];
259
+ }
260
+
261
+ export interface MigrationStep {
262
+ fromVersion: string;
263
+ toVersion: string;
264
+ name: string;
265
+ description: string;
266
+ executed: boolean;
267
+ timestamp?: string;
268
+ }