@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
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @autopilot-harness/port-runner — external process loop for hosts without stop-continue.
3
+ * No vendor Stop hook; CLI owns spawn + in-process ReviewEngine.handleStop.
4
+ */
5
+ export { RUNNER_PLATFORM, RUNNER_DEFAULT_MAX_ITERATIONS, RUNNER_MIN_RECOMMENDED_ITERATIONS, RUNNER_MAX_ITERATIONS_CLAMP, RUNNER_PROMPT_FILE_THRESHOLD, normalizeRunnerConfig, hasRunnerCommand, assertRunnerCommand, type RunnerConfig, type RunnerConfigInput, type RunnerPromptMode, } from "./config.js";
6
+ export { stableRunnerConversationId, runnerConversationFileToken, } from "./conversation-id.js";
7
+ export { RUNNER_EXECUTING_SUMMARY, buildFirstTurnPrompt, } from "./first-turn-prompt.js";
8
+ export { resolvePromptChannel, assertTemplateMatchesChannel, tokenizeCommandTemplate, expandCommandTemplate, resolveRunnerCwd, unlinkPromptFile, resolveChecklistPathInProject, type PromptChannel, type ExpandedCommand, } from "./command-template.js";
9
+ export { driverResultToStopStatus, type AgentDriver, type DriverResult, type DriverRunInput, } from "./driver.js";
10
+ export { CliDriver } from "./cli-driver.js";
11
+ export { MockDriver, type MockDriverStep } from "./mock-driver.js";
12
+ export { runStopTick, shouldContinueAfterStop, type RunStopTickInput, type RunStopTickResult, } from "./stop-tick.js";
13
+ export { canResumeRunnerSession, type ResumeDecision, } from "./resume.js";
14
+ export { runRunnerLoop, type RunRunnerLoopOptions, type RunnerLoopResult, type RunnerLoopOutcome, } from "./loop.js";
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,eAAe,EACf,6BAA6B,EAC7B,iCAAiC,EACjC,2BAA2B,EAC3B,4BAA4B,EAC5B,qBAAqB,EACrB,gBAAgB,EAChB,mBAAmB,EACnB,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,GACtB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,0BAA0B,EAC1B,2BAA2B,GAC5B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,wBAAwB,EACxB,oBAAoB,GACrB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,oBAAoB,EACpB,4BAA4B,EAC5B,uBAAuB,EACvB,qBAAqB,EACrB,gBAAgB,EAChB,gBAAgB,EAChB,6BAA6B,EAC7B,KAAK,aAAa,EAClB,KAAK,eAAe,GACrB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,wBAAwB,EACxB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,cAAc,GACpB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EAAE,UAAU,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEnE,OAAO,EACL,WAAW,EACX,uBAAuB,EACvB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,GACvB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,sBAAsB,EACtB,KAAK,cAAc,GACpB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,aAAa,EACb,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,GACvB,MAAM,WAAW,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @autopilot-harness/port-runner — external process loop for hosts without stop-continue.
3
+ * No vendor Stop hook; CLI owns spawn + in-process ReviewEngine.handleStop.
4
+ */
5
+ export { RUNNER_PLATFORM, RUNNER_DEFAULT_MAX_ITERATIONS, RUNNER_MIN_RECOMMENDED_ITERATIONS, RUNNER_MAX_ITERATIONS_CLAMP, RUNNER_PROMPT_FILE_THRESHOLD, normalizeRunnerConfig, hasRunnerCommand, assertRunnerCommand, } from "./config.js";
6
+ export { stableRunnerConversationId, runnerConversationFileToken, } from "./conversation-id.js";
7
+ export { RUNNER_EXECUTING_SUMMARY, buildFirstTurnPrompt, } from "./first-turn-prompt.js";
8
+ export { resolvePromptChannel, assertTemplateMatchesChannel, tokenizeCommandTemplate, expandCommandTemplate, resolveRunnerCwd, unlinkPromptFile, resolveChecklistPathInProject, } from "./command-template.js";
9
+ export { driverResultToStopStatus, } from "./driver.js";
10
+ export { CliDriver } from "./cli-driver.js";
11
+ export { MockDriver } from "./mock-driver.js";
12
+ export { runStopTick, shouldContinueAfterStop, } from "./stop-tick.js";
13
+ export { canResumeRunnerSession, } from "./resume.js";
14
+ export { runRunnerLoop, } from "./loop.js";
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,eAAe,EACf,6BAA6B,EAC7B,iCAAiC,EACjC,2BAA2B,EAC3B,4BAA4B,EAC5B,qBAAqB,EACrB,gBAAgB,EAChB,mBAAmB,GAIpB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,0BAA0B,EAC1B,2BAA2B,GAC5B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,wBAAwB,EACxB,oBAAoB,GACrB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,oBAAoB,EACpB,4BAA4B,EAC5B,uBAAuB,EACvB,qBAAqB,EACrB,gBAAgB,EAChB,gBAAgB,EAChB,6BAA6B,GAG9B,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,wBAAwB,GAIzB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EAAE,UAAU,EAAuB,MAAM,kBAAkB,CAAC;AAEnE,OAAO,EACL,WAAW,EACX,uBAAuB,GAGxB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,sBAAsB,GAEvB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,aAAa,GAId,MAAM,WAAW,CAAC"}
package/dist/loop.d.ts ADDED
@@ -0,0 +1,33 @@
1
+ import { type FollowupLocaleBundle, type PhaseActionConfig, type StateStore } from "@autopilot-harness/core";
2
+ import type { RunnerConfig } from "./config.js";
3
+ import type { AgentDriver } from "./driver.js";
4
+ import { runStopTick } from "./stop-tick.js";
5
+ export type RunnerLoopOutcome = "completed" | "budget_exhausted" | "stopped" | "error";
6
+ export interface RunnerLoopResult {
7
+ outcome: RunnerLoopOutcome;
8
+ iterations: number;
9
+ conversationId: string;
10
+ lastMessage?: string;
11
+ errorMessage?: string;
12
+ }
13
+ export interface RunRunnerLoopOptions {
14
+ store: StateStore;
15
+ projectRoot: string;
16
+ conversationId: string;
17
+ config: RunnerConfig;
18
+ /** When set, applyRun before the loop (fresh start). */
19
+ runSlug?: string;
20
+ phaseActions?: PhaseActionConfig;
21
+ /** Override driver (tests). Default: CliDriver when command set. */
22
+ driver?: AgentDriver;
23
+ localeBundle?: FollowupLocaleBundle;
24
+ /** Called before each agent turn with the prompt that will be sent. */
25
+ onPrompt?: (prompt: string, iteration: number) => void;
26
+ /** Override Stop tick (tests). Default: runStopTick. */
27
+ stopTick?: typeof runStopTick;
28
+ }
29
+ /**
30
+ * External Autopilot loop: spawn agent → handleStop → re-inject tip / stop.
31
+ */
32
+ export declare function runRunnerLoop(opts: RunRunnerLoopOptions): Promise<RunnerLoopResult>;
33
+ //# sourceMappingURL=loop.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["../src/loop.ts"],"names":[],"mappings":"AAAA,OAAO,EASL,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EACtB,KAAK,UAAU,EAChB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAIhD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAI/C,OAAO,EACL,WAAW,EAEZ,MAAM,gBAAgB,CAAC;AAExB,MAAM,MAAM,iBAAiB,GACzB,WAAW,GACX,kBAAkB,GAClB,SAAS,GACT,OAAO,CAAC;AAEZ,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,iBAAiB,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,UAAU,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,YAAY,CAAC;IACrB,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,iBAAiB,CAAC;IACjC,oEAAoE;IACpE,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,YAAY,CAAC,EAAE,oBAAoB,CAAC;IACpC,uEAAuE;IACvE,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACvD,wDAAwD;IACxD,QAAQ,CAAC,EAAE,OAAO,WAAW,CAAC;CAC/B;AAqCD;;GAEG;AACH,wBAAsB,aAAa,CACjC,IAAI,EAAE,oBAAoB,GACzB,OAAO,CAAC,gBAAgB,CAAC,CAgN3B"}
package/dist/loop.js ADDED
@@ -0,0 +1,223 @@
1
+ import { applyRun, firstUnchecked, isHarnessFollowupMessage, isSafeTrackSlug, loadProjectReviewConfig, normalizeProjectRoot, parseChecklist, sessionReviewRunnable, } from "@autopilot-harness/core";
2
+ import { RUNNER_PLATFORM, assertRunnerCommand } from "./config.js";
3
+ import { CliDriver } from "./cli-driver.js";
4
+ import { resolveChecklistPathInProject } from "./command-template.js";
5
+ import { driverResultToStopStatus } from "./driver.js";
6
+ import { buildFirstTurnPrompt } from "./first-turn-prompt.js";
7
+ import { canResumeRunnerSession } from "./resume.js";
8
+ import { runStopTick, shouldContinueAfterStop, } from "./stop-tick.js";
9
+ function resolveInitialPrompt(store, conversationId, projectRoot) {
10
+ const chain = store.getReviewChain(conversationId);
11
+ const pending = chain?.pending_followup?.trim() ?? "";
12
+ if (pending)
13
+ return pending;
14
+ const session = store.getSession(conversationId);
15
+ const slug = session?.track_id?.trim() ?? "";
16
+ const root = normalizeProjectRoot(store.projectRoot) ??
17
+ normalizeProjectRoot(projectRoot);
18
+ const checklistPath = session?.checklist_path?.trim();
19
+ if (!root || !slug || !checklistPath) {
20
+ throw new Error("Cannot build first-turn prompt: missing track or checklist path.");
21
+ }
22
+ if (!isSafeTrackSlug(slug)) {
23
+ throw new Error(`Unsafe track slug in session: "${slug.slice(0, 64)}"`);
24
+ }
25
+ const abs = resolveChecklistPathInProject(root, checklistPath);
26
+ if (!abs) {
27
+ throw new Error(`Checklist not found or outside project: ${checklistPath}`);
28
+ }
29
+ const cl = parseChecklist(abs, { projectRoot: root });
30
+ const item = firstUnchecked(cl);
31
+ if (!item) {
32
+ throw new Error(`No unchecked items in track "${slug}".`);
33
+ }
34
+ return buildFirstTurnPrompt({ slug, item });
35
+ }
36
+ /**
37
+ * External Autopilot loop: spawn agent → handleStop → re-inject tip / stop.
38
+ */
39
+ export async function runRunnerLoop(opts) {
40
+ const root = normalizeProjectRoot(opts.projectRoot) ??
41
+ normalizeProjectRoot(opts.store.projectRoot);
42
+ if (!root) {
43
+ return {
44
+ outcome: "error",
45
+ iterations: 0,
46
+ conversationId: opts.conversationId,
47
+ errorMessage: "Invalid project root.",
48
+ };
49
+ }
50
+ if (!opts.store.isConversationIdOk(opts.conversationId)) {
51
+ return {
52
+ outcome: "error",
53
+ iterations: 0,
54
+ conversationId: opts.conversationId,
55
+ errorMessage: "Invalid conversation id.",
56
+ };
57
+ }
58
+ const driver = opts.driver ??
59
+ (() => {
60
+ assertRunnerCommand(opts.config);
61
+ return new CliDriver(opts.config);
62
+ })();
63
+ if (opts.runSlug !== undefined) {
64
+ const runResult = applyRun(opts.store, opts.conversationId, root, {
65
+ slug: opts.runSlug === "" ? undefined : opts.runSlug,
66
+ config: opts.phaseActions,
67
+ platform: RUNNER_PLATFORM,
68
+ });
69
+ if (!runResult.ok) {
70
+ return {
71
+ outcome: "error",
72
+ iterations: 0,
73
+ conversationId: opts.conversationId,
74
+ errorMessage: runResult.userMessage,
75
+ };
76
+ }
77
+ }
78
+ else {
79
+ const resume = canResumeRunnerSession(opts.store, opts.conversationId, root);
80
+ if (!resume.ok) {
81
+ return {
82
+ outcome: "error",
83
+ iterations: 0,
84
+ conversationId: opts.conversationId,
85
+ errorMessage: resume.message,
86
+ };
87
+ }
88
+ }
89
+ let prompt;
90
+ try {
91
+ prompt = resolveInitialPrompt(opts.store, opts.conversationId, root);
92
+ }
93
+ catch (err) {
94
+ return {
95
+ outcome: "error",
96
+ iterations: 0,
97
+ conversationId: opts.conversationId,
98
+ errorMessage: err instanceof Error ? err.message : String(err),
99
+ };
100
+ }
101
+ const max = opts.config.maxIterations;
102
+ let lastMessage = prompt;
103
+ const reviewScope = loadProjectReviewConfig(root).reviewScope;
104
+ for (let i = 0; i < max; i += 1) {
105
+ opts.onPrompt?.(prompt, i);
106
+ let driverResult;
107
+ try {
108
+ driverResult = await driver.run({
109
+ prompt,
110
+ iteration: i,
111
+ conversationId: opts.conversationId,
112
+ projectRoot: root,
113
+ });
114
+ }
115
+ catch (err) {
116
+ return {
117
+ outcome: "error",
118
+ iterations: i + 1,
119
+ conversationId: opts.conversationId,
120
+ lastMessage: prompt,
121
+ errorMessage: err instanceof Error
122
+ ? err.message
123
+ : `Agent spawn failed: ${String(err)}`,
124
+ };
125
+ }
126
+ const status = driverResultToStopStatus(driverResult);
127
+ const tick = opts.stopTick ?? runStopTick;
128
+ let action;
129
+ try {
130
+ ({ action } = tick(opts.store, root, {
131
+ conversationId: opts.conversationId,
132
+ status,
133
+ loopCount: i,
134
+ }, opts.localeBundle));
135
+ }
136
+ catch (err) {
137
+ // Agent turn already finished — return structured error so callers can
138
+ // resume (pending / dirty tree) instead of an unhandled rejection.
139
+ return {
140
+ outcome: "error",
141
+ iterations: i + 1,
142
+ conversationId: opts.conversationId,
143
+ lastMessage: prompt,
144
+ errorMessage: err instanceof Error
145
+ ? err.message
146
+ : `Stop tick failed: ${String(err)}`,
147
+ };
148
+ }
149
+ if (shouldContinueAfterStop(action)) {
150
+ prompt = action.message.trim();
151
+ lastMessage = prompt;
152
+ continue;
153
+ }
154
+ // Explicit one-shot halt (loop:false) — do not redeliver pending in this start.
155
+ if (action && action.loop === false) {
156
+ return {
157
+ outcome: "stopped",
158
+ iterations: i + 1,
159
+ conversationId: opts.conversationId,
160
+ lastMessage: action.message,
161
+ };
162
+ }
163
+ const session = opts.store.getSession(opts.conversationId);
164
+ const chain = opts.store.getReviewChain(opts.conversationId);
165
+ let pending = chain?.pending_followup?.trim() ?? "";
166
+ const runnable = Boolean(session && sessionReviewRunnable(session, reviewScope));
167
+ // No transcript_path: ReviewEngine will not clear "delivered" pending
168
+ // (tryRedeliverPending skips; pendingBlocksAdvance fails open). Runner
169
+ // injected lastMessage as the agent prompt — ack matching *harness*
170
+ // followup only while still runnable (disarmed/paused must keep pending
171
+ // for a later resume; never clear unrelated pending text).
172
+ if (pending &&
173
+ pending === lastMessage &&
174
+ isHarnessFollowupMessage(pending) &&
175
+ runnable) {
176
+ try {
177
+ opts.store.clearPendingFollowupIf(opts.conversationId, (m) => m.trim() === pending);
178
+ }
179
+ catch {
180
+ /* best-effort */
181
+ }
182
+ pending =
183
+ opts.store.getReviewChain(opts.conversationId)?.pending_followup?.trim() ??
184
+ "";
185
+ }
186
+ // Null action + a *different* live pending: redeliver while still runnable.
187
+ if (pending && pending !== lastMessage && runnable) {
188
+ prompt = pending;
189
+ lastMessage = pending;
190
+ continue;
191
+ }
192
+ if (pending) {
193
+ return {
194
+ outcome: "stopped",
195
+ iterations: i + 1,
196
+ conversationId: opts.conversationId,
197
+ lastMessage: pending,
198
+ };
199
+ }
200
+ if (session?.phase === "done" || session?.phase === "idle") {
201
+ return {
202
+ outcome: "completed",
203
+ iterations: i + 1,
204
+ conversationId: opts.conversationId,
205
+ lastMessage: action?.message,
206
+ };
207
+ }
208
+ // No loop tip — stop cleanly (item may still be mid-flight without pending).
209
+ return {
210
+ outcome: "stopped",
211
+ iterations: i + 1,
212
+ conversationId: opts.conversationId,
213
+ lastMessage: action?.message ?? lastMessage,
214
+ };
215
+ }
216
+ return {
217
+ outcome: "budget_exhausted",
218
+ iterations: max,
219
+ conversationId: opts.conversationId,
220
+ lastMessage,
221
+ };
222
+ }
223
+ //# sourceMappingURL=loop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop.js","sourceRoot":"","sources":["../src/loop.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { AgentDriver, DriverResult, DriverRunInput } from "./driver.js";
2
+ export type MockDriverStep = DriverResult | ((input: DriverRunInput) => DriverResult | Promise<DriverResult>);
3
+ /**
4
+ * In-process driver for contract tests (research §5).
5
+ * Records every prompt; plays scripted exit codes / side effects.
6
+ */
7
+ export declare class MockDriver implements AgentDriver {
8
+ private readonly steps;
9
+ readonly calls: DriverRunInput[];
10
+ private stepIndex;
11
+ constructor(steps?: readonly MockDriverStep[]);
12
+ run(input: DriverRunInput): Promise<DriverResult>;
13
+ }
14
+ //# sourceMappingURL=mock-driver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock-driver.d.ts","sourceRoot":"","sources":["../src/mock-driver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7E,MAAM,MAAM,cAAc,GACtB,YAAY,GACZ,CAAC,CAAC,KAAK,EAAE,cAAc,KAAK,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC;AAEtE;;;GAGG;AACH,qBAAa,UAAW,YAAW,WAAW;IAIhC,OAAO,CAAC,QAAQ,CAAC,KAAK;IAHlC,QAAQ,CAAC,KAAK,EAAE,cAAc,EAAE,CAAM;IACtC,OAAO,CAAC,SAAS,CAAK;gBAEO,KAAK,GAAE,SAAS,cAAc,EAAO;IAE5D,GAAG,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC;CAYxD"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * In-process driver for contract tests (research §5).
3
+ * Records every prompt; plays scripted exit codes / side effects.
4
+ */
5
+ export class MockDriver {
6
+ steps;
7
+ calls = [];
8
+ stepIndex = 0;
9
+ constructor(steps = []) {
10
+ this.steps = steps;
11
+ }
12
+ async run(input) {
13
+ this.calls.push({ ...input });
14
+ const step = this.steps[this.stepIndex];
15
+ this.stepIndex += 1;
16
+ if (step === undefined) {
17
+ return { exitCode: 0, signal: null };
18
+ }
19
+ if (typeof step === "function") {
20
+ return step(input);
21
+ }
22
+ return step;
23
+ }
24
+ }
25
+ //# sourceMappingURL=mock-driver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock-driver.js","sourceRoot":"","sources":["../src/mock-driver.ts"],"names":[],"mappings":"AAMA;;;GAGG;AACH,MAAM,OAAO,UAAU;IAIQ;IAHpB,KAAK,GAAqB,EAAE,CAAC;IAC9B,SAAS,GAAG,CAAC,CAAC;IAEtB,YAA6B,QAAmC,EAAE;QAArC,UAAK,GAAL,KAAK,CAAgC;IAAG,CAAC;IAEtE,KAAK,CAAC,GAAG,CAAC,KAAqB;QAC7B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;QAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACxC,IAAI,CAAC,SAAS,IAAI,CAAC,CAAC;QACpB,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QACvC,CAAC;QACD,IAAI,OAAO,IAAI,KAAK,UAAU,EAAE,CAAC;YAC/B,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
@@ -0,0 +1,16 @@
1
+ import { type StateStore } from "@autopilot-harness/core";
2
+ export type ResumeDecision = {
3
+ ok: true;
4
+ reason: "pending" | "executing";
5
+ } | {
6
+ ok: false;
7
+ reason: "missing" | "paused" | "idle";
8
+ message: string;
9
+ };
10
+ /**
11
+ * Whether `runner start` may continue without `--run` (research §8).
12
+ * When there is no pending tip, gates must match first-turn prompt builders
13
+ * (track + in-project checklist + unchecked item) so resume never ok-then-throw.
14
+ */
15
+ export declare function canResumeRunnerSession(store: StateStore, conversationId: string, projectRoot: string): ResumeDecision;
16
+ //# sourceMappingURL=resume.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resume.d.ts","sourceRoot":"","sources":["../src/resume.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,UAAU,EAChB,MAAM,yBAAyB,CAAC;AAGjC,MAAM,MAAM,cAAc,GACtB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,SAAS,GAAG,WAAW,CAAA;CAAE,GAC7C;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1E;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,UAAU,EACjB,cAAc,EAAE,MAAM,EACtB,WAAW,EAAE,MAAM,GAClB,cAAc,CAyFhB"}
package/dist/resume.js ADDED
@@ -0,0 +1,88 @@
1
+ import { countUnchecked, isSafeTrackSlug, normalizeProjectRoot, parseChecklist, } from "@autopilot-harness/core";
2
+ import { resolveChecklistPathInProject } from "./command-template.js";
3
+ /**
4
+ * Whether `runner start` may continue without `--run` (research §8).
5
+ * When there is no pending tip, gates must match first-turn prompt builders
6
+ * (track + in-project checklist + unchecked item) so resume never ok-then-throw.
7
+ */
8
+ export function canResumeRunnerSession(store, conversationId, projectRoot) {
9
+ if (!store.isConversationIdOk(conversationId)) {
10
+ return {
11
+ ok: false,
12
+ reason: "missing",
13
+ message: "Invalid conversation id.",
14
+ };
15
+ }
16
+ const session = store.getSession(conversationId);
17
+ if (!session) {
18
+ return {
19
+ ok: false,
20
+ reason: "missing",
21
+ message: "No runner session. Start with: npx @autopilot-harness/cli runner start --run <slug>",
22
+ };
23
+ }
24
+ if (session.paused !== 0) {
25
+ return {
26
+ ok: false,
27
+ reason: "paused",
28
+ message: "Runner session is paused. Use Autopilot OFF / RESUME (or session tools) before starting again.",
29
+ };
30
+ }
31
+ const chain = store.getReviewChain(conversationId);
32
+ const pending = chain?.pending_followup?.trim() ?? "";
33
+ if (pending) {
34
+ return { ok: true, reason: "pending" };
35
+ }
36
+ if (session.phase === "executing") {
37
+ const root = normalizeProjectRoot(store.projectRoot) ??
38
+ normalizeProjectRoot(projectRoot);
39
+ const slug = session.track_id?.trim() ?? "";
40
+ const checklistPath = session.checklist_path?.trim() ?? "";
41
+ if (!root || !slug || !checklistPath) {
42
+ return {
43
+ ok: false,
44
+ reason: "idle",
45
+ message: "Cannot resume: missing track or checklist path. Start with: npx @autopilot-harness/cli runner start --run <slug>",
46
+ };
47
+ }
48
+ if (!isSafeTrackSlug(slug)) {
49
+ return {
50
+ ok: false,
51
+ reason: "idle",
52
+ message: `Unsafe track slug in session: "${slug.slice(0, 64)}"`,
53
+ };
54
+ }
55
+ try {
56
+ const abs = resolveChecklistPathInProject(root, checklistPath);
57
+ if (!abs) {
58
+ return {
59
+ ok: false,
60
+ reason: "idle",
61
+ message: "Checklist not found or outside project. Start with: npx @autopilot-harness/cli runner start --run <slug>",
62
+ };
63
+ }
64
+ const cl = parseChecklist(abs, { projectRoot: root });
65
+ if (countUnchecked(cl) > 0) {
66
+ return { ok: true, reason: "executing" };
67
+ }
68
+ return {
69
+ ok: false,
70
+ reason: "idle",
71
+ message: "Track has no unchecked items. Start with: npx @autopilot-harness/cli runner start --run <slug>",
72
+ };
73
+ }
74
+ catch {
75
+ return {
76
+ ok: false,
77
+ reason: "idle",
78
+ message: "Cannot read checklist for resume. Start with: npx @autopilot-harness/cli runner start --run <slug>",
79
+ };
80
+ }
81
+ }
82
+ return {
83
+ ok: false,
84
+ reason: "idle",
85
+ message: "Nothing to resume. Start with: npx @autopilot-harness/cli runner start --run <slug>",
86
+ };
87
+ }
88
+ //# sourceMappingURL=resume.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resume.js","sourceRoot":"","sources":["../src/resume.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import { type FollowupAction, type FollowupLocaleBundle, type StateStore, type StopHandlerInput } from "@autopilot-harness/core";
2
+ export interface RunStopTickInput {
3
+ conversationId: string;
4
+ status: StopHandlerInput["status"];
5
+ loopCount: number;
6
+ }
7
+ export interface RunStopTickResult {
8
+ action: FollowupAction | null;
9
+ }
10
+ /**
11
+ * Thin in-process Stop tick (research §1).
12
+ * No vendor hook / no transcriptPath in v1.
13
+ */
14
+ export declare function runStopTick(store: StateStore, projectRoot: string, input: RunStopTickInput, localeBundle?: FollowupLocaleBundle): RunStopTickResult;
15
+ /** True when the tick asks for another agent turn with a tip. */
16
+ export declare function shouldContinueAfterStop(action: FollowupAction | null): action is FollowupAction & {
17
+ loop: true;
18
+ message: string;
19
+ };
20
+ //# sourceMappingURL=stop-tick.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stop-tick.d.ts","sourceRoot":"","sources":["../src/stop-tick.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,KAAK,UAAU,EACf,KAAK,gBAAgB,EACtB,MAAM,yBAAyB,CAAC;AAGjC,MAAM,WAAW,gBAAgB;IAC/B,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IACnC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC;CAC/B;AAED;;;GAGG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,UAAU,EACjB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,gBAAgB,EACvB,YAAY,CAAC,EAAE,oBAAoB,GAClC,iBAAiB,CAanB;AAED,iEAAiE;AACjE,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,cAAc,GAAG,IAAI,GAC5B,MAAM,IAAI,cAAc,GAAG;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAO5D"}
@@ -0,0 +1,24 @@
1
+ import { createConfiguredReviewEngine, } from "@autopilot-harness/core";
2
+ import { RUNNER_PLATFORM } from "./config.js";
3
+ /**
4
+ * Thin in-process Stop tick (research §1).
5
+ * No vendor hook / no transcriptPath in v1.
6
+ */
7
+ export function runStopTick(store, projectRoot, input, localeBundle) {
8
+ const engine = createConfiguredReviewEngine(store, projectRoot, localeBundle);
9
+ const action = engine.handleStop({
10
+ conversationId: input.conversationId,
11
+ status: input.status,
12
+ loopCount: input.loopCount,
13
+ platform: RUNNER_PLATFORM,
14
+ });
15
+ return { action };
16
+ }
17
+ /** True when the tick asks for another agent turn with a tip. */
18
+ export function shouldContinueAfterStop(action) {
19
+ return Boolean(action &&
20
+ action.loop === true &&
21
+ typeof action.message === "string" &&
22
+ action.message.trim());
23
+ }
24
+ //# sourceMappingURL=stop-tick.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stop-tick.js","sourceRoot":"","sources":["../src/stop-tick.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,GAK7B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAY9C;;;GAGG;AACH,MAAM,UAAU,WAAW,CACzB,KAAiB,EACjB,WAAmB,EACnB,KAAuB,EACvB,YAAmC;IAEnC,MAAM,MAAM,GAAG,4BAA4B,CACzC,KAAK,EACL,WAAW,EACX,YAAY,CACb,CAAC;IACF,MAAM,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC;QAC/B,cAAc,EAAE,KAAK,CAAC,cAAc;QACpC,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,QAAQ,EAAE,eAAe;KAC1B,CAAC,CAAC;IACH,OAAO,EAAE,MAAM,EAAE,CAAC;AACpB,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,uBAAuB,CACrC,MAA6B;IAE7B,OAAO,OAAO,CACZ,MAAM;QACJ,MAAM,CAAC,IAAI,KAAK,IAAI;QACpB,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ;QAClC,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,CACxB,CAAC;AACJ,CAAC"}
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@autopilot-harness/port-runner",
3
+ "version": "0.12.0",
4
+ "description": "Autopilot harness external process runner for hosts without stop-continue (CLI loop + drivers)",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/mt2007/autopilot-harness.git",
9
+ "directory": "packages/ports/runner"
10
+ },
11
+ "homepage": "https://github.com/mt2007/autopilot-harness#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/mt2007/autopilot-harness/issues"
14
+ },
15
+ "type": "module",
16
+ "main": "./dist/index.js",
17
+ "types": "./dist/index.d.ts",
18
+ "exports": {
19
+ ".": {
20
+ "types": "./dist/index.d.ts",
21
+ "import": "./dist/index.js"
22
+ }
23
+ },
24
+ "files": [
25
+ "dist"
26
+ ],
27
+ "dependencies": {
28
+ "@autopilot-harness/core": "0.12.0"
29
+ },
30
+ "devDependencies": {
31
+ "typescript": "^5.8.2"
32
+ },
33
+ "engines": {
34
+ "node": ">=22"
35
+ },
36
+ "publishConfig": {
37
+ "access": "public"
38
+ },
39
+ "author": "mt2007 (https://github.com/mt2007)",
40
+ "keywords": [
41
+ "autopilot",
42
+ "harness",
43
+ "agent",
44
+ "ai",
45
+ "vibecoding",
46
+ "runner",
47
+ "checklist",
48
+ "code-review"
49
+ ],
50
+ "scripts": {
51
+ "build": "tsc -p tsconfig.json",
52
+ "typecheck": "tsc -p tsconfig.json --noEmit"
53
+ }
54
+ }