flanders 0.0.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/lib/ai/AiRunner.d.ts +24 -0
  2. package/lib/ai/AiRunner.js +100 -0
  3. package/lib/ai/AiSession.d.ts +32 -0
  4. package/lib/ai/AiSession.js +143 -0
  5. package/lib/ai/ClaudeAdapter.d.ts +12 -0
  6. package/lib/ai/ClaudeAdapter.js +345 -0
  7. package/lib/ai/CodexAdapter.d.ts +13 -0
  8. package/lib/ai/CodexAdapter.js +354 -0
  9. package/lib/ai/ToolAdapter.d.ts +52 -0
  10. package/lib/ai/ToolAdapter.js +2 -0
  11. package/lib/cli.js +56 -35
  12. package/lib/commands/Implement.d.ts +22 -8
  13. package/lib/commands/Implement.js +296 -171
  14. package/lib/commands/Install.d.ts +31 -3
  15. package/lib/commands/Install.js +649 -49
  16. package/lib/commands/InstallAvailabilityCheck.d.ts +8 -0
  17. package/lib/commands/InstallAvailabilityCheck.js +45 -0
  18. package/lib/commands/InstallModelProbe.d.ts +2 -0
  19. package/lib/commands/InstallModelProbe.js +74 -0
  20. package/lib/contexts.d.ts +5 -4
  21. package/lib/index.d.ts +5 -3
  22. package/lib/{PlanFile.d.ts → plan/PlanFile.d.ts} +8 -1
  23. package/lib/{PlanFile.js → plan/PlanFile.js} +44 -5
  24. package/lib/prompts/prompts.d.ts +48 -0
  25. package/lib/prompts/prompts.js +328 -0
  26. package/lib/prompts/skills.d.ts +3 -0
  27. package/lib/prompts/skills.js +463 -0
  28. package/lib/{Git.d.ts → system/Git.d.ts} +4 -2
  29. package/lib/{Git.js → system/Git.js} +63 -3
  30. package/lib/{ScriptRunner.d.ts → system/ScriptRunner.d.ts} +1 -1
  31. package/lib/system/ShellScriptContext.d.ts +36 -0
  32. package/lib/system/ShellScriptContext.js +70 -0
  33. package/lib/{fsUtils.d.ts → system/fsUtils.d.ts} +1 -1
  34. package/lib/{wait.d.ts → system/wait.d.ts} +1 -1
  35. package/lib/ui/BottomBlock.d.ts +9 -1
  36. package/lib/ui/BottomBlock.js +30 -14
  37. package/lib/ui/PromptHelper.d.ts +12 -0
  38. package/lib/ui/PromptHelper.js +32 -0
  39. package/lib/ui/TerminalSizeSource.d.ts +19 -0
  40. package/lib/ui/TerminalSizeSource.js +77 -0
  41. package/lib/ui/formatters.d.ts +14 -0
  42. package/lib/ui/formatters.js +65 -2
  43. package/lib/workspace/FlandersConfig.d.ts +23 -0
  44. package/lib/workspace/FlandersConfig.js +90 -0
  45. package/lib/workspace/SpecDiscovery.d.ts +12 -0
  46. package/lib/workspace/SpecDiscovery.js +40 -0
  47. package/lib/{Workspace.d.ts → workspace/Workspace.d.ts} +10 -2
  48. package/lib/{Workspace.js → workspace/Workspace.js} +52 -6
  49. package/package.json +3 -2
  50. package/lib/Claude.d.ts +0 -129
  51. package/lib/Claude.js +0 -387
  52. package/lib/ClaudeSession.d.ts +0 -34
  53. package/lib/ClaudeSession.js +0 -292
  54. package/lib/prompts.d.ts +0 -18
  55. package/lib/prompts.js +0 -221
  56. package/lib/skills.d.ts +0 -3
  57. package/lib/skills.js +0 -256
  58. /package/lib/{ScriptRunner.js → system/ScriptRunner.js} +0 -0
  59. /package/lib/{fsUtils.js → system/fsUtils.js} +0 -0
  60. /package/lib/{wait.js → system/wait.js} +0 -0
