@synaplink/orqlaude 0.5.6 → 0.7.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 (63) hide show
  1. package/README.md +36 -3
  2. package/dist/__tests__/v06.test.d.ts +1 -0
  3. package/dist/__tests__/v06.test.js +74 -0
  4. package/dist/__tests__/v06.test.js.map +1 -0
  5. package/dist/__tests__/v07.test.d.ts +1 -0
  6. package/dist/__tests__/v07.test.js +124 -0
  7. package/dist/__tests__/v07.test.js.map +1 -0
  8. package/dist/cli/about.d.ts +5 -0
  9. package/dist/cli/about.js +27 -0
  10. package/dist/cli/about.js.map +1 -0
  11. package/dist/cli/doctor.d.ts +1 -0
  12. package/dist/cli/doctor.js +180 -0
  13. package/dist/cli/doctor.js.map +1 -0
  14. package/dist/cli/easter_egg.d.ts +1 -0
  15. package/dist/cli/easter_egg.js +92 -0
  16. package/dist/cli/easter_egg.js.map +1 -0
  17. package/dist/cli/open.d.ts +6 -0
  18. package/dist/cli/open.js +57 -0
  19. package/dist/cli/open.js.map +1 -0
  20. package/dist/cli/taglines.d.ts +12 -0
  21. package/dist/cli/taglines.js +163 -0
  22. package/dist/cli/taglines.js.map +1 -0
  23. package/dist/cli/tail.d.ts +7 -0
  24. package/dist/cli/tail.js +87 -0
  25. package/dist/cli/tail.js.map +1 -0
  26. package/dist/cli/watch.d.ts +1 -0
  27. package/dist/cli/watch.js +169 -0
  28. package/dist/cli/watch.js.map +1 -0
  29. package/dist/cli.js +234 -43
  30. package/dist/cli.js.map +1 -1
  31. package/dist/lib/error_ui.d.ts +21 -0
  32. package/dist/lib/error_ui.js +59 -0
  33. package/dist/lib/error_ui.js.map +1 -0
  34. package/dist/lib/json_out.d.ts +9 -0
  35. package/dist/lib/json_out.js +15 -0
  36. package/dist/lib/json_out.js.map +1 -0
  37. package/dist/lib/notifications.d.ts +14 -0
  38. package/dist/lib/notifications.js +37 -0
  39. package/dist/lib/notifications.js.map +1 -0
  40. package/dist/lib/picker.d.ts +6 -0
  41. package/dist/lib/picker.js +50 -0
  42. package/dist/lib/picker.js.map +1 -0
  43. package/dist/lib/preferences.d.ts +25 -0
  44. package/dist/lib/preferences.js +32 -0
  45. package/dist/lib/preferences.js.map +1 -0
  46. package/dist/lib/process_lib.d.ts +8 -0
  47. package/dist/lib/process_lib.js +26 -0
  48. package/dist/lib/process_lib.js.map +1 -0
  49. package/dist/lib/spawn_cli.d.ts +31 -40
  50. package/dist/lib/spawn_cli.js +101 -55
  51. package/dist/lib/spawn_cli.js.map +1 -1
  52. package/dist/lib/state.d.ts +14 -1
  53. package/dist/lib/state.js.map +1 -1
  54. package/dist/lib/update_check.d.ts +1 -0
  55. package/dist/lib/update_check.js +78 -0
  56. package/dist/lib/update_check.js.map +1 -0
  57. package/dist/server.js +1 -1
  58. package/dist/telegram/notifier.js +30 -0
  59. package/dist/telegram/notifier.js.map +1 -1
  60. package/dist/tools/dispatch.js +66 -10
  61. package/dist/tools/dispatch.js.map +1 -1
  62. package/dist/tools/ping.js +1 -1
  63. package/package.json +1 -1
package/README.md CHANGED
@@ -226,17 +226,43 @@ False positives are acceptable here — we surface concerns, we don't auto-kill.
226
226
 
227
227
  ## CLI
228
228
 
229
- Two binaries are installed: `orqlaude` and the short alias `orql`. Use whichever feels right.
229
+ Two binaries are installed: `orqlaude` and the short alias `orql`. Use whichever feels right. All commands work the same.
230
+
231
+ ### Live (v0.6+)
230
232
 
