@autopilot-harness/cli 0.2.2 → 0.2.4
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.
- package/dist/assets/templates/.autopilotignore +92 -0
- package/dist/assets/templates/skills/autopilot-off/SKILL.md.tpl +8 -0
- package/dist/assets/templates/skills/autopilot-on/SKILL.md.tpl +14 -0
- package/dist/assets/templates/skills/autopilot-replan/SKILL.md.tpl +9 -0
- package/dist/assets/templates/skills/autopilot-resume/SKILL.md.tpl +10 -0
- package/dist/assets/templates/skills/autopilot-run/SKILL.md.tpl +12 -0
- package/dist/assets/templates/workflows/autopilot-executing.md +59 -0
- package/dist/assets/templates/workflows/autopilot-planning.md +42 -0
- package/dist/assets/vendor/runtime.mjs +130 -3
- package/dist/init/install.d.ts.map +1 -1
- package/dist/init/install.js +4 -9
- package/dist/init/install.js.map +1 -1
- package/dist/init/types.d.ts +1 -1
- package/dist/init/types.js +1 -1
- package/dist/locale-set.d.ts.map +1 -1
- package/dist/locale-set.js +3 -6
- package/dist/locale-set.js.map +1 -1
- package/dist/template-paths.d.ts +19 -0
- package/dist/template-paths.d.ts.map +1 -0
- package/dist/template-paths.js +66 -0
- package/dist/template-paths.js.map +1 -0
- package/package.json +24 -9
- package/assets/autopilot-harness-hook.mjs +0 -446
- package/assets/vendor/migrations/001_initial.sql +0 -62
- package/assets/vendor/migrations/002_pending_followup.sql +0 -4
- package/assets/vendor/migrations/003_reviewing_item.sql +0 -1
- package/assets/vendor/runtime.mjs +0 -5907
|
@@ -1,446 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Autopilot hook entry — marker: autopilot-harness
|
|
3
|
-
* Installed at .autopilot/bin/autopilot-harness-hook.mjs (copy, not symlink).
|
|
4
|
-
*
|
|
5
|
-
* Prefers bundled vendor/runtime.mjs (shipped by init/upgrade) so empty
|
|
6
|
-
* consumer projects work without @autopilot-harness/* in node_modules.
|
|
7
|
-
* Falls back to project-local packages, then fail-open.
|
|
8
|
-
*
|
|
9
|
-
* Events:
|
|
10
|
-
* Cursor: beforeSubmitPrompt | afterFileEdit | stop
|
|
11
|
-
* Claude Code: UserPromptSubmit | PostToolUse | Stop | StopFailure
|
|
12
|
-
*/
|
|
13
|
-
import fs from "node:fs";
|
|
14
|
-
import path from "node:path";
|
|
15
|
-
import { createRequire } from "node:module";
|
|
16
|
-
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
17
|
-
|
|
18
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
19
|
-
const projectRoot = (() => {
|
|
20
|
-
const resolved = path.resolve(__dirname, "..", "..");
|
|
21
|
-
try {
|
|
22
|
-
return fs.realpathSync(resolved);
|
|
23
|
-
} catch {
|
|
24
|
-
return resolved;
|
|
25
|
-
}
|
|
26
|
-
})();
|
|
27
|
-
|
|
28
|
-
const CURSOR_EVENTS = new Set([
|
|
29
|
-
"beforeSubmitPrompt",
|
|
30
|
-
"afterFileEdit",
|
|
31
|
-
"stop",
|
|
32
|
-
]);
|
|
33
|
-
const CLAUDE_EVENTS = new Set([
|
|
34
|
-
"UserPromptSubmit",
|
|
35
|
-
"PostToolUse",
|
|
36
|
-
"Stop",
|
|
37
|
-
"StopFailure",
|
|
38
|
-
]);
|
|
39
|
-
const KNOWN_PLATFORMS = new Set(["cursor", "claude-code"]);
|
|
40
|
-
|
|
41
|
-
function parseArgs(argv) {
|
|
42
|
-
const allowed = new Set([...CURSOR_EVENTS, ...CLAUDE_EVENTS]);
|
|
43
|
-
const out = { event: "beforeSubmitPrompt", platform: null };
|
|
44
|
-
for (let i = 0; i < argv.length; i++) {
|
|
45
|
-
if (argv[i] === "--event" && argv[i + 1]) {
|
|
46
|
-
const ev = String(argv[i + 1]);
|
|
47
|
-
// Do not consume the next flag as a value (`--event --platform …`).
|
|
48
|
-
if (ev.startsWith("--")) continue;
|
|
49
|
-
i += 1;
|
|
50
|
-
out.event = allowed.has(ev) ? ev : "beforeSubmitPrompt";
|
|
51
|
-
} else if (argv[i] === "--platform" && argv[i + 1]) {
|
|
52
|
-
const raw = String(argv[i + 1]);
|
|
53
|
-
if (raw.startsWith("--")) continue;
|
|
54
|
-
i += 1;
|
|
55
|
-
const p = raw.trim().toLowerCase();
|
|
56
|
-
out.platform = KNOWN_PLATFORMS.has(p) ? p : null;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
return out;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function isClaudeEvent(event) {
|
|
63
|
-
return CLAUDE_EVENTS.has(event);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/** Strong Claude Stop markers (override a lying `--platform cursor`). */
|
|
67
|
-
function isClaudeShapedStopPayload(payload) {
|
|
68
|
-
if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
|
|
69
|
-
return false;
|
|
70
|
-
}
|
|
71
|
-
const hookName = String(
|
|
72
|
-
payload.hook_event_name ?? payload.hookEventName ?? "",
|
|
73
|
-
).trim();
|
|
74
|
-
if (hookName === "Stop" || /^stopfailure$/i.test(hookName)) return true;
|
|
75
|
-
if (
|
|
76
|
-
typeof payload.stop_hook_active === "boolean" ||
|
|
77
|
-
typeof payload.stopHookActive === "boolean"
|
|
78
|
-
) {
|
|
79
|
-
return true;
|
|
80
|
-
}
|
|
81
|
-
return false;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
async function readStdin() {
|
|
85
|
-
const chunks = [];
|
|
86
|
-
for await (const chunk of process.stdin) chunks.push(chunk);
|
|
87
|
-
const raw = Buffer.concat(chunks).toString("utf8").trim();
|
|
88
|
-
if (!raw) return {};
|
|
89
|
-
try {
|
|
90
|
-
return JSON.parse(raw);
|
|
91
|
-
} catch {
|
|
92
|
-
return {};
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
async function tryImport(specifier) {
|
|
97
|
-
try {
|
|
98
|
-
return await import(specifier);
|
|
99
|
-
} catch {
|
|
100
|
-
return null;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
function isSymlinkOrUnreadable(filePath) {
|
|
105
|
-
try {
|
|
106
|
-
return fs.lstatSync(filePath).isSymbolicLink();
|
|
107
|
-
} catch {
|
|
108
|
-
// Cannot verify — refuse vendor load (fail-closed, match CLI policy).
|
|
109
|
-
return true;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/** Refuse vendor paths whose realpath escapes the project root. */
|
|
114
|
-
function realpathEscapesProject(filePath) {
|
|
115
|
-
try {
|
|
116
|
-
const realRoot = fs.realpathSync(projectRoot);
|
|
117
|
-
const real = fs.realpathSync(filePath);
|
|
118
|
-
return real !== realRoot && !real.startsWith(realRoot + path.sep);
|
|
119
|
-
} catch {
|
|
120
|
-
return true;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
async function loadVendorRuntime() {
|
|
125
|
-
const vendorDir = path.join(__dirname, "vendor");
|
|
126
|
-
const vendor = path.join(vendorDir, "runtime.mjs");
|
|
127
|
-
const migDir = path.join(vendorDir, "migrations");
|
|
128
|
-
const mig = path.join(migDir, "001_initial.sql");
|
|
129
|
-
if (!fs.existsSync(vendor) || !fs.existsSync(mig)) return null;
|
|
130
|
-
// Refuse symlink escape / unreadable lstat (same policy as CLI).
|
|
131
|
-
if (
|
|
132
|
-
isSymlinkOrUnreadable(vendorDir) ||
|
|
133
|
-
isSymlinkOrUnreadable(vendor) ||
|
|
134
|
-
isSymlinkOrUnreadable(migDir) ||
|
|
135
|
-
isSymlinkOrUnreadable(mig)
|
|
136
|
-
) {
|
|
137
|
-
return null;
|
|
138
|
-
}
|
|
139
|
-
if (realpathEscapesProject(vendor) || realpathEscapesProject(mig)) {
|
|
140
|
-
return null;
|
|
141
|
-
}
|
|
142
|
-
return tryImport(pathToFileURL(vendor).href);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
async function loadPortPackage(pkgName) {
|
|
146
|
-
try {
|
|
147
|
-
const require = createRequire(path.join(projectRoot, "package.json"));
|
|
148
|
-
const resolved = require.resolve(pkgName);
|
|
149
|
-
return tryImport(pathToFileURL(resolved).href);
|
|
150
|
-
} catch {
|
|
151
|
-
return null;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
async function loadCoreFromNodeModules() {
|
|
156
|
-
return loadPortPackage("@autopilot-harness/core");
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* Fail-open shapes must match the host:
|
|
161
|
-
* - Cursor submit → { continue: true }
|
|
162
|
-
* - Claude UserPromptSubmit → {} (allow; no decision:block)
|
|
163
|
-
* - other events → {}
|
|
164
|
-
*/
|
|
165
|
-
function failOpen(event) {
|
|
166
|
-
if (event === "beforeSubmitPrompt") {
|
|
167
|
-
writeReply(JSON.stringify({ continue: true }));
|
|
168
|
-
} else {
|
|
169
|
-
writeReply("{}");
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
/** At-most-once stdout so fail-open cannot append a second JSON blob. */
|
|
174
|
-
let replied = false;
|
|
175
|
-
function writeReply(text) {
|
|
176
|
-
if (replied) return;
|
|
177
|
-
process.stdout.write(text);
|
|
178
|
-
// Set only after a successful write so failOpen can still retry on throw.
|
|
179
|
-
replied = true;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
function createEngine(coreMod, store) {
|
|
183
|
-
return typeof coreMod.createConfiguredReviewEngine === "function"
|
|
184
|
-
? coreMod.createConfiguredReviewEngine(store, projectRoot)
|
|
185
|
-
: new coreMod.ReviewEngine(store, {
|
|
186
|
-
confirmRounds: 5,
|
|
187
|
-
reviewScope: "executing_only",
|
|
188
|
-
verifyEnabled: false,
|
|
189
|
-
verifyCommands: [],
|
|
190
|
-
maxIdleStops: 5,
|
|
191
|
-
maxErrorsBeforePause: 0,
|
|
192
|
-
projectRoot,
|
|
193
|
-
});
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
function cursorStopHandler(port) {
|
|
197
|
-
if (typeof port.handleCursorStop === "function") {
|
|
198
|
-
return port.handleCursorStop;
|
|
199
|
-
}
|
|
200
|
-
// Dual/legacy vendor: deprecated handleStop === Cursor only when Cursor
|
|
201
|
-
// submit exists. Never fall through to Claude-only package handleStop.
|
|
202
|
-
if (
|
|
203
|
-
typeof port.handleStop === "function" &&
|
|
204
|
-
typeof port.handleBeforeSubmitPrompt === "function"
|
|
205
|
-
) {
|
|
206
|
-
return port.handleStop;
|
|
207
|
-
}
|
|
208
|
-
return undefined;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
/**
|
|
212
|
-
* Resolve Claude Stop handler without falling through to Cursor's handleStop
|
|
213
|
-
* on the dual-port vendor (where deprecated `handleStop` === handleCursorStop).
|
|
214
|
-
* node_modules `@autopilot-harness/port-claude-code` exports Claude as handleStop
|
|
215
|
-
* and has no Cursor submit handler.
|
|
216
|
-
*/
|
|
217
|
-
function claudeStopHandler(port) {
|
|
218
|
-
if (typeof port.handleClaudeStop === "function") {
|
|
219
|
-
return port.handleClaudeStop;
|
|
220
|
-
}
|
|
221
|
-
if (
|
|
222
|
-
typeof port.handleStop === "function" &&
|
|
223
|
-
typeof port.handleBeforeSubmitPrompt !== "function"
|
|
224
|
-
) {
|
|
225
|
-
return port.handleStop;
|
|
226
|
-
}
|
|
227
|
-
return undefined;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
* Cursor IDE may also execute `.claude/settings.json` Stop hooks ("claude-project
|
|
232
|
-
* config") on the same user Stop. Those payloads are Cursor-shaped (`status`,
|
|
233
|
-
* lowercase `hook_event_name: "stop"`). Route them to the Cursor port so abort
|
|
234
|
-
* halts instead of Claude recover (decision:block), which Cursor merges back
|
|
235
|
-
* into followup and fights the real abort path.
|
|
236
|
-
*
|
|
237
|
-
* Heuristic (order matters):
|
|
238
|
-
* 1) Explicit Claude hook names (`Stop` / `StopFailure`) → not Cursor
|
|
239
|
-
* 2) Lowercase `stop` → Cursor
|
|
240
|
-
* 3) `stop_hook_active` present (Claude continuum) → not Cursor
|
|
241
|
-
* 4) Cursor status vocab + `conversation_id` → Cursor; bare `session_id` → Claude
|
|
242
|
-
*/
|
|
243
|
-
function isCursorShapedStopPayload(payload) {
|
|
244
|
-
if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
|
|
245
|
-
return false;
|
|
246
|
-
}
|
|
247
|
-
const hookName = String(
|
|
248
|
-
payload.hook_event_name ?? payload.hookEventName ?? "",
|
|
249
|
-
).trim();
|
|
250
|
-
if (hookName === "Stop" || /^stopfailure$/i.test(hookName)) return false;
|
|
251
|
-
if (hookName === "stop") return true;
|
|
252
|
-
|
|
253
|
-
// Claude Stop threads stop_hook_active (bool); Cursor uses loop_count.
|
|
254
|
-
if (
|
|
255
|
-
typeof payload.stop_hook_active === "boolean" ||
|
|
256
|
-
typeof payload.stopHookActive === "boolean"
|
|
257
|
-
) {
|
|
258
|
-
return false;
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
const statusRaw = String(payload.status ?? "")
|
|
262
|
-
.toLowerCase()
|
|
263
|
-
.trim();
|
|
264
|
-
const cursorStatus =
|
|
265
|
-
statusRaw === "aborted" ||
|
|
266
|
-
statusRaw === "cancelled" ||
|
|
267
|
-
statusRaw === "canceled" ||
|
|
268
|
-
statusRaw === "completed" ||
|
|
269
|
-
statusRaw === "error" ||
|
|
270
|
-
statusRaw === "failed";
|
|
271
|
-
if (!cursorStatus) return false;
|
|
272
|
-
|
|
273
|
-
const conversationId = String(
|
|
274
|
-
payload.conversation_id ?? payload.conversationId ?? "",
|
|
275
|
-
).trim();
|
|
276
|
-
if (conversationId) return true;
|
|
277
|
-
|
|
278
|
-
const sessionId = String(
|
|
279
|
-
payload.session_id ?? payload.sessionId ?? "",
|
|
280
|
-
).trim();
|
|
281
|
-
// Claude-shaped id without conversation_id → keep Claude path
|
|
282
|
-
if (sessionId) return false;
|
|
283
|
-
|
|
284
|
-
// Abort/cancel with no ids: prefer Cursor halt (no-op {}) over Claude recover
|
|
285
|
-
return (
|
|
286
|
-
statusRaw === "aborted" ||
|
|
287
|
-
statusRaw === "cancelled" ||
|
|
288
|
-
statusRaw === "canceled"
|
|
289
|
-
);
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
let bootEvent = "beforeSubmitPrompt";
|
|
293
|
-
|
|
294
|
-
async function main() {
|
|
295
|
-
const { event, platform: declaredPlatform } = parseArgs(
|
|
296
|
-
process.argv.slice(2),
|
|
297
|
-
);
|
|
298
|
-
bootEvent = event;
|
|
299
|
-
try {
|
|
300
|
-
const payload = await readStdin();
|
|
301
|
-
// Layer A: --platform; fall back to event-name heuristics for legacy installs.
|
|
302
|
-
const preferClaudePort =
|
|
303
|
-
declaredPlatform === "claude-code"
|
|
304
|
-
? true
|
|
305
|
-
: declaredPlatform === "cursor"
|
|
306
|
-
? false
|
|
307
|
-
: isClaudeEvent(event);
|
|
308
|
-
const claude = preferClaudePort;
|
|
309
|
-
|
|
310
|
-
const vendor = await loadVendorRuntime();
|
|
311
|
-
const port = vendor
|
|
312
|
-
? vendor
|
|
313
|
-
: claude
|
|
314
|
-
? await loadPortPackage("@autopilot-harness/port-claude-code")
|
|
315
|
-
: await loadPortPackage("@autopilot-harness/port-cursor");
|
|
316
|
-
const coreMod = vendor ?? (await loadCoreFromNodeModules());
|
|
317
|
-
|
|
318
|
-
const portReady = claude
|
|
319
|
-
? typeof port?.handleUserPromptSubmit === "function"
|
|
320
|
-
: typeof port?.handleBeforeSubmitPrompt === "function";
|
|
321
|
-
if (!portReady || !coreMod?.StateStore) {
|
|
322
|
-
failOpen(event);
|
|
323
|
-
return;
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
const store = new coreMod.StateStore(projectRoot);
|
|
327
|
-
try {
|
|
328
|
-
if (event === "beforeSubmitPrompt") {
|
|
329
|
-
const result = port.handleBeforeSubmitPrompt(
|
|
330
|
-
store,
|
|
331
|
-
payload,
|
|
332
|
-
projectRoot,
|
|
333
|
-
);
|
|
334
|
-
writeReply(JSON.stringify(result ?? {}));
|
|
335
|
-
return;
|
|
336
|
-
}
|
|
337
|
-
if (event === "afterFileEdit") {
|
|
338
|
-
port.handleAfterFileEdit?.(store, payload, projectRoot);
|
|
339
|
-
writeReply("{}");
|
|
340
|
-
return;
|
|
341
|
-
}
|
|
342
|
-
if (event === "stop") {
|
|
343
|
-
const stopFn = cursorStopHandler(port);
|
|
344
|
-
if (typeof stopFn !== "function") {
|
|
345
|
-
failOpen(event);
|
|
346
|
-
return;
|
|
347
|
-
}
|
|
348
|
-
const result = stopFn(createEngine(coreMod, store), payload);
|
|
349
|
-
writeReply(JSON.stringify(result ?? {}));
|
|
350
|
-
return;
|
|
351
|
-
}
|
|
352
|
-
if (event === "UserPromptSubmit") {
|
|
353
|
-
const result = port.handleUserPromptSubmit(
|
|
354
|
-
store,
|
|
355
|
-
payload,
|
|
356
|
-
projectRoot,
|
|
357
|
-
);
|
|
358
|
-
writeReply(JSON.stringify(result ?? {}));
|
|
359
|
-
return;
|
|
360
|
-
}
|
|
361
|
-
if (event === "PostToolUse") {
|
|
362
|
-
port.handlePostToolUse?.(store, payload, projectRoot);
|
|
363
|
-
writeReply("{}");
|
|
364
|
-
return;
|
|
365
|
-
}
|
|
366
|
-
if (event === "Stop") {
|
|
367
|
-
// Layer C: payload shape vs declared --platform (cross-fire / lying argv).
|
|
368
|
-
let useCursorStop = false;
|
|
369
|
-
if (isCursorShapedStopPayload(payload)) {
|
|
370
|
-
useCursorStop = true;
|
|
371
|
-
} else if (isClaudeShapedStopPayload(payload)) {
|
|
372
|
-
useCursorStop = false;
|
|
373
|
-
} else if (declaredPlatform === "cursor") {
|
|
374
|
-
useCursorStop = true;
|
|
375
|
-
} else {
|
|
376
|
-
useCursorStop = false;
|
|
377
|
-
}
|
|
378
|
-
if (useCursorStop) {
|
|
379
|
-
let stopFn = cursorStopHandler(port);
|
|
380
|
-
// Non-vendor Claude-only load + Cursor-shaped cross-fire needs Cursor port.
|
|
381
|
-
if (typeof stopFn !== "function") {
|
|
382
|
-
const cursorPort = await loadPortPackage(
|
|
383
|
-
"@autopilot-harness/port-cursor",
|
|
384
|
-
);
|
|
385
|
-
if (cursorPort) stopFn = cursorStopHandler(cursorPort);
|
|
386
|
-
}
|
|
387
|
-
if (typeof stopFn !== "function") {
|
|
388
|
-
failOpen(event);
|
|
389
|
-
return;
|
|
390
|
-
}
|
|
391
|
-
const result = stopFn(createEngine(coreMod, store), payload);
|
|
392
|
-
writeReply(JSON.stringify(result ?? {}));
|
|
393
|
-
return;
|
|
394
|
-
}
|
|
395
|
-
let stopFn = claudeStopHandler(port);
|
|
396
|
-
// Non-vendor Cursor-only load + Claude-shaped Stop needs Claude port.
|
|
397
|
-
if (typeof stopFn !== "function") {
|
|
398
|
-
const claudePort = await loadPortPackage(
|
|
399
|
-
"@autopilot-harness/port-claude-code",
|
|
400
|
-
);
|
|
401
|
-
if (claudePort) stopFn = claudeStopHandler(claudePort);
|
|
402
|
-
}
|
|
403
|
-
if (typeof stopFn !== "function") {
|
|
404
|
-
failOpen(event);
|
|
405
|
-
return;
|
|
406
|
-
}
|
|
407
|
-
const result = stopFn(createEngine(coreMod, store), payload);
|
|
408
|
-
writeReply(JSON.stringify(result ?? {}));
|
|
409
|
-
return;
|
|
410
|
-
}
|
|
411
|
-
if (event === "StopFailure") {
|
|
412
|
-
let failFn = port.handleStopFailure;
|
|
413
|
-
if (typeof failFn !== "function") {
|
|
414
|
-
const stopFn = claudeStopHandler(port);
|
|
415
|
-
if (typeof stopFn === "function") {
|
|
416
|
-
failFn = (engine, p) => stopFn(engine, p, { status: "error" });
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
if (typeof failFn !== "function") {
|
|
420
|
-
failOpen(event);
|
|
421
|
-
return;
|
|
422
|
-
}
|
|
423
|
-
const result = failFn(createEngine(coreMod, store), payload);
|
|
424
|
-
writeReply(JSON.stringify(result ?? {}));
|
|
425
|
-
return;
|
|
426
|
-
}
|
|
427
|
-
writeReply("{}");
|
|
428
|
-
} finally {
|
|
429
|
-
try {
|
|
430
|
-
store.close();
|
|
431
|
-
} catch {
|
|
432
|
-
/* ignore */
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
} catch (err) {
|
|
436
|
-
console.error("[autopilot-harness] hook error:", err?.message ?? err);
|
|
437
|
-
failOpen(event);
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
main().catch((err) => {
|
|
442
|
-
console.error("[autopilot-harness] hook error:", err?.message ?? err);
|
|
443
|
-
// Prefer the parsed event when main() assigned it; else Cursor-safe default.
|
|
444
|
-
failOpen(bootEvent);
|
|
445
|
-
process.exitCode = 0;
|
|
446
|
-
});
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
CREATE TABLE IF NOT EXISTS _schema_meta (
|
|
2
|
-
key TEXT PRIMARY KEY,
|
|
3
|
-
value TEXT NOT NULL
|
|
4
|
-
);
|
|
5
|
-
|
|
6
|
-
CREATE TABLE IF NOT EXISTS workspace (
|
|
7
|
-
root_path TEXT PRIMARY KEY,
|
|
8
|
-
token_hash TEXT,
|
|
9
|
-
platform TEXT NOT NULL,
|
|
10
|
-
surface TEXT NOT NULL DEFAULT 'ide',
|
|
11
|
-
integration TEXT NOT NULL DEFAULT 'hook',
|
|
12
|
-
locale TEXT NOT NULL DEFAULT 'en',
|
|
13
|
-
created_at TEXT NOT NULL
|
|
14
|
-
);
|
|
15
|
-
|
|
16
|
-
CREATE TABLE IF NOT EXISTS sessions (
|
|
17
|
-
conversation_id TEXT PRIMARY KEY,
|
|
18
|
-
platform TEXT NOT NULL,
|
|
19
|
-
session_title TEXT,
|
|
20
|
-
session_title_source TEXT,
|
|
21
|
-
title_updated_at TEXT,
|
|
22
|
-
track_id TEXT NOT NULL DEFAULT '_pending',
|
|
23
|
-
track_title TEXT,
|
|
24
|
-
checklist_path TEXT NOT NULL DEFAULT '',
|
|
25
|
-
phase TEXT NOT NULL DEFAULT 'idle',
|
|
26
|
-
armed INTEGER NOT NULL DEFAULT 0,
|
|
27
|
-
paused INTEGER NOT NULL DEFAULT 0,
|
|
28
|
-
paused_reason TEXT,
|
|
29
|
-
pending_action TEXT,
|
|
30
|
-
track_candidates_json TEXT,
|
|
31
|
-
project_root TEXT NOT NULL,
|
|
32
|
-
code_root TEXT NOT NULL,
|
|
33
|
-
worktree_path TEXT,
|
|
34
|
-
worktree_branch TEXT,
|
|
35
|
-
error_count INTEGER NOT NULL DEFAULT 0,
|
|
36
|
-
last_error TEXT,
|
|
37
|
-
idle_stop_count INTEGER NOT NULL DEFAULT 0,
|
|
38
|
-
cli_bound_at TEXT,
|
|
39
|
-
last_active_at TEXT NOT NULL,
|
|
40
|
-
updated_at TEXT NOT NULL
|
|
41
|
-
);
|
|
42
|
-
|
|
43
|
-
CREATE TABLE IF NOT EXISTS tracks (
|
|
44
|
-
track_id TEXT PRIMARY KEY,
|
|
45
|
-
slug TEXT NOT NULL,
|
|
46
|
-
checklist_path TEXT NOT NULL,
|
|
47
|
-
plan_path TEXT,
|
|
48
|
-
brief_path TEXT,
|
|
49
|
-
updated_at TEXT NOT NULL
|
|
50
|
-
);
|
|
51
|
-
|
|
52
|
-
CREATE TABLE IF NOT EXISTS review_chains (
|
|
53
|
-
conversation_id TEXT PRIMARY KEY,
|
|
54
|
-
fix_round INTEGER NOT NULL DEFAULT 0,
|
|
55
|
-
confirm_left INTEGER,
|
|
56
|
-
chain_pending INTEGER NOT NULL DEFAULT 0,
|
|
57
|
-
code_edited INTEGER NOT NULL DEFAULT 0,
|
|
58
|
-
item_confirm_complete INTEGER NOT NULL DEFAULT 0,
|
|
59
|
-
updated_at TEXT NOT NULL
|
|
60
|
-
);
|
|
61
|
-
|
|
62
|
-
INSERT OR IGNORE INTO _schema_meta (key, value) VALUES ('schema_version', '1');
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
ALTER TABLE review_chains ADD COLUMN reviewing_item_id TEXT;
|