@claudexor/cli 1.0.1

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 (131) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +22 -0
  3. package/dist/args.d.ts +12 -0
  4. package/dist/args.d.ts.map +1 -0
  5. package/dist/args.js +88 -0
  6. package/dist/args.js.map +1 -0
  7. package/dist/attachment-resolver.d.ts +11 -0
  8. package/dist/attachment-resolver.d.ts.map +1 -0
  9. package/dist/attachment-resolver.js +61 -0
  10. package/dist/attachment-resolver.js.map +1 -0
  11. package/dist/capabilities.d.ts +13 -0
  12. package/dist/capabilities.d.ts.map +1 -0
  13. package/dist/capabilities.js +90 -0
  14. package/dist/capabilities.js.map +1 -0
  15. package/dist/claudexord.d.ts +3 -0
  16. package/dist/claudexord.d.ts.map +1 -0
  17. package/dist/claudexord.js +564 -0
  18. package/dist/claudexord.js.map +1 -0
  19. package/dist/cli-io.d.ts +28 -0
  20. package/dist/cli-io.d.ts.map +1 -0
  21. package/dist/cli-io.js +37 -0
  22. package/dist/cli-io.js.map +1 -0
  23. package/dist/cli.d.ts +3 -0
  24. package/dist/cli.d.ts.map +1 -0
  25. package/dist/cli.js +1459 -0
  26. package/dist/cli.js.map +1 -0
  27. package/dist/command-registry.d.ts +105 -0
  28. package/dist/command-registry.d.ts.map +1 -0
  29. package/dist/command-registry.js +516 -0
  30. package/dist/command-registry.js.map +1 -0
  31. package/dist/daemon-lifecycle.d.ts +18 -0
  32. package/dist/daemon-lifecycle.d.ts.map +1 -0
  33. package/dist/daemon-lifecycle.js +62 -0
  34. package/dist/daemon-lifecycle.js.map +1 -0
  35. package/dist/daemon-run.d.ts +86 -0
  36. package/dist/daemon-run.d.ts.map +1 -0
  37. package/dist/daemon-run.js +269 -0
  38. package/dist/daemon-run.js.map +1 -0
  39. package/dist/decision.d.ts +18 -0
  40. package/dist/decision.d.ts.map +1 -0
  41. package/dist/decision.js +46 -0
  42. package/dist/decision.js.map +1 -0
  43. package/dist/live.d.ts +26 -0
  44. package/dist/live.d.ts.map +1 -0
  45. package/dist/live.js +311 -0
  46. package/dist/live.js.map +1 -0
  47. package/dist/mcp-runner.d.ts +41 -0
  48. package/dist/mcp-runner.d.ts.map +1 -0
  49. package/dist/mcp-runner.js +306 -0
  50. package/dist/mcp-runner.js.map +1 -0
  51. package/dist/ops-commands.d.ts +11 -0
  52. package/dist/ops-commands.d.ts.map +1 -0
  53. package/dist/ops-commands.js +358 -0
  54. package/dist/ops-commands.js.map +1 -0
  55. package/dist/orchestrate-options.d.ts +9 -0
  56. package/dist/orchestrate-options.d.ts.map +1 -0
  57. package/dist/orchestrate-options.js +16 -0
  58. package/dist/orchestrate-options.js.map +1 -0
  59. package/dist/orphan-reaper.d.ts +9 -0
  60. package/dist/orphan-reaper.d.ts.map +1 -0
  61. package/dist/orphan-reaper.js +97 -0
  62. package/dist/orphan-reaper.js.map +1 -0
  63. package/dist/orphan-sweeper.d.ts +7 -0
  64. package/dist/orphan-sweeper.d.ts.map +1 -0
  65. package/dist/orphan-sweeper.js +289 -0
  66. package/dist/orphan-sweeper.js.map +1 -0
  67. package/dist/plugins.d.ts +44 -0
  68. package/dist/plugins.d.ts.map +1 -0
  69. package/dist/plugins.js +1383 -0
  70. package/dist/plugins.js.map +1 -0
  71. package/dist/primary-output.d.ts +14 -0
  72. package/dist/primary-output.d.ts.map +1 -0
  73. package/dist/primary-output.js +34 -0
  74. package/dist/primary-output.js.map +1 -0
  75. package/dist/registry.d.ts +26 -0
  76. package/dist/registry.d.ts.map +1 -0
  77. package/dist/registry.js +71 -0
  78. package/dist/registry.js.map +1 -0
  79. package/dist/release.d.ts +14 -0
  80. package/dist/release.d.ts.map +1 -0
  81. package/dist/release.js +49 -0
  82. package/dist/release.js.map +1 -0
  83. package/dist/repl.d.ts +26 -0
  84. package/dist/repl.d.ts.map +1 -0
  85. package/dist/repl.js +277 -0
  86. package/dist/repl.js.map +1 -0
  87. package/dist/review-command.d.ts +3 -0
  88. package/dist/review-command.d.ts.map +1 -0
  89. package/dist/review-command.js +83 -0
  90. package/dist/review-command.js.map +1 -0
  91. package/dist/reviewer-options.d.ts +18 -0
  92. package/dist/reviewer-options.d.ts.map +1 -0
  93. package/dist/reviewer-options.js +110 -0
  94. package/dist/reviewer-options.js.map +1 -0
  95. package/dist/run-options.d.ts +8 -0
  96. package/dist/run-options.d.ts.map +1 -0
  97. package/dist/run-options.js +50 -0
  98. package/dist/run-options.js.map +1 -0
  99. package/dist/run-secret-scan.d.ts +2 -0
  100. package/dist/run-secret-scan.d.ts.map +1 -0
  101. package/dist/run-secret-scan.js +5 -0
  102. package/dist/run-secret-scan.js.map +1 -0
  103. package/dist/settings-command.d.ts +3 -0
  104. package/dist/settings-command.d.ts.map +1 -0
  105. package/dist/settings-command.js +202 -0
  106. package/dist/settings-command.js.map +1 -0
  107. package/dist/settings-display.d.ts +3 -0
  108. package/dist/settings-display.d.ts.map +1 -0
  109. package/dist/settings-display.js +33 -0
  110. package/dist/settings-display.js.map +1 -0
  111. package/dist/settings-service.d.ts +15 -0
  112. package/dist/settings-service.d.ts.map +1 -0
  113. package/dist/settings-service.js +91 -0
  114. package/dist/settings-service.js.map +1 -0
  115. package/dist/setup-jobs.d.ts +28 -0
  116. package/dist/setup-jobs.d.ts.map +1 -0
  117. package/dist/setup-jobs.js +477 -0
  118. package/dist/setup-jobs.js.map +1 -0
  119. package/dist/spec.d.ts +84 -0
  120. package/dist/spec.d.ts.map +1 -0
  121. package/dist/spec.js +438 -0
  122. package/dist/spec.js.map +1 -0
  123. package/dist/trust-command.d.ts +3 -0
  124. package/dist/trust-command.d.ts.map +1 -0
  125. package/dist/trust-command.js +80 -0
  126. package/dist/trust-command.js.map +1 -0
  127. package/dist/trust-services.d.ts +7 -0
  128. package/dist/trust-services.d.ts.map +1 -0
  129. package/dist/trust-services.js +35 -0
  130. package/dist/trust-services.js.map +1 -0
  131. package/package.json +59 -0
