@autopilot-harness/cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +55 -0
- package/assets/autopilot-harness-hook.mjs +193 -0
- package/assets/vendor/migrations/001_initial.sql +62 -0
- package/assets/vendor/migrations/002_pending_followup.sql +4 -0
- package/assets/vendor/migrations/003_reviewing_item.sql +1 -0
- package/assets/vendor/runtime.mjs +5524 -0
- package/dist/assets/autopilot-harness-hook.mjs +193 -0
- package/dist/assets/vendor/migrations/001_initial.sql +62 -0
- package/dist/assets/vendor/migrations/002_pending_followup.sql +4 -0
- package/dist/assets/vendor/migrations/003_reviewing_item.sql +1 -0
- package/dist/assets/vendor/runtime.mjs +5524 -0
- package/dist/bin.d.ts +3 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +300 -0
- package/dist/bin.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/init/config-merge.d.ts +27 -0
- package/dist/init/config-merge.d.ts.map +1 -0
- package/dist/init/config-merge.js +115 -0
- package/dist/init/config-merge.js.map +1 -0
- package/dist/init/default-config.d.ts +17 -0
- package/dist/init/default-config.d.ts.map +1 -0
- package/dist/init/default-config.js +101 -0
- package/dist/init/default-config.js.map +1 -0
- package/dist/init/hooks-merge.d.ts +25 -0
- package/dist/init/hooks-merge.d.ts.map +1 -0
- package/dist/init/hooks-merge.js +134 -0
- package/dist/init/hooks-merge.js.map +1 -0
- package/dist/init/install.d.ts +31 -0
- package/dist/init/install.d.ts.map +1 -0
- package/dist/init/install.js +829 -0
- package/dist/init/install.js.map +1 -0
- package/dist/init/platforms.d.ts +60 -0
- package/dist/init/platforms.d.ts.map +1 -0
- package/dist/init/platforms.js +275 -0
- package/dist/init/platforms.js.map +1 -0
- package/dist/init/tui.d.ts +65 -0
- package/dist/init/tui.d.ts.map +1 -0
- package/dist/init/tui.js +549 -0
- package/dist/init/tui.js.map +1 -0
- package/dist/init/types.d.ts +75 -0
- package/dist/init/types.d.ts.map +1 -0
- package/dist/init/types.js +9 -0
- package/dist/init/types.js.map +1 -0
- package/dist/init/wizard-copy.d.ts +74 -0
- package/dist/init/wizard-copy.d.ts.map +1 -0
- package/dist/init/wizard-copy.js +173 -0
- package/dist/init/wizard-copy.js.map +1 -0
- package/dist/init/wizard-helpers.d.ts +103 -0
- package/dist/init/wizard-helpers.d.ts.map +1 -0
- package/dist/init/wizard-helpers.js +724 -0
- package/dist/init/wizard-helpers.js.map +1 -0
- package/dist/locale-set.d.ts +24 -0
- package/dist/locale-set.d.ts.map +1 -0
- package/dist/locale-set.js +286 -0
- package/dist/locale-set.js.map +1 -0
- package/dist/names.d.ts +5 -0
- package/dist/names.d.ts.map +1 -0
- package/dist/names.js +5 -0
- package/dist/names.js.map +1 -0
- package/dist/project-fs.d.ts +48 -0
- package/dist/project-fs.d.ts.map +1 -0
- package/dist/project-fs.js +210 -0
- package/dist/project-fs.js.map +1 -0
- package/dist/read-untrusted-file.d.ts +41 -0
- package/dist/read-untrusted-file.d.ts.map +1 -0
- package/dist/read-untrusted-file.js +362 -0
- package/dist/read-untrusted-file.js.map +1 -0
- package/dist/session.d.ts +38 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +242 -0
- package/dist/session.js.map +1 -0
- package/dist/status-doctor.d.ts +22 -0
- package/dist/status-doctor.d.ts.map +1 -0
- package/dist/status-doctor.js +712 -0
- package/dist/status-doctor.js.map +1 -0
- package/dist/uninstall.d.ts +31 -0
- package/dist/uninstall.d.ts.map +1 -0
- package/dist/uninstall.js +333 -0
- package/dist/uninstall.js.map +1 -0
- package/dist/upgrade.d.ts +29 -0
- package/dist/upgrade.d.ts.map +1 -0
- package/dist/upgrade.js +290 -0
- package/dist/upgrade.js.map +1 -0
- package/dist/vendor-entry.d.ts +6 -0
- package/dist/vendor-entry.d.ts.map +1 -0
- package/dist/vendor-entry.js +16 -0
- package/dist/vendor-entry.js.map +1 -0
- package/package.json +54 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { stockTriggers } from "@autopilot-harness/i18n";
|
|
2
|
+
import { mergePlatformBindings, mergedIncludesAllRequested, normalizeBinding, primaryBinding, MAX_PLATFORM_BINDINGS, } from "./platforms.js";
|
|
3
|
+
import { normalizePlansDir } from "./wizard-helpers.js";
|
|
4
|
+
function resolveConfigPlatforms(opts) {
|
|
5
|
+
if (opts.platforms && opts.platforms.length > 0) {
|
|
6
|
+
const list = mergePlatformBindings([], opts.platforms);
|
|
7
|
+
if (!mergedIncludesAllRequested(list, opts.platforms)) {
|
|
8
|
+
throw new Error(`platforms list exceeds cap of ${MAX_PLATFORM_BINDINGS} unique entries; trim the list and retry`);
|
|
9
|
+
}
|
|
10
|
+
return list;
|
|
11
|
+
}
|
|
12
|
+
const b = normalizeBinding(opts.platform ?? "cursor", opts.surface ?? "ide");
|
|
13
|
+
return b ? [b] : [{ id: "cursor", surface: "ide" }];
|
|
14
|
+
}
|
|
15
|
+
function formatPlatformsYamlBlock(platforms) {
|
|
16
|
+
const lines = ["platforms:"];
|
|
17
|
+
for (const b of platforms) {
|
|
18
|
+
lines.push(` - id: ${b.id}`);
|
|
19
|
+
lines.push(` surface: ${b.surface}`);
|
|
20
|
+
}
|
|
21
|
+
return lines.join("\n");
|
|
22
|
+
}
|
|
23
|
+
/** Default `.autopilot/config.yml` body for init (v0.1). */
|
|
24
|
+
export function defaultConfigYaml(opts) {
|
|
25
|
+
const plansNorm = normalizePlansDir(opts.plansDir);
|
|
26
|
+
const plansDir = plansNorm.ok ? plansNorm.value : "plans";
|
|
27
|
+
const verifyEnabled = Boolean(opts.verifyEnabled);
|
|
28
|
+
const maxErrors = typeof opts.maxErrorsBeforePause === "number" &&
|
|
29
|
+
Number.isInteger(opts.maxErrorsBeforePause) &&
|
|
30
|
+
opts.maxErrorsBeforePause >= 0
|
|
31
|
+
? opts.maxErrorsBeforePause
|
|
32
|
+
: 0;
|
|
33
|
+
const platforms = resolveConfigPlatforms(opts);
|
|
34
|
+
const primary = primaryBinding(platforms);
|
|
35
|
+
const triggers = stockTriggers(opts.locale);
|
|
36
|
+
const on = JSON.stringify(triggers.on);
|
|
37
|
+
const run = JSON.stringify(triggers.run);
|
|
38
|
+
const off = JSON.stringify(triggers.off);
|
|
39
|
+
const resume = JSON.stringify(triggers.resume);
|
|
40
|
+
const replan = JSON.stringify(triggers.replan);
|
|
41
|
+
const resumeReview = JSON.stringify(triggers.resume_review);
|
|
42
|
+
return `# Autopilot Harness — project config (init defaults)
|
|
43
|
+
# Enabled hosts (id + surface). surface: ide | cli | runner
|
|
44
|
+
${formatPlatformsYamlBlock(platforms)}
|
|
45
|
+
# Primary host (installable preferred) — kept for older readers
|
|
46
|
+
platform: ${primary.id}
|
|
47
|
+
surface: ${primary.surface}
|
|
48
|
+
integration: hook
|
|
49
|
+
locale: ${opts.locale}
|
|
50
|
+
|
|
51
|
+
artifacts:
|
|
52
|
+
plans_dir: ${plansDir}
|
|
53
|
+
files:
|
|
54
|
+
brief: brief.md
|
|
55
|
+
plan: plan.md
|
|
56
|
+
checklist: checklist.md
|
|
57
|
+
|
|
58
|
+
cli:
|
|
59
|
+
preferred_name: Autopilot
|
|
60
|
+
|
|
61
|
+
session:
|
|
62
|
+
stale_after_hours: 72
|
|
63
|
+
|
|
64
|
+
concurrency:
|
|
65
|
+
mode: one_executor
|
|
66
|
+
worktree: false
|
|
67
|
+
worktrees_dir: .autopilot/worktrees
|
|
68
|
+
|
|
69
|
+
review:
|
|
70
|
+
# executing_only = self-review only after Autopilot RUN; project = any product-code edit
|
|
71
|
+
scope: ${opts.reviewScope ?? "executing_only"}
|
|
72
|
+
# 5 = full lenses; 3 = light mode (lenses 1→2→5 only)
|
|
73
|
+
confirm_rounds: 5
|
|
74
|
+
verify:
|
|
75
|
+
enabled: ${verifyEnabled}
|
|
76
|
+
# When enabled, Agent runs these and writes .autopilot/verify-last.json:
|
|
77
|
+
# commands:
|
|
78
|
+
# - id: test
|
|
79
|
+
# run: "pnpm test"
|
|
80
|
+
# required: true
|
|
81
|
+
stuck:
|
|
82
|
+
max_idle_stops: 5
|
|
83
|
+
errors:
|
|
84
|
+
# Consecutive turn errors/aborts before pause (repeated_errors).
|
|
85
|
+
# 0 = never pause (unlimited recoveries); e.g. 5 = pause after 5.
|
|
86
|
+
max_before_pause: ${maxErrors}
|
|
87
|
+
|
|
88
|
+
triggers:
|
|
89
|
+
match: line_start
|
|
90
|
+
on: ${on}
|
|
91
|
+
run: ${run}
|
|
92
|
+
off: ${off}
|
|
93
|
+
resume: ${resume}
|
|
94
|
+
replan: ${replan}
|
|
95
|
+
resume_review: ${resumeReview}
|
|
96
|
+
|
|
97
|
+
security:
|
|
98
|
+
require_token: false
|
|
99
|
+
`;
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=default-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"default-config.js","sourceRoot":"","sources":["../../src/init/default-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { HookCommand, HooksFile } from "./types.js";
|
|
2
|
+
export declare function autopilotHookCommand(event: string): HookCommand;
|
|
3
|
+
/** True when project Autopilot stop entry disables Cursor's default loop cap. */
|
|
4
|
+
export declare function autopilotStopHasUnlimitedLoop(hooks: HooksFile): boolean;
|
|
5
|
+
/** True when a hook command belongs to Autopilot (merge/strip/uninstall). */
|
|
6
|
+
export declare function isAutopilotCommand(cmd: string | undefined): boolean;
|
|
7
|
+
/** Ensure hooks.json shape is merge-safe; otherwise refuse (do not wipe). */
|
|
8
|
+
export declare function validateHooksShape(hooks: HooksFile): string | null;
|
|
9
|
+
/** Merge Autopilot hook entries into an existing or empty hooks.json. */
|
|
10
|
+
export declare function mergeHooksJson(existing: HooksFile | null): HooksFile;
|
|
11
|
+
/**
|
|
12
|
+
* Remove Autopilot hook entries from every event list; keep foreign hooks.
|
|
13
|
+
* Does not delete the hooks.json file — caller decides write/unlink.
|
|
14
|
+
*/
|
|
15
|
+
export declare function stripAutopilotHooks(existing: HooksFile): HooksFile;
|
|
16
|
+
/** Counts of Autopilot commands per required event. */
|
|
17
|
+
export declare function summarizeAutopilotHooks(hooks: HooksFile): {
|
|
18
|
+
missingEvents: string[];
|
|
19
|
+
duplicates: number;
|
|
20
|
+
};
|
|
21
|
+
/** True when each Autopilot event has exactly one Autopilot command. */
|
|
22
|
+
export declare function hasCompleteAutopilotHooks(hooks: HooksFile): boolean;
|
|
23
|
+
/** Count duplicate Autopilot commands per event (doctor WARN). */
|
|
24
|
+
export declare function countAutopilotDuplicates(hooks: HooksFile): number;
|
|
25
|
+
//# sourceMappingURL=hooks-merge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks-merge.d.ts","sourceRoot":"","sources":["../../src/init/hooks-merge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAGzD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAY/D;AAED,iFAAiF;AACjF,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAWvE;AAED,6EAA6E;AAC7E,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAInE;AAQD,6EAA6E;AAC7E,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,GAAG,IAAI,CA0BlE;AAED,yEAAyE;AACzE,wBAAgB,cAAc,CAAC,QAAQ,EAAE,SAAS,GAAG,IAAI,GAAG,SAAS,CAwBpE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,SAAS,GAAG,SAAS,CAelE;AAED,uDAAuD;AACvD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,SAAS,GAAG;IACzD,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;CACpB,CAgBA;AAED,wEAAwE;AACxE,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAGnE;AAED,kEAAkE;AAClE,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAEjE"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { AUTOPILOT_EVENTS } from "./types.js";
|
|
2
|
+
export function autopilotHookCommand(event) {
|
|
3
|
+
const base = {
|
|
4
|
+
command: `node .autopilot/bin/autopilot-harness-hook.mjs --event ${event}`,
|
|
5
|
+
};
|
|
6
|
+
// Cursor defaults loop_limit to 5 for stop hooks that omit the field.
|
|
7
|
+
// Autopilot's fix + multi-angle confirm chain routinely exceeds 5
|
|
8
|
+
// auto-followups in one streak; without null the stop hook is skipped
|
|
9
|
+
// mid-chain (e.g. after confirm 3/5) and pending_followup stalls.
|
|
10
|
+
if (event === "stop") {
|
|
11
|
+
return { ...base, loop_limit: null };
|
|
12
|
+
}
|
|
13
|
+
return base;
|
|
14
|
+
}
|
|
15
|
+
/** True when project Autopilot stop entry disables Cursor's default loop cap. */
|
|
16
|
+
export function autopilotStopHasUnlimitedLoop(hooks) {
|
|
17
|
+
const stops = hooks.hooks?.stop;
|
|
18
|
+
if (!Array.isArray(stops))
|
|
19
|
+
return false;
|
|
20
|
+
return stops.some((h) => {
|
|
21
|
+
if (!h || typeof h !== "object" || Array.isArray(h))
|
|
22
|
+
return false;
|
|
23
|
+
return (isAutopilotCommand(h.command) &&
|
|
24
|
+
Object.prototype.hasOwnProperty.call(h, "loop_limit") &&
|
|
25
|
+
h.loop_limit === null);
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
/** True when a hook command belongs to Autopilot (merge/strip/uninstall). */
|
|
29
|
+
export function isAutopilotCommand(cmd) {
|
|
30
|
+
return (typeof cmd === "string" && cmd.includes("autopilot-harness-hook.mjs"));
|
|
31
|
+
}
|
|
32
|
+
/** Collapse controls before reflecting untrusted hooks keys into CLI errors. */
|
|
33
|
+
function safeHooksKeyLabel(key) {
|
|
34
|
+
const cleaned = key.replace(/[\u0000-\u001f\u007f]+/g, " ").replace(/ +/g, " ").trim();
|
|
35
|
+
return cleaned || "?";
|
|
36
|
+
}
|
|
37
|
+
/** Ensure hooks.json shape is merge-safe; otherwise refuse (do not wipe). */
|
|
38
|
+
export function validateHooksShape(hooks) {
|
|
39
|
+
if (Array.isArray(hooks.hooks)) {
|
|
40
|
+
return 'hooks.json "hooks" must be an object, not an array.';
|
|
41
|
+
}
|
|
42
|
+
if (!hooks.hooks || typeof hooks.hooks !== "object") {
|
|
43
|
+
return 'hooks.json "hooks" must be an object.';
|
|
44
|
+
}
|
|
45
|
+
for (const [key, value] of Object.entries(hooks.hooks)) {
|
|
46
|
+
const label = safeHooksKeyLabel(key);
|
|
47
|
+
if (value == null)
|
|
48
|
+
continue;
|
|
49
|
+
if (!Array.isArray(value)) {
|
|
50
|
+
return `hooks.json hooks.${label} must be an array of { command } entries.`;
|
|
51
|
+
}
|
|
52
|
+
for (const entry of value) {
|
|
53
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
|
|
54
|
+
return `hooks.json hooks.${label} contains a non-object entry.`;
|
|
55
|
+
}
|
|
56
|
+
if (entry.command != null &&
|
|
57
|
+
typeof entry.command !== "string") {
|
|
58
|
+
return `hooks.json hooks.${label} has a non-string command.`;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
/** Merge Autopilot hook entries into an existing or empty hooks.json. */
|
|
65
|
+
export function mergeHooksJson(existing) {
|
|
66
|
+
const base = existing && typeof existing === "object"
|
|
67
|
+
? {
|
|
68
|
+
version: existing.version ?? 1,
|
|
69
|
+
hooks: { ...(existing.hooks ?? {}) },
|
|
70
|
+
}
|
|
71
|
+
: { version: 1, hooks: {} };
|
|
72
|
+
const shapeError = validateHooksShape(base);
|
|
73
|
+
if (shapeError) {
|
|
74
|
+
throw new Error(shapeError);
|
|
75
|
+
}
|
|
76
|
+
for (const event of AUTOPILOT_EVENTS) {
|
|
77
|
+
const current = Array.isArray(base.hooks[event])
|
|
78
|
+
? [...base.hooks[event]]
|
|
79
|
+
: [];
|
|
80
|
+
const kept = current.filter((h) => !isAutopilotCommand(h?.command));
|
|
81
|
+
kept.push(autopilotHookCommand(event));
|
|
82
|
+
base.hooks[event] = kept;
|
|
83
|
+
}
|
|
84
|
+
return base;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Remove Autopilot hook entries from every event list; keep foreign hooks.
|
|
88
|
+
* Does not delete the hooks.json file — caller decides write/unlink.
|
|
89
|
+
*/
|
|
90
|
+
export function stripAutopilotHooks(existing) {
|
|
91
|
+
const base = {
|
|
92
|
+
version: existing.version ?? 1,
|
|
93
|
+
hooks: { ...(existing.hooks ?? {}) },
|
|
94
|
+
};
|
|
95
|
+
const shapeError = validateHooksShape(base);
|
|
96
|
+
if (shapeError) {
|
|
97
|
+
throw new Error(shapeError);
|
|
98
|
+
}
|
|
99
|
+
for (const [event, value] of Object.entries(base.hooks)) {
|
|
100
|
+
if (!Array.isArray(value))
|
|
101
|
+
continue;
|
|
102
|
+
base.hooks[event] = value.filter((h) => !isAutopilotCommand(h?.command));
|
|
103
|
+
}
|
|
104
|
+
return base;
|
|
105
|
+
}
|
|
106
|
+
/** Counts of Autopilot commands per required event. */
|
|
107
|
+
export function summarizeAutopilotHooks(hooks) {
|
|
108
|
+
const bag = hooks.hooks && typeof hooks.hooks === "object" && !Array.isArray(hooks.hooks)
|
|
109
|
+
? hooks.hooks
|
|
110
|
+
: {};
|
|
111
|
+
const missingEvents = [];
|
|
112
|
+
let duplicates = 0;
|
|
113
|
+
for (const event of AUTOPILOT_EVENTS) {
|
|
114
|
+
const list = Array.isArray(bag[event])
|
|
115
|
+
? bag[event]
|
|
116
|
+
: [];
|
|
117
|
+
const n = list.filter((h) => isAutopilotCommand(h?.command)).length;
|
|
118
|
+
if (n === 0)
|
|
119
|
+
missingEvents.push(event);
|
|
120
|
+
if (n > 1)
|
|
121
|
+
duplicates += n - 1;
|
|
122
|
+
}
|
|
123
|
+
return { missingEvents, duplicates };
|
|
124
|
+
}
|
|
125
|
+
/** True when each Autopilot event has exactly one Autopilot command. */
|
|
126
|
+
export function hasCompleteAutopilotHooks(hooks) {
|
|
127
|
+
const { missingEvents, duplicates } = summarizeAutopilotHooks(hooks);
|
|
128
|
+
return missingEvents.length === 0 && duplicates === 0;
|
|
129
|
+
}
|
|
130
|
+
/** Count duplicate Autopilot commands per event (doctor WARN). */
|
|
131
|
+
export function countAutopilotDuplicates(hooks) {
|
|
132
|
+
return summarizeAutopilotHooks(hooks).duplicates;
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=hooks-merge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks-merge.js","sourceRoot":"","sources":["../../src/init/hooks-merge.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { InitResult, InitYesOptions } from "./types.js";
|
|
2
|
+
export { mergeHooksJson, stripAutopilotHooks, isAutopilotCommand, countAutopilotDuplicates, validateHooksShape, hasCompleteAutopilotHooks, summarizeAutopilotHooks, autopilotStopHasUnlimitedLoop, autopilotHookCommand, } from "./hooks-merge.js";
|
|
3
|
+
export type { InitYesOptions, InitResult, HooksFile } from "./types.js";
|
|
4
|
+
/** Skills written by init; uninstall must remove the same set. */
|
|
5
|
+
export declare const AUTOPILOT_SKILL_NAMES: readonly ["autopilot-on", "autopilot-run", "autopilot-off", "autopilot-resume", "autopilot-replan"];
|
|
6
|
+
/** Workflow docs written by init; uninstall must remove the same set. */
|
|
7
|
+
export declare const AUTOPILOT_WORKFLOW_FILES: readonly ["autopilot-planning.md", "autopilot-executing.md"];
|
|
8
|
+
/**
|
|
9
|
+
* Write `.autopilotignore` when missing; when present, append template pattern
|
|
10
|
+
* lines that are not already present or commented-out (never delete user lines).
|
|
11
|
+
*/
|
|
12
|
+
export declare function ensureAutopilotIgnore(projectRoot: string, templatesRoot: string): string | null;
|
|
13
|
+
export type PreflightResult = {
|
|
14
|
+
ok: true;
|
|
15
|
+
} | {
|
|
16
|
+
ok: false;
|
|
17
|
+
error: string;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Read-only checks before force-refresh / upgrade mutates the project.
|
|
21
|
+
* Ensures templates, hook asset, and hooks.json are merge-safe (fail closed).
|
|
22
|
+
*/
|
|
23
|
+
export declare function preflightForceRefresh(projectRoot: string): PreflightResult;
|
|
24
|
+
/**
|
|
25
|
+
* Non-interactive init (`--yes`). Writes .autopilot + merges .cursor/hooks.json.
|
|
26
|
+
* `--force` refreshes hook/skills/pin/hooks merge but does **not** overwrite
|
|
27
|
+
* an existing config.yml, except when `mergePlatforms` / `--add-platform`
|
|
28
|
+
* updates the `platforms` list (committed only after hooks succeed).
|
|
29
|
+
*/
|
|
30
|
+
export declare function installInitYes(opts: InitYesOptions): InitResult;
|
|
31
|
+
//# sourceMappingURL=install.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../src/init/install.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAGV,UAAU,EACV,cAAc,EACf,MAAM,YAAY,CAAC;AAuCpB,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,kBAAkB,EAClB,wBAAwB,EACxB,kBAAkB,EAClB,yBAAyB,EACzB,uBAAuB,EACvB,6BAA6B,EAC7B,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAIxE,kEAAkE;AAClE,eAAO,MAAM,qBAAqB,qGAMxB,CAAC;AAEX,yEAAyE;AACzE,eAAO,MAAM,wBAAwB,8DAG3B,CAAC;AAwRX;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE,MAAM,GACpB,MAAM,GAAG,IAAI,CA6Df;AAqMD,MAAM,MAAM,eAAe,GAAG;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1E;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,eAAe,CAiD1E;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,cAAc,GAAG,UAAU,CAsY/D"}
|