@@ -0,0 +1,354 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CodexAdapter = void 0;
4
+ exports.formatCodexCommand = formatCodexCommand;
5
+ const COMMAND_INLINE_MAX = 120;
6
+ const RATE_LIMIT_SUBSTRINGS = [
7
+ "out of credits",
8
+ "refill",
9
+ "usage limit",
10
+ "rate limit",
11
+ "rate-limit",
12
+ "rate_limit",
13
+ "quota",
14
+ "too many requests"
15
+ ];
16
+ const RATE_LIMIT_429_RE = /\b429\b/;
17
+ const EIGHT_MINUTES_MS = 8 * 60000;
18
+ const TWELVE_MINUTES_MS = 12 * 60000;
19
+ const FIVE_XX_RE = /\b5\d{2}\b/;
20
+ const STATUS_408_RE = /\b408\b/;
21
+ const STATUS_425_RE = /\b425\b/;
22
+ const TRANSPORT_SUBSTRINGS = [
23
+ "timeout",
24
+ "timed out",
25
+ "connection reset",
26
+ "connection refused",
27
+ "socket hang up",
28
+ "temporarily unavailable",
29
+ "service unavailable",
30
+ "gateway",
31
+ "network",
32
+ "econnreset",
33
+ "econnrefused",
34
+ "enotfound",
35
+ "etimedout",
36
+ "eai_again"
37
+ ];
38
+ function formatCodexCommand(command) {
39
+ if (!command)
40
+ return "";
41
+ const firstLine = command.split("\n")[0];
42
+ if (firstLine.length > COMMAND_INLINE_MAX) {
43
+ return firstLine.slice(0, COMMAND_INLINE_MAX - 3) + "...";
44
+ }
45
+ return firstLine;
46
+ }
47
+ function isRateLimitMessage(message) {
48
+ const lower = message.trim().toLowerCase();
49
+ for (const sub of RATE_LIMIT_SUBSTRINGS) {
50
+ if (lower.includes(sub))
51
+ return true;
52
+ }
53
+ return RATE_LIMIT_429_RE.test(message.trim());
54
+ }
55
+ function isRetryableHttpStatus(message) {
56
+ const trimmed = message.trim();
57
+ if (FIVE_XX_RE.test(trimmed))
58
+ return true;
59
+ if (STATUS_408_RE.test(trimmed))
60
+ return true;
61
+ if (STATUS_425_RE.test(trimmed))
62
+ return true;
63
+ return false;
64
+ }
65
+ function isRetryableTransport(message) {
66
+ const lower = message.trim().toLowerCase();
67
+ for (const sub of TRANSPORT_SUBSTRINGS) {
68
+ if (lower.includes(sub))
69
+ return true;
70
+ }
71
+ return false;
72
+ }
73
+ class CodexAdapter {
74
+ constructor(_contexts) {
75
+ this._contexts = _contexts;
76
+ }
77
+ invoke(args) {
78
+ const iter = new CodexAdapterIterator(args, this._contexts);
79
+ return {
80
+ [Symbol.asyncIterator]() {
81
+ return iter;
82
+ }
83
+ };
84
+ }
85
+ }
86
+ exports.CodexAdapter = CodexAdapter;
87
+ class CodexAdapterIterator {
88
+ constructor(_args, _contexts) {
89
+ this._args = _args;
90
+ this._contexts = _contexts;
91
+ this._proc = null;
92
+ this._capturedSessionId = null;
93
+ this._queue = [];
94
+ this._done = false;
95
+ this._waitResolve = null;
96
+ this._abortListener = null;
97
+ this._exitPromise = null;
98
+ this._sawTurnCompleted = false;
99
+ this._receivedAnyEvent = false;
100
+ this._fallbackAttempted = false;
101
+ this._usedResumeOrFork = false;
102
+ this._start(false);
103
+ }
104
+ _start(useExecFallback) {
105
+ var _a, _b, _c;
106
+ const isResume = !useExecFallback && !!this._args.resumeSessionId;
107
+ const isFork = !useExecFallback && !!this._args.forkParentSessionId;
108
+ this._usedResumeOrFork = isResume || isFork;
109
+ const argv = this._buildArgv(isResume, isFork);
110
+ const spawnOptions = { stdio: "pipe" };
111
+ const proc = this._contexts.script.spawn("codex", argv, spawnOptions);
112
+ this._proc = proc;
113
+ (_a = proc.stdin) === null || _a === void 0 ? void 0 : _a.write(this._args.prompt);
114
+ (_b = proc.stdin) === null || _b === void 0 ? void 0 : _b.end();
115
+ let exitResolve = null;
116
+ this._exitPromise = new Promise(resolve => { exitResolve = resolve; });
117
+ let buffer = "";
118
+ (_c = proc.stdout) === null || _c === void 0 ? void 0 : _c.on("data", (chunk) => {
119
+ buffer += String(chunk);
120
+ for (;;) {
121
+ const nl = buffer.indexOf("\n");
122
+ if (nl < 0)
123
+ break;
124
+ const line = buffer.slice(0, nl).replace(/\r$/, "");
125
+ buffer = buffer.slice(nl + 1);
126
+ if (line) {
127
+ this._handleLine(line);
128
+ }
129
+ }
130
+ });
131
+ proc.on("error", (e) => {
132
+ if (this._done) {
133
+ exitResolve === null || exitResolve === void 0 ? void 0 : exitResolve();
134
+ return;
135
+ }
136
+ this._done = true;
137
+ const err = e instanceof Error ? e : new Error(String(e));
138
+ if (err.code === "ENOENT") {
139
+ this._queue.push({ type: "error", retryable: false, message: "codex binary not found" });
140
+ }
141
+ else {
142
+ this._queue.push({ type: "error", retryable: false, message: err.message });
143
+ }
144
+ this._wake();
145
+ exitResolve === null || exitResolve === void 0 ? void 0 : exitResolve();
146
+ });
147
+ proc.on("exit", (code, signal) => {
148
+ if (this._done) {
149
+ exitResolve === null || exitResolve === void 0 ? void 0 : exitResolve();
150
+ return;
151
+ }
152
+ if (this._usedResumeOrFork && !this._receivedAnyEvent && !this._fallbackAttempted) {
153
+ this._fallbackAttempted = true;
154
+ this._queue.push({
155
+ type: "output",
156
+ title: "Continuity lost",
157
+ subtitle: "",
158
+ details: "codex resume/fork unavailable in installed CLI"
159
+ });
160
+ this._cleanup();
161
+ this._sawTurnCompleted = false;
162
+ this._receivedAnyEvent = false;
163
+ this._usedResumeOrFork = false;
164
+ exitResolve === null || exitResolve === void 0 ? void 0 : exitResolve();
165
+ this._start(true);
166
+ this._wake();
167
+ return;
168
+ }
169
+ if (this._sawTurnCompleted) {
170
+ this._queue.push({ type: "done" });
171
+ }
172
+ else if (signal) {
173
+ this._queue.push({
174
+ type: "error",
175
+ retryable: true,
176
+ message: `codex terminated by signal ${signal}`
177
+ });
178
+ }
179
+ else {
180
+ this._queue.push({
181
+ type: "error",
182
+ retryable: true,
183
+ message: `codex exited unexpectedly (code ${code} signal ${signal})`
184
+ });
185
+ }
186
+ this._done = true;
187
+ this._wake();
188
+ exitResolve === null || exitResolve === void 0 ? void 0 : exitResolve();
189
+ });
190
+ this._abortListener = () => {
191
+ if (this._proc) {
192
+ this._proc.kill("SIGINT");
193
+ }
194
+ this._done = true;
195
+ this._wake();
196
+ };
197
+ if (this._args.abortSignal.aborted) {
198
+ this._abortListener();
199
+ }
200
+ else {
201
+ this._args.abortSignal.addEventListener("abort", this._abortListener, { once: true });
202
+ }
203
+ }
204
+ _buildArgv(isResume, isFork) {
205
+ const argv = [];
206
+ if (isResume) {
207
+ argv.push("resume", this._args.resumeSessionId);
208
+ }
209
+ else if (isFork) {
210
+ argv.push("fork", this._args.forkParentSessionId);
211
+ }
212
+ else {
213
+ argv.push("exec");
214
+ }
215
+ argv.push("--json");
216
+ argv.push("-c", "approval_policy=never");
217
+ argv.push("-c", "sandbox_mode=danger-full-access");
218
+ if (this._args.model) {
219
+ argv.push("-m", this._args.model);
220
+ }
221
+ if (this._args.effort) {
222
+ argv.push("-c", `model_reasoning_effort=${this._args.effort}`);
223
+ }
224
+ argv.push("-");
225
+ return argv;
226
+ }
227
+ _handleLine(line) {
228
+ var _a, _b, _c;
229
+ if (this._done)
230
+ return;
231
+ let parsed = null;
232
+ try {
233
+ parsed = JSON.parse(line);
234
+ }
235
+ catch {
236
+ return;
237
+ }
238
+ if (!parsed)
239
+ return;
240
+ this._receivedAnyEvent = true;
241
+ if (parsed.thread_id && parsed.thread_id !== this._capturedSessionId) {
242
+ this._capturedSessionId = parsed.thread_id;
243
+ this._queue.push({ type: "session", id: parsed.thread_id });
244
+ }
245
+ if (parsed.type === "item.completed" && parsed.item) {
246
+ this._handleItemCompleted(parsed.item);
247
+ }
248
+ else if (parsed.type === "turn.completed") {
249
+ this._sawTurnCompleted = true;
250
+ if (parsed.usage && this._args.onUsage) {
251
+ this._args.onUsage({
252
+ inputTokens: (_a = parsed.usage.input_tokens) !== null && _a !== void 0 ? _a : 0,
253
+ outputTokens: (_b = parsed.usage.output_tokens) !== null && _b !== void 0 ? _b : 0
254
+ });
255
+ }
256
+ }
257
+ else if (parsed.type === "error") {
258
+ this._handleFailure(typeof parsed.message === "string" ? parsed.message : "unknown error");
259
+ }
260
+ else if (parsed.type === "turn.failed") {
261
+ this._handleFailure(typeof ((_c = parsed.error) === null || _c === void 0 ? void 0 : _c.message) === "string" ? parsed.error.message : "unknown error");
262
+ }
263
+ this._wake();
264
+ }
265
+ _handleItemCompleted(item) {
266
+ if (item.type === "agent_message") {
267
+ this._queue.push({
268
+ type: "output",
269
+ title: "Assistant",
270
+ subtitle: "",
271
+ details: typeof item.text === "string" ? item.text : ""
272
+ });
273
+ }
274
+ else if (item.type === "command_execution") {
275
+ this._queue.push({
276
+ type: "output",
277
+ title: "command",
278
+ subtitle: formatCodexCommand(item.command),
279
+ details: typeof item.aggregated_output === "string" ? item.aggregated_output : ""
280
+ });
281
+ }
282
+ else if (item.type === "reasoning") {
283
+ this._queue.push({
284
+ type: "output",
285
+ title: "Thinking",
286
+ subtitle: "",
287
+ details: typeof item.text === "string" ? item.text : ""
288
+ });
289
+ }
290
+ }
291
+ _handleFailure(message) {
292
+ if (isRateLimitMessage(message)) {
293
+ const r = EIGHT_MINUTES_MS + Math.round(this._contexts.random.random() * (TWELVE_MINUTES_MS - EIGHT_MINUTES_MS));
294
+ this._queue.push({
295
+ type: "rate_limit",
296
+ waitUntilMs: this._contexts.time.now() + r
297
+ });
298
+ }
299
+ else if (isRetryableHttpStatus(message)) {
300
+ this._queue.push({ type: "error", retryable: true, message });
301
+ }
302
+ else if (isRetryableTransport(message)) {
303
+ this._queue.push({ type: "error", retryable: true, message });
304
+ }
305
+ else {
306
+ this._queue.push({ type: "error", retryable: false, message });
307
+ }
308
+ this._done = true;
309
+ }
310
+ _wake() {
311
+ if (this._waitResolve) {
312
+ const resolve = this._waitResolve;
313
+ this._waitResolve = null;
314
+ resolve();
315
+ }
316
+ }
317
+ _wait() {
318
+ return new Promise(resolve => {
319
+ this._waitResolve = resolve;
320
+ });
321
+ }
322
+ async next() {
323
+ for (;;) {
324
+ if (this._queue.length > 0) {
325
+ return { value: this._queue.shift(), done: false };
326
+ }
327
+ if (this._done && this._queue.length === 0) {
328
+ this._cleanup();
329
+ if (this._exitPromise) {
330
+ await this._exitPromise;
331
+ }
332
+ return { value: undefined, done: true };
333
+ }
334
+ await this._wait();
335
+ }
336
+ }
337
+ async return() {
338
+ this._done = true;
339
+ this._cleanup();
340
+ if (this._proc) {
341
+ this._proc.kill("SIGINT");
342
+ if (this._exitPromise) {
343
+ await this._exitPromise;
344
+ }
345
+ }
346
+ return { value: undefined, done: true };
347
+ }
348
+ _cleanup() {
349
+ if (this._abortListener) {
350
+ this._args.abortSignal.removeEventListener("abort", this._abortListener);
351
+ this._abortListener = null;
352
+ }
353
+ }
354
+ }
@@ -0,0 +1,52 @@
1
+ export type ToolEventOutput = Readonly<{
2
+ type: "output";
3
+ title: string;
4
+ subtitle: string;
5
+ details: string;
6
+ }>;
7
+ export type ToolEventSession = Readonly<{
8
+ type: "session";
9
+ id: string;
10
+ }>;
11
+ export type ToolEventError = Readonly<{
12
+ type: "error";
13
+ retryable: boolean;
14
+ message: string;
15
+ }>;
16
+ export type ToolEventRateLimit = Readonly<{
17
+ type: "rate_limit";
18
+ waitUntilMs: number;
19
+ }>;
20
+ export type ToolEventDone = Readonly<{
21
+ type: "done";
22
+ }>;
23
+ export type ToolEvent = ToolEventOutput | ToolEventSession | ToolEventError | ToolEventRateLimit | ToolEventDone;
24
+ export type ToolAdapterUsageCallback = (usage: Readonly<{
25
+ inputTokens: number;
26
+ outputTokens: number;
27
+ }>) => void;
28
+ type ToolAdapterInvokeArgsBase = Readonly<{
29
+ prompt: string;
30
+ model: string;
31
+ effort: string;
32
+ abortSignal: AbortSignal;
33
+ onUsage?: ToolAdapterUsageCallback;
34
+ }>;
35
+ export type ToolAdapterInvokeArgsFresh = ToolAdapterInvokeArgsBase & Readonly<{
36
+ resumeSessionId?: undefined;
37
+ forkParentSessionId?: undefined;
38
+ }>;
39
+ export type ToolAdapterInvokeArgsResume = ToolAdapterInvokeArgsBase & Readonly<{
40
+ resumeSessionId: string;
41
+ forkParentSessionId?: undefined;
42
+ }>;
43
+ export type ToolAdapterInvokeArgsFork = ToolAdapterInvokeArgsBase & Readonly<{
44
+ resumeSessionId?: undefined;
45
+ forkParentSessionId: string;
46
+ }>;
47
+ export type ToolAdapterInvokeArgs = ToolAdapterInvokeArgsFresh | ToolAdapterInvokeArgsResume | ToolAdapterInvokeArgsFork;
48
+ export interface ToolAdapter {
49
+ invoke(args: ToolAdapterInvokeArgs): AsyncIterable<ToolEvent>;
50
+ }
51
+ export type ToolName = "claude" | "codex";
52
+ export {};
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/lib/cli.js CHANGED
@@ -41,37 +41,27 @@ const os = __importStar(require("os"));
41
41
  const path = __importStar(require("path"));