231
233
  ```sh
234
+ orql watch <plan_id> # live-updating dashboard (1Hz, Ctrl-C to exit)
235
+ orql tail [plan_id] # tail -f the audit log; filter by plan if given
236
+ orql open <plan_id> # open every PR from a plan in your browser
237
+ orql doctor # end-to-end health check
238
+ orql about # the easter egg
239
+ ```
240
+
241
+ ### Local desktop notifications (macOS)
242
+
243
+ ```sh
244
+ orql notify on # enable; the Telegram bot will also fire osascript banners
245
+ orql notify off # disable
246
+ orql notify test # send a test notification
247
+ orql notify status # is it on?
248
+ ```
249
+
250
+ ### Read-only inspection (`--json` on every one)
251
+
252
+
253
+
254
+ ```sh
255
+ orql # banner + active-plan summary
232
256
  orql list # every plan in this project
233
- orql status <plan_id> # refreshed status of one plan
234
- orql show <plan_id> # raw plan JSON
257
+ orql status [plan_id] # if omitted, picker prompts
258
+ orql show [plan_id] # raw plan JSON
235
259
  orql history --limit 50 # tail audit log
236
260
  orql where # show resolved state dir
237
261
  orql help
238
262
  ```
239
263
 
264
+ Every read command supports `--json` to emit machine-readable output for scripting.
265
+
240
266
  Read-only. For active orchestration, use the MCP from inside Claude Code.
241
267
 
242
268
  ### Branding & colors (v0.5+)
@@ -337,6 +363,13 @@ The bot uses raw `fetch` against Telegram's Bot API — zero extra deps. State i
337
363
  **Symptom: `ENOENT: no such file or directory, mkdir '/.orqlaude'` on `create_plan`.**
338
364
  Your MCP host launched orqlaude with `cwd=/`. v0.3.2+ auto-falls back to `~/.orqlaude/projects/...` but the explicit fix is to set `ORQLAUDE_STATE_DIR` in your `.mcp.json` env block (see `.mcp.json.template`). Verify with `mcp__orqlaude__ping` — it now returns `warnings` and `state_dir_source`.
339
365
 
366
+ **Symptom: `spawn_via_cli` returned a PID but `status()` shows `died_at_launch` shortly after, with a stderr_excerpt + command_line.**
367
+ This is the v0.7.0 hardening doing its job. The child `claude -p` process exited within the 1.5s healthcheck window. Read `stderr_excerpt` (or open `stderr_path` directly) for the cause. Common ones:
368
+ 1. `claude` isn't authenticated on this user account (`claude auth status` to check; `claude auth login --claudeai` to fix).
369
+ 2. The `--mcp-config` JSON references a server entry that doesn't exist (rare; orqlaude validates this pre-spawn).
370
+ 3. The user's environment lacks something `claude` needs (HOME, locale).
371
+ Copy the `command_line` field and paste it into a shell to reproduce by hand.
372
+
340
373
  **Symptom: spawn_task chip appeared, agent ran, but `status()` shows the task as `dispatched` forever.**
341
374
  The child agent isn't calling `checkin` on its first turn — its prompt didn't get the orqlaude protocol block, or `mcp__orqlaude__checkin` isn't available in the spawned session. Manual unblock: `register_spawn(plan_id, task_id, session_id)` where session_id is the child's session UUID (find via `mcp__ccd_session_mgmt__list_sessions`). For the proper fix, make sure orqlaude is in the spawned worktree's `.mcp.json` (commit `.mcp.json` to the repo so worktrees inherit it).
