@fkqfkq123/opencode-autopilot 0.1.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 (107) hide show
  1. package/README.md +462 -0
  2. package/README.zh-CN.md +464 -0
  3. package/dist/packages/adapters/opencode/src/opencode-session-client.d.ts +188 -0
  4. package/dist/packages/adapters/opencode/src/opencode-session-client.js +382 -0
  5. package/dist/packages/core/src/artifacts/artifact-evaluator.d.ts +17 -0
  6. package/dist/packages/core/src/artifacts/artifact-evaluator.js +1 -0
  7. package/dist/packages/core/src/artifacts/artifact.d.ts +7 -0
  8. package/dist/packages/core/src/artifacts/artifact.js +1 -0
  9. package/dist/packages/core/src/human-actions/human-action-record.d.ts +10 -0
  10. package/dist/packages/core/src/human-actions/human-action-record.js +1 -0
  11. package/dist/packages/core/src/human-actions/human-action.d.ts +13 -0
  12. package/dist/packages/core/src/human-actions/human-action.js +1 -0
  13. package/dist/packages/core/src/human-actions/question.d.ts +8 -0
  14. package/dist/packages/core/src/human-actions/question.js +1 -0
  15. package/dist/packages/core/src/state/phase.d.ts +2 -0
  16. package/dist/packages/core/src/state/phase.js +1 -0
  17. package/dist/packages/core/src/state/workflow-runtime-state.d.ts +14 -0
  18. package/dist/packages/core/src/state/workflow-runtime-state.js +1 -0
  19. package/dist/packages/core/src/state/workflow-state.d.ts +13 -0
  20. package/dist/packages/core/src/state/workflow-state.js +1 -0
  21. package/dist/packages/core/src/transitions/default-phase-transition.d.ts +5 -0
  22. package/dist/packages/core/src/transitions/default-phase-transition.js +195 -0
  23. package/dist/packages/core/src/transitions/phase-transition.d.ts +22 -0
  24. package/dist/packages/core/src/transitions/phase-transition.js +1 -0
  25. package/dist/packages/core/src/transitions/transition-action.d.ts +20 -0
  26. package/dist/packages/core/src/transitions/transition-action.js +1 -0
  27. package/dist/packages/runtime/src/artifacts/file-system-artifact-evaluator.d.ts +36 -0
  28. package/dist/packages/runtime/src/artifacts/file-system-artifact-evaluator.js +1213 -0
  29. package/dist/packages/runtime/src/attach/attach-service.d.ts +15 -0
  30. package/dist/packages/runtime/src/attach/attach-service.js +31 -0
  31. package/dist/packages/runtime/src/bootstrap/create-harness.d.ts +33 -0
  32. package/dist/packages/runtime/src/bootstrap/create-harness.js +79 -0
  33. package/dist/packages/runtime/src/bootstrap/initialize-workflow.d.ts +8 -0
  34. package/dist/packages/runtime/src/bootstrap/initialize-workflow.js +33 -0
  35. package/dist/packages/runtime/src/commands/create-opencode-workflow-commands.d.ts +12 -0
  36. package/dist/packages/runtime/src/commands/create-opencode-workflow-commands.js +24 -0
  37. package/dist/packages/runtime/src/commands/default-workflow-command-runner.d.ts +4 -0
  38. package/dist/packages/runtime/src/commands/default-workflow-command-runner.js +343 -0
  39. package/dist/packages/runtime/src/commands/opencode-plugin-command-adapter.d.ts +20 -0
  40. package/dist/packages/runtime/src/commands/opencode-plugin-command-adapter.js +22 -0
  41. package/dist/packages/runtime/src/commands/workflow-command-runner.d.ts +19 -0
  42. package/dist/packages/runtime/src/commands/workflow-command-runner.js +1 -0
  43. package/dist/packages/runtime/src/commands/workflow-open-request.d.ts +10 -0
  44. package/dist/packages/runtime/src/commands/workflow-open-request.js +220 -0
  45. package/dist/packages/runtime/src/config/skill-registry.d.ts +15 -0
  46. package/dist/packages/runtime/src/config/skill-registry.js +108 -0
  47. package/dist/packages/runtime/src/config/workflow-config.d.ts +17 -0
  48. package/dist/packages/runtime/src/config/workflow-config.js +51 -0
  49. package/dist/packages/runtime/src/diagnostics/workflow-diagnostics-format.d.ts +4 -0
  50. package/dist/packages/runtime/src/diagnostics/workflow-diagnostics-format.js +70 -0
  51. package/dist/packages/runtime/src/diagnostics/workflow-doctor.d.ts +23 -0
  52. package/dist/packages/runtime/src/diagnostics/workflow-doctor.js +120 -0
  53. package/dist/packages/runtime/src/engine/default-workflow-engine.d.ts +9 -0
  54. package/dist/packages/runtime/src/engine/default-workflow-engine.js +337 -0
  55. package/dist/packages/runtime/src/engine/workflow-engine.d.ts +28 -0
  56. package/dist/packages/runtime/src/engine/workflow-engine.js +1 -0
  57. package/dist/packages/runtime/src/events/file-system-workflow-event-store.d.ts +8 -0
  58. package/dist/packages/runtime/src/events/file-system-workflow-event-store.js +28 -0
  59. package/dist/packages/runtime/src/events/workflow-event-store.d.ts +10 -0
  60. package/dist/packages/runtime/src/events/workflow-event-store.js +1 -0
  61. package/dist/packages/runtime/src/index.d.ts +4 -0
  62. package/dist/packages/runtime/src/index.js +4 -0
  63. package/dist/packages/runtime/src/install/workflow-installer.d.ts +15 -0
  64. package/dist/packages/runtime/src/install/workflow-installer.js +111 -0
  65. package/dist/packages/runtime/src/plugin/workflow-plugin-entry.d.ts +167 -0
  66. package/dist/packages/runtime/src/plugin/workflow-plugin-entry.js +340 -0
  67. package/dist/packages/runtime/src/presentation/human-action-renderer.d.ts +13 -0
  68. package/dist/packages/runtime/src/presentation/human-action-renderer.js +161 -0
  69. package/dist/packages/runtime/src/presentation/watch-renderer.d.ts +12 -0
  70. package/dist/packages/runtime/src/presentation/watch-renderer.js +17 -0
  71. package/dist/packages/runtime/src/recovery/basic-recovery-classifier.d.ts +4 -0
  72. package/dist/packages/runtime/src/recovery/basic-recovery-classifier.js +12 -0
  73. package/dist/packages/runtime/src/recovery/recovery-classifier.d.ts +4 -0
  74. package/dist/packages/runtime/src/recovery/recovery-classifier.js +1 -0
  75. package/dist/packages/runtime/src/scheduling/immediate-tick-scheduler.d.ts +9 -0
  76. package/dist/packages/runtime/src/scheduling/immediate-tick-scheduler.js +28 -0
  77. package/dist/packages/runtime/src/scheduling/tick-scheduler.d.ts +3 -0
  78. package/dist/packages/runtime/src/scheduling/tick-scheduler.js +1 -0
  79. package/dist/packages/runtime/src/sessions/file-system-session-coordinator.d.ts +19 -0
  80. package/dist/packages/runtime/src/sessions/file-system-session-coordinator.js +132 -0
  81. package/dist/packages/runtime/src/sessions/session-activity-monitor.d.ts +22 -0
  82. package/dist/packages/runtime/src/sessions/session-activity-monitor.js +112 -0
  83. package/dist/packages/runtime/src/sessions/session-coordinator.d.ts +24 -0
  84. package/dist/packages/runtime/src/sessions/session-coordinator.js +1 -0
  85. package/dist/packages/runtime/src/shared/json-file.d.ts +2 -0
  86. package/dist/packages/runtime/src/shared/json-file.js +19 -0
  87. package/dist/packages/runtime/src/state/file-system-human-action-store.d.ts +15 -0
  88. package/dist/packages/runtime/src/state/file-system-human-action-store.js +69 -0
  89. package/dist/packages/runtime/src/state/file-system-workflow-state-store.d.ts +15 -0
  90. package/dist/packages/runtime/src/state/file-system-workflow-state-store.js +59 -0
  91. package/dist/packages/runtime/src/state/human-action-service.d.ts +21 -0
  92. package/dist/packages/runtime/src/state/human-action-service.js +80 -0
  93. package/dist/packages/runtime/src/state/human-action-store.d.ts +9 -0
  94. package/dist/packages/runtime/src/state/human-action-store.js +1 -0
  95. package/dist/packages/runtime/src/state/workflow-state-store.d.ts +11 -0
  96. package/dist/packages/runtime/src/state/workflow-state-store.js +1 -0
  97. package/dist/packages/runtime/src/subtasks/noop-subtask-tracker.d.ts +4 -0
  98. package/dist/packages/runtime/src/subtasks/noop-subtask-tracker.js +5 -0
  99. package/dist/packages/runtime/src/subtasks/subtask-tracker.d.ts +3 -0
  100. package/dist/packages/runtime/src/subtasks/subtask-tracker.js +1 -0
  101. package/dist/packages/runtime/src/workspace/workflow-workspace.d.ts +31 -0
  102. package/dist/packages/runtime/src/workspace/workflow-workspace.js +43 -0
  103. package/dist/plugin.d.ts +1 -0
  104. package/dist/plugin.js +1 -0
  105. package/dist/src/cli.d.ts +1 -0
  106. package/dist/src/cli.js +175 -0
  107. package/package.json +56 -0