42
42
  const readline = __importStar(require("readline"));
43
43
  const Flanders_1 = require("./Flanders");
44
- const spawnContext = {
45
- spawn(command, args, options) {
46
- const child = (0, child_process_1.spawn)(command, [...args], options);
47
- const proc = {
48
- on(event, listener) {
49
- child.on(event, listener);
50
- },
51
- kill(signal) {
52
- child.kill(signal);
53
- },
54
- stdout: child.stdout ? {
55
- on(event, listener) {
56
- child.stdout.on(event, listener);
57
- }
58
- } : undefined,
59
- stderr: child.stderr ? {
60
- on(event, listener) {
61
- child.stderr.on(event, listener);
62
- }
63
- } : undefined,
64
- stdin: child.stdin ? {
65
- write(chunk) {
66
- child.stdin.write(chunk);
67
- },
68
- end() {
69
- child.stdin.end();
70
- }
71
- } : undefined
72
- };
73
- return proc;
74
- }
44
+ const ShellScriptContext_1 = require("./system/ShellScriptContext");
45
+ const TerminalSizeSource_1 = require("./ui/TerminalSizeSource");
46
+ const rawSpawn = (command, args, options) => {
47
+ var _a;
48
+ const child = (0, child_process_1.spawn)(command, [...args], options);
49
+ const raw = {
50
+ pid: (_a = child.pid) !== null && _a !== void 0 ? _a : 0,
51
+ stdout: child.stdout,
52
+ stderr: child.stderr,
53
+ stdin: child.stdin,
54
+ on(event, listener) {
55
+ child.on(event, listener);
56
+ },
57
+ kill(signal) {
58
+ child.kill(signal);
59
+ }
60
+ };
61
+ return raw;
62
+ };
63
+ const killPrimitive = (pid, signal) => {
64
+ process.kill(pid, signal);
75
65
  };
76
66
  const fsContext = {
77
67
  async readFile(p) {
@@ -81,6 +71,9 @@ const fsContext = {
81
71
  await fs_1.promises.mkdir(path.dirname(p), { recursive: true });
82
72
  await fs_1.promises.writeFile(p, content, "utf8");
83
73
  },
74
+ async rename(oldP, newP) {
75
+ await fs_1.promises.rename(oldP, newP);
76
+ },
84
77
  async readdir(p) {
85
78
  const entries = await fs_1.promises.readdir(p, { withFileTypes: true });
86
79
  return entries.map(e => ({
@@ -132,6 +125,32 @@ const timeContext = {
132
125
  };
133
126
  }
134
127
  };
128
+ const randomContext = {
129
+ random() {
130
+ return Math.random();
131
+ }
132
+ };
133
+ const RESIZE_POLL_MS = 200;
134
+ const readTerminalSize = () => {
135
+ var _a, _b;
136
+ const stream = process.stdout;
137
+ const handle = stream._handle;
138
+ if (!handle || typeof handle.getWindowSize !== "function") {
139
+ return null;
140
+ }
141
+ const size = [0, 0];
142
+ const err = handle.getWindowSize(size);
143
+ const cols = (_a = size[0]) !== null && _a !== void 0 ? _a : 0;
144
+ const rows = (_b = size[1]) !== null && _b !== void 0 ? _b : 0;
145
+ if (err || cols <= 0) {
146
+ return null;
147
+ }
148
+ return { columns: cols, rows };
149
+ };
150
+ const terminalSize = new TerminalSizeSource_1.TerminalSizeSource(readTerminalSize, listener => {
151
+ process.stdout.on("resize", listener);
152
+ return () => { process.stdout.off("resize", listener); };
153
+ }, timeContext, RESIZE_POLL_MS);
135
154
  const outputContext = {
136
155
  write(text) {
137
156
  process.stdout.write(text);
@@ -140,14 +159,13 @@ const outputContext = {
140
159
  process.stderr.write(text);
141
160
  },
142
161
  columns() {
143
- return process.stdout.columns || 80;
162
+ return terminalSize.columns();
144
163
  },
145
164
  rows() {
146
- return process.stdout.rows || 24;
165
+ return terminalSize.rows();
147
166
  },
148
167
  onResize(listener) {
149
- process.stdout.on("resize", listener);
150
- return () => { process.stdout.off("resize", listener); };
168
+ return terminalSize.onResize(listener);
151
169
  }
152
170
  };
153
171
  const platformContext = {
@@ -161,6 +179,7 @@ const platformContext = {
161
179
  return os.homedir();
162
180
  }
163
181
  };
182
+ const spawnContext = new ShellScriptContext_1.ShellScriptContext(rawSpawn, killPrimitive, platformContext);
164
183
  const ask = (() => {
165
184
  let rl = null;
166
185
  const ensure = () => {
@@ -297,6 +316,7 @@ const flanders = new Flanders_1.Flanders(process.argv.slice(2), { projectRoot: p
297
316
  script: spawnContext,
298
317
  fs: fsContext,
299
318
  time: timeContext,
319
+ random: randomContext,
300
320
  platform: platformContext,
301
321
  ask: ask.context,
302
322
  output: outputContext
@@ -311,6 +331,7 @@ const end = async () => {
311
331
  outputContext.write("Shutting down...\n");
312
332
  try {
313
333
  await flanders.dispose();
334
+ terminalSize.dispose();
314
335
  }
315
336
  catch (e) {
316
337
  outputContext.writeError(`${e instanceof Error ? (_a = e.stack) !== null && _a !== void 0 ? _a : e.message : String(e)}\n`);
@@ -1,14 +1,15 @@
1
- import type { AskContext, ClaudeContext, FsContext, OutputContext, ScriptContext, TimeContext } from "../contexts";
1
+ import type { FsContext, OutputContext, RandomContext, ScriptContext, TimeContext } from "../contexts";
2
+ import type { FlandersConfig } from "../workspace/FlandersConfig";
2
3
  import type { Activity } from "../ui/BottomBlock";
3
- import { PlatformContext } from "../Workspace";
4
+ import { PlatformContext } from "../workspace/Workspace";
4
5
  export type { Activity };
5
6
  export type ImplementContexts = Readonly<{
6
- claude: ClaudeContext;
7
+ claude: ScriptContext;
7
8
  script: ScriptContext;
8
9
  fs: FsContext;
9
10
  time: TimeContext;
11
+ random: RandomContext;
10
12
  platform: PlatformContext;
11
- ask: AskContext;
12
13
  output: OutputContext;
13
14
  }>;
14
15
  export type ImplementOptions = Readonly<{
@@ -18,8 +19,10 @@ export declare class Implement {
18
19
  private _options;
19
20
  private _contexts;
20
21
  private _disposed;
22
+ private _config;
21
23
  private _contractList;
22
24
  private _ruleList;
25
+ private _behaviorRuleList;
23
26
  private _workspace;
24
27
  private _block;
25
28
  private _buffered;
@@ -27,6 +30,8 @@ export declare class Implement {
27
30
  private _currentPrepSessionId;
28
31
  private _activeSession;
29
32
  private _activeScript;
33
+ private _activeReviewerSessions;
34
+ private _reviewerStates;
30
35
  private _currentIndexLabel;
31
36
  private _currentIteration;
32
37
  private _currentTask;
@@ -34,27 +39,36 @@ export declare class Implement {
34
39
  private _taskRateLimitMs;
35
40
  private _taskRateLimitStartedAt;
36
41
  private _taskTokens;
42
+ private _restingFooterKind;
37
43
  private _runPromise;
44
+ get config(): FlandersConfig | null;
38
45
  constructor(rawArgs: readonly string[], _options: ImplementOptions, _contexts: ImplementContexts);
39
46
  result(): Promise<number>;
40
47
  private _run;
41
48
  private _selectPlan;
42
- private _askOutput;
43
- private _promptPlanChoice;
44
49
  private _detectBuildAndTest;
45
50
  private _setActivity;
46
51
  private _activeSeconds;
47
52
  private _persistMetrics;
48
53
  private _updateMetrics;
54
+ private _reviewerMatchesWorker;
55
+ private _prepActive;
56
+ private _gitOutputContext;
49
57
  private _runTask;
50
58
  private _prepStage;
51
59
  private _workerStage;
60
+ private _appendLinkedContent;
52
61
  private _buildStage;
53
62
  private _testStage;
63
+ private _setReviewerState;
64
+ private _renderReviewingFooter;
54
65
  private _reviewerStage;
55
- private _parseReviewVerdict;
66
+ private _runOneReviewerToVerdict;
56
67
  private _formatPathList;
57
- private _runClaude;
68
+ private _getAdapter;
69
+ private _defaultRunAiCallbacks;
70
+ private _runAi;
71
+ private _runAiWith;
58
72
  private _runScript;
59
73
  private _writeLog;
60
74
  private _writeErrorLog;