@made-by-moonlight/athene-core 0.9.1

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 (285) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +241 -0
  3. package/dist/activity-events.d.ts +42 -0
  4. package/dist/activity-events.d.ts.map +1 -0
  5. package/dist/activity-events.js +192 -0
  6. package/dist/activity-events.js.map +1 -0
  7. package/dist/activity-log.d.ts +71 -0
  8. package/dist/activity-log.d.ts.map +1 -0
  9. package/dist/activity-log.js +203 -0
  10. package/dist/activity-log.js.map +1 -0
  11. package/dist/activity-signal.d.ts +20 -0
  12. package/dist/activity-signal.d.ts.map +1 -0
  13. package/dist/activity-signal.js +91 -0
  14. package/dist/activity-signal.js.map +1 -0
  15. package/dist/agent-report.d.ts +148 -0
  16. package/dist/agent-report.d.ts.map +1 -0
  17. package/dist/agent-report.js +516 -0
  18. package/dist/agent-report.js.map +1 -0
  19. package/dist/agent-selection.d.ts +31 -0
  20. package/dist/agent-selection.d.ts.map +1 -0
  21. package/dist/agent-selection.js +69 -0
  22. package/dist/agent-selection.js.map +1 -0
  23. package/dist/agent-workspace-hooks.d.ts +74 -0
  24. package/dist/agent-workspace-hooks.d.ts.map +1 -0
  25. package/dist/agent-workspace-hooks.js +988 -0
  26. package/dist/agent-workspace-hooks.js.map +1 -0
  27. package/dist/atomic-write.d.ts +6 -0
  28. package/dist/atomic-write.d.ts.map +1 -0
  29. package/dist/atomic-write.js +49 -0
  30. package/dist/atomic-write.js.map +1 -0
  31. package/dist/cleanup-stack.d.ts +37 -0
  32. package/dist/cleanup-stack.d.ts.map +1 -0
  33. package/dist/cleanup-stack.js +45 -0
  34. package/dist/cleanup-stack.js.map +1 -0
  35. package/dist/code-review-manager.d.ts +118 -0
  36. package/dist/code-review-manager.d.ts.map +1 -0
  37. package/dist/code-review-manager.js +719 -0
  38. package/dist/code-review-manager.js.map +1 -0
  39. package/dist/code-review-store.d.ts +114 -0
  40. package/dist/code-review-store.d.ts.map +1 -0
  41. package/dist/code-review-store.js +346 -0
  42. package/dist/code-review-store.js.map +1 -0
  43. package/dist/config-generator.d.ts +84 -0
  44. package/dist/config-generator.d.ts.map +1 -0
  45. package/dist/config-generator.js +295 -0
  46. package/dist/config-generator.js.map +1 -0
  47. package/dist/config.d.ts +55 -0
  48. package/dist/config.d.ts.map +1 -0
  49. package/dist/config.js +852 -0
  50. package/dist/config.js.map +1 -0
  51. package/dist/daemon-children.d.ts +55 -0
  52. package/dist/daemon-children.d.ts.map +1 -0
  53. package/dist/daemon-children.js +435 -0
  54. package/dist/daemon-children.js.map +1 -0
  55. package/dist/dashboard-notifications.d.ts +42 -0
  56. package/dist/dashboard-notifications.d.ts.map +1 -0
  57. package/dist/dashboard-notifications.js +123 -0
  58. package/dist/dashboard-notifications.js.map +1 -0
  59. package/dist/events-db.d.ts +39 -0
  60. package/dist/events-db.d.ts.map +1 -0
  61. package/dist/events-db.js +185 -0
  62. package/dist/events-db.js.map +1 -0
  63. package/dist/feature-flags.d.ts +2 -0
  64. package/dist/feature-flags.d.ts.map +1 -0
  65. package/dist/feature-flags.js +9 -0
  66. package/dist/feature-flags.js.map +1 -0
  67. package/dist/feedback-tools.d.ts +97 -0
  68. package/dist/feedback-tools.d.ts.map +1 -0
  69. package/dist/feedback-tools.js +161 -0
  70. package/dist/feedback-tools.js.map +1 -0
  71. package/dist/file-lock.d.ts +5 -0
  72. package/dist/file-lock.d.ts.map +1 -0
  73. package/dist/file-lock.js +59 -0
  74. package/dist/file-lock.js.map +1 -0
  75. package/dist/format-automated-comments.d.ts +18 -0
  76. package/dist/format-automated-comments.d.ts.map +1 -0
  77. package/dist/gh-trace.d.ts +57 -0
  78. package/dist/gh-trace.d.ts.map +1 -0
  79. package/dist/gh-trace.js +320 -0
  80. package/dist/gh-trace.js.map +1 -0
  81. package/dist/git-activity.d.ts +10 -0
  82. package/dist/git-activity.d.ts.map +1 -0
  83. package/dist/git-activity.js +30 -0
  84. package/dist/git-activity.js.map +1 -0
  85. package/dist/global-config.d.ts +1085 -0
  86. package/dist/global-config.d.ts.map +1 -0
  87. package/dist/global-config.js +1067 -0
  88. package/dist/global-config.js.map +1 -0
  89. package/dist/index.d.ts +91 -0
  90. package/dist/index.d.ts.map +1 -0
  91. package/dist/index.js +59 -0
  92. package/dist/index.js.map +1 -0
  93. package/dist/key-value.d.ts +7 -0
  94. package/dist/key-value.d.ts.map +1 -0
  95. package/dist/key-value.js +24 -0
  96. package/dist/key-value.js.map +1 -0
  97. package/dist/lifecycle-manager.d.ts +22 -0
  98. package/dist/lifecycle-manager.d.ts.map +1 -0
  99. package/dist/lifecycle-manager.js +2813 -0
  100. package/dist/lifecycle-manager.js.map +1 -0
  101. package/dist/lifecycle-state.d.ts +28 -0
  102. package/dist/lifecycle-state.d.ts.map +1 -0
  103. package/dist/lifecycle-state.js +446 -0
  104. package/dist/lifecycle-state.js.map +1 -0
  105. package/dist/lifecycle-status-decisions.d.ts +85 -0
  106. package/dist/lifecycle-status-decisions.d.ts.map +1 -0
  107. package/dist/lifecycle-status-decisions.js +262 -0
  108. package/dist/lifecycle-status-decisions.js.map +1 -0
  109. package/dist/lifecycle-transition.d.ts +81 -0
  110. package/dist/lifecycle-transition.d.ts.map +1 -0
  111. package/dist/lifecycle-transition.js +207 -0
  112. package/dist/lifecycle-transition.js.map +1 -0
  113. package/dist/metadata.d.ts +54 -0
  114. package/dist/metadata.d.ts.map +1 -0
  115. package/dist/metadata.js +484 -0
  116. package/dist/metadata.js.map +1 -0
  117. package/dist/migration/storage-v2.d.ts +76 -0
  118. package/dist/migration/storage-v2.d.ts.map +1 -0
  119. package/dist/migration/storage-v2.js +1614 -0
  120. package/dist/migration/storage-v2.js.map +1 -0
  121. package/dist/notification-data.d.ts +135 -0
  122. package/dist/notification-data.d.ts.map +1 -0
  123. package/dist/notification-data.js +204 -0
  124. package/dist/notification-data.js.map +1 -0
  125. package/dist/notification-observability.d.ts +21 -0
  126. package/dist/notification-observability.d.ts.map +1 -0
  127. package/dist/notification-observability.js +154 -0
  128. package/dist/notification-observability.js.map +1 -0
  129. package/dist/notifier-resolution.d.ts +14 -0
  130. package/dist/notifier-resolution.d.ts.map +1 -0
  131. package/dist/notifier-resolution.js +23 -0
  132. package/dist/notifier-resolution.js.map +1 -0
  133. package/dist/observability.d.ts +100 -0
  134. package/dist/observability.d.ts.map +1 -0
  135. package/dist/observability.js +535 -0
  136. package/dist/observability.js.map +1 -0
  137. package/dist/opencode-agents-md.d.ts +3 -0
  138. package/dist/opencode-agents-md.d.ts.map +1 -0
  139. package/dist/opencode-agents-md.js +40 -0
  140. package/dist/opencode-agents-md.js.map +1 -0
  141. package/dist/opencode-config.d.ts +2 -0
  142. package/dist/opencode-config.d.ts.map +1 -0
  143. package/dist/opencode-config.js +17 -0
  144. package/dist/opencode-config.js.map +1 -0
  145. package/dist/opencode-session-id.d.ts +2 -0
  146. package/dist/opencode-session-id.d.ts.map +1 -0
  147. package/dist/opencode-session-id.js +12 -0
  148. package/dist/opencode-session-id.js.map +1 -0
  149. package/dist/opencode-shared.d.ts +80 -0
  150. package/dist/opencode-shared.d.ts.map +1 -0
  151. package/dist/opencode-shared.js +202 -0
  152. package/dist/opencode-shared.js.map +1 -0
  153. package/dist/orchestrator-prompt.d.ts +19 -0
  154. package/dist/orchestrator-prompt.d.ts.map +1 -0
  155. package/dist/orchestrator-prompt.js +130 -0
  156. package/dist/orchestrator-prompt.js.map +1 -0
  157. package/dist/orchestrator-session-strategy.d.ts +5 -0
  158. package/dist/orchestrator-session-strategy.d.ts.map +1 -0
  159. package/dist/orchestrator-session-strategy.js +13 -0
  160. package/dist/orchestrator-session-strategy.js.map +1 -0
  161. package/dist/paths.d.ts +145 -0
  162. package/dist/paths.d.ts.map +1 -0
  163. package/dist/paths.js +288 -0
  164. package/dist/paths.js.map +1 -0
  165. package/dist/platform.d.ts +32 -0
  166. package/dist/platform.d.ts.map +1 -0
  167. package/dist/platform.js +211 -0
  168. package/dist/platform.js.map +1 -0
  169. package/dist/plugin-registry.d.ts +15 -0
  170. package/dist/plugin-registry.d.ts.map +1 -0
  171. package/dist/plugin-registry.js +499 -0
  172. package/dist/plugin-registry.js.map +1 -0
  173. package/dist/portfolio-projects.d.ts +7 -0
  174. package/dist/portfolio-projects.d.ts.map +1 -0
  175. package/dist/portfolio-projects.js +65 -0
  176. package/dist/portfolio-projects.js.map +1 -0
  177. package/dist/portfolio-registry.d.ts +42 -0
  178. package/dist/portfolio-registry.d.ts.map +1 -0
  179. package/dist/portfolio-registry.js +311 -0
  180. package/dist/portfolio-registry.js.map +1 -0
  181. package/dist/portfolio-routing.d.ts +5 -0
  182. package/dist/portfolio-routing.d.ts.map +1 -0
  183. package/dist/portfolio-routing.js +24 -0
  184. package/dist/portfolio-routing.js.map +1 -0
  185. package/dist/portfolio-session-service.d.ts +15 -0
  186. package/dist/portfolio-session-service.d.ts.map +1 -0
  187. package/dist/portfolio-session-service.js +206 -0
  188. package/dist/portfolio-session-service.js.map +1 -0
  189. package/dist/process-cache.d.ts +32 -0
  190. package/dist/process-cache.d.ts.map +1 -0
  191. package/dist/process-cache.js +44 -0
  192. package/dist/process-cache.js.map +1 -0
  193. package/dist/project-resolver.d.ts +5 -0
  194. package/dist/project-resolver.d.ts.map +1 -0
  195. package/dist/project-resolver.js +20 -0
  196. package/dist/project-resolver.js.map +1 -0
  197. package/dist/prompt-builder.d.ts +42 -0
  198. package/dist/prompt-builder.d.ts.map +1 -0
  199. package/dist/prompt-builder.js +182 -0
  200. package/dist/prompt-builder.js.map +1 -0
  201. package/dist/prompts/orchestrator.md.js +4 -0
  202. package/dist/prompts/orchestrator.md.js.map +1 -0
  203. package/dist/query-activity-events.d.ts +42 -0
  204. package/dist/query-activity-events.d.ts.map +1 -0
  205. package/dist/query-activity-events.js +170 -0
  206. package/dist/query-activity-events.js.map +1 -0
  207. package/dist/recovery/actions.d.ts +7 -0
  208. package/dist/recovery/actions.d.ts.map +1 -0
  209. package/dist/recovery/index.d.ts +8 -0
  210. package/dist/recovery/index.d.ts.map +1 -0
  211. package/dist/recovery/logger.d.ts +12 -0
  212. package/dist/recovery/logger.d.ts.map +1 -0
  213. package/dist/recovery/manager.d.ts +24 -0
  214. package/dist/recovery/manager.d.ts.map +1 -0
  215. package/dist/recovery/scanner.d.ts +11 -0
  216. package/dist/recovery/scanner.d.ts.map +1 -0
  217. package/dist/recovery/types.d.ts +170 -0
  218. package/dist/recovery/types.d.ts.map +1 -0
  219. package/dist/recovery/validator.d.ts +8 -0
  220. package/dist/recovery/validator.d.ts.map +1 -0
  221. package/dist/report-watcher.d.ts +93 -0
  222. package/dist/report-watcher.d.ts.map +1 -0
  223. package/dist/report-watcher.js +182 -0
  224. package/dist/report-watcher.js.map +1 -0
  225. package/dist/scm-webhook-utils.d.ts +6 -0
  226. package/dist/scm-webhook-utils.d.ts.map +1 -0
  227. package/dist/scm-webhook-utils.js +36 -0
  228. package/dist/scm-webhook-utils.js.map +1 -0
  229. package/dist/session-manager.d.ts +22 -0
  230. package/dist/session-manager.d.ts.map +1 -0
  231. package/dist/session-manager.js +3077 -0
  232. package/dist/session-manager.js.map +1 -0
  233. package/dist/spawn-target.d.ts +23 -0
  234. package/dist/spawn-target.d.ts.map +1 -0
  235. package/dist/spawn-target.js +39 -0
  236. package/dist/spawn-target.js.map +1 -0
  237. package/dist/storage-key.d.ts +9 -0
  238. package/dist/storage-key.d.ts.map +1 -0
  239. package/dist/storage-key.js +59 -0
  240. package/dist/storage-key.js.map +1 -0
  241. package/dist/tmux.d.ts +39 -0
  242. package/dist/tmux.d.ts.map +1 -0
  243. package/dist/tmux.js +141 -0
  244. package/dist/tmux.js.map +1 -0
  245. package/dist/types.d.ts +1496 -0
  246. package/dist/types.d.ts.map +1 -0
  247. package/dist/types.js +215 -0
  248. package/dist/types.js.map +1 -0
  249. package/dist/update-cache.d.ts +59 -0
  250. package/dist/update-cache.d.ts.map +1 -0
  251. package/dist/update-cache.js +77 -0
  252. package/dist/update-cache.js.map +1 -0
  253. package/dist/utils/metadata-flatten.d.ts +3 -0
  254. package/dist/utils/metadata-flatten.d.ts.map +1 -0
  255. package/dist/utils/metadata-flatten.js +18 -0
  256. package/dist/utils/metadata-flatten.js.map +1 -0
  257. package/dist/utils/pr.d.ts +7 -0
  258. package/dist/utils/pr.d.ts.map +1 -0
  259. package/dist/utils/pr.js +97 -0
  260. package/dist/utils/pr.js.map +1 -0
  261. package/dist/utils/session-from-metadata.d.ts +16 -0
  262. package/dist/utils/session-from-metadata.d.ts.map +1 -0
  263. package/dist/utils/session-from-metadata.js +87 -0
  264. package/dist/utils/session-from-metadata.js.map +1 -0
  265. package/dist/utils/session-id.d.ts +4 -0
  266. package/dist/utils/session-id.d.ts.map +1 -0
  267. package/dist/utils/session-id.js +9 -0
  268. package/dist/utils/session-id.js.map +1 -0
  269. package/dist/utils/validation.d.ts +9 -0
  270. package/dist/utils/validation.d.ts.map +1 -0
  271. package/dist/utils/validation.js +45 -0
  272. package/dist/utils/validation.js.map +1 -0
  273. package/dist/utils.d.ts +65 -0
  274. package/dist/utils.d.ts.map +1 -0
  275. package/dist/utils.js +189 -0
  276. package/dist/utils.js.map +1 -0
  277. package/dist/version-compare.d.ts +27 -0
  278. package/dist/version-compare.d.ts.map +1 -0
  279. package/dist/version-compare.js +121 -0
  280. package/dist/version-compare.js.map +1 -0
  281. package/dist/windows-pty-registry.d.ts +27 -0
  282. package/dist/windows-pty-registry.d.ts.map +1 -0
  283. package/dist/windows-pty-registry.js +109 -0
  284. package/dist/windows-pty-registry.js.map +1 -0
  285. package/package.json +110 -0