@@ -0,0 +1,382 @@
1
+ import { randomUUID } from "node:crypto";
2
+ export class InMemoryOpencodeSessionClient {
3
+ sessions = new Map();
4
+ eventQueue = new Map();
5
+ async createSession(input) {
6
+ const sessionId = randomUUID();
7
+ this.sessions.set(sessionId, {
8
+ sessionId,
9
+ title: input.title,
10
+ status: "idle",
11
+ prompts: [],
12
+ });
13
+ this.enqueue(sessionId, { type: "session.created", sessionId });
14
+ return { sessionId };
15
+ }
16
+ async ensureSessionReady(sessionId, title) {
17
+ if (!this.sessions.has(sessionId)) {
18
+ this.sessions.set(sessionId, {
19
+ sessionId,
20
+ title,
21
+ status: "idle",
22
+ prompts: [],
23
+ });
24
+ }
25
+ }
26
+ async injectPrompt(input) {
27
+ let session = this.sessions.get(input.sessionId);
28
+ if (!session) {
29
+ session = {
30
+ sessionId: input.sessionId,
31
+ title: "recovered",
32
+ status: "idle",
33
+ prompts: [],
34
+ };
35
+ this.sessions.set(input.sessionId, session);
36
+ }
37
+ session.status = "running";
38
+ this.enqueue(input.sessionId, { type: "session.status", sessionId: input.sessionId, payload: { type: "busy" } });
39
+ session.prompts.push(input.prompt);
40
+ session.status = "idle";
41
+ this.enqueue(input.sessionId, { type: "session.idle", sessionId: input.sessionId });
42
+ return {
43
+ dispatchMode: "in_memory_inline",
44
+ statusBefore: "idle",
45
+ };
46
+ }
47
+ async abort(sessionId) {
48
+ const session = this.sessions.get(sessionId);
49
+ if (!session) {
50
+ return;
51
+ }
52
+ session.status = "failed";
53
+ this.enqueue(sessionId, { type: "session.error", sessionId, payload: { message: "aborted" } });
54
+ }
55
+ async getSessionStatus(sessionId) {
56
+ const session = this.sessions.get(sessionId);
57
+ return session?.status ?? "missing";
58
+ }
59
+ async *streamEvents(_sessionId) {
60
+ while (true) {
61
+ const queue = this.eventQueue.get(_sessionId) ?? [];
62
+ if (queue.length > 0) {
63
+ const next = queue.shift();
64
+ this.eventQueue.set(_sessionId, queue);
65
+ if (next) {
66
+ yield next;
67
+ continue;
68
+ }
69
+ }
70
+ await new Promise((resolve) => setTimeout(resolve, 10));
71
+ }
72
+ }
73
+ enqueue(sessionId, event) {
74
+ const queue = this.eventQueue.get(sessionId) ?? [];
75
+ queue.push(event);
76
+ this.eventQueue.set(sessionId, queue);
77
+ }
78
+ }
79
+ export class SdkOpencodeSessionClient {
80
+ client;
81
+ eventQueue = new Map();
82
+ knownSessions = new Set();
83
+ eventPumpStarted = false;
84
+ constructor(client) {
85
+ this.client = client;
86
+ }
87
+ unwrapFields(value) {
88
+ if (!value || typeof value !== "object") {
89
+ return null;
90
+ }
91
+ if ("data" in value && value.data && typeof value.data === "object") {
92
+ return value.data;
93
+ }
94
+ return value;
95
+ }
96
+ async createSession(input) {
97
+ this.ensureEventPump();
98
+ const session = this.unwrapFields(await this.client.session.create({
99
+ body: { title: input.title },
100
+ }));
101
+ if (!session?.id) {
102
+ throw new Error("OpenCode SDK createSession response did not include id");
103
+ }
104
+ this.knownSessions.add(session.id);
105
+ this.enqueue(session.id, { type: "session.created", sessionId: session.id });
106
+ return { sessionId: session.id };
107
+ }
108
+ async ensureSessionReady(sessionId, _title) {
109
+ this.ensureEventPump();
110
+ this.knownSessions.add(sessionId);
111
+ }
112
+ async injectPrompt(input) {
113
+ this.ensureEventPump();
114
+ this.knownSessions.add(input.sessionId);
115
+ const request = {
116
+ path: { id: input.sessionId },
117
+ body: {
118
+ parts: [
119
+ {
120
+ type: "text",
121
+ text: input.prompt,
122
+ },
123
+ ],
124
+ ...(input.agent ? { agent: input.agent } : {}),
125
+ ...(input.model
126
+ ? {
127
+ model: {
128
+ providerID: input.model.providerID,
129
+ modelID: input.model.modelID,
130
+ ...(input.model.variant ? { variant: input.model.variant } : {}),
131
+ },
132
+ }
133
+ : {}),
134
+ },
135
+ };
136
+ const currentStatus = await this.getSessionStatus(input.sessionId);
137
+ if (currentStatus === "running" && this.client.session.promptAsync) {
138
+ await this.client.session.promptAsync(request);
139
+ return {
140
+ dispatchMode: "sdk_prompt_async",
141
+ statusBefore: currentStatus,
142
+ };
143
+ }
144
+ void this.client.session.prompt(request).catch((error) => {
145
+ this.enqueue(input.sessionId, {
146
+ type: "session.error",
147
+ sessionId: input.sessionId,
148
+ payload: {
149
+ message: error instanceof Error ? error.message : String(error),
150
+ },
151
+ });
152
+ });
153
+ return {
154
+ dispatchMode: "sdk_prompt_background",
155
+ statusBefore: currentStatus,
156
+ };
157
+ }
158
+ async abort(sessionId) {
159
+ await this.client.session.abort({ path: { id: sessionId } });
160
+ }
161
+ async getSessionStatus(sessionId) {
162
+ if (!this.client.session.status) {
163
+ return this.knownSessions.has(sessionId) ? "idle" : "missing";
164
+ }
165
+ try {
166
+ const status = this.unwrapFields(await this.client.session.status({ path: { id: sessionId } }));
167
+ if (status?.type === "busy" || status?.type === "retry" || status?.type === "running") {
168
+ return "running";
169
+ }
170
+ return this.knownSessions.has(sessionId) ? "idle" : "missing";
171
+ }
172
+ catch (error) {
173
+ const message = error instanceof Error ? error.message : String(error);
174
+ if (message.includes("404") || message.includes("not found")) {
175
+ return "missing";
176
+ }
177
+ throw error;
178
+ }
179
+ }
180
+ async *streamEvents(sessionId) {
181
+ this.ensureEventPump();
182
+ while (true) {
183
+ const queue = this.eventQueue.get(sessionId) ?? [];
184
+ if (queue.length > 0) {
185
+ const next = queue.shift();
186
+ this.eventQueue.set(sessionId, queue);
187
+ if (next) {
188
+ yield next;
189
+ continue;
190
+ }
191
+ }
192
+ await new Promise((resolve) => setTimeout(resolve, 10));
193
+ }
194
+ }
195
+ ensureEventPump() {
196
+ if (this.eventPumpStarted || !this.client.event?.subscribe) {
197
+ return;
198
+ }
199
+ this.eventPumpStarted = true;
200
+ void this.startEventPump();
201
+ }
202
+ async startEventPump() {
203
+ const subscription = await this.client.event?.subscribe?.();
204
+ if (!subscription) {
205
+ return;
206
+ }
207
+ for await (const event of subscription.stream) {
208
+ const sessionID = typeof event.properties?.sessionID === "string"
209
+ ? event.properties.sessionID
210
+ : undefined;
211
+ if (!sessionID || !this.knownSessions.has(sessionID)) {
212
+ continue;
213
+ }
214
+ if (event.type === "session.status" || event.type === "session.idle" || event.type === "session.error") {
215
+ this.enqueue(sessionID, {
216
+ type: event.type,
217
+ sessionId: sessionID,
218
+ ...(event.properties ? { payload: event.properties } : {}),
219
+ });
220
+ }
221
+ }
222
+ }
223
+ enqueue(sessionId, event) {
224
+ const queue = this.eventQueue.get(sessionId) ?? [];
225
+ queue.push(event);
226
+ this.eventQueue.set(sessionId, queue);
227
+ }
228
+ }
229
+ export class HttpOpencodeSessionClient {
230
+ options;
231
+ constructor(options) {
232
+ this.options = options;
233
+ }
234
+ async ensureSessionReady(_sessionId, _title) { }
235
+ async createSession(input) {
236
+ const data = await this.request("POST", "/session", {
237
+ title: input.title,
238
+ });
239
+ if (!data.id) {
240
+ throw new Error("Opencode createSession response did not include id");
241
+ }
242
+ return { sessionId: data.id };
243
+ }
244
+ async injectPrompt(input) {
245
+ const body = {
246
+ parts: [
247
+ {
248
+ type: "text",
249
+ text: input.prompt,
250
+ },
251
+ ],
252
+ };
253
+ if (input.agent) {
254
+ body.agent = input.agent;
255
+ }
256
+ if (input.model) {
257
+ body.model = {
258
+ providerID: input.model.providerID,
259
+ modelID: input.model.modelID,
260
+ };
261
+ if (input.model.variant) {
262
+ body.variant = input.model.variant;
263
+ }
264
+ }
265
+ await this.requestVoid("POST", `/session/${encodeURIComponent(input.sessionId)}/prompt_async`, body);
266
+ return {
267
+ dispatchMode: "http_prompt_async",
268
+ statusBefore: "idle",
269
+ };
270
+ }
271
+ async abort(sessionId) {
272
+ await this.requestVoid("POST", `/session/${encodeURIComponent(sessionId)}/abort`);
273
+ }
274
+ async getSessionStatus(sessionId) {
275
+ const data = await this.request("GET", "/session/status");
276
+ const info = data[sessionId];
277
+ if (!info) {
278
+ return "missing";
279
+ }
280
+ if (info.type === "busy" || info.type === "retry") {
281
+ return "running";
282
+ }
283
+ return "idle";
284
+ }
285
+ async *streamEvents(_sessionId) {
286
+ const headers = {};
287
+ if (this.options.password) {
288
+ const token = Buffer.from(`:${this.options.password}`).toString("base64");
289
+ headers.Authorization = `Basic ${token}`;
290
+ }
291
+ const response = await fetch(new URL("/event", this.options.baseUrl), {
292
+ headers,
293
+ });
294
+ if (!response.ok || !response.body) {
295
+ throw new Error(`Opencode event stream failed: ${response.status} ${response.statusText}`);
296
+ }
297
+ const reader = response.body.getReader();
298
+ const decoder = new TextDecoder();
299
+ let buffer = "";
300
+ while (true) {
301
+ const result = await reader.read();
302
+ if (result.done) {
303
+ break;
304
+ }
305
+ buffer += decoder.decode(result.value, { stream: true });
306
+ const chunks = buffer.split("\n\n");
307
+ buffer = chunks.pop() ?? "";
308
+ for (const chunk of chunks) {
309
+ const dataLine = chunk
310
+ .split("\n")
311
+ .find((line) => line.startsWith("data:"));
312
+ if (!dataLine) {
313
+ continue;
314
+ }
315
+ const raw = dataLine.slice(5).trim();
316
+ if (!raw) {
317
+ continue;
318
+ }
319
+ let parsed;
320
+ try {
321
+ parsed = JSON.parse(raw);
322
+ }
323
+ catch {
324
+ continue;
325
+ }
326
+ if (!parsed || typeof parsed !== "object") {
327
+ continue;
328
+ }
329
+ const event = parsed;
330
+ const sessionID = typeof event.properties?.sessionID === "string"
331
+ ? event.properties.sessionID
332
+ : undefined;
333
+ if (sessionID !== _sessionId || !event.type) {
334
+ continue;
335
+ }
336
+ const nextEvent = {
337
+ type: event.type,
338
+ sessionId: sessionID,
339
+ };
340
+ if (event.properties) {
341
+ nextEvent.payload = event.properties;
342
+ }
343
+ yield nextEvent;
344
+ }
345
+ }
346
+ }
347
+ async request(method, path, body) {
348
+ const headers = {
349
+ "Content-Type": "application/json",
350
+ };
351
+ if (this.options.password) {
352
+ const token = Buffer.from(`:${this.options.password}`).toString("base64");
353
+ headers.Authorization = `Basic ${token}`;
354
+ }
355
+ const response = await fetch(new URL(path, this.options.baseUrl), {
356
+ method,
357
+ headers,
358
+ body: body === undefined ? undefined : JSON.stringify(body),
359
+ });
360
+ if (!response.ok) {
361
+ throw new Error(`Opencode request failed: ${response.status} ${response.statusText}`);
362
+ }
363
+ return (await response.json());
364
+ }
365
+ async requestVoid(method, path, body) {
366
+ const headers = {
367
+ "Content-Type": "application/json",
368
+ };
369
+ if (this.options.password) {
370
+ const token = Buffer.from(`:${this.options.password}`).toString("base64");
371
+ headers.Authorization = `Basic ${token}`;
372
+ }
373
+ const response = await fetch(new URL(path, this.options.baseUrl), {
374
+ method,
375
+ headers,
376
+ body: body === undefined ? undefined : JSON.stringify(body),
377
+ });
378
+ if (!response.ok && response.status !== 204) {
379
+ throw new Error(`Opencode request failed: ${response.status} ${response.statusText}`);
380
+ }
381
+ }
382
+ }
@@ -0,0 +1,17 @@
1
+ import type { Question } from "../human-actions/question";
2
+ import type { Phase } from "../state/phase";
3
+ import type { WorkflowState } from "../state/workflow-state";
4
+ export interface ArtifactEvaluation {
5
+ valid: boolean;
6
+ readyForNextPhase: boolean;
7
+ missing: string[];
8
+ summary?: string;
9
+ questions?: Question[];
10
+ requiresApproval?: boolean;
11
+ reportStatus?: "pass" | "fail" | "unknown";
12
+ hasBlockingSeverity?: boolean;
13
+ }
14
+ export interface ArtifactEvaluator {
15
+ evaluate(state: WorkflowState): Promise<ArtifactEvaluation>;
16
+ prepareForPhase?(workflowId: string, phase: Phase, previousPhase: Phase): Promise<void>;
17
+ }
@@ -0,0 +1,7 @@
1
+ export interface ArtifactRef {
2
+ id: string;
3
+ type: string;
4
+ uri: string;
5
+ version: number;
6
+ updatedAt: string;
7
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,10 @@
1
+ import type { HumanAction } from "./human-action";
2
+ export type HumanActionStatus = "pending" | "presented" | "responded" | "consumed";
3
+ export interface HumanActionRecord {
4
+ id: string;
5
+ workflowId: string;
6
+ action: HumanAction;
7
+ status: HumanActionStatus;
8
+ createdAt: string;
9
+ respondedAt?: string;
10
+ }
@@ -0,0 +1,13 @@
1
+ import type { Phase } from "../state/phase";
2
+ import type { Question } from "./question";
3
+ export type HumanActionType = "need_answers" | "need_approval" | "blocked" | "done";
4
+ export interface HumanAction {
5
+ type: HumanActionType;
6
+ workflowId: string;
7
+ phase: Phase;
8
+ reason: string;
9
+ required: boolean;
10
+ questions?: Question[];
11
+ summary?: string;
12
+ createdAt: string;
13
+ }
@@ -0,0 +1,8 @@
1
+ export type QuestionPriority = "required" | "recommended" | "optional";
2
+ export interface Question {
3
+ id: string;
4
+ priority: QuestionPriority;
5
+ text: string;
6
+ canAutoResolve: boolean;
7
+ suggestedAnswer?: string;
8
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ export type Phase = "spec_refinement" | "plan" | "develop" | "review" | "test" | "done" | "blocked";
2
+ export type WorkflowStatus = "pending" | "in_progress" | "waiting_human" | "completed" | "blocked";
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,14 @@
1
+ export type RecoveryState = "idle" | "recovering";
2
+ export interface WorkflowRuntimeState {
3
+ workflowId: string;
4
+ preferredForegroundSessionId?: string | null;
5
+ leaseOwner?: string;
6
+ leaseExpiresAt?: string;
7
+ recoveryState: RecoveryState;
8
+ waitingHumanActionId?: string | null;
9
+ consecutiveFailures: number;
10
+ refinementAttempts?: number;
11
+ refinementLastDispatchSummary?: string | null;
12
+ refinementEscalationReason?: string | null;
13
+ lastContinuationAt?: string;
14
+ }
@@ -0,0 +1,13 @@
1
+ import type { Phase, WorkflowStatus } from "./phase";
2
+ export interface WorkflowState {
3
+ workflowId: string;
4
+ phase: Phase;
5
+ status: WorkflowStatus;
6
+ approved: boolean;
7
+ iteration: number;
8
+ maxIterations: number;
9
+ blockReason: string | null;
10
+ activeSessionId: string | null;
11
+ phaseEnteredAt: string;
12
+ updatedAt: string;
13
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,5 @@
1
+ import type { PhaseTransition, PhaseTransitionInput } from "./phase-transition";
2
+ import type { TransitionAction } from "./transition-action";
3
+ export declare class DefaultPhaseTransition implements PhaseTransition {
4
+ decide(input: PhaseTransitionInput): Promise<TransitionAction>;
5
+ }