@@ -0,0 +1,477 @@
1
+ import { spawn } from "node:child_process";
2
+ import { randomUUID } from "node:crypto";
3
+ import { chmodSync, mkdirSync, writeFileSync } from "node:fs";
4
+ import { join } from "node:path";
5
+ import { harnessRuntimeEnv } from "@claudexor/core";
6
+ import { daemonDir } from "@claudexor/daemon";
7
+ import { appendLine, noProjectRepoRoot, readJsonSafe, redactSecrets } from "@claudexor/util";
8
+ import { ControlSetupJob as ControlSetupJobSchema } from "@claudexor/schema";
9
+ import { buildGateway } from "./registry.js";
10
+ const NO_PROJECT_ROOT = noProjectRepoRoot();
11
+ /**
12
+ * Doctor verification runs IN-PROCESS (buildGateway().statusAll) — never as a
13
+ * `claudexor ...` shell command. The bundled .app daemon has no global
14
+ * `claudexor` binary on PATH, so the previous shell form always exited 127.
15
+ */
16
+ const SETUP_PROFILES = {
17
+ codex: {
18
+ guideUrl: "https://developers.openai.com/codex",
19
+ installCommand: "npm install -g @openai/codex",
20
+ loginCommand: "codex login",
21
+ note: "Codex native login seeds the local CLI session; API-key fallback can be stored as the openai secret ref.",
22
+ installRiskFlags: ["network_download", "global_npm_install"],
23
+ },
24
+ claude: {
25
+ guideUrl: "https://docs.anthropic.com/en/docs/claude-code",
26
+ installCommand: "npm install -g @anthropic-ai/claude-code",
27
+ loginCommand: "claude /login",
28
+ note: "Claude Code native login is preferred; Anthropic API-key fallback can be stored as the anthropic secret ref.",
29
+ installRiskFlags: ["network_download", "global_npm_install"],
30
+ },
31
+ cursor: {
32
+ guideUrl: "https://docs.cursor.com/cli",
33
+ installCommand: "curl https://cursor.com/install -fsS | bash",
34
+ loginCommand: "cursor-agent login",
35
+ note: "Cursor native CLI login is reused when available.",
36
+ installRiskFlags: ["network_download", "shell_pipe", "no_static_sha256", "may_prompt_for_privilege"],
37
+ },
38
+ opencode: {
39
+ guideUrl: "https://opencode.ai/docs",
40
+ installCommand: "curl -fsSL https://opencode.ai/install | bash",
41
+ loginCommand: "opencode auth login",
42
+ note: "OpenCode native auth is reused when available.",
43
+ installRiskFlags: ["network_download", "shell_pipe", "no_static_sha256", "may_prompt_for_privilege"],
44
+ },
45
+ raw: {
46
+ guideUrl: "https://platform.openai.com/docs",
47
+ installCommand: null,
48
+ loginCommand: null,
49
+ note: "Raw API routes use stored secret refs instead of a native CLI login.",
50
+ installRiskFlags: [],
51
+ },
52
+ };
53
+ /** Native login command for a harness (null = API-key refs only). Single
54
+ * source for both the setup-job Terminal handoff and `claudexor auth login`. */
55
+ export function nativeLoginCommand(harness) {
56
+ return SETUP_PROFILES[harness]?.loginCommand ?? null;
57
+ }
58
+ /** Honest display label for the in-process doctor phase of a setup job. */
59
+ function inProcessDoctorLabel(harness) {
60
+ return harness === "raw" ? "(in-process doctor: all harnesses)" : `(in-process doctor: ${harness})`;
61
+ }
62
+ const SETUP_JOBS_DIR = join(daemonDir(), "setup-jobs");
63
+ const SETUP_JOBS_REGISTRY = join(SETUP_JOBS_DIR, "jobs.json");
64
+ /** A hung installer must reach a visible terminal state, not run forever. */
65
+ const SETUP_JOB_TIMEOUT_MS = 15 * 60_000;
66
+ export function createSetupJobManager(opts = {}) {
67
+ const jobs = new Map();
68
+ const children = new Map();
69
+ const timeouts = new Map();
70
+ const statusAll = opts.statusAll ?? (() => buildGateway({ includeFakes: false }).statusAll({ cwd: NO_PROJECT_ROOT }));
71
+ // Durable registry: a daemon restart must not erase job history. Jobs that
72
+ // were mid-flight when the daemon died are marked failed (honest terminal),
73
+ // except Terminal logins, which legitimately outlive the daemon process.
74
+ mkdirSync(SETUP_JOBS_DIR, { recursive: true, mode: 0o700 });
75
+ const persisted = readJsonSafe(SETUP_JOBS_REGISTRY);
76
+ if (Array.isArray(persisted)) {
77
+ for (const raw of persisted) {
78
+ const parsed = ControlSetupJobSchema.safeParse(raw);
79
+ if (!parsed.success)
80
+ continue;
81
+ const job = parsed.data;
82
+ if (job.state === "running" || job.state === "queued") {
83
+ jobs.set(job.jobId, {
84
+ ...job,
85
+ state: "failed",
86
+ finishedAt: new Date().toISOString(),
87
+ message: `${job.harness} ${job.action} job was interrupted by a daemon restart.`,
88
+ });
89
+ }
90
+ else {
91
+ jobs.set(job.jobId, job);
92
+ }
93
+ }
94
+ }
95
+ const persist = () => {
96
+ try {
97
+ writeFileSync(SETUP_JOBS_REGISTRY, JSON.stringify([...jobs.values()], null, 2) + "\n", { mode: 0o600 });
98
+ }
99
+ catch {
100
+ /* registry persistence is best-effort; state stays authoritative in memory */
101
+ }
102
+ };
103
+ const save = (job) => {
104
+ jobs.set(job.jobId, job);
105
+ persist();
106
+ return job;
107
+ };
108
+ const update = (jobId, patch) => {
109
+ const prev = jobs.get(jobId);
110
+ if (!prev)
111
+ throw Object.assign(new Error("setup job not found"), { status: 404 });
112
+ return save({ ...prev, ...patch });
113
+ };
114
+ const writeJobLog = (job, line) => {
115
+ if (!job.logPath)
116
+ return;
117
+ appendLine(job.logPath, `[${new Date().toISOString()}] ${redactSecrets(line)}`);
118
+ };
119
+ const noteJobOutput = (jobId) => {
120
+ const current = jobs.get(jobId);
121
+ if (!current || current.state !== "running")
122
+ return;
123
+ const now = nowForDto();
124
+ update(jobId, {
125
+ firstOutputAt: current.firstOutputAt ?? now,
126
+ lastOutputAt: now,
127
+ message: current.firstOutputAt
128
+ ? `Running allowlisted ${current.harness} ${current.action} job. Latest output at ${now}.`
129
+ : `Running allowlisted ${current.harness} ${current.action} job. First output received.`,
130
+ });
131
+ };
132
+ /**
133
+ * In-process doctor: probes the harness through the SAME gateway code the
134
+ * Harness Doctor screen uses. No shell, no PATH dependency — the bundled
135
+ * .app daemon has no global `claudexor` binary (the old shell form was a
136
+ * guaranteed exit 127).
137
+ */
138
+ const doctorTimeoutMs = opts.doctorTimeoutMs ?? 60_000;
139
+ const runInProcessDoctor = (jobId) => {
140
+ void (async () => {
141
+ const job = jobs.get(jobId);
142
+ if (!job || job.state !== "running")
143
+ return;
144
+ writeJobLog(job, `doctor: probing ${job.harness} in-process (no shell, no PATH dependency)`);
145
+ try {
146
+ const statuses = await Promise.race([
147
+ statusAll(),
148
+ new Promise((_, reject) => {
149
+ const t = setTimeout(() => reject(new Error(`doctor timed out after ${doctorTimeoutMs / 1000}s`)), doctorTimeoutMs);
150
+ t.unref();
151
+ }),
152
+ ]);
153
+ noteJobOutput(jobId);
154
+ const targets = job.harness === "raw" ? statuses : statuses.filter((s) => s.id === job.harness);
155
+ if (targets.length === 0)
156
+ throw new Error(`no doctor report for harness '${job.harness}'`);
157
+ for (const s of targets) {
158
+ const checks = s.checks.map((c) => `${c.id}:${c.status}`).join(", ");
159
+ writeJobLog(job, `doctor ${s.id}: ${s.status}${checks ? ` — ${checks}` : ""}`);
160
+ for (const reason of s.reasons ?? [])
161
+ writeJobLog(job, `doctor ${s.id}: ${reason}`);
162
+ }
163
+ const ok = targets.every((s) => s.status === "ok");
164
+ const degraded = targets.some((s) => s.status === "degraded");
165
+ const reasons = targets.flatMap((s) => s.reasons ?? []).slice(0, 2).join("; ");
166
+ const message = ok
167
+ ? `${job.harness} doctor passed (in-process).`
168
+ : `${job.harness} doctor reports ${degraded ? "degraded" : "unavailable"}: ${reasons || "see the job log for checks"}`;
169
+ // A cancel may have landed while statusAll() was in flight; a terminal
170
+ // cancelled state must never be overwritten by a late doctor verdict.
171
+ const beforeTerminal = jobs.get(jobId);
172
+ if (!beforeTerminal || beforeTerminal.state !== "running")
173
+ return;
174
+ const done = update(jobId, { state: ok ? "succeeded" : "failed", finishedAt: nowForDto(), message });
175
+ writeJobLog(done, message);
176
+ }
177
+ catch (err) {
178
+ const message = `in-process doctor failed: ${err instanceof Error ? err.message : String(err)}`;
179
+ const current = jobs.get(jobId);
180
+ // Same cancel-race guard as the success path: only a still-running
181
+ // job may take a terminal verdict from this async phase.
182
+ if (!current || current.state !== "running")
183
+ return;
184
+ const failed = update(jobId, { state: "failed", finishedAt: nowForDto(), message });
185
+ writeJobLog(failed, message);
186
+ }
187
+ })();
188
+ };
189
+ const startInProcessDoctorJob = (job) => {
190
+ const started = update(job.jobId, {
191
+ state: "running",
192
+ startedAt: nowForDto(),
193
+ message: `Running in-process ${job.harness} doctor.`,
194
+ });
195
+ runInProcessDoctor(job.jobId);
196
+ return started;
197
+ };
198
+ const startShellJob = (job, command, onSuccess) => {
199
+ const started = update(job.jobId, { state: "running", startedAt: nowForDto(), message: `Running allowlisted ${job.harness} ${job.action} job.` });
200
+ writeJobLog(started, `$ ${command}`);
201
+ const child = spawn("/bin/bash", ["-lc", command], {
202
+ cwd: NO_PROJECT_ROOT,
203
+ env: setupJobEnv(),
204
+ stdio: ["ignore", "pipe", "pipe"],
205
+ });
206
+ children.set(job.jobId, child);
207
+ // Watchdog: a wedged install/doctor must surface as a failed terminal state.
208
+ const watchdog = setTimeout(() => {
209
+ const current = jobs.get(job.jobId);
210
+ if (!current || current.state !== "running")
211
+ return;
212
+ writeJobLog(current, `watchdog: job exceeded ${SETUP_JOB_TIMEOUT_MS / 60000} minutes; terminating`);
213
+ child.kill("SIGTERM");
214
+ setTimeout(() => child.kill("SIGKILL"), 5_000).unref();
215
+ const failed = update(job.jobId, {
216
+ state: "failed",
217
+ finishedAt: nowForDto(),
218
+ message: `${job.harness} ${job.action} job timed out after ${SETUP_JOB_TIMEOUT_MS / 60000} minutes and was terminated.`,
219
+ });
220
+ writeJobLog(failed, failed.message);
221
+ }, SETUP_JOB_TIMEOUT_MS);
222
+ watchdog.unref();
223
+ timeouts.set(job.jobId, watchdog);
224
+ child.stdout.on("data", (chunk) => { noteJobOutput(job.jobId); writeJobLog(jobs.get(job.jobId) ?? started, String(chunk)); });
225
+ child.stderr.on("data", (chunk) => { noteJobOutput(job.jobId); writeJobLog(jobs.get(job.jobId) ?? started, String(chunk)); });
226
+ child.on("error", (err) => {
227
+ children.delete(job.jobId);
228
+ clearTimeout(timeouts.get(job.jobId));
229
+ timeouts.delete(job.jobId);
230
+ const failed = update(job.jobId, { state: "failed", finishedAt: nowForDto(), message: `Setup job failed to start: ${err.message}` });
231
+ writeJobLog(failed, failed.message);
232
+ });
233
+ child.on("exit", (code, signal) => {
234
+ children.delete(job.jobId);
235
+ clearTimeout(timeouts.get(job.jobId));
236
+ timeouts.delete(job.jobId);
237
+ const current = jobs.get(job.jobId);
238
+ if (!current || current.state === "cancelled" || current.state === "failed")
239
+ return;
240
+ const ok = code === 0;
241
+ if (ok && onSuccess) {
242
+ // The shell phase finished; the job stays running for the in-process
243
+ // doctor phase, which owns the terminal state.
244
+ const phase = update(job.jobId, { message: `${job.harness} ${job.action} shell phase finished; verifying with in-process doctor.` });
245
+ writeJobLog(phase, phase.message);
246
+ onSuccess(job.jobId);
247
+ return;
248
+ }
249
+ const message = ok
250
+ ? `${job.harness} ${job.action} job finished.`
251
+ : `${job.harness} ${job.action} job failed with ${signal ? `signal ${signal}` : `exit code ${code ?? "unknown"}`}.`;
252
+ const done = update(job.jobId, { state: ok ? "succeeded" : "failed", finishedAt: nowForDto(), message });
253
+ writeJobLog(done, message);
254
+ });
255
+ return started;
256
+ };
257
+ const startTerminalLoginJob = (job, command) => {
258
+ // The Terminal-handoff login uses macOS `open -a Terminal`. On non-darwin
259
+ // there is no such affordance: fail with a typed, actionable state rather
260
+ // than spawn a missing binary (whose unhandled ENOENT `error` event could
261
+ // take down the daemon). The manual command is disclosed so the user can
262
+ // run the native login themselves.
263
+ if (process.platform !== "darwin") {
264
+ const failed = update(job.jobId, {
265
+ state: "failed",
266
+ startedAt: nowForDto(),
267
+ finishedAt: nowForDto(),
268
+ message: `Terminal-handoff login is macOS-only. Run the ${job.harness} native login yourself, then recheck Harness Doctor: ${command}`,
269
+ });
270
+ writeJobLog(failed, failed.message);
271
+ return failed;
272
+ }
273
+ const scriptPath = join(SETUP_JOBS_DIR, `${job.jobId}.command`);
274
+ const script = `#!/usr/bin/env bash
275
+ set -euo pipefail
276
+ ${command}
277
+ printf '\\nClaudexor setup command finished. Press Return to close this window. '
278
+ IFS= read -r _
279
+ `;
280
+ writeFileSync(scriptPath, script, { mode: 0o700 });
281
+ chmodSync(scriptPath, 0o700);
282
+ writeJobLog(job, `Terminal script: ${scriptPath}`);
283
+ const child = spawn("/usr/bin/open", ["-a", "Terminal", scriptPath], { detached: true, stdio: "ignore" });
284
+ // The waiting transition lands FIRST (same synchronous tick as spawn —
285
+ // child 'error'/'exit' events cannot fire mid-tick), so startedAt is
286
+ // always stamped before any handler can run.
287
+ const waiting = update(job.jobId, {
288
+ state: "waiting_for_input",
289
+ startedAt: nowForDto(),
290
+ message: `Opened allowlisted ${job.harness} login in Terminal. Complete native auth there, then recheck Harness Doctor.`,
291
+ });
292
+ // A missing/blocked `open` must land as a typed failure, never an
293
+ // unhandled 'error' event that crashes the daemon. `open` can also fail
294
+ // AFTER spawning (nonzero exit, or killed by signal) — that path must not
295
+ // leave the job parked on waiting_for_input either. One transition wins
296
+ // (settled flag), and a job the user already CANCELLED (or any other
297
+ // terminal state) is never overwritten by a late child event — the same
298
+ // cancel-race guard the doctor path uses.
299
+ let settled = false;
300
+ const failJob = (detail) => {
301
+ if (settled)
302
+ return;
303
+ settled = true;
304
+ const current = jobs.get(job.jobId);
305
+ if (!current || current.state !== "waiting_for_input")
306
+ return;
307
+ const failed = update(job.jobId, {
308
+ state: "failed",
309
+ finishedAt: nowForDto(),
310
+ message: `Could not open Terminal for ${job.harness} login: ${detail}. Run it yourself, then recheck Harness Doctor: ${command}`,
311
+ });
312
+ writeJobLog(failed, failed.message);
313
+ };
314
+ child.on("error", (err) => failJob(err.message));
315
+ child.on("exit", (code, signal) => {
316
+ if (code === 0)
317
+ return;
318
+ failJob(code === null ? `\`open -a Terminal\` was terminated by signal ${signal ?? "unknown"}` : `\`open -a Terminal\` exited with code ${code}`);
319
+ });
320
+ child.unref();
321
+ return waiting;
322
+ };
323
+ return {
324
+ create(input) {
325
+ mkdirSync(SETUP_JOBS_DIR, { recursive: true, mode: 0o700 });
326
+ const p = (input ?? {});
327
+ const harness = typeof p["harness"] === "string" ? p["harness"] : "";
328
+ const action = typeof p["action"] === "string" ? p["action"] : "";
329
+ const profile = SETUP_PROFILES[harness];
330
+ if (!profile)
331
+ throw new Error("unknown harness");
332
+ if (action !== "install" && action !== "login" && action !== "doctor" && action !== "store_key")
333
+ throw new Error("unsupported setup job action");
334
+ const jobId = `setup-${Date.now().toString(36)}-${randomUUID().slice(0, 8)}`;
335
+ const logPath = join(SETUP_JOBS_DIR, `${jobId}.log`);
336
+ // Honest retry accounting: a new job for the same harness+action after a
337
+ // failed one IS the user retrying.
338
+ const priorFailures = [...jobs.values()].filter((j) => j.harness === harness && j.action === action && (j.state === "failed" || j.state === "cancelled")).length;
339
+ const base = {
340
+ jobId,
341
+ harness: harness,
342
+ action,
343
+ state: "queued",
344
+ command: null,
345
+ guideUrl: profile.guideUrl,
346
+ logPath,
347
+ message: profile.note,
348
+ riskFlags: action === "install" ? profile.installRiskFlags : [],
349
+ requiresConfirmation: false,
350
+ createdAt: nowForDto(),
351
+ startedAt: null,
352
+ firstOutputAt: null,
353
+ lastOutputAt: null,
354
+ finishedAt: null,
355
+ retryCount: priorFailures,
356
+ };
357
+ writeJobLog(base, `created ${harness} ${action}${priorFailures > 0 ? ` (retry #${priorFailures})` : ""}`);
358
+ if (action === "login") {
359
+ if (!profile.loginCommand) {
360
+ return save({
361
+ ...base,
362
+ state: "not_supported",
363
+ finishedAt: nowForDto(),
364
+ message: `${harness} has no native login command; store API-key fallback refs in Settings.`,
365
+ });
366
+ }
367
+ const job = save({ ...base, command: profile.loginCommand });
368
+ return startTerminalLoginJob(job, job.command ?? "");
369
+ }
370
+ if (action === "doctor") {
371
+ const job = save({ ...base, command: inProcessDoctorLabel(harness) });
372
+ return startInProcessDoctorJob(job);
373
+ }
374
+ if (action === "store_key") {
375
+ // Honest message: this job only verifies via doctor. The key itself is
376
+ // stored by the separate Settings store-secret call, never by this job.
377
+ const job = save({
378
+ ...base,
379
+ command: inProcessDoctorLabel(harness),
380
+ message: `Running post-store doctor for ${harness}. (The key itself is saved via Settings > secrets, not by this job.)`,
381
+ });
382
+ return startInProcessDoctorJob(job);
383
+ }
384
+ if (!profile.installCommand) {
385
+ return save({
386
+ ...base,
387
+ state: "not_supported",
388
+ finishedAt: nowForDto(),
389
+ message: `${harness} has no native installer; use stored API-key fallback refs instead.`,
390
+ });
391
+ }
392
+ return save({
393
+ ...base,
394
+ state: "waiting_for_input",
395
+ command: profile.installCommand,
396
+ requiresConfirmation: true,
397
+ message: `Confirm to run allowlisted ${harness} installer. Risks: ${profile.installRiskFlags.join(", ") || "standard process execution"}.`,
398
+ });
399
+ },
400
+ confirm(input) {
401
+ const p = (input ?? {});
402
+ const jobId = typeof p["jobId"] === "string" ? p["jobId"] : "";
403
+ const confirmed = p["confirmed"] !== false;
404
+ const job = jobs.get(jobId);
405
+ if (!job)
406
+ throw Object.assign(new Error("setup job not found"), { status: 404 });
407
+ if (!confirmed)
408
+ return job;
409
+ if (!job.requiresConfirmation || job.action !== "install" || !job.command) {
410
+ throw new Error("setup job does not require confirmation");
411
+ }
412
+ if (job.state !== "waiting_for_input") {
413
+ throw new Error(`setup job cannot be confirmed while ${job.state}`);
414
+ }
415
+ const ready = save({ ...job, requiresConfirmation: false });
416
+ // Shell phase = the native installer only; verification runs in-process.
417
+ return startShellJob(ready, ready.command ?? "", runInProcessDoctor);
418
+ },
419
+ list() {
420
+ return [...jobs.values()].sort((a, b) => a.createdAt.localeCompare(b.createdAt));
421
+ },
422
+ status(input) {
423
+ const p = (input ?? {});
424
+ const jobId = typeof p["jobId"] === "string" ? p["jobId"] : "";
425
+ const job = jobs.get(jobId);
426
+ if (!job)
427
+ throw Object.assign(new Error("setup job not found"), { status: 404 });
428
+ return job;
429
+ },
430
+ cancel(input) {
431
+ const p = (input ?? {});
432
+ const jobId = typeof p["jobId"] === "string" ? p["jobId"] : "";
433
+ const job = jobs.get(jobId);
434
+ if (!job)
435
+ throw Object.assign(new Error("setup job not found"), { status: 404 });
436
+ // A terminal job has nothing to cancel; overwriting `succeeded`/`failed`
437
+ // with `cancelled` would falsify history (the Terminal-handoff child
438
+ // handlers already refuse this overwrite — the endpoint must too).
439
+ // Idempotent: return the terminal record unchanged.
440
+ if (job.state === "succeeded" || job.state === "failed" || job.state === "cancelled" || job.state === "not_supported") {
441
+ return job;
442
+ }
443
+ const child = children.get(jobId);
444
+ if (child) {
445
+ child.kill("SIGTERM");
446
+ children.delete(jobId);
447
+ }
448
+ clearTimeout(timeouts.get(jobId));
449
+ timeouts.delete(jobId);
450
+ const cancelled = update(jobId, { state: "cancelled", finishedAt: nowForDto(), message: `Cancelled ${job.harness} ${job.action} setup job.` });
451
+ writeJobLog(cancelled, cancelled.message);
452
+ return cancelled;
453
+ },
454
+ };
455
+ }
456
+ function setupJobEnv() {
457
+ const runtime = harnessRuntimeEnv();
458
+ const env = {
459
+ HOME: runtime.HOME,
460
+ PATH: runtime.PATH,
461
+ SHELL: process.env.SHELL ?? "/bin/bash",
462
+ TMPDIR: process.env.TMPDIR,
463
+ LANG: process.env.LANG,
464
+ LC_ALL: process.env.LC_ALL,
465
+ USER: process.env.USER,
466
+ LOGNAME: process.env.LOGNAME,
467
+ };
468
+ for (const key of Object.keys(env)) {
469
+ if (env[key] === undefined)
470
+ delete env[key];
471
+ }
472
+ return env;
473
+ }
474
+ function nowForDto() {
475
+ return new Date().toISOString();
476
+ }
477
+ //# sourceMappingURL=setup-jobs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup-jobs.js","sourceRoot":"","sources":["../src/setup-jobs.ts"],"names":[],"mappings":"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"}
package/dist/spec.d.ts ADDED
@@ -0,0 +1,84 @@
1
+ import { type SpecDraft, type SpecFieldChange } from "@claudexor/interview";
2
+ import { type InterviewAnswer, type InterviewQuestion, type SpecPack } from "@claudexor/schema";
3
+ export interface SpecAnswersFile {
4
+ answers: InterviewAnswer[];
5
+ /** Present in the draft questions file so freezing can reuse the exact grounding plan. */
6
+ planRunId?: string;
7
+ planDir?: string;
8
+ questions?: InterviewQuestion[];
9
+ summary?: string;
10
+ success_criteria?: string[];
11
+ non_goals?: string[];
12
+ forbidden_approaches?: string[];
13
+ decided_tradeoffs?: string[];
14
+ tests?: string[];
15
+ }
16
+ export interface SpecCommandResult {
17
+ status: "questions" | "frozen";
18
+ planRunId: string;
19
+ planDir: string;
20
+ questionsPath?: string;
21
+ specId?: string;
22
+ specDir?: string;
23
+ specHash?: string;
24
+ runHint?: string;
25
+ questions: InterviewQuestion[];
26
+ changes?: SpecFieldChange[];
27
+ }
28
+ export interface LoadedFrozenSpec {
29
+ spec: SpecPack;
30
+ specPath: string;
31
+ specHash: string;
32
+ }
33
+ export declare function loadFrozenSpec(path: string): LoadedFrozenSpec;
34
+ export declare function resolveRunTestCommands(cliTests: string[] | undefined, spec: SpecPack | null): string[] | undefined;
35
+ /**
36
+ * The grounding-plan instruction that DRIVES extractQuestionsFromPlan: it tells the
37
+ * harness to end its read-only plan with a structured `## Open Questions` block in
38
+ * the exact format the parser below understands. Kept HERE, beside its parser, so the
39
+ * producer instruction and consumer stay a co-located contract pair (the daemon
40
+ * surface just calls this — Bible §1: surfaces stay thin).
41
+ */
42
+ /** One already-answered decision, carried into a follow-up tier so the interview
43
+ * goes DEEPER instead of re-asking. */
44
+ export interface PriorDecision {
45
+ question: string;
46
+ answer: string;
47
+ }
48
+ export declare function buildGroundingPrompt(prompt: string, priorDecisions?: PriorDecision[]): string;
49
+ /**
50
+ * Parse the grounding plan's "Open Questions" section into an interactive interview.
51
+ *
52
+ * The grounding prompt (see claudexord.specQuestions) asks the harness to end its
53
+ * plan with an `## Open Questions` section, one bullet per decision, in the format:
54
+ *
55
+ * - [single] Which auth flow? :: OAuth :: API key :: Both
56
+ * - [multi] Which platforms? :: iOS :: Android :: Web
57
+ * - [text] Any naming constraints?
58
+ *
59
+ * `[single|multi|text]` is the answer kind; `::` separates the question from each
60
+ * option. Parsing is TOLERANT so the quiz degrades gracefully and old plans still
61
+ * work: an untagged bullet with no `::` becomes a free-text question (the previous
62
+ * behavior); an untagged bullet WITH options defaults to single-choice; a tagged
63
+ * choice question with no options falls back to text. `(none)` is skipped. This is
64
+ * plain delimiter parsing of the harness's own structured output (a data shape we
65
+ * instructed), not a governance signal — it does not infer risk/success/etc.
66
+ */
67
+ export declare function extractQuestionsFromPlan(plan: string): InterviewQuestion[];
68
+ export declare function readAnswers(path: string): SpecAnswersFile;
69
+ export declare function draftFromPlanAndAnswers(prompt: string, plan: string, questions: InterviewQuestion[], file: SpecAnswersFile): SpecDraft;
70
+ /**
71
+ * Validate submitted answers against the question contract BEFORE freezing — fail
72
+ * loudly (Bible §5: no silent guessing) rather than freeze a malformed SpecPack.
73
+ * Rejects an answer for an unknown question id, unknown option ids, more than one
74
+ * option on a single-choice question, and free text where the question disallows it.
75
+ */
76
+ export declare function validateAnswers(questions: InterviewQuestion[], answers: InterviewAnswer[]): void;
77
+ export declare function freezeSpecFromGrounding(prompt: string, plan: string, answers: SpecAnswersFile): Promise<SpecPack>;
78
+ export declare function persistSpec(repoRoot: string, spec: SpecPack, plan: string, previous?: SpecPack | null): {
79
+ specDir: string;
80
+ specHash: string;
81
+ changes: SpecFieldChange[];
82
+ };
83
+ export declare function loadPreviousSpec(path?: string): SpecPack | null;
84
+ //# sourceMappingURL=spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spec.d.ts","sourceRoot":"","sources":["../src/spec.ts"],"names":[],"mappings":"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"}