@@ -0,0 +1,1496 @@
1
+ import type { ObservabilityLevel } from "./observability.js";
2
+ /**
3
+ * Athene — Core Type Definitions
4
+ *
5
+ * This file defines ALL interfaces and types that the system uses.
6
+ * Every plugin, CLI command, and web API route builds against these.
7
+ *
8
+ * Architecture: 8 plugin slots + core services
9
+ * 1. Runtime — where sessions execute (tmux, docker, k8s, process)
10
+ * 2. Agent — AI coding tool (claude-code, codex, aider)
11
+ * 3. Workspace — code isolation (worktree, clone)
12
+ * 4. Tracker — issue tracking (github, linear, jira)
13
+ * 5. SCM — source platform + PR/CI/reviews (github, gitlab)
14
+ * 6. Notifier — push notifications (desktop, slack, webhook)
15
+ * 7. Terminal — human interaction UI (iterm2, web, none)
16
+ * 8. Lifecycle Manager (core, not pluggable)
17
+ */
18
+ /** Unique session identifier, e.g. "my-app-1", "backend-12" */
19
+ export type SessionId = string;
20
+ export type SessionKind = "worker" | "orchestrator";
21
+ export type CanonicalSessionState = "not_started" | "working" | "idle" | "needs_input" | "stuck" | "detecting" | "done" | "terminated";
22
+ export type CanonicalSessionReason = "spawn_requested" | "agent_acknowledged" | "task_in_progress" | "pr_created" | "pr_closed_waiting_decision" | "fixing_ci" | "resolving_review_comments" | "awaiting_user_input" | "awaiting_external_review" | "research_complete" | "merged_waiting_decision" | "manually_killed" | "pr_merged" | "auto_cleanup" | "runtime_lost" | "agent_process_exited" | "probe_failure" | "error_in_process";
23
+ export type CanonicalPRState = "none" | "open" | "merged" | "closed";
24
+ export type CanonicalPRReason = "not_created" | "in_progress" | "ci_failing" | "review_pending" | "changes_requested" | "approved" | "merge_ready" | "merged" | "closed_unmerged" | "cleared_on_restore";
25
+ export type CanonicalRuntimeState = "unknown" | "alive" | "exited" | "missing" | "probe_failed";
26
+ export type CanonicalRuntimeReason = "spawn_incomplete" | "process_running" | "process_missing" | "tmux_missing" | "manual_kill_requested" | "pr_merged_cleanup" | "auto_cleanup" | "probe_error";
27
+ export interface SessionStateRecord {
28
+ kind: SessionKind;
29
+ state: CanonicalSessionState;
30
+ reason: CanonicalSessionReason;
31
+ startedAt: string | null;
32
+ completedAt: string | null;
33
+ terminatedAt: string | null;
34
+ lastTransitionAt: string;
35
+ }
36
+ export interface PRStateRecord {
37
+ state: CanonicalPRState;
38
+ reason: CanonicalPRReason;
39
+ number: number | null;
40
+ url: string | null;
41
+ lastObservedAt: string | null;
42
+ }
43
+ export interface RuntimeStateRecord {
44
+ state: CanonicalRuntimeState;
45
+ reason: CanonicalRuntimeReason;
46
+ lastObservedAt: string | null;
47
+ handle: RuntimeHandle | null;
48
+ tmuxName: string | null;
49
+ }
50
+ export interface CanonicalSessionLifecycle {
51
+ version: 2;
52
+ session: SessionStateRecord;
53
+ pr: PRStateRecord;
54
+ runtime: RuntimeStateRecord;
55
+ }
56
+ /** Session lifecycle states */
57
+ export type SessionStatus = "spawning" | "working" | "detecting" | "pr_open" | "ci_failed" | "review_pending" | "changes_requested" | "approved" | "mergeable" | "merged" | "cleanup" | "needs_input" | "stuck" | "errored" | "killed" | "idle" | "done" | "terminated";
58
+ /** Activity state as detected by the agent plugin */
59
+ export type ActivityState = "active" | "ready" | "idle" | "waiting_input" | "blocked" | "exited";
60
+ /** Activity state constants */
61
+ export declare const ACTIVITY_STATE: {
62
+ ACTIVE: "active";
63
+ READY: "ready";
64
+ IDLE: "idle";
65
+ WAITING_INPUT: "waiting_input";
66
+ BLOCKED: "blocked";
67
+ EXITED: "exited";
68
+ };
69
+ export type ActivitySignalState = "valid" | "stale" | "null" | "unavailable" | "probe_failure";
70
+ export type ActivitySignalSource = "native" | "terminal" | "hook" | "runtime" | "none";
71
+ export interface ActivitySignal {
72
+ /** Confidence bucket for the activity probe result. */
73
+ state: ActivitySignalState;
74
+ /** The observed activity value, if one was surfaced. */
75
+ activity: ActivityState | null;
76
+ /** Timestamp that makes timing-based inferences safe, when available. */
77
+ timestamp?: Date;
78
+ /** Where the activity signal came from. */
79
+ source: ActivitySignalSource;
80
+ /** Optional extra detail for stale / failed probes. */
81
+ detail?: string;
82
+ }
83
+ /** Result of activity detection, carrying both the state and an optional timestamp. */
84
+ export interface ActivityDetection {
85
+ state: ActivityState;
86
+ /** When activity was last observed (e.g., agent log file mtime) */
87
+ timestamp?: Date;
88
+ }
89
+ /** A single entry in the AO activity JSONL log, written by agent plugins. */
90
+ export interface ActivityLogEntry {
91
+ /** ISO 8601 timestamp */
92
+ ts: string;
93
+ /** Activity state derived from terminal output, agent-native data, or a platform-event hook */
94
+ state: ActivityState;
95
+ /**
96
+ * Provenance of this entry:
97
+ * - "terminal": classified from terminal output (regex/heuristic; deprecated for hook-capable agents)
98
+ * - "native": read from the agent's own JSONL/API
99
+ * - "hook": emitted by an agent lifecycle hook (e.g. Claude Code's PermissionRequest, Stop, StopFailure)
100
+ */
101
+ source: "terminal" | "native" | "hook";
102
+ /** Raw terminal snippet, hook event name, or other context that caused waiting_input/blocked (for debugging) */
103
+ trigger?: string;
104
+ }
105
+ /** Default threshold (ms) before a "ready" session becomes "idle". */
106
+ export declare const DEFAULT_READY_THRESHOLD_MS = 300000;
107
+ /** Default window (ms) for "active" state — activity newer than this is "active", older is "ready". */
108
+ export declare const DEFAULT_ACTIVE_WINDOW_MS = 30000;
109
+ /** Session status constants */
110
+ export declare const SESSION_STATUS: {
111
+ SPAWNING: "spawning";
112
+ WORKING: "working";
113
+ DETECTING: "detecting";
114
+ PR_OPEN: "pr_open";
115
+ CI_FAILED: "ci_failed";
116
+ REVIEW_PENDING: "review_pending";
117
+ CHANGES_REQUESTED: "changes_requested";
118
+ APPROVED: "approved";
119
+ MERGEABLE: "mergeable";
120
+ MERGED: "merged";
121
+ CLEANUP: "cleanup";
122
+ NEEDS_INPUT: "needs_input";
123
+ STUCK: "stuck";
124
+ ERRORED: "errored";
125
+ IDLE: "idle";
126
+ KILLED: "killed";
127
+ DONE: "done";
128
+ TERMINATED: "terminated";
129
+ };
130
+ /** Statuses that indicate the session is in a terminal (dead) state. */
131
+ export declare const TERMINAL_STATUSES: ReadonlySet<SessionStatus>;
132
+ /** Activity states that indicate the session is no longer running. */
133
+ export declare const TERMINAL_ACTIVITIES: ReadonlySet<ActivityState>;
134
+ /** Statuses that must never be restored. */
135
+ export declare const NON_RESTORABLE_STATUSES: ReadonlySet<SessionStatus>;
136
+ /** Check if a session is in a terminal (dead) state. */
137
+ export declare function isTerminalSession(session: {
138
+ status: SessionStatus;
139
+ activity: ActivityState | null;
140
+ lifecycle?: CanonicalSessionLifecycle;
141
+ }): boolean;
142
+ /** Check if a session can be restored. */
143
+ export declare function isRestorable(session: {
144
+ status: SessionStatus;
145
+ activity: ActivityState | null;
146
+ lifecycle?: CanonicalSessionLifecycle;
147
+ }): boolean;
148
+ /** A running agent session */
149
+ export interface Session {
150
+ /** Unique session ID, e.g. "my-app-3" */
151
+ id: SessionId;
152
+ /** Which project this session belongs to */
153
+ projectId: string;
154
+ /** Current lifecycle status */
155
+ status: SessionStatus;
156
+ /** Activity state from agent plugin (null = not yet determined) */
157
+ activity: ActivityState | null;
158
+ /** Explicit confidence/availability contract for the current activity signal. */
159
+ activitySignal: ActivitySignal;
160
+ /** Canonical lifecycle truth persisted in metadata. */
161
+ lifecycle: CanonicalSessionLifecycle;
162
+ /** Git branch name */
163
+ branch: string | null;
164
+ /** Issue identifier (if working on an issue) */
165
+ issueId: string | null;
166
+ /** PR info (once PR is created) */
167
+ pr: PRInfo | null;
168
+ /** All PRs opened by this session (across multiple repos). Always in sync with pr —
169
+ * single-PR sessions have prs = [pr], no-PR sessions have prs = [].
170
+ * Populated from metadata field "prs" (comma-separated URLs) on load. */
171
+ prs: PRInfo[];
172
+ /** Workspace path on disk */
173
+ workspacePath: string | null;
174
+ /** Runtime handle for communicating with the session */
175
+ runtimeHandle: RuntimeHandle | null;
176
+ /** Agent session info (summary, cost, etc.) */
177
+ agentInfo: AgentSessionInfo | null;
178
+ /** When the session was created */
179
+ createdAt: Date;
180
+ /** Last activity timestamp */
181
+ lastActivityAt: Date;
182
+ /** When this session was last restored (undefined if never restored) */
183
+ restoredAt?: Date;
184
+ /** Metadata key-value pairs */
185
+ metadata: Record<string, string>;
186
+ }
187
+ export declare function isOrchestratorSession(session: {
188
+ id: SessionId;
189
+ metadata?: Record<string, string>;
190
+ }, sessionPrefix?: string, allSessionPrefixes?: string[]): boolean;
191
+ /** Config for creating a new session */
192
+ export interface SessionSpawnConfig {
193
+ projectId: string;
194
+ issueId?: string;
195
+ branch?: string;
196
+ prompt?: string;
197
+ /** Override the agent plugin for this session (e.g. "codex", "claude-code") */
198
+ agent?: string;
199
+ /** Override the OpenCode subagent for this session (e.g. "sisyphus", "oracle") */
200
+ subagent?: string;
201
+ }
202
+ /** Config for creating an orchestrator session */
203
+ export interface OrchestratorSpawnConfig {
204
+ projectId: string;
205
+ systemPrompt?: string;
206
+ /** Override the agent plugin for this orchestrator (e.g. "codex", "claude-code", "opencode") */
207
+ agent?: string;
208
+ }
209
+ /**
210
+ * Runtime determines WHERE and HOW agent sessions execute.
211
+ * tmux, docker, kubernetes, child processes, SSH, cloud sandboxes, etc.
212
+ */
213
+ export interface Runtime {
214
+ readonly name: string;
215
+ /** Create a new session environment and return a handle */
216
+ create(config: RuntimeCreateConfig): Promise<RuntimeHandle>;
217
+ /** Destroy a session environment */
218
+ destroy(handle: RuntimeHandle): Promise<void>;
219
+ /** Send a text message/prompt to the running agent */
220
+ sendMessage(handle: RuntimeHandle, message: string): Promise<void>;
221
+ /** Capture recent output from the session */
222
+ getOutput(handle: RuntimeHandle, lines?: number): Promise<string>;
223
+ /** Check if the session environment is still alive */
224
+ isAlive(handle: RuntimeHandle): Promise<boolean>;
225
+ /** Get resource metrics (uptime, memory, etc.) */
226
+ getMetrics?(handle: RuntimeHandle): Promise<RuntimeMetrics>;
227
+ /** Get info needed to attach a human to this session (for Terminal plugin) */
228
+ getAttachInfo?(handle: RuntimeHandle): Promise<AttachInfo>;
229
+ /**
230
+ * Optional: validate that this runtime's prerequisites are present before
231
+ * it is exercised by `athene spawn`. Throw with an actionable, human-readable
232
+ * message; the CLI catches and formats the error.
233
+ */
234
+ preflight?(context: PreflightContext): Promise<void>;
235
+ }
236
+ export interface RuntimeCreateConfig {
237
+ sessionId: SessionId;
238
+ workspacePath: string;
239
+ launchCommand: string;
240
+ environment: Record<string, string>;
241
+ }
242
+ /** Opaque handle returned by runtime.create() */
243
+ export interface RuntimeHandle {
244
+ /** Runtime-specific identifier (tmux session name, container ID, pod name, etc.) */
245
+ id: string;
246
+ /** Which runtime created this handle */
247
+ runtimeName: string;
248
+ /** Runtime-specific data */
249
+ data: Record<string, unknown>;
250
+ }
251
+ export interface RuntimeMetrics {
252
+ uptimeMs: number;
253
+ memoryMb?: number;
254
+ cpuPercent?: number;
255
+ }
256
+ export interface AttachInfo {
257
+ /** How to connect: tmux attach, docker exec, SSH, web URL, etc. */
258
+ type: "tmux" | "docker" | "ssh" | "web" | "process";
259
+ /** For tmux: session name. For docker: container ID. For web: URL. */
260
+ target: string;
261
+ /** Optional: command to run to attach */
262
+ command?: string;
263
+ }
264
+ /**
265
+ * Agent adapter for a specific AI coding tool.
266
+ * Knows how to launch, detect activity, and extract session info.
267
+ */
268
+ export declare const PROCESS_PROBE_INDETERMINATE: "indeterminate";
269
+ export type ProcessProbeResult = boolean | typeof PROCESS_PROBE_INDETERMINATE;
270
+ export declare function isProcessProbeIndeterminate(result: ProcessProbeResult): result is typeof PROCESS_PROBE_INDETERMINATE;
271
+ export interface Agent {
272
+ readonly name: string;
273
+ /** Process name to look for (e.g. "claude", "codex", "aider") */
274
+ readonly processName: string;
275
+ /**
276
+ * How the initial user prompt is delivered.
277
+ * Defaults to inline, meaning the agent embeds the prompt in getLaunchCommand().
278
+ * Use post-launch for interactive CLIs that must start first and receive input over stdin.
279
+ */
280
+ readonly promptDelivery?: "inline" | "post-launch";
281
+ /** Get the shell command to launch this agent */
282
+ getLaunchCommand(config: AgentLaunchConfig): string;
283
+ /** Get environment variables for the agent process */
284
+ getEnvironment(config: AgentLaunchConfig): Record<string, string>;
285
+ /**
286
+ * Detect what the agent is currently doing from terminal output.
287
+ * @deprecated Use getActivityState() instead - this uses hacky terminal parsing.
288
+ */
289
+ detectActivity(terminalOutput: string): ActivityState;
290
+ /**
291
+ * Get current activity state using agent-native mechanism (JSONL, SQLite, etc.).
292
+ * This is the preferred method for activity detection.
293
+ * @param readyThresholdMs - ms before "ready" becomes "idle" (default: DEFAULT_READY_THRESHOLD_MS)
294
+ */
295
+ getActivityState(session: Session, readyThresholdMs?: number): Promise<ActivityDetection | null>;
296
+ /**
297
+ * Check if agent process is running (given runtime handle).
298
+ *
299
+ * Returns "indeterminate" when the probe could not reliably determine
300
+ * liveness (for example, `ps`/`tmux` timed out or failed). Callers must
301
+ * treat that as no verdict, not as a missing process.
302
+ */
303
+ isProcessRunning(handle: RuntimeHandle): Promise<ProcessProbeResult>;
304
+ /** Extract information from agent's internal data (summary, cost, session ID) */
305
+ getSessionInfo(session: Session): Promise<AgentSessionInfo | null>;
306
+ /**
307
+ * Optional: get a launch command that resumes a previous session.
308
+ * Returns null if no previous session is found (caller falls back to getLaunchCommand).
309
+ */
310
+ getRestoreCommand?(session: Session, project: ProjectConfig): Promise<string | null>;
311
+ /**
312
+ * Optional: run setup BEFORE the agent process is launched.
313
+ *
314
+ * Use this when a plugin needs to observe state that the agent itself will
315
+ * mutate at startup. Captured *after* the workspace exists but *before*
316
+ * `runtime.create()` spawns the agent — so the snapshot is taken cleanly,
317
+ * with no race against the agent's own initialization writes.
318
+ *
319
+ * Receives only the workspace path because the full Session object (with
320
+ * runtime handle, lifecycle, etc.) does not exist yet at this point.
321
+ */
322
+ preLaunchSetup?(workspacePath: string): Promise<void>;
323
+ /** Optional: run setup after agent is launched (e.g. configure MCP servers) */
324
+ postLaunchSetup?(session: Session): Promise<void>;
325
+ /**
326
+ * Optional: Set up agent-specific hooks/config in the workspace for automatic metadata updates.
327
+ * Called once per workspace during athene start and when creating new worktrees.
328
+ *
329
+ * Each agent plugin implements this for their own config format:
330
+ * - Claude Code: writes .claude/settings.json with PostToolUse hook
331
+ * - Codex: whatever config mechanism Codex uses
332
+ * - Aider: .aider.conf.yml or similar
333
+ * - OpenCode: its own config
334
+ *
335
+ * CRITICAL: The dashboard depends on metadata being auto-updated when agents
336
+ * run git/gh commands. Without this, PRs created by agents never show up.
337
+ */
338
+ setupWorkspaceHooks?(workspacePath: string, config: WorkspaceHooksConfig): Promise<void>;
339
+ /**
340
+ * Optional: Record an activity observation to the session's JSONL activity log.
341
+ * Called by the lifecycle manager during each poll cycle with captured terminal output.
342
+ *
343
+ * Plugins classify the terminal output (via detectActivity) and append a JSONL entry
344
+ * to `{session.workspacePath}/.ao/activity.jsonl`. The next `getActivityState()` call
345
+ * reads from this file to detect states like `waiting_input` and `blocked`.
346
+ *
347
+ * Agents with native JSONL (Claude Code, Codex) should NOT implement this — their
348
+ * `getActivityState` already reads richer data from the agent's own session files.
349
+ */
350
+ recordActivity?(session: Session, terminalOutput: string): Promise<void>;
351
+ /**
352
+ * Optional: validate that this agent's prerequisites are present before
353
+ * it is exercised by `athene spawn`. Throw with an actionable error message.
354
+ */
355
+ preflight?(context: PreflightContext): Promise<void>;
356
+ }
357
+ export interface AgentLaunchConfig {
358
+ sessionId: SessionId;
359
+ projectConfig: ProjectConfig;
360
+ /**
361
+ * Per-session workspace path. Differs from `projectConfig.path` when the
362
+ * workspace plugin (e.g. worktree mode) creates an isolated checkout per
363
+ * session. Plugins that need the agent's actual cwd — for cwd-derived
364
+ * lookups, --work-dir flags, file-based discovery — must use this when
365
+ * present. Falls back to `projectConfig.path` when undefined (clone-mode
366
+ * workspaces, or plugins not yet plumbing it through).
367
+ */
368
+ workspacePath?: string;
369
+ issueId?: string;
370
+ prompt?: string;
371
+ permissions?: AgentPermissionInput;
372
+ model?: string;
373
+ /**
374
+ * System prompt to pass to the agent for orchestrator context.
375
+ * - Claude Code: --append-system-prompt
376
+ * - Codex: --system-prompt or AGENTS.md
377
+ * - Aider: --system-prompt flag
378
+ * - OpenCode: equivalent mechanism
379
+ *
380
+ * For short prompts only. For long prompts, use systemPromptFile instead
381
+ * to avoid shell/tmux truncation issues.
382
+ */
383
+ systemPrompt?: string;
384
+ /**
385
+ * Path to a file containing the system prompt.
386
+ * Preferred over systemPrompt for long prompts (e.g. orchestrator prompts)
387
+ * because inlining 2000+ char prompts in shell commands causes truncation.
388
+ *
389
+ * When set, takes precedence over systemPrompt.
390
+ * - Claude Code: --append-system-prompt "$(cat /path/to/file)"
391
+ * - Codex/Aider: similar shell substitution
392
+ */
393
+ systemPromptFile?: string;
394
+ /**
395
+ * Specialized OpenCode subagent to use (e.g., sisyphus, oracle, librarian).
396
+ * Requires oh-my-opencode to be installed.
397
+ * Use --subagent flag to select the subagent.
398
+ */
399
+ subagent?: string;
400
+ }
401
+ export interface WorkspaceHooksConfig {
402
+ /** Data directory where session metadata files are stored */
403
+ dataDir: string;
404
+ /** Optional session ID (may not be known at workspace setup time) */
405
+ sessionId?: string;
406
+ }
407
+ export interface AgentSessionInfo {
408
+ /** Agent's auto-generated summary of what it's working on */
409
+ summary: string | null;
410
+ /** True when summary is a fallback (e.g. truncated first user message), not a real agent summary */
411
+ summaryIsFallback?: boolean;
412
+ /** Agent's internal session ID (for resume) */
413
+ agentSessionId: string | null;
414
+ /** Agent-owned metadata worth persisting for later restore. */
415
+ metadata?: Record<string, string>;
416
+ /** Estimated cost so far */
417
+ cost?: CostEstimate;
418
+ }
419
+ export interface CostEstimate {
420
+ inputTokens: number;
421
+ outputTokens: number;
422
+ estimatedCostUsd: number;
423
+ }
424
+ /**
425
+ * Workspace manages code isolation — how each session gets its own copy of the repo.
426
+ */
427
+ export interface Workspace {
428
+ readonly name: string;
429
+ /** Create an isolated workspace for a session */
430
+ create(config: WorkspaceCreateConfig): Promise<WorkspaceInfo>;
431
+ /** Destroy a workspace */
432
+ destroy(workspacePath: string): Promise<void>;
433
+ /** List existing workspaces for a project */
434
+ list(projectId: string): Promise<WorkspaceInfo[]>;
435
+ /**
436
+ * Optional: find a pre-existing AO-managed workspace that already tracks the
437
+ * requested branch and can be adopted instead of creating a fresh workspace.
438
+ */
439
+ findManagedWorkspace?(config: WorkspaceCreateConfig): Promise<WorkspaceInfo | null>;
440
+ /** Optional: run hooks after workspace creation (symlinks, installs, etc.) */
441
+ postCreate?(info: WorkspaceInfo, project: ProjectConfig): Promise<void>;
442
+ /** Optional: check if a workspace exists and is a valid git repo */
443
+ exists?(workspacePath: string): Promise<boolean>;
444
+ /** Optional: restore a workspace (e.g. recreate a worktree for an existing branch) */
445
+ restore?(config: WorkspaceCreateConfig, workspacePath: string): Promise<WorkspaceInfo>;
446
+ /**
447
+ * Optional: validate that this workspace's prerequisites (e.g. git in PATH,
448
+ * write access to the worktree root) are present before `athene spawn`.
449
+ */
450
+ preflight?(context: PreflightContext): Promise<void>;
451
+ }
452
+ export interface WorkspaceCreateConfig {
453
+ projectId: string;
454
+ project: ProjectConfig;
455
+ sessionId: SessionId;
456
+ branch: string;
457
+ /** Override the base directory for worktrees (e.g. V2 project-scoped dir). */
458
+ worktreeDir?: string;
459
+ }
460
+ export interface WorkspaceInfo {
461
+ path: string;
462
+ branch: string;
463
+ sessionId: SessionId;
464
+ projectId: string;
465
+ }
466
+ /**
467
+ * Issue/task tracker integration — GitHub Issues, Linear, Jira, etc.
468
+ */
469
+ export interface Tracker {
470
+ readonly name: string;
471
+ /** Fetch issue details */
472
+ getIssue(identifier: string, project: ProjectConfig): Promise<Issue>;
473
+ /** Check if issue is completed/closed */
474
+ isCompleted(identifier: string, project: ProjectConfig): Promise<boolean>;
475
+ /** Generate a URL for the issue */
476
+ issueUrl(identifier: string, project: ProjectConfig): string;
477
+ /** Extract a human-readable label from an issue URL (e.g., "INT-1327", "#42") */
478
+ issueLabel?(url: string, project: ProjectConfig): string;
479
+ /** Generate a git branch name for the issue */
480
+ branchName(identifier: string, project: ProjectConfig): string;
481
+ /** Generate a prompt for the agent to work on this issue */
482
+ generatePrompt(identifier: string, project: ProjectConfig): Promise<string>;
483
+ /** Optional: list issues with filters */
484
+ listIssues?(filters: IssueFilters, project: ProjectConfig): Promise<Issue[]>;
485
+ /** Optional: update issue state */
486
+ updateIssue?(identifier: string, update: IssueUpdate, project: ProjectConfig): Promise<void>;
487
+ /** Optional: create a new issue */
488
+ createIssue?(input: CreateIssueInput, project: ProjectConfig): Promise<Issue>;
489
+ /**
490
+ * Optional: validate that this tracker's prerequisites (auth tokens, CLI
491
+ * tools) are present before `athene spawn` runs. Throw with an actionable
492
+ * error message.
493
+ */
494
+ preflight?(context: PreflightContext): Promise<void>;
495
+ }
496
+ export interface Issue {
497
+ id: string;
498
+ title: string;
499
+ description: string;
500
+ url: string;
501
+ state: "open" | "in_progress" | "closed" | "cancelled";
502
+ labels: string[];
503
+ assignee?: string;
504
+ priority?: number;
505
+ branchName?: string;
506
+ }
507
+ export interface IssueFilters {
508
+ state?: "open" | "closed" | "all";
509
+ labels?: string[];
510
+ assignee?: string;
511
+ limit?: number;
512
+ }
513
+ export interface IssueUpdate {
514
+ state?: "open" | "in_progress" | "closed";
515
+ labels?: string[];
516
+ removeLabels?: string[];
517
+ assignee?: string;
518
+ comment?: string;
519
+ }
520
+ export interface CreateIssueInput {
521
+ title: string;
522
+ description: string;
523
+ labels?: string[];
524
+ assignee?: string;
525
+ priority?: number;
526
+ }
527
+ /**
528
+ * Source code management platform — PR lifecycle, CI checks, code reviews.
529
+ * This is the richest plugin interface, covering the full PR pipeline.
530
+ */
531
+ export interface SCM {
532
+ readonly name: string;
533
+ verifyWebhook?(request: SCMWebhookRequest, project: ProjectConfig): Promise<SCMWebhookVerificationResult>;
534
+ parseWebhook?(request: SCMWebhookRequest, project: ProjectConfig): Promise<SCMWebhookEvent | null>;
535
+ /** Detect if a session has an open PR (by branch name) */
536
+ detectPR(session: Session, project: ProjectConfig): Promise<PRInfo | null>;
537
+ /** Resolve a PR reference (number or URL) into canonical PR metadata. */
538
+ resolvePR?(reference: string, project: ProjectConfig): Promise<PRInfo>;
539
+ /** Assign a PR to the currently authenticated user, if supported. */
540
+ assignPRToCurrentUser?(pr: PRInfo): Promise<void>;
541
+ /** Check out the PR branch into a workspace. Returns true if branch changed. */
542
+ checkoutPR?(pr: PRInfo, workspacePath: string): Promise<boolean>;
543
+ /** Get current PR state */
544
+ getPRState(pr: PRInfo): Promise<PRState>;
545
+ /** Get PR summary with stats (state, title, additions, deletions). Optional. */
546
+ getPRSummary?(pr: PRInfo): Promise<{
547
+ state: PRState;
548
+ title: string;
549
+ additions: number;
550
+ deletions: number;
551
+ }>;
552
+ /** Merge a PR */
553
+ mergePR(pr: PRInfo, method?: MergeMethod): Promise<void>;
554
+ /** Close a PR without merging */
555
+ closePR(pr: PRInfo): Promise<void>;
556
+ /** Get individual CI check statuses */
557
+ getCIChecks(pr: PRInfo): Promise<CICheck[]>;
558
+ /** Get failed CI jobs/steps with a bounded failed-log tail, if supported. */
559
+ getCIFailureSummary?(pr: PRInfo, failedChecks?: CICheck[]): Promise<CIFailureSummary | null>;
560
+ /** Get overall CI summary */
561
+ getCISummary(pr: PRInfo): Promise<CIStatus>;
562
+ /** Get all reviews on a PR */
563
+ getReviews(pr: PRInfo): Promise<Review[]>;
564
+ /** Get the overall review decision */
565
+ getReviewDecision(pr: PRInfo): Promise<ReviewDecision>;
566
+ /** Get pending (unresolved) review comments */
567
+ getPendingComments(pr: PRInfo): Promise<ReviewComment[]>;
568
+ /**
569
+ * Get all review threads (human + bot) with isBot flag.
570
+ * Single GraphQL call for all review threads (human + bot) with review summaries.
571
+ * Returns unresolved threads only.
572
+ *
573
+ * Optional — plugins that do not implement this method will fall back to
574
+ * `getPendingComments()` (which lacks `isBot` classification and review
575
+ * summaries). New SCM plugins should prefer implementing this method.
576
+ *
577
+ * @since 0.6.0 — replaces the removed `getAutomatedComments` method.
578
+ */
579
+ getReviewThreads?(pr: PRInfo): Promise<ReviewThreadsResult>;
580
+ /** Check if PR is ready to merge */
581
+ getMergeability(pr: PRInfo): Promise<MergeReadiness>;
582
+ /**
583
+ * Batch fetch PR data for multiple PRs in a single GraphQL query.
584
+ * Used by the orchestrator to poll all active sessions efficiently.
585
+ *
586
+ * This is an optimization method that, when implemented, can dramatically
587
+ * reduce API calls by fetching data for multiple PRs in one request
588
+ * instead of calling getPRState/getCISummary/getReviewDecision separately
589
+ * for each PR.
590
+ *
591
+ * @param prs - Array of PR information to fetch data for
592
+ * @param observer - Optional observer for batch operation metrics
593
+ * @returns Map keyed by "${owner}/${repo}#${number}" containing enrichment data
594
+ */
595
+ enrichSessionsPRBatch?(prs: PRInfo[], observer?: BatchObserver, repos?: string[]): Promise<Map<string, PREnrichmentData>>;
596
+ /**
597
+ * Optional: validate that this SCM's prerequisites (auth, CLI tools) are
598
+ * present before `athene spawn` runs. Plugins should consult
599
+ * `context.intent.willClaimExistingPR` and skip PR-write prereqs when the
600
+ * spawn won't exercise them.
601
+ */
602
+ preflight?(context: PreflightContext): Promise<void>;
603
+ }
604
+ /**
605
+ * Batch enrichment data returned by SCM plugins.
606
+ * Contains all the information the orchestrator needs for status detection.
607
+ */
608
+ export interface PREnrichmentData {
609
+ /** Current PR state */
610
+ state: PRState;
611
+ /** Overall CI status */
612
+ ciStatus: CIStatus;
613
+ /** Review decision */
614
+ reviewDecision: ReviewDecision;
615
+ /** Whether the PR is mergeable based on CI, reviews, and merge state */
616
+ mergeable: boolean;
617
+ /** PR title */
618
+ title?: string;
619
+ /** Number of additions */
620
+ additions?: number;
621
+ /** Number of deletions */
622
+ deletions?: number;
623
+ /** Whether PR is a draft */
624
+ isDraft?: boolean;
625
+ /** Whether PR has merge conflicts */
626
+ hasConflicts?: boolean;
627
+ /** Whether PR is behind base branch */
628
+ isBehind?: boolean;
629
+ /** List of blockers preventing merge */
630
+ blockers?: string[];
631
+ }
632
+ /**
633
+ * Observer for GraphQL batch PR enrichment operations.
634
+ * Used by SCM plugins to report batch success/failure to the observability system.
635
+ */
636
+ export interface BatchObserver {
637
+ /** Record a successful batch enrichment */
638
+ recordSuccess(data: {
639
+ batchIndex: number;
640
+ totalBatches: number;
641
+ prCount: number;
642
+ durationMs: number;
643
+ }): void;
644
+ /** Record a failed batch enrichment */
645
+ recordFailure(data: {
646
+ batchIndex: number;
647
+ totalBatches: number;
648
+ prCount: number;
649
+ error: string;
650
+ durationMs: number;
651
+ }): void;
652
+ /** Log a message at a specific level */
653
+ log(level: ObservabilityLevel, message: string): void;
654
+ /** Called after ETag guards with repos where Guard 1 returned 304 (no PR list changes). */
655
+ reportPRListUnchangedRepos?(repos: Set<string>): void;
656
+ }
657
+ export interface PRInfo {
658
+ number: number;
659
+ url: string;
660
+ title: string;
661
+ owner: string;
662
+ repo: string;
663
+ branch: string;
664
+ baseBranch: string;
665
+ isDraft: boolean;
666
+ }
667
+ export type PRState = "open" | "merged" | "closed";
668
+ /** PR state constants */
669
+ export declare const PR_STATE: {
670
+ OPEN: "open";
671
+ MERGED: "merged";
672
+ CLOSED: "closed";
673
+ };
674
+ export type MergeMethod = "merge" | "squash" | "rebase";
675
+ export interface SCMWebhookRequest {
676
+ method: string;
677
+ headers: Record<string, string | string[] | undefined>;
678
+ body: string;
679
+ rawBody?: Uint8Array;
680
+ path?: string;
681
+ query?: Record<string, string | string[] | undefined>;
682
+ }
683
+ export interface SCMWebhookVerificationResult {
684
+ ok: boolean;
685
+ reason?: string;
686
+ deliveryId?: string;
687
+ eventType?: string;
688
+ }
689
+ export type SCMWebhookEventKind = "pull_request" | "ci" | "review" | "comment" | "push" | "unknown";
690
+ export interface SCMWebhookEvent {
691
+ provider: string;
692
+ kind: SCMWebhookEventKind;
693
+ action: string;
694
+ rawEventType: string;
695
+ deliveryId?: string;
696
+ projectId?: string;
697
+ repository?: {
698
+ owner: string;
699
+ name: string;
700
+ };
701
+ prNumber?: number;
702
+ branch?: string;
703
+ sha?: string;
704
+ timestamp?: Date;
705
+ data: Record<string, unknown>;
706
+ }
707
+ export interface CICheck {
708
+ name: string;
709
+ status: "pending" | "running" | "passed" | "failed" | "skipped";
710
+ url?: string;
711
+ conclusion?: string;
712
+ startedAt?: Date;
713
+ completedAt?: Date;
714
+ }
715
+ export interface CIFailureSummary {
716
+ failedJobs: Array<{
717
+ name: string;
718
+ failedStep?: string;
719
+ runUrl: string;
720
+ logTail?: string;
721
+ }>;
722
+ }
723
+ export type CIStatus = "pending" | "passing" | "failing" | "none";
724
+ /** CI status constants */
725
+ export declare const CI_STATUS: {
726
+ PENDING: "pending";
727
+ PASSING: "passing";
728
+ FAILING: "failing";
729
+ NONE: "none";
730
+ };
731
+ export interface Review {
732
+ author: string;
733
+ state: "approved" | "changes_requested" | "commented" | "dismissed" | "pending";
734
+ body?: string;
735
+ submittedAt: Date;
736
+ }
737
+ export type ReviewDecision = "approved" | "changes_requested" | "pending" | "none";
738
+ export interface ReviewComment {
739
+ id: string;
740
+ /** GraphQL node ID of the review thread (for resolveReviewThread mutation). */
741
+ threadId?: string;
742
+ author: string;
743
+ body: string;
744
+ path?: string;
745
+ line?: number;
746
+ isResolved: boolean;
747
+ createdAt: Date;
748
+ url: string;
749
+ /** Whether the comment was authored by a known bot */
750
+ isBot?: boolean;
751
+ }
752
+ export interface ReviewSummary {
753
+ author: string;
754
+ state: string;
755
+ body: string;
756
+ submittedAt: Date;
757
+ }
758
+ export interface ReviewThreadsResult {
759
+ threads: ReviewComment[];
760
+ reviews: ReviewSummary[];
761
+ }
762
+ export interface AutomatedComment {
763
+ id: string;
764
+ botName: string;
765
+ body: string;
766
+ path?: string;
767
+ line?: number;
768
+ severity: "error" | "warning" | "info";
769
+ createdAt: Date;
770
+ url: string;
771
+ }
772
+ export interface MergeReadiness {
773
+ mergeable: boolean;
774
+ ciPassing: boolean;
775
+ approved: boolean;
776
+ noConflicts: boolean;
777
+ blockers: string[];
778
+ }
779
+ /**
780
+ * Batch enrichment data returned by SCM plugins.
781
+ * Contains all the information the orchestrator needs for status detection.
782
+ */
783
+ export interface PREnrichmentData {
784
+ /** Current PR state */
785
+ state: PRState;
786
+ /** Overall CI status */
787
+ ciStatus: CIStatus;
788
+ /** Review decision */
789
+ reviewDecision: ReviewDecision;
790
+ /** Whether the PR is mergeable based on CI, reviews, and merge state */
791
+ mergeable: boolean;
792
+ /** PR title */
793
+ title?: string;
794
+ /** Number of additions */
795
+ additions?: number;
796
+ /** Number of deletions */
797
+ deletions?: number;
798
+ /** Whether PR is a draft */
799
+ isDraft?: boolean;
800
+ /** Whether PR has merge conflicts */
801
+ hasConflicts?: boolean;
802
+ /** Whether PR is behind base branch */
803
+ isBehind?: boolean;
804
+ /** List of blockers preventing merge */
805
+ blockers?: string[];
806
+ /** Individual CI check results (populated from batch enrichment when available) */
807
+ ciChecks?: CICheck[];
808
+ }
809
+ /**
810
+ * Observer for GraphQL batch PR enrichment operations.
811
+ * Used by SCM plugins to report batch success/failure to the observability system.
812
+ */
813
+ export interface BatchObserver {
814
+ /** Record a successful batch enrichment */
815
+ recordSuccess(data: {
816
+ batchIndex: number;
817
+ totalBatches: number;
818
+ prCount: number;
819
+ durationMs: number;
820
+ }): void;
821
+ /** Record a failed batch enrichment */
822
+ recordFailure(data: {
823
+ batchIndex: number;
824
+ totalBatches: number;
825
+ prCount: number;
826
+ error: string;
827
+ durationMs: number;
828
+ }): void;
829
+ /** Log a message at a specific level */
830
+ log(level: ObservabilityLevel, message: string): void;
831
+ }
832
+ /**
833
+ * Notifier is the PRIMARY interface between the orchestrator and the human.
834
+ * The human walks away after spawning agents. Notifications bring them back.
835
+ *
836
+ * Push, not pull. The human never polls.
837
+ */
838
+ export interface Notifier {
839
+ readonly name: string;
840
+ /** Push a notification to the human */
841
+ notify(event: OrchestratorEvent): Promise<void>;
842
+ /** Push a notification with actionable buttons/links */
843
+ notifyWithActions?(event: OrchestratorEvent, actions: NotifyAction[]): Promise<void>;
844
+ /** Post a message to a channel (for team-visible notifiers like Slack) */
845
+ post?(message: string, context?: NotifyContext): Promise<string | null>;
846
+ }
847
+ export interface NotifyAction {
848
+ label: string;
849
+ url?: string;
850
+ callbackEndpoint?: string;
851
+ }
852
+ export interface NotifyContext {
853
+ sessionId?: SessionId;
854
+ projectId?: string;
855
+ prUrl?: string;
856
+ channel?: string;
857
+ }
858
+ /**
859
+ * Terminal manages how humans view/interact with running sessions.
860
+ * Opens IDE tabs, browser windows, or terminal sessions.
861
+ */
862
+ export interface Terminal {
863
+ readonly name: string;
864
+ /** Open a session for human interaction */
865
+ openSession(session: Session): Promise<void>;
866
+ /** Open all sessions for a project */
867
+ openAll(sessions: Session[]): Promise<void>;
868
+ /** Check if a session is already open in a tab/window */
869
+ isSessionOpen?(session: Session): Promise<boolean>;
870
+ }
871
+ /** Priority levels for events — determines notification routing */
872
+ export type EventPriority = "urgent" | "action" | "warning" | "info";
873
+ /** All orchestrator event types */
874
+ export type EventType = "session.spawn_started" | "session.spawned" | "session.working" | "session.exited" | "session.killed" | "session.idle" | "session.stuck" | "session.needs_input" | "session.errored" | "pr.created" | "pr.updated" | "pr.merged" | "pr.closed" | "ci.passing" | "ci.failing" | "ci.fix_sent" | "ci.fix_failed" | "review.pending" | "review.approved" | "review.changes_requested" | "review.comments_sent" | "review.comments_unresolved" | "automated_review.found" | "automated_review.fix_sent" | "merge.ready" | "merge.conflicts" | "merge.completed" | "reaction.triggered" | "reaction.escalated" | "summary.all_complete";
875
+ /** An event emitted by the orchestrator */
876
+ export interface OrchestratorEvent {
877
+ id: string;
878
+ type: EventType;
879
+ priority: EventPriority;
880
+ sessionId: SessionId;
881
+ projectId: string;
882
+ timestamp: Date;
883
+ message: string;
884
+ data: Record<string, unknown>;
885
+ }
886
+ /** A configured automatic reaction to an event */
887
+ export interface ReactionConfig {
888
+ /** Whether this reaction is enabled */
889
+ auto: boolean;
890
+ /** What to do: send message to agent, notify human, auto-merge */
891
+ action: "send-to-agent" | "notify" | "auto-merge";
892
+ /** Message to send (for send-to-agent) */
893
+ message?: string;
894
+ /** Priority for notifications */
895
+ priority?: EventPriority;
896
+ /** How many times to retry send-to-agent before escalating */
897
+ retries?: number;
898
+ /** Escalate to human notification after this many failures or this duration */
899
+ escalateAfter?: number | string;
900
+ /** Threshold duration for time-based triggers (e.g. "10m" for stuck detection) */
901
+ threshold?: string;
902
+ /** Whether to include a summary in the notification */
903
+ includeSummary?: boolean;
904
+ }
905
+ export interface ReactionResult {
906
+ reactionType: string;
907
+ success: boolean;
908
+ action: string;
909
+ message?: string;
910
+ escalated: boolean;
911
+ }
912
+ /**
913
+ * Power management configuration.
914
+ * Controls system sleep behavior while AO is running.
915
+ */
916
+ export interface PowerConfig {
917
+ /**
918
+ * Prevent macOS idle sleep while AO is running.
919
+ * Uses `caffeinate -i -w <pid>` to hold an assertion.
920
+ * Defaults to true on macOS, no-op on other platforms.
921
+ */
922
+ preventIdleSleep: boolean;
923
+ }
924
+ /** Lifecycle-level orchestration configuration. */
925
+ export interface LifecycleConfig {
926
+ /**
927
+ * When a session's PR is detected as merged, automatically tear down the
928
+ * tmux runtime, remove the worktree, and archive the session metadata.
929
+ * Defaults to true so `athene status` does not retain stale merged entries.
930
+ */
931
+ autoCleanupOnMerge: boolean;
932
+ /**
933
+ * Maximum time (ms) to wait after a session enters `merged` before forcing
934
+ * cleanup regardless of agent activity. If the agent becomes idle sooner,
935
+ * cleanup happens then. Defaults to 5 minutes.
936
+ */
937
+ mergeCleanupIdleGraceMs: number;
938
+ }
939
+ export interface ObservabilityConfig {
940
+ /** Minimum structured log level to persist/mirror. Defaults to "warn". */
941
+ logLevel: ObservabilityLevel;
942
+ /** Mirror structured observability logs to stderr. Defaults to false. */
943
+ stderr: boolean;
944
+ }
945
+ /** Top-level orchestrator configuration (from agent-orchestrator.yaml) */
946
+ export interface OrchestratorConfig {
947
+ /** Optional JSON Schema hint for editor autocomplete/validation. */
948
+ "$schema"?: string;
949
+ /**
950
+ * Path to the config file (set automatically during load).
951
+ * Used for hash-based directory structure.
952
+ * All paths are auto-derived from this location.
953
+ */
954
+ configPath: string;
955
+ /** Web dashboard port (defaults to 3000) */
956
+ port?: number;
957
+ /** Terminal WebSocket server port (defaults to 3001) */
958
+ terminalPort?: number;
959
+ /** Direct terminal WebSocket server port (defaults to 3003) */
960
+ directTerminalPort?: number;
961
+ /** Milliseconds before a "ready" session becomes "idle" (default: 300000 = 5 min) */
962
+ readyThresholdMs: number;
963
+ /** Power management settings (idle sleep prevention, etc.). Populated with defaults post-validation. */
964
+ power?: PowerConfig;
965
+ /**
966
+ * Lifecycle-level orchestration settings. Populated with defaults by Zod
967
+ * when loaded from YAML, but typed as optional so hand-constructed test
968
+ * configs remain valid. Consumers should destructure with defaults rather
969
+ * than dereferencing directly. Mirrors the `power?` pattern above.
970
+ */
971
+ lifecycle?: LifecycleConfig;
972
+ /**
973
+ * Process observability settings. Populated with defaults by Zod when loaded
974
+ * from YAML, but optional for hand-constructed tests.
975
+ */
976
+ observability?: ObservabilityConfig;
977
+ /** Default plugin selections */
978
+ defaults: DefaultPlugins;
979
+ /** Installer-managed external plugin descriptors */
980
+ plugins?: InstalledPluginConfig[];
981
+ /** Project configurations */
982
+ projects: Record<string, ProjectConfig>;
983
+ /** Dashboard UI configuration */
984
+ dashboard?: DashboardConfig;
985
+ /** Notification channel configs */
986
+ notifiers: Record<string, NotifierConfig>;
987
+ /** Notification routing by priority */
988
+ notificationRouting: Record<EventPriority, string[]>;
989
+ /** Default reaction configs */
990
+ reactions: Record<string, ReactionConfig>;
991
+ /**
992
+ * Internal: External plugin entries collected from inline tracker/scm/notifier configs.
993
+ * Used by plugin-registry for manifest validation. Set automatically during config validation.
994
+ */
995
+ _externalPluginEntries?: ExternalPluginEntryRef[];
996
+ }
997
+ export interface DegradedProjectEntry {
998
+ projectId: string;
999
+ path: string;
1000
+ resolveError: string;
1001
+ }
1002
+ export interface LoadedConfig extends OrchestratorConfig {
1003
+ degradedProjects: Record<string, DegradedProjectEntry>;
1004
+ }
1005
+ /**
1006
+ * Structured location of an external plugin config.
1007
+ * Used to update config with manifest.name after loading (avoids parsing dotted strings).
1008
+ */
1009
+ export type ExternalPluginLocation = {
1010
+ kind: "project";
1011
+ projectId: string;
1012
+ configType: "tracker" | "scm";
1013
+ } | {
1014
+ kind: "notifier";
1015
+ notifierId: string;
1016
+ };
1017
+ /**
1018
+ * Reference to an external plugin config (from inline tracker/scm/notifier configs).
1019
+ * Used for manifest.name validation during plugin loading.
1020
+ */
1021
+ export interface ExternalPluginEntryRef {
1022
+ /** Where this config came from (for error messages) */
1023
+ source: string;
1024
+ /** Structured location for updating config (avoids parsing source string) */
1025
+ location: ExternalPluginLocation;
1026
+ /** The slot this plugin fills */
1027
+ slot: "tracker" | "scm" | "notifier";
1028
+ /** npm package name (if specified) */
1029
+ package?: string;
1030
+ /** Local path (if specified) */
1031
+ path?: string;
1032
+ /**
1033
+ * Expected plugin name (manifest.name).
1034
+ * Only set when user explicitly specified `plugin` field.
1035
+ * When undefined, any manifest.name is accepted and config is updated with it.
1036
+ */
1037
+ expectedPluginName?: string;
1038
+ }
1039
+ /**
1040
+ * Dashboard attention zone display mode.
1041
+ *
1042
+ * - "simple" (default): collapses the 5 detailed zones into 4 by merging
1043
+ * REVIEW + RESPOND into a single ACTION column. The card-level badges
1044
+ * still expose the underlying state (ci_failed, needs_input, changes_requested).
1045
+ * - "detailed": preserves the original 5-zone Kanban layout for power users
1046
+ * who want REVIEW and RESPOND as distinct columns.
1047
+ */
1048
+ export type DashboardAttentionZoneMode = "simple" | "detailed";
1049
+ export interface DashboardConfig {
1050
+ /** Attention zone layout (defaults to "simple") */
1051
+ attentionZones?: DashboardAttentionZoneMode;
1052
+ }
1053
+ export interface DefaultPlugins {
1054
+ runtime: string;
1055
+ agent: string;
1056
+ workspace: string;
1057
+ notifiers: string[];
1058
+ orchestrator?: {
1059
+ agent?: string;
1060
+ };
1061
+ worker?: {
1062
+ agent?: string;
1063
+ };
1064
+ }
1065
+ export type InstalledPluginSource = "registry" | "npm" | "local";
1066
+ export interface InstalledPluginConfig {
1067
+ /** Stable logical plugin name used in config and CLI UX */
1068
+ name: string;
1069
+ /** Where the plugin should be resolved from */
1070
+ source: InstalledPluginSource;
1071
+ /** Package name for registry/npm-managed plugins */
1072
+ package?: string;
1073
+ /** Requested version/range for installer-managed plugins */
1074
+ version?: string;
1075
+ /** Filesystem path for local plugins */
1076
+ path?: string;
1077
+ /** Installer-managed enable flag (defaults to true) */
1078
+ enabled?: boolean;
1079
+ }
1080
+ export interface RoleAgentConfig {
1081
+ agent?: string;
1082
+ agentConfig?: AgentSpecificConfig;
1083
+ }
1084
+ export interface ProjectConfig {
1085
+ /** Display name */
1086
+ name: string;
1087
+ /** Repository path for the configured SCM provider, e.g. "owner/repo" or "group/subgroup/repo" (optional — omitted when no remote detected) */
1088
+ repo?: string;
1089
+ /** Local path to the repo */
1090
+ path: string;
1091
+ resolveError?: string;
1092
+ /** Default branch (main, master, next, develop, etc.) */
1093
+ defaultBranch: string;
1094
+ /** Session name prefix (e.g. "app" → "app-1", "app-2") */
1095
+ sessionPrefix: string;
1096
+ /** Whether this project is active in portfolio and dashboard surfaces */
1097
+ enabled?: boolean;
1098
+ /** Override default runtime */
1099
+ runtime?: string;
1100
+ /** Override default agent */
1101
+ agent?: string;
1102
+ /** Override default workspace */
1103
+ workspace?: string;
1104
+ /** Environment variables forwarded into worker session runtimes (AO_* internals always win) */
1105
+ env?: Record<string, string>;
1106
+ /** Issue tracker configuration */
1107
+ tracker?: TrackerConfig;
1108
+ /** SCM configuration (usually inferred from repo) */
1109
+ scm?: SCMConfig;
1110
+ /** Files/dirs to symlink into workspaces */
1111
+ symlinks?: string[];
1112
+ /** Commands to run after workspace creation */
1113
+ postCreate?: string[];
1114
+ /** Agent-specific configuration */
1115
+ agentConfig?: AgentSpecificConfig;
1116
+ orchestrator?: RoleAgentConfig;
1117
+ worker?: RoleAgentConfig;
1118
+ /** Per-project reaction overrides */
1119
+ reactions?: Record<string, Partial<ReactionConfig>>;
1120
+ /** Inline rules/instructions passed to every agent prompt */
1121
+ agentRules?: string;
1122
+ /** Path to a file containing agent rules (relative to project path) */
1123
+ agentRulesFile?: string;
1124
+ /** Rules for the orchestrator agent (stored, reserved for future use) */
1125
+ orchestratorRules?: string;
1126
+ orchestratorSessionStrategy?: "reuse" | "delete" | "ignore" | "delete-new" | "ignore-new" | "kill-previous";
1127
+ opencodeIssueSessionStrategy?: "reuse" | "delete" | "ignore";
1128
+ }
1129
+ export interface TrackerConfig {
1130
+ /**
1131
+ * Plugin name (manifest.name). Required when using built-in plugins.
1132
+ * Optional when `package` or `path` is specified (will be inferred from manifest).
1133
+ * When both plugin and package/path are specified, manifest.name must match plugin.
1134
+ *
1135
+ * POST-VALIDATION INVARIANT: After validateConfig(), this field is ALWAYS populated.
1136
+ * Either from user input, inferred from repo (github/gitlab), or auto-generated from
1137
+ * package/path via generateTempPluginName(). The optional typing exists for raw config
1138
+ * input before validation. Downstream code can safely assume non-null after validation.
1139
+ */
1140
+ plugin?: string;
1141
+ /** npm package name for external plugins (e.g. "@acme/ao-plugin-tracker-jira") */
1142
+ package?: string;
1143
+ /** Local filesystem path for external plugins (relative to config file or absolute) */
1144
+ path?: string;
1145
+ /** Plugin-specific config (e.g. teamId for Linear) */
1146
+ [key: string]: unknown;
1147
+ }
1148
+ export interface SCMConfig {
1149
+ /**
1150
+ * Plugin name (manifest.name). Required when using built-in plugins.
1151
+ * Optional when `package` or `path` is specified (will be inferred from manifest).
1152
+ * When both plugin and package/path are specified, manifest.name must match plugin.
1153
+ *
1154
+ * POST-VALIDATION INVARIANT: After validateConfig(), this field is ALWAYS populated.
1155
+ * Either from user input, inferred from repo (github/gitlab), or auto-generated from
1156
+ * package/path via generateTempPluginName(). The optional typing exists for raw config
1157
+ * input before validation. Downstream code can safely assume non-null after validation.
1158
+ */
1159
+ plugin?: string;
1160
+ /** npm package name for external plugins (e.g. "@acme/ao-plugin-scm-bitbucket") */
1161
+ package?: string;
1162
+ /** Local filesystem path for external plugins (relative to config file or absolute) */
1163
+ path?: string;
1164
+ webhook?: SCMWebhookConfig;
1165
+ [key: string]: unknown;
1166
+ }
1167
+ export interface SCMWebhookConfig {
1168
+ enabled?: boolean;
1169
+ path?: string;
1170
+ secretEnvVar?: string;
1171
+ signatureHeader?: string;
1172
+ eventHeader?: string;
1173
+ deliveryHeader?: string;
1174
+ maxBodyBytes?: number;
1175
+ }
1176
+ export interface NotifierConfig {
1177
+ /**
1178
+ * Plugin name (manifest.name). Required when using built-in plugins.
1179
+ * Optional when `package` or `path` is specified (will be inferred from manifest).
1180
+ * When both plugin and package/path are specified, manifest.name must match plugin.
1181
+ *
1182
+ * POST-VALIDATION INVARIANT: After validateConfig(), this field is ALWAYS populated.
1183
+ * Either from user input or auto-generated from package/path via generateTempPluginName().
1184
+ * The optional typing exists for raw config input before validation.
1185
+ * Downstream code can safely assume non-null after validation.
1186
+ */
1187
+ plugin?: string;
1188
+ /** npm package name for external plugins (e.g. "@acme/ao-plugin-notifier-teams") */
1189
+ package?: string;
1190
+ /** Local filesystem path for external plugins (relative to config file or absolute) */
1191
+ path?: string;
1192
+ [key: string]: unknown;
1193
+ }
1194
+ export interface AgentSpecificConfig {
1195
+ permissions?: AgentPermissionMode;
1196
+ model?: string;
1197
+ orchestratorModel?: string;
1198
+ [key: string]: unknown;
1199
+ }
1200
+ export interface OpenCodeAgentConfig extends AgentSpecificConfig {
1201
+ opencodeSessionId?: string;
1202
+ }
1203
+ /**
1204
+ * Canonical cross-agent permission policy mode.
1205
+ *
1206
+ * Semantics:
1207
+ * - permissionless: run without interactive permission prompts (most permissive mode).
1208
+ * - default: use the agent's normal/default permission model.
1209
+ * - auto-edit: automatically approve edit actions where the agent supports granular approval policies.
1210
+ * - suggest: conservative mode that asks for approval on higher-risk/untrusted actions where supported.
1211
+ *
1212
+ * Note: Not every agent exposes all granular policies; plugins map these modes to
1213
+ * their closest supported behavior.
1214
+ */
1215
+ export type AgentPermissionMode = "permissionless" | "default" | "auto-edit" | "suggest";
1216
+ /** Backward-compatible legacy alias accepted in config parsing. */
1217
+ export type LegacyAgentPermissionMode = "skip";
1218
+ /** Raw permission input (supports legacy aliases). */
1219
+ export type AgentPermissionInput = AgentPermissionMode | LegacyAgentPermissionMode;
1220
+ /** Normalize legacy aliases to canonical permission modes. */
1221
+ export declare function normalizeAgentPermissionMode(mode: string | undefined): AgentPermissionMode | undefined;
1222
+ /** Plugin slot types */
1223
+ export type PluginSlot = "runtime" | "agent" | "workspace" | "tracker" | "scm" | "notifier" | "terminal";
1224
+ /** Plugin manifest — what every plugin exports */
1225
+ export interface PluginManifest {
1226
+ /** Plugin name (e.g. "tmux", "claude-code", "github") */
1227
+ name: string;
1228
+ /** Which slot this plugin fills */
1229
+ slot: PluginSlot;
1230
+ /** Human-readable description */
1231
+ description: string;
1232
+ /** Version */
1233
+ version: string;
1234
+ /** Human-readable display name (e.g. "Claude Code") */
1235
+ displayName?: string;
1236
+ }
1237
+ /** What a plugin module must export */
1238
+ export interface PluginModule<T = unknown> {
1239
+ manifest: PluginManifest;
1240
+ create(config?: Record<string, unknown>): T;
1241
+ /** Optional: detect whether this plugin's runtime/binary is available on the system. */
1242
+ detect?(): boolean;
1243
+ }
1244
+ /**
1245
+ * Context passed to a plugin's `preflight()` method.
1246
+ *
1247
+ * Describes the **intent** of the operation (what it will do), not the CLI
1248
+ * flags that triggered it. Plugins should never know about specific flag
1249
+ * names — translate flags into intent at the CLI boundary so adding a new
1250
+ * flag doesn't ripple into every plugin that cares about a related operation.
1251
+ */
1252
+ export interface PreflightContext {
1253
+ /** The project the operation runs against. */
1254
+ project: ProjectConfig;
1255
+ /** What the operation will do. Plugins decide whether their prereqs apply. */
1256
+ intent: {
1257
+ /** Whether the spawn is for a worker session or the orchestrator. */
1258
+ role: "worker" | "orchestrator";
1259
+ /**
1260
+ * Whether the operation will exercise SCM PR-write paths
1261
+ * (e.g. claiming an existing PR for the new session). When false, an SCM
1262
+ * plugin's preflight can skip PR-write prereqs.
1263
+ */
1264
+ willClaimExistingPR: boolean;
1265
+ };
1266
+ }
1267
+ /**
1268
+ * Session metadata stored as JSON files under projects/{projectId}/sessions/.
1269
+ *
1270
+ * Session files are named with user-facing session IDs (e.g., "ao-1.json").
1271
+ * The tmuxName field matches the session ID (e.g., "ao-1") — no hash prefix.
1272
+ */
1273
+ export interface SessionMetadata {
1274
+ worktree: string;
1275
+ branch: string;
1276
+ status: string;
1277
+ lifecycle?: CanonicalSessionLifecycle;
1278
+ tmuxName?: string;
1279
+ issue?: string;
1280
+ issueTitle?: string;
1281
+ pr?: string;
1282
+ prAutoDetect?: boolean;
1283
+ summary?: string;
1284
+ project?: string;
1285
+ agent?: string;
1286
+ createdAt?: string;
1287
+ runtimeHandle?: RuntimeHandle;
1288
+ restoredAt?: string;
1289
+ role?: string;
1290
+ dashboard?: {
1291
+ port?: number;
1292
+ terminalWsPort?: number;
1293
+ directTerminalWsPort?: number;
1294
+ };
1295
+ opencodeSessionId?: string;
1296
+ claudeSessionUuid?: string;
1297
+ codexThreadId?: string;
1298
+ codexModel?: string;
1299
+ restoreFallbackReason?: string;
1300
+ pinnedSummary?: string;
1301
+ userPrompt?: string;
1302
+ /**
1303
+ * Human-readable display name for the session.
1304
+ *
1305
+ * Populated automatically at spawn time from the best available task context
1306
+ * (issue title, user prompt, or orchestrator system prompt). Can be
1307
+ * overwritten later via the dashboard rename UI — the session ID (`ao-N`)
1308
+ * remains the canonical identifier; only display surfaces are affected.
1309
+ *
1310
+ * Whether this value should beat PR/issue titles in the dashboard depends
1311
+ * on `displayNameUserSet` — auto-derived values stay below live tracker
1312
+ * signals, user-set values win over them.
1313
+ */
1314
+ displayName?: string;
1315
+ /**
1316
+ * Set to `true` when the user explicitly renamed the session via the
1317
+ * dashboard. The dashboard fallback chain promotes `displayName` above
1318
+ * PR/issue titles only when this flag is true, so an auto-derived spawn-time
1319
+ * `displayName` doesn't shadow a live PR title for sessions the user never
1320
+ * touched.
1321
+ */
1322
+ displayNameUserSet?: boolean;
1323
+ }
1324
+ /**
1325
+ * Why a session was killed. Recorded as the lifecycle reason so observability
1326
+ * can distinguish human action from automated teardown (e.g. PR merge cleanup).
1327
+ */
1328
+ export type LifecycleKillReason = "manually_killed" | "pr_merged" | "auto_cleanup";
1329
+ /**
1330
+ * Outcome of a kill() call. `cleaned` means resources were torn down this
1331
+ * invocation; `alreadyTerminated` means the session was already archived and
1332
+ * kill() was a no-op. Callers can use this to avoid double-notifying.
1333
+ */
1334
+ export interface KillResult {
1335
+ cleaned: boolean;
1336
+ alreadyTerminated: boolean;
1337
+ }
1338
+ export interface KillOptions {
1339
+ purgeOpenCode?: boolean;
1340
+ reason?: LifecycleKillReason;
1341
+ }
1342
+ /** Session manager — CRUD for sessions */
1343
+ export interface SessionManager {
1344
+ spawn(config: SessionSpawnConfig): Promise<Session>;
1345
+ spawnOrchestrator(config: OrchestratorSpawnConfig): Promise<Session>;
1346
+ ensureOrchestrator(config: OrchestratorSpawnConfig): Promise<Session>;
1347
+ /**
1348
+ * Replace the canonical orchestrator with a fresh one. If an orchestrator
1349
+ * already exists for the project, it is killed, its metadata deleted, and a
1350
+ * new orchestrator spawned with no carryover state. Ignores
1351
+ * `orchestratorSessionStrategy` — replacement is the whole point.
1352
+ */
1353
+ relaunchOrchestrator(config: OrchestratorSpawnConfig): Promise<Session>;
1354
+ restore(sessionId: SessionId): Promise<Session>;
1355
+ list(projectId?: string): Promise<Session[]>;
1356
+ get(sessionId: SessionId): Promise<Session | null>;
1357
+ kill(sessionId: SessionId, options?: KillOptions): Promise<KillResult>;
1358
+ cleanup(projectId?: string, options?: {
1359
+ dryRun?: boolean;
1360
+ purgeOpenCode?: boolean;
1361
+ }): Promise<CleanupResult>;
1362
+ send(sessionId: SessionId, message: string): Promise<void>;
1363
+ claimPR(sessionId: SessionId, prRef: string, options?: ClaimPROptions): Promise<ClaimPRResult>;
1364
+ }
1365
+ /** OpenCode-specific session manager with remap capability */
1366
+ export interface OpenCodeSessionManager extends SessionManager {
1367
+ /** Remap session to OpenCode session ID, returns the mapped OpenCode session ID */
1368
+ remap(sessionId: SessionId, force?: boolean): Promise<string>;
1369
+ listCached(projectId?: string): Promise<Session[]>;
1370
+ invalidateCache(): void;
1371
+ }
1372
+ export interface ClaimPROptions {
1373
+ assignOnGithub?: boolean;
1374
+ takeover?: boolean;
1375
+ }
1376
+ export interface ClaimPRResult {
1377
+ sessionId: SessionId;
1378
+ projectId: string;
1379
+ pr: PRInfo;
1380
+ branchChanged: boolean;
1381
+ githubAssigned: boolean;
1382
+ githubAssignmentError?: string;
1383
+ takenOverFrom: SessionId[];
1384
+ }
1385
+ /** Type guard to check if a SessionManager supports OpenCode-specific remap operation */
1386
+ export declare function isOpenCodeSessionManager(sm: SessionManager): sm is OpenCodeSessionManager;
1387
+ export interface CleanupResult {
1388
+ killed: string[];
1389
+ skipped: string[];
1390
+ errors: Array<{
1391
+ sessionId: string;
1392
+ error: string;
1393
+ }>;
1394
+ }
1395
+ /** Lifecycle manager — state machine + reaction engine */
1396
+ export interface LifecycleManager {
1397
+ /** Start the lifecycle polling loop */
1398
+ start(intervalMs?: number): void;
1399
+ /** Stop the lifecycle polling loop */
1400
+ stop(): void;
1401
+ /** Get current state for all sessions */
1402
+ getStates(): Map<SessionId, SessionStatus>;
1403
+ /** Force-check a specific session now */
1404
+ check(sessionId: SessionId): Promise<void>;
1405
+ }
1406
+ /** Plugin registry — discovery + loading */
1407
+ export interface PluginRegistry {
1408
+ /** Register a plugin, optionally with config to pass to create() */
1409
+ register(plugin: PluginModule, config?: Record<string, unknown>): void;
1410
+ /** Get a plugin by slot and name */
1411
+ get<T>(slot: PluginSlot, name: string): T | null;
1412
+ /** List plugins for a slot */
1413
+ list(slot: PluginSlot): PluginManifest[];
1414
+ /** Load built-in plugins, optionally with orchestrator config for plugin settings */
1415
+ loadBuiltins(config?: OrchestratorConfig, importFn?: (pkg: string) => Promise<unknown>): Promise<void>;
1416
+ /** Load plugins from config (npm packages, local paths) */
1417
+ loadFromConfig(config: OrchestratorConfig, importFn?: (pkg: string) => Promise<unknown>): Promise<void>;
1418
+ }
1419
+ /**
1420
+ * Detect if an error indicates that an issue was not found in the tracker.
1421
+ * Used by spawn validation to distinguish "not found" from other errors (auth, network, etc).
1422
+ *
1423
+ * Uses specific patterns to avoid matching infrastructure errors like "API key not found",
1424
+ * "Team not found", "Configuration not found", etc.
1425
+ */
1426
+ export declare function isIssueNotFoundError(err: unknown): boolean;
1427
+ /** Thrown when a session cannot be restored (e.g. merged, still working). */
1428
+ export declare class SessionNotRestorableError extends Error {
1429
+ readonly sessionId: string;
1430
+ readonly reason: string;
1431
+ constructor(sessionId: string, reason: string);
1432
+ }
1433
+ /** Thrown when a workspace is missing and cannot be recreated. */
1434
+ export declare class WorkspaceMissingError extends Error {
1435
+ readonly path: string;
1436
+ readonly detail?: string | undefined;
1437
+ constructor(path: string, detail?: string | undefined);
1438
+ }
1439
+ /** Thrown when a session lookup fails (session does not exist). */
1440
+ export declare class SessionNotFoundError extends Error {
1441
+ readonly sessionId: string;
1442
+ constructor(sessionId: string);
1443
+ }
1444
+ /** Thrown when no agent-orchestrator.yaml config file can be found. */
1445
+ export declare class ConfigNotFoundError extends Error {
1446
+ constructor(message?: string);
1447
+ }
1448
+ export type ProjectResolveErrorKind = "malformed" | "invalid" | "old-format";
1449
+ /** Thrown when a project cannot be resolved into an effective runtime config. */
1450
+ export declare class ProjectResolveError extends Error {
1451
+ readonly projectId: string;
1452
+ readonly reasonKind?: ProjectResolveErrorKind | undefined;
1453
+ constructor(projectId: string, message: string, reasonKind?: ProjectResolveErrorKind | undefined);
1454
+ }
1455
+ /** A project entry in the portfolio index (merged from discovery + registration + preferences) */
1456
+ export interface PortfolioProject {
1457
+ id: string;
1458
+ name: string;
1459
+ configPath: string;
1460
+ configProjectKey: string;
1461
+ repoPath: string;
1462
+ repo?: string;
1463
+ defaultBranch?: string;
1464
+ sessionPrefix: string;
1465
+ source: "discovered" | "registered" | "config";
1466
+ enabled: boolean;
1467
+ pinned: boolean;
1468
+ lastSeenAt: string;
1469
+ resolveError?: string;
1470
+ }
1471
+ /** User preferences overlay (canonical, small file) */
1472
+ export interface PortfolioPreferences {
1473
+ version: 1;
1474
+ defaultProjectId?: string;
1475
+ projectOrder?: string[];
1476
+ projects?: Record<string, {
1477
+ pinned?: boolean;
1478
+ enabled?: boolean;
1479
+ displayName?: string;
1480
+ }>;
1481
+ }
1482
+ /** Registered projects (explicit `athene project add`) */
1483
+ export interface PortfolioRegistered {
1484
+ version: 1;
1485
+ projects: Array<{
1486
+ path: string;
1487
+ configProjectKey?: string;
1488
+ addedAt: string;
1489
+ }>;
1490
+ }
1491
+ /** Aggregated portfolio session with project context */
1492
+ export interface PortfolioSession {
1493
+ session: Session;
1494
+ project: PortfolioProject;
1495
+ }
1496
+ //# sourceMappingURL=types.d.ts.map