342
375
 
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,74 @@
1
+ import { test } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { promises as fs } from "node:fs";
4
+ import path from "node:path";
5
+ import os from "node:os";
6
+ /** v0.6.0 regression tests covering the polish-pack modules. */
7
+ test("preferences: read/write/update round-trip", async () => {
8
+ const fakeHome = await fs.mkdtemp(path.join(os.tmpdir(), "orqlaude-prefs-"));
9
+ const realHome = process.env.HOME;
10
+ process.env.HOME = fakeHome;
11
+ try {
12
+ // Re-import so PREFS_PATH picks up the new HOME. The module caches the
13
+ // path at import time, so this technique only works in a fresh worker —
14
+ // we accept that and validate the shape rather than the path.
15
+ const { readPreferences, updatePreferences } = await import(`../lib/preferences.js?cache=${Date.now()}`);
16
+ let prefs = await readPreferences();
17
+ assert.deepEqual(prefs, {});
18
+ await updatePreferences((p) => {
19
+ p.welcomedAt = 1234;
20
+ p.localNotifications = true;
21
+ });
22
+ prefs = await readPreferences();
23
+ assert.equal(prefs.welcomedAt, 1234);
24
+ assert.equal(prefs.localNotifications, true);
25
+ }
26
+ finally {
27
+ if (realHome)
28
+ process.env.HOME = realHome;
29
+ else
30
+ delete process.env.HOME;
31
+ }
32
+ });
33
+ test("error_ui: formatError attaches suggestions for known patterns", async () => {
34
+ const { formatError } = await import("../lib/error_ui.js");
35
+ assert.match(formatError(new Error("Plan not found: abc")).suggestion, /orql list/);
36
+ assert.match(formatError(new Error("EACCES: write failed")).suggestion, /ORQLAUDE_STATE_DIR/);
37
+ assert.match(formatError(new Error("ENOENT: nope")).suggestion, /missing path|orql setup/);
38
+ // Unknown messages get no suggestion (returns undefined).
39
+ assert.equal(formatError(new Error("something obscure")).suggestion, undefined);
40
+ });
41
+ test("json_out: hasJsonFlag detects --json anywhere in args", async () => {
42
+ const { hasJsonFlag } = await import("../lib/json_out.js");
43
+ assert.equal(hasJsonFlag([]), false);
44
+ assert.equal(hasJsonFlag(["foo"]), false);
45
+ assert.equal(hasJsonFlag(["--json"]), true);
46
+ assert.equal(hasJsonFlag(["foo", "--json", "bar"]), true);
47
+ });
48
+ test("notifications: isNotificationsAvailable matches platform", async () => {
49
+ const { isNotificationsAvailable } = await import("../lib/notifications.js");
50
+ assert.equal(isNotificationsAvailable(), process.platform === "darwin");
51
+ });
52
+ test("error_ui: errorLine includes ✗ glyph and optional suggestion", async () => {
53
+ const { errorLine } = await import("../lib/error_ui.js");
54
+ const noSuggestion = errorLine("bad");
55
+ // String includes "bad" and the glyph "✗"
56
+ assert.ok(noSuggestion.includes("✗"));
57
+ assert.ok(noSuggestion.includes("bad"));
58
+ const withSuggestion = errorLine("bad", "try foo");
59
+ assert.ok(withSuggestion.includes("try foo"));
60
+ assert.ok(withSuggestion.includes("→"));
61
+ });
62
+ test("v0.6.1 taglines: exactly 149, all non-empty, no consecutive duplicates", async () => {
63
+ const { TAGLINES } = await import("../cli/taglines.js");
64
+ assert.equal(TAGLINES.length, 149);
65
+ for (let i = 0; i < TAGLINES.length; i++) {
66
+ assert.ok(typeof TAGLINES[i] === "string" && TAGLINES[i].length > 0, `tagline ${i} is empty`);
67
+ }
68
+ // The picker uses a never-repeat-last constraint, so duplicates between
69
+ // non-adjacent indices are fine — but adjacent duplicates would defeat it.
70
+ for (let i = 1; i < TAGLINES.length; i++) {
71
+ assert.notEqual(TAGLINES[i], TAGLINES[i - 1], `adjacent duplicate at ${i - 1}/${i}`);
72
+ }
73
+ });
74
+ //# sourceMappingURL=v06.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"v06.test.js","sourceRoot":"","sources":["../../src/__tests__/v06.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,124 @@
1
+ import { test } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { promises as fs, existsSync } from "node:fs";
4
+ import path from "node:path";
5
+ import os from "node:os";
6
+ import { execSync } from "node:child_process";
7
+ import { isProcessAlive } from "../lib/process_lib.js";
8
+ import { spawnAgnetViaCli } from "../lib/spawn_cli.js";
9
+ /**
10
+ * v0.7.0: process-liveness + spawn robustness regression tests.
11
+ */
12
+ test("isProcessAlive: own PID is alive", () => {
13
+ assert.equal(isProcessAlive(process.pid), true);
14
+ });
15
+ test("isProcessAlive: PID 1 reports alive (init exists on every OS)", () => {
16
+ // We don't OWN pid 1, but isProcessAlive should report true via EPERM
17
+ // detection rather than returning false.
18
+ assert.equal(isProcessAlive(1), true);
19
+ });
20
+ test("isProcessAlive: impossibly large PID is dead", () => {
21
+ // 2^31 - 1 is past any realistic process table.
22
+ assert.equal(isProcessAlive(2147483647), false);
23
+ });
24
+ test("isProcessAlive: 0 / negative / undefined are dead", () => {
25
+ assert.equal(isProcessAlive(0), false);
26
+ assert.equal(isProcessAlive(-1), false);
27
+ assert.equal(isProcessAlive(undefined), false);
28
+ assert.equal(isProcessAlive(null), false);
29
+ });
30
+ test("spawnAgnetViaCli: rejects when claude binary doesn't exist", async () => {
31
+ // Build a minimal fake git repo so createWorktreeForTask doesn't fail
32
+ // earlier on its own.
33
+ const dir = await mkTempGitRepo();
34
+ await assert.rejects(() => spawnAgnetViaCli({
35
+ projectRoot: dir,
36
+ stateDir: path.join(dir, ".orqlaude"),
37
+ planId: "deadbeef-1111-2222-3333-444444444444",
38
+ taskId: "11111111-2222-3333-4444-555555555555",
39
+ agnetName: "Test",
40
+ prompt: "noop",
41
+ claudeBin: "/nonexistent/path/to/claude",
42
+ healthCheckDelayMs: 0,
43
+ }), /not executable|ENOENT|EACCES/i);
44
+ });
45
+ test("spawnAgnetViaCli: when child dies at launch, throws with stderr + commandLine", async () => {
46
+ // Use /bin/false (or `false` on PATH) — it exits immediately with code 1.
47
+ // The healthcheck should detect the dead PID and throw with autopsy info.
48
+ const falseBin = existsSync("/bin/false") ? "/bin/false" : "/usr/bin/false";
49
+ if (!existsSync(falseBin)) {
50
+ // Skip on platforms without /bin/false; the contract is otherwise
51
+ // verified by the other tests.
52
+ return;
53
+ }
54
+ const dir = await mkTempGitRepo();
55
+ await assert.rejects(() => spawnAgnetViaCli({
56
+ projectRoot: dir,
57
+ stateDir: path.join(dir, ".orqlaude"),
58
+ planId: "deadbeef-1111-2222-3333-444444444444",
59
+ taskId: "22222222-3333-4444-5555-666666666666",
60
+ agnetName: "Dies",
61
+ prompt: "this prompt should appear in the command line echo",
62
+ claudeBin: falseBin,
63
+ healthCheckDelayMs: 500, // short
64
+ }), (err) => {
65
+ // The error message must include:
66
+ // • "died at launch"
67
+ // • the command line (so we can copy-paste to reproduce)
68
+ // • mention of the prompt as the last arg
69
+ assert.match(err.message, /died at launch/i);
70
+ assert.match(err.message, /Command line:/i);
71
+ assert.match(err.message, /this prompt should appear in the command line echo/);
72
+ return true;
73
+ });
74
+ // After failure, the stderr log file should exist in the worktree.
75
+ const worktreeBase = path.join(dir, ".orqlaude-worktrees");
76
+ const found = await fs.readdir(worktreeBase);
77
+ assert.ok(found.length > 0, "expected a worktree to have been created before the spawn died");
78
+ });
79
+ test("spawnAgnetViaCli: prompt is the LAST positional argv element", async () => {
80
+ // Same /bin/false trick but assert on the exact shape of commandLine
81
+ // captured in the thrown error.
82
+ const falseBin = existsSync("/bin/false") ? "/bin/false" : "/usr/bin/false";
83
+ if (!existsSync(falseBin))
84
+ return;
85
+ const dir = await mkTempGitRepo();
86
+ let captured = null;
87
+ try {
88
+ await spawnAgnetViaCli({
89
+ projectRoot: dir,
90
+ stateDir: path.join(dir, ".orqlaude"),
91
+ planId: "deadbeef-aaaa-bbbb-cccc-dddddddddddd",
92
+ taskId: "33333333-4444-5555-6666-777777777777",
93
+ agnetName: "ArgOrder",
94
+ prompt: "ZZZ_PROMPT_SENTINEL_ZZZ",
95
+ claudeBin: falseBin,
96
+ healthCheckDelayMs: 500,
97
+ });
98
+ }
99
+ catch (err) {
100
+ captured = err.message;
101
+ }
102
+ assert.ok(captured, "expected the spawn to fail and surface the command line");
103
+ // Pull the command-line line from the error message.
104
+ const m = captured.match(/Command line:\n\s*(.+)/);
105
+ assert.ok(m, "error message should contain 'Command line:'");
106
+ const cmd = m[1];
107
+ // The last shell token should be the quoted prompt — i.e. the prompt
108
+ // sentinel should appear AFTER every --flag.
109
+ const promptIdx = cmd.lastIndexOf("ZZZ_PROMPT_SENTINEL_ZZZ");
110
+ const lastFlagIdx = Math.max(cmd.lastIndexOf("--session-id"), cmd.lastIndexOf("--output-format"), cmd.lastIndexOf("--permission-mode"), cmd.lastIndexOf("--mcp-config"));
111
+ assert.ok(promptIdx > lastFlagIdx, `prompt must appear after the last flag — got cmd=\n${cmd}`);
112
+ });
113
+ async function mkTempGitRepo() {
114
+ const raw = await fs.mkdtemp(path.join(os.tmpdir(), "orqlaude-v07-"));
115
+ const real = await fs.realpath(raw);
116
+ execSync("git init -q", { cwd: real });
117
+ execSync("git config user.email t@e", { cwd: real });
118
+ execSync("git config user.name t", { cwd: real });
119
+ // Need at least one commit so `git worktree add -b ...` succeeds.
120
+ await fs.writeFile(path.join(real, "README.md"), "test\n");
121
+ execSync("git add . && git commit -q -m init", { cwd: real });
122
+ return real;
123
+ }
124
+ //# sourceMappingURL=v07.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"v07.test.js","sourceRoot":"","sources":["../../src/__tests__/v07.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * `orql about` — the easter egg. Print a small stylized "what is this"
3
+ * blurb in the brand palette. Just because.
4
+ */
5
+ export declare function showAbout(version: string): number;
@@ -0,0 +1,27 @@
1
+ import { style } from "../lib/style.js";
2
+ /**
3
+ * `orql about` — the easter egg. Print a small stylized "what is this"
4
+ * blurb in the brand palette. Just because.
5
+ */
6
+ export function showAbout(version) {
7
+ const lines = [
8
+ "",
9
+ ` ${style.coral("◆")} ${style.bold(style.coral("orqlaude"))}`,
10
+ "",
11
+ ` ${style.sand("one Claude session decomposes a task,")}`,
12
+ ` ${style.sand("approves a budget,")}`,
13
+ ` ${style.sand("dispatches a fleet of")} ${style.coral("Agnets")} ${style.sand("—")}`,
14
+ ` ${style.sand("each in its own worktree, named, tracked,")}`,
15
+ ` ${style.sand("brokered, budgeted, watchable.")}`,
16
+ "",
17
+ ` ${style.dim(`v${version} · MIT · @synaplink/orqlaude`)}`,
18
+ "",
19
+ ` ${style.cream("\"More agents working on a task in parallel is just")}`,
20
+ ` ${style.cream("a faster way of reaching")} ${style.coral("the same insight")}.${style.cream("\"")}`,
21
+ ` ${style.dim("— Claude (probably)")}`,
22
+ "",
23
+ ];
24
+ process.stdout.write(lines.join("\n"));
25
+ return 0;
26
+ }
27
+ //# sourceMappingURL=about.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"about.js","sourceRoot":"","sources":["../../src/cli/about.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAExC;;;GAGG;AAEH,MAAM,UAAU,SAAS,CAAC,OAAe;IACvC,MAAM,KAAK,GAAG;QACZ,EAAE;QACF,KAAK,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,EAAE;QAC9D,EAAE;QACF,KAAK,KAAK,CAAC,IAAI,CAAC,uCAAuC,CAAC,EAAE;QAC1D,KAAK,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,EAAE;QACvC,KAAK,KAAK,CAAC,IAAI,CAAC,uBAAuB,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;QACtF,KAAK,KAAK,CAAC,IAAI,CAAC,2CAA2C,CAAC,EAAE;QAC9D,KAAK,KAAK,CAAC,IAAI,CAAC,gCAAgC,CAAC,EAAE;QACnD,EAAE;QACF,KAAK,KAAK,CAAC,GAAG,CAAC,IAAI,OAAO,8BAA8B,CAAC,EAAE;QAC3D,EAAE;QACF,KAAK,KAAK,CAAC,KAAK,CAAC,qDAAqD,CAAC,EAAE;QACzE,KAAK,KAAK,CAAC,KAAK,CAAC,0BAA0B,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,kBAAkB,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE;QACtG,KAAK,KAAK,CAAC,GAAG,CAAC,qBAAqB,CAAC,EAAE;QACvC,EAAE;KACH,CAAC;IACF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACvC,OAAO,CAAC,CAAC;AACX,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function runDoctor(currentVersion: string): Promise<number>;
@@ -0,0 +1,180 @@
1
+ import { execSync } from "node:child_process";
2
+ import { existsSync } from "node:fs";
3
+ import path from "node:path";
4
+ import { style, banner } from "../lib/style.js";
5
+ import { discoverClaudeBinary } from "../lib/spawn_cli.js";
6
+ import { resolveStateDir } from "../lib/state_dir.js";
7
+ import { probeTelegramStatus } from "../lib/telegram_status.js";
8
+ import { findDesktopConfigPath, readDesktopConfig } from "../lib/desktop_config.js";
9
+ export async function runDoctor(currentVersion) {
10
+ console.log(banner());
11
+ console.log("");
12
+ console.log(style.bold(style.cream("doctor")));
13
+ console.log("");
14
+ const checks = [];
15
+ // 1. Node version
16
+ const nodeVer = process.version.replace(/^v/, "");
17
+ const major = parseInt(nodeVer.split(".")[0], 10);
18
+ checks.push({
19
+ name: "Node.js >= 22",
20
+ status: major >= 22 ? "ok" : "fail",
21
+ detail: `Node ${nodeVer}`,
22
+ fix: major < 22 ? "Install Node 22+ (brew install node@22)" : undefined,
23
+ });
24
+ // 2. claude binary
25
+ try {
26
+ const claudeBin = discoverClaudeBinary();
27
+ let claudeVer = "(version probe failed)";
28
+ try {
29
+ claudeVer = execSync(`"${claudeBin}" --version`, { encoding: "utf8", timeout: 3000 }).trim();
30
+ }
31
+ catch {
32
+ /* ignore */
33
+ }
34
+ checks.push({ name: "claude binary", status: "ok", detail: `${claudeBin} (${claudeVer})` });
35
+ }
36
+ catch (err) {
37
+ checks.push({
38
+ name: "claude binary",
39
+ status: "fail",
40
+ detail: err.message,
41
+ fix: "Install Claude Code, or set CLAUDE_BIN env var to its path. spawn_via_cli won't work without this.",
42
+ });
43
+ }
44
+ // 3. gh CLI
45
+ try {
46
+ const ghVer = execSync("gh --version", { encoding: "utf8", timeout: 3000 }).split("\n")[0];
47
+ let authed = false;
48
+ try {
49
+ execSync("gh auth status", { encoding: "utf8", timeout: 3000, stdio: "pipe" });
50
+ authed = true;
51
+ }
52
+ catch {
53
+ authed = false;
54
+ }
55
+ checks.push({
56
+ name: "gh CLI + auth",
57
+ status: authed ? "ok" : "warn",
58
+ detail: authed ? ghVer : `${ghVer} (not authenticated)`,
59
+ fix: authed ? undefined : "Run `gh auth login` so Agnets can open PRs.",
60
+ });
61
+ }
62
+ catch {
63
+ checks.push({
64
+ name: "gh CLI + auth",
65
+ status: "warn",
66
+ detail: "gh not installed",
67
+ fix: "brew install gh; gh auth login. Agnets can still run without it, but PRs won't auto-open.",
68
+ });
69
+ }
70
+ // 4. Resolved state dir
71
+ const stateRes = resolveStateDir();
72
+ const stateOk = stateRes.source === "env" || stateRes.source === "project-root" || stateRes.source === "worktree";
73
+ checks.push({
74
+ name: "state dir",
75
+ status: stateOk ? "ok" : "warn",
76
+ detail: `${stateRes.path} (source: ${stateRes.source})`,
77
+ fix: stateOk
78
+ ? undefined
79
+ : `Run \`orql setup\` from your project to pin state via ORQLAUDE_STATE_DIR in the Desktop MCP config.`,
80
+ });
81
+ // 5. Claude Desktop MCP config
82
+ const cfgPath = findDesktopConfigPath();
83
+ if (existsSync(cfgPath)) {
84
+ try {
85
+ const cfg = await readDesktopConfig(cfgPath);
86
+ const entry = cfg?.mcpServers?.orqlaude;
87
+ if (!entry) {
88
+ checks.push({
89
+ name: "Desktop MCP config",
90
+ status: "fail",
91
+ detail: `${cfgPath} exists, but no orqlaude entry`,
92
+ fix: "Run `orql setup` in your project to add the entry.",
93
+ });
94
+ }
95
+ else if (!entry.env?.ORQLAUDE_STATE_DIR) {
96
+ checks.push({
97
+ name: "Desktop MCP config",
98
+ status: "warn",
99
+ detail: "orqlaude entry present but has no ORQLAUDE_STATE_DIR env",
100
+ fix: "Run `orql setup` to pin a state dir; without it, MCP cwd=/ can split state.",
101
+ });
102
+ }
103
+ else {
104
+ checks.push({
105
+ name: "Desktop MCP config",
106
+ status: "ok",
107
+ detail: `ORQLAUDE_STATE_DIR → ${entry.env.ORQLAUDE_STATE_DIR}`,
108
+ });
109
+ }
110
+ }
111
+ catch (err) {
112
+ checks.push({
113
+ name: "Desktop MCP config",
114
+ status: "fail",
115
+ detail: err.message,
116
+ });
117
+ }
118
+ }
119
+ else {
120
+ checks.push({
121
+ name: "Desktop MCP config",
122
+ status: "warn",
123
+ detail: `${cfgPath} does not exist`,
124
+ fix: "Run `orql setup` to create it.",
125
+ });
126
+ }
127
+ // 6. Telegram
128
+ const tg = await probeTelegramStatus(stateRes.path);
129
+ let tgStatus = "ok";
130
+ if (tg.status === "unconfigured")
131
+ tgStatus = "warn";
132
+ else if (tg.status === "stale" || tg.status === "configured" || tg.status === "started")
133
+ tgStatus = "warn";
134
+ checks.push({
135
+ name: "Telegram bot",
136
+ status: tgStatus,
137
+ detail: `${tg.status} (token: ${tg.hasToken ? "set" : "missing"}, whitelist: ${tg.whitelistSize})`,
138
+ fix: tg.status === "unconfigured"
139
+ ? "`orql tg setup` to wire a bot — optional but recommended."
140
+ : tg.status === "stale" || tg.status === "configured" || tg.status === "started"
141
+ ? "Run `orql tg start` from your project to bring the bot online."
142
+ : undefined,
143
+ });
144
+ // 7. orqlaude self-test (MCP server startup)
145
+ try {
146
+ const serverPath = path.resolve(path.dirname(new URL(import.meta.url).pathname), "..", "server.js");
147
+ if (existsSync(serverPath)) {
148
+ checks.push({ name: "orqlaude MCP server", status: "ok", detail: `${serverPath}` });
149
+ }
150
+ else {
151
+ checks.push({
152
+ name: "orqlaude MCP server",
153
+ status: "fail",
154
+ detail: `Missing ${serverPath}`,
155
+ fix: "Reinstall: npm i -g @synaplink/orqlaude@latest",
156
+ });
157
+ }
158
+ }
159
+ catch (err) {
160
+ checks.push({ name: "orqlaude MCP server", status: "warn", detail: err.message });
161
+ }
162
+ // Render
163
+ const counts = { ok: 0, warn: 0, fail: 0 };
164
+ for (const c of checks) {
165
+ counts[c.status]++;
166
+ const glyph = c.status === "ok"
167
+ ? style.coral("✓")
168
+ : c.status === "warn"
169
+ ? style.crimson("⚠")
170
+ : style.crimson("✗");
171
+ console.log(` ${glyph} ${style.bold(c.name.padEnd(26))} ${c.detail}`);
172
+ if (c.fix)
173
+ console.log(` ${style.coral("→")} ${style.sand(c.fix)}`);
174
+ }
175
+ console.log("");
176
+ const summary = `${style.coral(`${counts.ok} ok`)} · ${style.crimson(`${counts.warn} warn`)} · ${style.crimson(`${counts.fail} fail`)}`;
177
+ console.log(` ${summary} ${style.dim(`(orqlaude ${currentVersion})`)}`);
178
+ return counts.fail > 0 ? 1 : 0;
179
+ }
180
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function runEasterEgg(): Promise<number>;
@@ -0,0 +1,92 @@
1
+ import { TAGLINES } from "./taglines.js";
2
+ import { style } from "../lib/style.js";
3
+ /**
4
+ * Bare `orql` easter egg — a never-repeating typewriter cycling through
5
+ * 149 tagline variants under the orqlaude diamond logo. Runs until Ctrl-C.
6
+ *
7
+ * The natural terminal cursor sits at the end of each tagline while it's
8
+ * displayed and blinks on its own — no explicit blink animation needed.
9
+ */
10
+ const ESC = "\x1b[";
11
+ const SAVE = `${ESC}s`;
12
+ const RESTORE = `${ESC}u`;
13
+ const CLEAR_TO_EOL = `${ESC}K`;
14
+ const SAND_FG = `${ESC}38;2;185;182;171m`;
15
+ const RESET = `${ESC}0m`;
16
+ const TYPE_MIN_MS = 28;
17
+ const TYPE_MAX_MS = 90;
18
+ const HOLD_MIN_MS = 1100;
19
+ const HOLD_MAX_MS = 2200;
20
+ const ERASE_MIN_MS = 12;
21
+ const ERASE_MAX_MS = 30;
22
+ const BETWEEN_MIN_MS = 280;
23
+ const BETWEEN_MAX_MS = 600;
24
+ export async function runEasterEgg() {
25
+ return new Promise((resolve) => {
26
+ let stopped = false;
27
+ const onSig = () => {
28
+ stopped = true;
29
+ // Move cursor below the tagline line and reset, then exit.
30
+ process.stdout.write(RESET + "\n\n");
31
+ resolve(0);
32
+ };
33
+ process.on("SIGINT", onSig);
34
+ // Static logo + wordmark. Last line ends without a newline so the
35
+ // cursor sits where taglines should animate.
36
+ const logo = [
37
+ ` ${style.coral("◆◆◆")}`,
38
+ ` ${style.coral("◆ ◆")} ${style.bold(style.coral("orqlaude"))}`,
39
+ ` ${style.coral("◆◆◆")} `, // trailing spaces are the "padding" before the tagline
40
+ ];
41
+ process.stdout.write("\n" + logo.join("\n"));
42
+ process.stdout.write(SAVE);
43
+ // Animate in a loop. We do this without `await` in the main scope so
44
+ // SIGINT can interrupt cleanly via the `stopped` flag check between
45
+ // sleeps.
46
+ (async () => {
47
+ let lastIdx = -1;
48
+ while (!stopped) {
49
+ let idx = Math.floor(Math.random() * TAGLINES.length);
50
+ // Never repeat the previous tagline.
51
+ while (idx === lastIdx) {
52
+ idx = Math.floor(Math.random() * TAGLINES.length);
53
+ }
54
+ lastIdx = idx;
55
+ const tagline = TAGLINES[idx];
56
+ // Reset cursor + clear any leftover from the previous tagline.
57
+ process.stdout.write(RESTORE + CLEAR_TO_EOL + SAND_FG);
58
+ // Type out character by character. Each char is plain text — the
59
+ // SAND_FG above persists until we reset, so a single \b backspace
60
+ // erases one visible character.
61
+ for (let i = 0; i < tagline.length; i++) {
62
+ if (stopped)
63
+ return;
64
+ process.stdout.write(tagline[i]);
65
+ await sleep(rand(TYPE_MIN_MS, TYPE_MAX_MS));
66
+ }
67
+ // Hold while the natural terminal cursor blinks at the end.
68
+ await sleep(rand(HOLD_MIN_MS, HOLD_MAX_MS));
69
+ if (stopped)
70
+ return;
71
+ // Erase backwards for a satisfying "delete" feel.
72
+ for (let i = tagline.length; i > 0; i--) {
73
+ if (stopped)
74
+ return;
75
+ process.stdout.write("\b \b");
76
+ await sleep(rand(ERASE_MIN_MS, ERASE_MAX_MS));
77
+ }
78
+ process.stdout.write(RESET);
79
+ await sleep(rand(BETWEEN_MIN_MS, BETWEEN_MAX_MS));
80
+ }
81
+ })().catch(() => {
82
+ /* swallow — never crash on the easter egg */
83
+ });
84
+ });
85
+ }
86
+ function sleep(ms) {
87
+ return new Promise((res) => setTimeout(res, ms));
88
+ }
89
+ function rand(min, max) {
90
+ return min + Math.random() * (max - min);
91
+ }
92
+ //# sourceMappingURL=easter_egg.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"easter_egg.js","sourceRoot":"","sources":["../../src/cli/easter_egg.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * `orql open <plan_id>` — open every PR URL the fleet produced in the
3
+ * default browser, plus print worktree paths for tasks that don't yet
4
+ * have PRs.
5
+ */
6
+ export declare function openPlan(stateDir: string, planId: string): Promise<number>;