@autopilot-harness/port-runner 0.12.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 (46) hide show
  1. package/LICENSE +21 -0
  2. package/dist/cli-driver.d.ts +11 -0
  3. package/dist/cli-driver.d.ts.map +1 -0
  4. package/dist/cli-driver.js +59 -0
  5. package/dist/cli-driver.js.map +1 -0
  6. package/dist/command-template.d.ts +42 -0
  7. package/dist/command-template.d.ts.map +1 -0
  8. package/dist/command-template.js +219 -0
  9. package/dist/command-template.js.map +1 -0
  10. package/dist/config.d.ts +46 -0
  11. package/dist/config.d.ts.map +1 -0
  12. package/dist/config.js +69 -0
  13. package/dist/config.js.map +1 -0
  14. package/dist/conversation-id.d.ts +8 -0
  15. package/dist/conversation-id.d.ts.map +1 -0
  16. package/dist/conversation-id.js +30 -0
  17. package/dist/conversation-id.js.map +1 -0
  18. package/dist/driver.d.ts +19 -0
  19. package/dist/driver.d.ts.map +1 -0
  20. package/dist/driver.js +10 -0
  21. package/dist/driver.js.map +1 -0
  22. package/dist/first-turn-prompt.d.ts +11 -0
  23. package/dist/first-turn-prompt.d.ts.map +1 -0
  24. package/dist/first-turn-prompt.js +24 -0
  25. package/dist/first-turn-prompt.js.map +1 -0
  26. package/dist/index.d.ts +15 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +15 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/loop.d.ts +33 -0
  31. package/dist/loop.d.ts.map +1 -0
  32. package/dist/loop.js +223 -0
  33. package/dist/loop.js.map +1 -0
  34. package/dist/mock-driver.d.ts +14 -0
  35. package/dist/mock-driver.d.ts.map +1 -0
  36. package/dist/mock-driver.js +25 -0
  37. package/dist/mock-driver.js.map +1 -0
  38. package/dist/resume.d.ts +16 -0
  39. package/dist/resume.d.ts.map +1 -0
  40. package/dist/resume.js +88 -0
  41. package/dist/resume.js.map +1 -0
  42. package/dist/stop-tick.d.ts +20 -0
  43. package/dist/stop-tick.d.ts.map +1 -0
  44. package/dist/stop-tick.js +24 -0
  45. package/dist/stop-tick.js.map +1 -0
  46. package/package.json +54 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Autopilot Harness contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,11 @@
1
+ import type { RunnerConfig } from "./config.js";
2
+ import type { AgentDriver, DriverResult, DriverRunInput } from "./driver.js";
3
+ /**
4
+ * Spawn `runner.command` with `{prompt}` / `{prompt_file}` (shell: false).
5
+ */
6
+ export declare class CliDriver implements AgentDriver {
7
+ private readonly config;
8
+ constructor(config: RunnerConfig);
9
+ run(input: DriverRunInput): Promise<DriverResult>;
10
+ }
11
+ //# sourceMappingURL=cli-driver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-driver.d.ts","sourceRoot":"","sources":["../src/cli-driver.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAOhD,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7E;;GAEG;AACH,qBAAa,SAAU,YAAW,WAAW;IAC/B,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,YAAY;IAI3C,GAAG,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC;CA2CxD"}
@@ -0,0 +1,59 @@
1
+ import { spawn } from "node:child_process";
2
+ import { assertRunnerCommand } from "./config.js";
3
+ import { expandCommandTemplate, resolveRunnerCwd, unlinkPromptFile, } from "./command-template.js";
4
+ /**
5
+ * Spawn `runner.command` with `{prompt}` / `{prompt_file}` (shell: false).
6
+ */
7
+ export class CliDriver {
8
+ config;
9
+ constructor(config) {
10
+ this.config = config;
11
+ assertRunnerCommand(config);
12
+ }
13
+ async run(input) {
14
+ let promptFilePath;
15
+ try {
16
+ // Fail cwd before writing prompt files (avoid orphan files on bad config).
17
+ const cwd = resolveRunnerCwd(input.projectRoot, this.config.cwd);
18
+ const expanded = expandCommandTemplate(this.config, {
19
+ tip: input.prompt,
20
+ projectRoot: input.projectRoot,
21
+ conversationId: input.conversationId,
22
+ iteration: input.iteration,
23
+ });
24
+ promptFilePath = expanded.promptFilePath;
25
+ const env = {
26
+ ...process.env,
27
+ ...this.config.env,
28
+ };
29
+ return await new Promise((resolve, reject) => {
30
+ let settled = false;
31
+ const child = spawn(expanded.file, expanded.args, {
32
+ cwd,
33
+ env,
34
+ shell: false,
35
+ stdio: "inherit",
36
+ });
37
+ child.on("error", (err) => {
38
+ if (settled)
39
+ return;
40
+ settled = true;
41
+ reject(err);
42
+ });
43
+ child.on("close", (code, signal) => {
44
+ if (settled)
45
+ return;
46
+ settled = true;
47
+ resolve({
48
+ exitCode: code,
49
+ signal: signal ?? null,
50
+ });
51
+ });
52
+ });
53
+ }
54
+ finally {
55
+ unlinkPromptFile(promptFilePath);
56
+ }
57
+ }
58
+ }
59
+ //# sourceMappingURL=cli-driver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-driver.js","sourceRoot":"","sources":["../src/cli-driver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EACL,qBAAqB,EACrB,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,uBAAuB,CAAC;AAG/B;;GAEG;AACH,MAAM,OAAO,SAAS;IACS;IAA7B,YAA6B,MAAoB;QAApB,WAAM,GAAN,MAAM,CAAc;QAC/C,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,KAAqB;QAC7B,IAAI,cAAkC,CAAC;QACvC,IAAI,CAAC;YACH,2EAA2E;YAC3E,MAAM,GAAG,GAAG,gBAAgB,CAAC,KAAK,CAAC,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,MAAM,QAAQ,GAAG,qBAAqB,CAAC,IAAI,CAAC,MAAM,EAAE;gBAClD,GAAG,EAAE,KAAK,CAAC,MAAM;gBACjB,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,cAAc,EAAE,KAAK,CAAC,cAAc;gBACpC,SAAS,EAAE,KAAK,CAAC,SAAS;aAC3B,CAAC,CAAC;YACH,cAAc,GAAG,QAAQ,CAAC,cAAc,CAAC;YACzC,MAAM,GAAG,GAAsB;gBAC7B,GAAG,OAAO,CAAC,GAAG;gBACd,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG;aACnB,CAAC;YAEF,OAAO,MAAM,IAAI,OAAO,CAAe,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBACzD,IAAI,OAAO,GAAG,KAAK,CAAC;gBACpB,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE;oBAChD,GAAG;oBACH,GAAG;oBACH,KAAK,EAAE,KAAK;oBACZ,KAAK,EAAE,SAAS;iBACjB,CAAC,CAAC;gBACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;oBACxB,IAAI,OAAO;wBAAE,OAAO;oBACpB,OAAO,GAAG,IAAI,CAAC;oBACf,MAAM,CAAC,GAAG,CAAC,CAAC;gBACd,CAAC,CAAC,CAAC;gBACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE;oBACjC,IAAI,OAAO;wBAAE,OAAO;oBACpB,OAAO,GAAG,IAAI,CAAC;oBACf,OAAO,CAAC;wBACN,QAAQ,EAAE,IAAI;wBACd,MAAM,EAAE,MAAM,IAAI,IAAI;qBACvB,CAAC,CAAC;gBACL,CAAC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC;gBAAS,CAAC;YACT,gBAAgB,CAAC,cAAc,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,42 @@
1
+ import type { RunnerConfig, RunnerPromptMode } from "./config.js";
2
+ export type PromptChannel = "argv" | "file";
3
+ export interface ExpandedCommand {
4
+ file: string;
5
+ args: string[];
6
+ /** Set when a prompt file was written for this turn. */
7
+ promptFilePath?: string;
8
+ channel: PromptChannel;
9
+ }
10
+ /**
11
+ * Decide argv vs file channel (research §4 / §10).
12
+ * Long tips with only `{prompt}` still use argv as one element (shell:false).
13
+ */
14
+ export declare function resolvePromptChannel(template: string, tip: string, mode: RunnerPromptMode): PromptChannel;
15
+ /**
16
+ * Fail closed before writing prompt files when the template mixes channels
17
+ * that cannot both be satisfied for the chosen channel.
18
+ */
19
+ export declare function assertTemplateMatchesChannel(template: string, channel: PromptChannel): void;
20
+ /**
21
+ * Split template on whitespace; keep `{prompt}` / `{prompt_file}` atomic.
22
+ * No shell expansion — caller must spawn with `shell: false`.
23
+ */
24
+ export declare function tokenizeCommandTemplate(template: string): string[];
25
+ /** Best-effort cleanup after a turn. */
26
+ export declare function unlinkPromptFile(filePath: string | undefined): void;
27
+ /**
28
+ * Expand `runner.command` into spawn file + args for one tip.
29
+ */
30
+ export declare function expandCommandTemplate(config: RunnerConfig, opts: {
31
+ tip: string;
32
+ projectRoot: string;
33
+ conversationId: string;
34
+ iteration: number;
35
+ }): ExpandedCommand;
36
+ /** Resolve cwd under project (or project root). */
37
+ export declare function resolveRunnerCwd(projectRoot: string, cwd: string): string;
38
+ /**
39
+ * Resolve a session checklist path under the project root (fail closed).
40
+ */
41
+ export declare function resolveChecklistPathInProject(projectRoot: string, checklistPath: string): string | null;
42
+ //# sourceMappingURL=command-template.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-template.d.ts","sourceRoot":"","sources":["../src/command-template.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAOlE,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,MAAM,CAAC;AAE5C,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,wDAAwD;IACxD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,aAAa,CAAC;CACxB;AAMD;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,gBAAgB,GACrB,aAAa,CAyBf;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,aAAa,GACrB,IAAI,CAsBN;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAwBlE;AA8BD,wCAAwC;AACxC,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAOnE;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,YAAY,EACpB,IAAI,EAAE;IACJ,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;CACnB,GACA,eAAe,CA8CjB;AAED,mDAAmD;AACnD,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,MAAM,GACV,MAAM,CAqBR;AAED;;GAEG;AACH,wBAAgB,6BAA6B,CAC3C,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE,MAAM,GACpB,MAAM,GAAG,IAAI,CAaf"}
@@ -0,0 +1,219 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { isLexicallyInsideProject, isRealpathInsideProject, normalizeProjectRoot, } from "@autopilot-harness/core";
4
+ import { RUNNER_PROMPT_FILE_THRESHOLD } from "./config.js";
5
+ import { runnerConversationFileToken } from "./conversation-id.js";
6
+ const PROMPT_TOKEN = "{prompt}";
7
+ const PROMPT_FILE_TOKEN = "{prompt_file}";
8
+ function templateHas(template, token) {
9
+ return template.includes(token);
10
+ }
11
+ /**
12
+ * Decide argv vs file channel (research §4 / §10).
13
+ * Long tips with only `{prompt}` still use argv as one element (shell:false).
14
+ */
15
+ export function resolvePromptChannel(template, tip, mode) {
16
+ const hasFile = templateHas(template, PROMPT_FILE_TOKEN);
17
+ const hasArgv = templateHas(template, PROMPT_TOKEN);
18
+ if (mode === "file") {
19
+ if (!hasFile) {
20
+ throw new Error("prompt_mode=file requires {prompt_file} in runner.command");
21
+ }
22
+ return "file";
23
+ }
24
+ if (mode === "argv") {
25
+ if (!hasArgv) {
26
+ throw new Error("prompt_mode=argv requires {prompt} in runner.command");
27
+ }
28
+ return "argv";
29
+ }
30
+ // auto
31
+ if (hasFile && tip.length > RUNNER_PROMPT_FILE_THRESHOLD)
32
+ return "file";
33
+ if (hasFile && !hasArgv)
34
+ return "file";
35
+ if (hasArgv)
36
+ return "argv";
37
+ if (hasFile)
38
+ return "file";
39
+ throw new Error("runner.command must include {prompt} and/or {prompt_file}");
40
+ }
41
+ /**
42
+ * Fail closed before writing prompt files when the template mixes channels
43
+ * that cannot both be satisfied for the chosen channel.
44
+ */
45
+ export function assertTemplateMatchesChannel(template, channel) {
46
+ const hasFile = templateHas(template, PROMPT_FILE_TOKEN);
47
+ const hasArgv = templateHas(template, PROMPT_TOKEN);
48
+ if (channel === "argv") {
49
+ if (!hasArgv) {
50
+ throw new Error("argv channel requires {prompt} in runner.command");
51
+ }
52
+ if (hasFile) {
53
+ throw new Error("runner.command has both {prompt} and {prompt_file}; use prompt_mode=file or remove {prompt_file}");
54
+ }
55
+ return;
56
+ }
57
+ if (!hasFile) {
58
+ throw new Error("file channel requires {prompt_file} in runner.command");
59
+ }
60
+ if (hasArgv) {
61
+ throw new Error("runner.command has both {prompt} and {prompt_file}; use prompt_mode=argv or remove {prompt}");
62
+ }
63
+ }
64
+ /**
65
+ * Split template on whitespace; keep `{prompt}` / `{prompt_file}` atomic.
66
+ * No shell expansion — caller must spawn with `shell: false`.
67
+ */
68
+ export function tokenizeCommandTemplate(template) {
69
+ const trimmed = template.trim();
70
+ if (!trimmed)
71
+ return [];
72
+ const tokens = [];
73
+ let i = 0;
74
+ while (i < trimmed.length) {
75
+ while (i < trimmed.length && /\s/.test(trimmed[i]))
76
+ i += 1;
77
+ if (i >= trimmed.length)
78
+ break;
79
+ if (trimmed.startsWith(PROMPT_TOKEN, i)) {
80
+ tokens.push(PROMPT_TOKEN);
81
+ i += PROMPT_TOKEN.length;
82
+ continue;
83
+ }
84
+ if (trimmed.startsWith(PROMPT_FILE_TOKEN, i)) {
85
+ tokens.push(PROMPT_FILE_TOKEN);
86
+ i += PROMPT_FILE_TOKEN.length;
87
+ continue;
88
+ }
89
+ let j = i;
90
+ while (j < trimmed.length && !/\s/.test(trimmed[j]))
91
+ j += 1;
92
+ tokens.push(trimmed.slice(i, j));
93
+ i = j;
94
+ }
95
+ return tokens;
96
+ }
97
+ function writePromptFile(projectRoot, conversationId, iteration, tip) {
98
+ const root = normalizeProjectRoot(projectRoot);
99
+ if (!root)
100
+ throw new Error("Invalid project root for prompt file.");
101
+ const dir = path.join(root, ".autopilot", "runner-prompts");
102
+ fs.mkdirSync(dir, { recursive: true });
103
+ const name = `${runnerConversationFileToken(conversationId)}-${iteration}.txt`;
104
+ const filePath = path.join(dir, name);
105
+ // Lexical check before create — realpath fails on missing leaves.
106
+ if (!isLexicallyInsideProject(root, filePath)) {
107
+ throw new Error("prompt file path escaped project root");
108
+ }
109
+ fs.writeFileSync(filePath, tip, "utf8");
110
+ if (!isRealpathInsideProject(root, filePath)) {
111
+ try {
112
+ fs.unlinkSync(filePath);
113
+ }
114
+ catch {
115
+ /* ignore */
116
+ }
117
+ throw new Error("prompt file path escaped project root");
118
+ }
119
+ return filePath;
120
+ }
121
+ /** Best-effort cleanup after a turn. */
122
+ export function unlinkPromptFile(filePath) {
123
+ if (!filePath)
124
+ return;
125
+ try {
126
+ fs.unlinkSync(filePath);
127
+ }
128
+ catch {
129
+ /* ignore */
130
+ }
131
+ }
132
+ /**
133
+ * Expand `runner.command` into spawn file + args for one tip.
134
+ */
135
+ export function expandCommandTemplate(config, opts) {
136
+ const template = config.command.trim();
137
+ if (!template) {
138
+ throw new Error("runner.command is empty");
139
+ }
140
+ const channel = resolvePromptChannel(template, opts.tip, config.promptMode);
141
+ // Validate before writing any prompt file (avoid leaks on mixed templates).
142
+ assertTemplateMatchesChannel(template, channel);
143
+ let promptFilePath;
144
+ try {
145
+ if (channel === "file") {
146
+ promptFilePath = writePromptFile(opts.projectRoot, opts.conversationId, opts.iteration, opts.tip);
147
+ }
148
+ const tokens = tokenizeCommandTemplate(template);
149
+ if (tokens.length === 0) {
150
+ throw new Error("runner.command produced no argv");
151
+ }
152
+ const replaced = tokens.map((t) => {
153
+ if (t === PROMPT_TOKEN)
154
+ return opts.tip;
155
+ if (t === PROMPT_FILE_TOKEN) {
156
+ if (!promptFilePath) {
157
+ throw new Error("{prompt_file} expansion missing path");
158
+ }
159
+ return promptFilePath;
160
+ }
161
+ return t;
162
+ });
163
+ const [file, ...args] = replaced;
164
+ if (!file)
165
+ throw new Error("runner.command missing executable");
166
+ return { file, args, promptFilePath, channel };
167
+ }
168
+ catch (err) {
169
+ unlinkPromptFile(promptFilePath);
170
+ throw err;
171
+ }
172
+ }
173
+ /** Resolve cwd under project (or project root). */
174
+ export function resolveRunnerCwd(projectRoot, cwd) {
175
+ const root = normalizeProjectRoot(projectRoot);
176
+ if (!root)
177
+ throw new Error("Invalid project root for runner cwd.");
178
+ const absRoot = fs.realpathSync(root);
179
+ if (!cwd.trim())
180
+ return absRoot;
181
+ const abs = path.resolve(absRoot, cwd.trim());
182
+ // Lexical first so a missing path is not misreported as an escape.
183
+ if (!isLexicallyInsideProject(absRoot, abs)) {
184
+ throw new Error("runner.cwd must stay inside the project root");
185
+ }
186
+ if (!fs.existsSync(abs)) {
187
+ throw new Error(`runner.cwd does not exist: ${cwd.trim()}`);
188
+ }
189
+ if (!isRealpathInsideProject(absRoot, abs)) {
190
+ throw new Error("runner.cwd must stay inside the project root");
191
+ }
192
+ const real = fs.realpathSync(abs);
193
+ if (!fs.statSync(real).isDirectory()) {
194
+ throw new Error(`runner.cwd must be a directory: ${cwd.trim()}`);
195
+ }
196
+ return real;
197
+ }
198
+ /**
199
+ * Resolve a session checklist path under the project root (fail closed).
200
+ */
201
+ export function resolveChecklistPathInProject(projectRoot, checklistPath) {
202
+ const root = normalizeProjectRoot(projectRoot);
203
+ if (!root || !checklistPath.trim())
204
+ return null;
205
+ const abs = path.isAbsolute(checklistPath)
206
+ ? checklistPath
207
+ : path.join(root, checklistPath);
208
+ try {
209
+ if (!fs.existsSync(abs))
210
+ return null;
211
+ if (!isRealpathInsideProject(root, abs))
212
+ return null;
213
+ return fs.realpathSync(abs);
214
+ }
215
+ catch {
216
+ return null;
217
+ }
218
+ }
219
+ //# sourceMappingURL=command-template.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-template.js","sourceRoot":"","sources":["../src/command-template.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EACL,wBAAwB,EACxB,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,4BAA4B,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,2BAA2B,EAAE,MAAM,sBAAsB,CAAC;AAEnE,MAAM,YAAY,GAAG,UAAU,CAAC;AAChC,MAAM,iBAAiB,GAAG,eAAe,CAAC;AAY1C,SAAS,WAAW,CAAC,QAAgB,EAAE,KAAa;IAClD,OAAO,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAClC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAClC,QAAgB,EAChB,GAAW,EACX,IAAsB;IAEtB,MAAM,OAAO,GAAG,WAAW,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC;IACzD,MAAM,OAAO,GAAG,WAAW,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IACpD,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CACb,2DAA2D,CAC5D,CAAC;QACJ,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;QAC1E,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,OAAO;IACP,IAAI,OAAO,IAAI,GAAG,CAAC,MAAM,GAAG,4BAA4B;QAAE,OAAO,MAAM,CAAC;IACxE,IAAI,OAAO,IAAI,CAAC,OAAO;QAAE,OAAO,MAAM,CAAC;IACvC,IAAI,OAAO;QAAE,OAAO,MAAM,CAAC;IAC3B,IAAI,OAAO;QAAE,OAAO,MAAM,CAAC;IAC3B,MAAM,IAAI,KAAK,CACb,2DAA2D,CAC5D,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,4BAA4B,CAC1C,QAAgB,EAChB,OAAsB;IAEtB,MAAM,OAAO,GAAG,WAAW,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC;IACzD,MAAM,OAAO,GAAG,WAAW,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IACpD,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;QACvB,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;QACtE,CAAC;QACD,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CACb,kGAAkG,CACnG,CAAC;QACJ,CAAC;QACD,OAAO;IACT,CAAC;IACD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;IAC3E,CAAC;IACD,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,6FAA6F,CAC9F,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CAAC,QAAgB;IACtD,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;IAChC,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IACxB,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;QAC1B,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC;YAAE,CAAC,IAAI,CAAC,CAAC;QAC5D,IAAI,CAAC,IAAI,OAAO,CAAC,MAAM;YAAE,MAAM;QAC/B,IAAI,OAAO,CAAC,UAAU,CAAC,YAAY,EAAE,CAAC,CAAC,EAAE,CAAC;YACxC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAC1B,CAAC,IAAI,YAAY,CAAC,MAAM,CAAC;YACzB,SAAS;QACX,CAAC;QACD,IAAI,OAAO,CAAC,UAAU,CAAC,iBAAiB,EAAE,CAAC,CAAC,EAAE,CAAC;YAC7C,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YAC/B,CAAC,IAAI,iBAAiB,CAAC,MAAM,CAAC;YAC9B,SAAS;QACX,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,CAAC;QACV,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC;YAAE,CAAC,IAAI,CAAC,CAAC;QAC7D,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACjC,CAAC,GAAG,CAAC,CAAC;IACR,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,eAAe,CACtB,WAAmB,EACnB,cAAsB,EACtB,SAAiB,EACjB,GAAW;IAEX,MAAM,IAAI,GAAG,oBAAoB,CAAC,WAAW,CAAC,CAAC;IAC/C,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IACpE,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,EAAE,gBAAgB,CAAC,CAAC;IAC5D,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACvC,MAAM,IAAI,GAAG,GAAG,2BAA2B,CAAC,cAAc,CAAC,IAAI,SAAS,MAAM,CAAC;IAC/E,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACtC,kEAAkE;IAClE,IAAI,CAAC,wBAAwB,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAC3D,CAAC;IACD,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;IACxC,IAAI,CAAC,uBAAuB,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,CAAC;QAC7C,IAAI,CAAC;YACH,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAC1B,CAAC;QAAC,MAAM,CAAC;YACP,YAAY;QACd,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAC3D,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,wCAAwC;AACxC,MAAM,UAAU,gBAAgB,CAAC,QAA4B;IAC3D,IAAI,CAAC,QAAQ;QAAE,OAAO;IACtB,IAAI,CAAC;QACH,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACP,YAAY;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CACnC,MAAoB,EACpB,IAKC;IAED,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;IACvC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC7C,CAAC;IACD,MAAM,OAAO,GAAG,oBAAoB,CAClC,QAAQ,EACR,IAAI,CAAC,GAAG,EACR,MAAM,CAAC,UAAU,CAClB,CAAC;IACF,4EAA4E;IAC5E,4BAA4B,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAEhD,IAAI,cAAkC,CAAC;IACvC,IAAI,CAAC;QACH,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;YACvB,cAAc,GAAG,eAAe,CAC9B,IAAI,CAAC,WAAW,EAChB,IAAI,CAAC,cAAc,EACnB,IAAI,CAAC,SAAS,EACd,IAAI,CAAC,GAAG,CACT,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,uBAAuB,CAAC,QAAQ,CAAC,CAAC;QACjD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;QACrD,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YAChC,IAAI,CAAC,KAAK,YAAY;gBAAE,OAAO,IAAI,CAAC,GAAG,CAAC;YACxC,IAAI,CAAC,KAAK,iBAAiB,EAAE,CAAC;gBAC5B,IAAI,CAAC,cAAc,EAAE,CAAC;oBACpB,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;gBAC1D,CAAC;gBACD,OAAO,cAAc,CAAC;YACxB,CAAC;YACD,OAAO,CAAC,CAAC;QACX,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,GAAG,QAAQ,CAAC;QACjC,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;QAChE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,CAAC;IACjD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,gBAAgB,CAAC,cAAc,CAAC,CAAC;QACjC,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC;AAED,mDAAmD;AACnD,MAAM,UAAU,gBAAgB,CAC9B,WAAmB,EACnB,GAAW;IAEX,MAAM,IAAI,GAAG,oBAAoB,CAAC,WAAW,CAAC,CAAC;IAC/C,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IACnE,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IACtC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE;QAAE,OAAO,OAAO,CAAC;IAChC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;IAC9C,mEAAmE;IACnE,IAAI,CAAC,wBAAwB,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IAClE,CAAC;IACD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,8BAA8B,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAC9D,CAAC;IACD,IAAI,CAAC,uBAAuB,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,CAAC;QAC3C,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IAClE,CAAC;IACD,MAAM,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;IAClC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;QACrC,MAAM,IAAI,KAAK,CAAC,mCAAmC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACnE,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,6BAA6B,CAC3C,WAAmB,EACnB,aAAqB;IAErB,MAAM,IAAI,GAAG,oBAAoB,CAAC,WAAW,CAAC,CAAC;IAC/C,IAAI,CAAC,IAAI,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE;QAAE,OAAO,IAAI,CAAC;IAChD,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC;QACxC,CAAC,CAAC,aAAa;QACf,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;IACnC,IAAI,CAAC;QACH,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;QACrC,IAAI,CAAC,uBAAuB,CAAC,IAAI,EAAE,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;QACrD,OAAO,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,46 @@
1
+ /** Autopilot session / Stop platform id for the external runner. */
2
+ export declare const RUNNER_PLATFORM = "runner";
3
+ /** Default iteration budget (covers fix + confirm×5 headroom). */
4
+ export declare const RUNNER_DEFAULT_MAX_ITERATIONS = 32;
5
+ /** Soft lower bound for doctor WARN (below this, confirm×5 is risky). */
6
+ export declare const RUNNER_MIN_RECOMMENDED_ITERATIONS = 8;
7
+ /** Clamp range for max_iterations. */
8
+ export declare const RUNNER_MAX_ITERATIONS_CLAMP: {
9
+ readonly min: 1;
10
+ readonly max: 500;
11
+ };
12
+ /** Tip length above which `auto` prefers `{prompt_file}` when the template allows it. */
13
+ export declare const RUNNER_PROMPT_FILE_THRESHOLD = 4000;
14
+ export type RunnerPromptMode = "argv" | "file" | "auto";
15
+ /**
16
+ * Runner block under `.autopilot/config.yml` (normalized).
17
+ * `command` empty/omitted → CliDriver start must FAIL.
18
+ */
19
+ export interface RunnerConfig {
20
+ /** Agent CLI template with `{prompt}` and/or `{prompt_file}`. */
21
+ command: string;
22
+ maxIterations: number;
23
+ /** Absolute cwd; empty → project root. */
24
+ cwd: string;
25
+ env: Readonly<Record<string, string>>;
26
+ promptMode: RunnerPromptMode;
27
+ }
28
+ export interface RunnerConfigInput {
29
+ command?: unknown;
30
+ max_iterations?: unknown;
31
+ maxIterations?: unknown;
32
+ cwd?: unknown;
33
+ env?: unknown;
34
+ prompt_mode?: unknown;
35
+ promptMode?: unknown;
36
+ }
37
+ /** Normalize untrusted YAML/flag input into a RunnerConfig. */
38
+ export declare function normalizeRunnerConfig(input?: RunnerConfigInput | null): RunnerConfig;
39
+ /** True when CliDriver has a usable command template. */
40
+ export declare function hasRunnerCommand(config: RunnerConfig): boolean;
41
+ /**
42
+ * Refuse start when command is missing (CliDriver path).
43
+ * MockDriver tests pass an explicit driver and skip this.
44
+ */
45
+ export declare function assertRunnerCommand(config: RunnerConfig): void;
46
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,eAAO,MAAM,eAAe,WAAW,CAAC;AAExC,kEAAkE;AAClE,eAAO,MAAM,6BAA6B,KAAK,CAAC;AAEhD,yEAAyE;AACzE,eAAO,MAAM,iCAAiC,IAAI,CAAC;AAEnD,sCAAsC;AACtC,eAAO,MAAM,2BAA2B;;;CAAgC,CAAC;AAEzE,yFAAyF;AACzF,eAAO,MAAM,4BAA4B,OAAO,CAAC;AAEjD,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAExD;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,iEAAiE;IACjE,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,0CAA0C;IAC1C,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACtC,UAAU,EAAE,gBAAgB,CAAC;CAC9B;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AA0BD,+DAA+D;AAC/D,wBAAgB,qBAAqB,CAAC,KAAK,CAAC,EAAE,iBAAiB,GAAG,IAAI,GAAG,YAAY,CAkBpF;AAED,yDAAyD;AACzD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAE9D;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAO9D"}
package/dist/config.js ADDED
@@ -0,0 +1,69 @@
1
+ /** Autopilot session / Stop platform id for the external runner. */
2
+ export const RUNNER_PLATFORM = "runner";
3
+ /** Default iteration budget (covers fix + confirm×5 headroom). */
4
+ export const RUNNER_DEFAULT_MAX_ITERATIONS = 32;
5
+ /** Soft lower bound for doctor WARN (below this, confirm×5 is risky). */
6
+ export const RUNNER_MIN_RECOMMENDED_ITERATIONS = 8;
7
+ /** Clamp range for max_iterations. */
8
+ export const RUNNER_MAX_ITERATIONS_CLAMP = { min: 1, max: 500 };
9
+ /** Tip length above which `auto` prefers `{prompt_file}` when the template allows it. */
10
+ export const RUNNER_PROMPT_FILE_THRESHOLD = 4000;
11
+ function clampIterations(n) {
12
+ const { min, max } = RUNNER_MAX_ITERATIONS_CLAMP;
13
+ if (!Number.isFinite(n) || !Number.isInteger(n)) {
14
+ return RUNNER_DEFAULT_MAX_ITERATIONS;
15
+ }
16
+ return Math.min(max, Math.max(min, n));
17
+ }
18
+ function asStringMap(raw) {
19
+ if (!raw || typeof raw !== "object" || Array.isArray(raw))
20
+ return {};
21
+ const out = {};
22
+ for (const [k, v] of Object.entries(raw)) {
23
+ if (typeof k !== "string" || !k.trim())
24
+ continue;
25
+ if (typeof v === "string")
26
+ out[k] = v;
27
+ else if (typeof v === "number" || typeof v === "boolean")
28
+ out[k] = String(v);
29
+ }
30
+ return out;
31
+ }
32
+ function parsePromptMode(raw) {
33
+ if (raw === "argv" || raw === "file" || raw === "auto")
34
+ return raw;
35
+ return "auto";
36
+ }
37
+ /** Normalize untrusted YAML/flag input into a RunnerConfig. */
38
+ export function normalizeRunnerConfig(input) {
39
+ const command = typeof input?.command === "string" ? input.command.trim() : "";
40
+ const maxRaw = input?.max_iterations ?? input?.maxIterations;
41
+ const maxIterations = typeof maxRaw === "number"
42
+ ? clampIterations(maxRaw)
43
+ : typeof maxRaw === "string" && maxRaw.trim()
44
+ ? clampIterations(Number(maxRaw.trim()))
45
+ : RUNNER_DEFAULT_MAX_ITERATIONS;
46
+ const cwd = typeof input?.cwd === "string" ? input.cwd.trim() : "";
47
+ return {
48
+ command,
49
+ maxIterations,
50
+ cwd,
51
+ env: asStringMap(input?.env),
52
+ promptMode: parsePromptMode(input?.prompt_mode ?? input?.promptMode),
53
+ };
54
+ }
55
+ /** True when CliDriver has a usable command template. */
56
+ export function hasRunnerCommand(config) {
57
+ return Boolean(config.command.trim());
58
+ }
59
+ /**
60
+ * Refuse start when command is missing (CliDriver path).
61
+ * MockDriver tests pass an explicit driver and skip this.
62
+ */
63
+ export function assertRunnerCommand(config) {
64
+ if (!hasRunnerCommand(config)) {
65
+ throw new Error("runner.command is required (set it in .autopilot/config.yml or --command). " +
66
+ "Init does not write a fake default command.");
67
+ }
68
+ }
69
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,MAAM,CAAC,MAAM,eAAe,GAAG,QAAQ,CAAC;AAExC,kEAAkE;AAClE,MAAM,CAAC,MAAM,6BAA6B,GAAG,EAAE,CAAC;AAEhD,yEAAyE;AACzE,MAAM,CAAC,MAAM,iCAAiC,GAAG,CAAC,CAAC;AAEnD,sCAAsC;AACtC,MAAM,CAAC,MAAM,2BAA2B,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAW,CAAC;AAEzE,yFAAyF;AACzF,MAAM,CAAC,MAAM,4BAA4B,GAAG,IAAI,CAAC;AA4BjD,SAAS,eAAe,CAAC,CAAS;IAChC,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,2BAA2B,CAAC;IACjD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;QAChD,OAAO,6BAA6B,CAAC;IACvC,CAAC;IACD,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;AACzC,CAAC;AAED,SAAS,WAAW,CAAC,GAAY;IAC/B,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IACrE,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAA8B,CAAC,EAAE,CAAC;QACpE,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE;YAAE,SAAS;QACjD,IAAI,OAAO,CAAC,KAAK,QAAQ;YAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;aACjC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,OAAO,CAAC,KAAK,SAAS;YAAE,GAAG,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IAC/E,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,eAAe,CAAC,GAAY;IACnC,IAAI,GAAG,KAAK,MAAM,IAAI,GAAG,KAAK,MAAM,IAAI,GAAG,KAAK,MAAM;QAAE,OAAO,GAAG,CAAC;IACnE,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,+DAA+D;AAC/D,MAAM,UAAU,qBAAqB,CAAC,KAAgC;IACpE,MAAM,OAAO,GACX,OAAO,KAAK,EAAE,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACjE,MAAM,MAAM,GAAG,KAAK,EAAE,cAAc,IAAI,KAAK,EAAE,aAAa,CAAC;IAC7D,MAAM,aAAa,GACjB,OAAO,MAAM,KAAK,QAAQ;QACxB,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC;QACzB,CAAC,CAAC,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,EAAE;YAC3C,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;YACxC,CAAC,CAAC,6BAA6B,CAAC;IACtC,MAAM,GAAG,GAAG,OAAO,KAAK,EAAE,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACnE,OAAO;QACL,OAAO;QACP,aAAa;QACb,GAAG;QACH,GAAG,EAAE,WAAW,CAAC,KAAK,EAAE,GAAG,CAAC;QAC5B,UAAU,EAAE,eAAe,CAAC,KAAK,EAAE,WAAW,IAAI,KAAK,EAAE,UAAU,CAAC;KACrE,CAAC;AACJ,CAAC;AAED,yDAAyD;AACzD,MAAM,UAAU,gBAAgB,CAAC,MAAoB;IACnD,OAAO,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;AACxC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAoB;IACtD,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CACb,6EAA6E;YAC3E,6CAA6C,CAChD,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Stable conversation id for the project-scoped runner executor.
3
+ * `runner:` + first 16 hex of sha256(realpath(projectRoot)).
4
+ */
5
+ export declare function stableRunnerConversationId(projectRoot: string): string;
6
+ /** Hash fragment for prompt filenames (not the full conversation id). */
7
+ export declare function runnerConversationFileToken(conversationId: string): string;
8
+ //# sourceMappingURL=conversation-id.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversation-id.d.ts","sourceRoot":"","sources":["../src/conversation-id.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAatE;AAED,yEAAyE;AACzE,wBAAgB,2BAA2B,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAK1E"}
@@ -0,0 +1,30 @@
1
+ import { createHash } from "node:crypto";
2
+ import fs from "node:fs";
3
+ import { normalizeProjectRoot } from "@autopilot-harness/core";
4
+ /**
5
+ * Stable conversation id for the project-scoped runner executor.
6
+ * `runner:` + first 16 hex of sha256(realpath(projectRoot)).
7
+ */
8
+ export function stableRunnerConversationId(projectRoot) {
9
+ const root = normalizeProjectRoot(projectRoot);
10
+ if (!root) {
11
+ throw new Error("Invalid project root for runner conversation id.");
12
+ }
13
+ let real;
14
+ try {
15
+ real = fs.realpathSync(root);
16
+ }
17
+ catch {
18
+ real = root;
19
+ }
20
+ const hex = createHash("sha256").update(real, "utf8").digest("hex").slice(0, 16);
21
+ return `runner:${hex}`;
22
+ }
23
+ /** Hash fragment for prompt filenames (not the full conversation id). */
24
+ export function runnerConversationFileToken(conversationId) {
25
+ return createHash("sha256")
26
+ .update(conversationId, "utf8")
27
+ .digest("hex")
28
+ .slice(0, 16);
29
+ }
30
+ //# sourceMappingURL=conversation-id.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversation-id.js","sourceRoot":"","sources":["../src/conversation-id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAE/D;;;GAGG;AACH,MAAM,UAAU,0BAA0B,CAAC,WAAmB;IAC5D,MAAM,IAAI,GAAG,oBAAoB,CAAC,WAAW,CAAC,CAAC;IAC/C,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;IACtE,CAAC;IACD,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QACH,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,GAAG,IAAI,CAAC;IACd,CAAC;IACD,MAAM,GAAG,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACjF,OAAO,UAAU,GAAG,EAAE,CAAC;AACzB,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,2BAA2B,CAAC,cAAsB;IAChE,OAAO,UAAU,CAAC,QAAQ,CAAC;SACxB,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC;SAC9B,MAAM,CAAC,KAAK,CAAC;SACb,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAClB,CAAC"}
@@ -0,0 +1,19 @@
1
+ /** Result of one agent turn (CLI spawn or mock). */
2
+ export interface DriverResult {
3
+ /** Process exit code; null if killed by signal only. */
4
+ exitCode: number | null;
5
+ signal?: NodeJS.Signals | null;
6
+ }
7
+ export interface DriverRunInput {
8
+ prompt: string;
9
+ iteration: number;
10
+ conversationId: string;
11
+ projectRoot: string;
12
+ }
13
+ /** Pluggable agent backend for the Runner loop. */
14
+ export interface AgentDriver {
15
+ run(input: DriverRunInput): Promise<DriverResult>;
16
+ }
17
+ /** Map spawn/mock outcome to ReviewEngine Stop status (research §7). */
18
+ export declare function driverResultToStopStatus(result: DriverResult): "completed" | "error" | "aborted";
19
+ //# sourceMappingURL=driver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../src/driver.ts"],"names":[],"mappings":"AAAA,oDAAoD;AACpD,MAAM,WAAW,YAAY;IAC3B,wDAAwD;IACxD,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,mDAAmD;AACnD,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;CACnD;AAED,wEAAwE;AACxE,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,YAAY,GACnB,WAAW,GAAG,OAAO,GAAG,SAAS,CAKnC"}
package/dist/driver.js ADDED
@@ -0,0 +1,10 @@
1
+ /** Map spawn/mock outcome to ReviewEngine Stop status (research §7). */
2
+ export function driverResultToStopStatus(result) {
3
+ const sig = result.signal;
4
+ if (sig === "SIGINT" || sig === "SIGTERM")
5
+ return "aborted";
6
+ if (result.exitCode === 0)
7
+ return "completed";
8
+ return "error";
9
+ }
10
+ //# sourceMappingURL=driver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"driver.js","sourceRoot":"","sources":["../src/driver.ts"],"names":[],"mappings":"AAmBA,wEAAwE;AACxE,MAAM,UAAU,wBAAwB,CACtC,MAAoB;IAEpB,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC;IAC1B,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC5D,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC;QAAE,OAAO,WAAW,CAAC;IAC9C,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { ChecklistItem } from "@autopilot-harness/core";
2
+ /** Condensed executing workflow (English stock; followups use ReviewEngine locale). */
3
+ export declare const RUNNER_EXECUTING_SUMMARY = "Implement only the current unchecked checklist item (align with plan.md).\nWhen required, write .autopilot/verify-last.json with matching itemId (and ok: true for hand-written reports).\nEnd the turn by exiting the agent process so the Runner can inject the next fix/confirm/advance tip.\nDo not invent Advance/Done; do not commit/push unless an Advance/Done tip explicitly asks for a local commit.\nFollow only the next Runner-injected message for review lenses.";
4
+ /**
5
+ * First-turn prompt after `--run` when there is no pending followup.
6
+ */
7
+ export declare function buildFirstTurnPrompt(opts: {
8
+ slug: string;
9
+ item: ChecklistItem;
10
+ }): string;
11
+ //# sourceMappingURL=first-turn-prompt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"first-turn-prompt.d.ts","sourceRoot":"","sources":["../src/first-turn-prompt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAE7D,uFAAuF;AACvF,eAAO,MAAM,wBAAwB,odAI2B,CAAC;AAEjE;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,aAAa,CAAC;CACrB,GAAG,MAAM,CAaT"}
@@ -0,0 +1,24 @@
1
+ /** Condensed executing workflow (English stock; followups use ReviewEngine locale). */
2
+ export const RUNNER_EXECUTING_SUMMARY = `Implement only the current unchecked checklist item (align with plan.md).
3
+ When required, write .autopilot/verify-last.json with matching itemId (and ok: true for hand-written reports).
4
+ End the turn by exiting the agent process so the Runner can inject the next fix/confirm/advance tip.
5
+ Do not invent Advance/Done; do not commit/push unless an Advance/Done tip explicitly asks for a local commit.
6
+ Follow only the next Runner-injected message for review lenses.`;
7
+ /**
8
+ * First-turn prompt after `--run` when there is no pending followup.
9
+ */
10
+ export function buildFirstTurnPrompt(opts) {
11
+ const title = opts.item.title?.trim() || opts.item.id;
12
+ return [
13
+ "[Autopilot Runner — executing]",
14
+ "",
15
+ `Track: ${opts.slug}`,
16
+ `Current item: ${opts.item.id} — ${title}`,
17
+ "",
18
+ RUNNER_EXECUTING_SUMMARY,
19
+ "",
20
+ "Rules: implement only this item; write verify-last.json when required; end the turn",
21
+ "(exit the agent process). Do not invent Advance/Done — wait for the next Runner inject.",
22
+ ].join("\n");
23
+ }
24
+ //# sourceMappingURL=first-turn-prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"first-turn-prompt.js","sourceRoot":"","sources":["../src/first-turn-prompt.ts"],"names":[],"mappings":"AAEA,uFAAuF;AACvF,MAAM,CAAC,MAAM,wBAAwB,GAAG;;;;gEAIwB,CAAC;AAEjE;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAGpC;IACC,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;IACtD,OAAO;QACL,gCAAgC;QAChC,EAAE;QACF,UAAU,IAAI,CAAC,IAAI,EAAE;QACrB,iBAAiB,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,KAAK,EAAE;QAC1C,EAAE;QACF,wBAAwB;QACxB,EAAE;QACF,qFAAqF;QACrF,yFAAyF;KAC1F,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}