ghostrail 0.0.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 (218) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +16 -0
  3. package/README.md +56 -0
  4. package/dist/agent/claude-code.d.ts +37 -0
  5. package/dist/agent/claude-code.d.ts.map +1 -0
  6. package/dist/agent/claude-code.js +74 -0
  7. package/dist/agent/claude-code.js.map +1 -0
  8. package/dist/agent/index.d.ts +4 -0
  9. package/dist/agent/index.d.ts.map +1 -0
  10. package/dist/agent/index.js +4 -0
  11. package/dist/agent/index.js.map +1 -0
  12. package/dist/agent/prompt.d.ts +9 -0
  13. package/dist/agent/prompt.d.ts.map +1 -0
  14. package/dist/agent/prompt.js +15 -0
  15. package/dist/agent/prompt.js.map +1 -0
  16. package/dist/agent/result.d.ts +16 -0
  17. package/dist/agent/result.d.ts.map +1 -0
  18. package/dist/agent/result.js +56 -0
  19. package/dist/agent/result.js.map +1 -0
  20. package/dist/args.d.ts +27 -0
  21. package/dist/args.d.ts.map +1 -0
  22. package/dist/args.js +25 -0
  23. package/dist/args.js.map +1 -0
  24. package/dist/backend/container.d.ts +18 -0
  25. package/dist/backend/container.d.ts.map +1 -0
  26. package/dist/backend/container.js +70 -0
  27. package/dist/backend/container.js.map +1 -0
  28. package/dist/backend/docker.d.ts +22 -0
  29. package/dist/backend/docker.d.ts.map +1 -0
  30. package/dist/backend/docker.js +38 -0
  31. package/dist/backend/docker.js.map +1 -0
  32. package/dist/backend/fs.d.ts +9 -0
  33. package/dist/backend/fs.d.ts.map +1 -0
  34. package/dist/backend/fs.js +21 -0
  35. package/dist/backend/fs.js.map +1 -0
  36. package/dist/backend/index.d.ts +7 -0
  37. package/dist/backend/index.d.ts.map +1 -0
  38. package/dist/backend/index.js +6 -0
  39. package/dist/backend/index.js.map +1 -0
  40. package/dist/backend/local-worktree.d.ts +17 -0
  41. package/dist/backend/local-worktree.d.ts.map +1 -0
  42. package/dist/backend/local-worktree.js +51 -0
  43. package/dist/backend/local-worktree.js.map +1 -0
  44. package/dist/backend/proc.d.ts +24 -0
  45. package/dist/backend/proc.d.ts.map +1 -0
  46. package/dist/backend/proc.js +103 -0
  47. package/dist/backend/proc.js.map +1 -0
  48. package/dist/backend/types.d.ts +75 -0
  49. package/dist/backend/types.d.ts.map +1 -0
  50. package/dist/backend/types.js +12 -0
  51. package/dist/backend/types.js.map +1 -0
  52. package/dist/bin.d.ts +3 -0
  53. package/dist/bin.d.ts.map +1 -0
  54. package/dist/bin.js +10 -0
  55. package/dist/bin.js.map +1 -0
  56. package/dist/board/index.d.ts +4 -0
  57. package/dist/board/index.d.ts.map +1 -0
  58. package/dist/board/index.js +4 -0
  59. package/dist/board/index.js.map +1 -0
  60. package/dist/board/page.d.ts +3 -0
  61. package/dist/board/page.d.ts.map +1 -0
  62. package/dist/board/page.js +55 -0
  63. package/dist/board/page.js.map +1 -0
  64. package/dist/board/server.d.ts +36 -0
  65. package/dist/board/server.d.ts.map +1 -0
  66. package/dist/board/server.js +110 -0
  67. package/dist/board/server.js.map +1 -0
  68. package/dist/board/stats.d.ts +26 -0
  69. package/dist/board/stats.d.ts.map +1 -0
  70. package/dist/board/stats.js +57 -0
  71. package/dist/board/stats.js.map +1 -0
  72. package/dist/cli/commands.d.ts +39 -0
  73. package/dist/cli/commands.d.ts.map +1 -0
  74. package/dist/cli/commands.js +224 -0
  75. package/dist/cli/commands.js.map +1 -0
  76. package/dist/cli.d.ts +16 -0
  77. package/dist/cli.d.ts.map +1 -0
  78. package/dist/cli.js +45 -0
  79. package/dist/cli.js.map +1 -0
  80. package/dist/commands/help.d.ts +6 -0
  81. package/dist/commands/help.d.ts.map +1 -0
  82. package/dist/commands/help.js +29 -0
  83. package/dist/commands/help.js.map +1 -0
  84. package/dist/config/duration.d.ts +14 -0
  85. package/dist/config/duration.d.ts.map +1 -0
  86. package/dist/config/duration.js +25 -0
  87. package/dist/config/duration.js.map +1 -0
  88. package/dist/config/index.d.ts +5 -0
  89. package/dist/config/index.d.ts.map +1 -0
  90. package/dist/config/index.js +4 -0
  91. package/dist/config/index.js.map +1 -0
  92. package/dist/config/load.d.ts +26 -0
  93. package/dist/config/load.d.ts.map +1 -0
  94. package/dist/config/load.js +306 -0
  95. package/dist/config/load.js.map +1 -0
  96. package/dist/config/result.d.ts +18 -0
  97. package/dist/config/result.d.ts.map +1 -0
  98. package/dist/config/result.js +7 -0
  99. package/dist/config/result.js.map +1 -0
  100. package/dist/config/schema.d.ts +77 -0
  101. package/dist/config/schema.d.ts.map +1 -0
  102. package/dist/config/schema.js +35 -0
  103. package/dist/config/schema.js.map +1 -0
  104. package/dist/factory/build.d.ts +39 -0
  105. package/dist/factory/build.d.ts.map +1 -0
  106. package/dist/factory/build.js +85 -0
  107. package/dist/factory/build.js.map +1 -0
  108. package/dist/gate/gate.d.ts +12 -0
  109. package/dist/gate/gate.d.ts.map +1 -0
  110. package/dist/gate/gate.js +22 -0
  111. package/dist/gate/gate.js.map +1 -0
  112. package/dist/gate/index.d.ts +2 -0
  113. package/dist/gate/index.d.ts.map +1 -0
  114. package/dist/gate/index.js +2 -0
  115. package/dist/gate/index.js.map +1 -0
  116. package/dist/global/index.d.ts +3 -0
  117. package/dist/global/index.d.ts.map +1 -0
  118. package/dist/global/index.js +3 -0
  119. package/dist/global/index.js.map +1 -0
  120. package/dist/global/stage.d.ts +13 -0
  121. package/dist/global/stage.d.ts.map +1 -0
  122. package/dist/global/stage.js +24 -0
  123. package/dist/global/stage.js.map +1 -0
  124. package/dist/global/store.d.ts +30 -0
  125. package/dist/global/store.d.ts.map +1 -0
  126. package/dist/global/store.js +65 -0
  127. package/dist/global/store.js.map +1 -0
  128. package/dist/lock/file-lock.d.ts +16 -0
  129. package/dist/lock/file-lock.d.ts.map +1 -0
  130. package/dist/lock/file-lock.js +51 -0
  131. package/dist/lock/file-lock.js.map +1 -0
  132. package/dist/loop/branch.d.ts +14 -0
  133. package/dist/loop/branch.d.ts.map +1 -0
  134. package/dist/loop/branch.js +24 -0
  135. package/dist/loop/branch.js.map +1 -0
  136. package/dist/loop/engine.d.ts +37 -0
  137. package/dist/loop/engine.d.ts.map +1 -0
  138. package/dist/loop/engine.js +204 -0
  139. package/dist/loop/engine.js.map +1 -0
  140. package/dist/loop/index.d.ts +6 -0
  141. package/dist/loop/index.d.ts.map +1 -0
  142. package/dist/loop/index.js +3 -0
  143. package/dist/loop/index.js.map +1 -0
  144. package/dist/loop/ports.d.ts +97 -0
  145. package/dist/loop/ports.d.ts.map +1 -0
  146. package/dist/loop/ports.js +2 -0
  147. package/dist/loop/ports.js.map +1 -0
  148. package/dist/loop/record.d.ts +26 -0
  149. package/dist/loop/record.d.ts.map +1 -0
  150. package/dist/loop/record.js +2 -0
  151. package/dist/loop/record.js.map +1 -0
  152. package/dist/publish/gh.d.ts +24 -0
  153. package/dist/publish/gh.d.ts.map +1 -0
  154. package/dist/publish/gh.js +109 -0
  155. package/dist/publish/gh.js.map +1 -0
  156. package/dist/publish/githost.d.ts +54 -0
  157. package/dist/publish/githost.d.ts.map +1 -0
  158. package/dist/publish/githost.js +33 -0
  159. package/dist/publish/githost.js.map +1 -0
  160. package/dist/publish/github-publisher.d.ts +30 -0
  161. package/dist/publish/github-publisher.d.ts.map +1 -0
  162. package/dist/publish/github-publisher.js +51 -0
  163. package/dist/publish/github-publisher.js.map +1 -0
  164. package/dist/publish/index.d.ts +4 -0
  165. package/dist/publish/index.d.ts.map +1 -0
  166. package/dist/publish/index.js +4 -0
  167. package/dist/publish/index.js.map +1 -0
  168. package/dist/respond/index.d.ts +4 -0
  169. package/dist/respond/index.d.ts.map +1 -0
  170. package/dist/respond/index.js +4 -0
  171. package/dist/respond/index.js.map +1 -0
  172. package/dist/respond/respond.d.ts +42 -0
  173. package/dist/respond/respond.d.ts.map +1 -0
  174. package/dist/respond/respond.js +128 -0
  175. package/dist/respond/respond.js.map +1 -0
  176. package/dist/respond/select.d.ts +22 -0
  177. package/dist/respond/select.d.ts.map +1 -0
  178. package/dist/respond/select.js +31 -0
  179. package/dist/respond/select.js.map +1 -0
  180. package/dist/respond/store.d.ts +25 -0
  181. package/dist/respond/store.d.ts.map +1 -0
  182. package/dist/respond/store.js +49 -0
  183. package/dist/respond/store.js.map +1 -0
  184. package/dist/secrets/redact.d.ts +11 -0
  185. package/dist/secrets/redact.d.ts.map +1 -0
  186. package/dist/secrets/redact.js +21 -0
  187. package/dist/secrets/redact.js.map +1 -0
  188. package/dist/source/index.d.ts +2 -0
  189. package/dist/source/index.d.ts.map +1 -0
  190. package/dist/source/index.js +2 -0
  191. package/dist/source/index.js.map +1 -0
  192. package/dist/source/linear.d.ts +61 -0
  193. package/dist/source/linear.d.ts.map +1 -0
  194. package/dist/source/linear.js +166 -0
  195. package/dist/source/linear.js.map +1 -0
  196. package/dist/store/events.d.ts +105 -0
  197. package/dist/store/events.d.ts.map +1 -0
  198. package/dist/store/events.js +64 -0
  199. package/dist/store/events.js.map +1 -0
  200. package/dist/store/file-store.d.ts +49 -0
  201. package/dist/store/file-store.d.ts.map +1 -0
  202. package/dist/store/file-store.js +188 -0
  203. package/dist/store/file-store.js.map +1 -0
  204. package/dist/store/index.d.ts +3 -0
  205. package/dist/store/index.d.ts.map +1 -0
  206. package/dist/store/index.js +3 -0
  207. package/dist/store/index.js.map +1 -0
  208. package/dist/version.d.ts +3 -0
  209. package/dist/version.d.ts.map +1 -0
  210. package/dist/version.js +21 -0
  211. package/dist/version.js.map +1 -0
  212. package/package.json +52 -0
  213. package/templates/content-loop/README.md +23 -0
  214. package/templates/content-loop/ghostrail.toml +36 -0
  215. package/templates/content-loop/prompts/draft.md +29 -0
  216. package/templates/fix-bugs-local/README.md +23 -0
  217. package/templates/fix-bugs-local/ghostrail.toml +37 -0
  218. package/templates/fix-bugs-local/prompts/fix-bug.md +27 -0
@@ -0,0 +1,55 @@
1
+ /** The self-contained board page: polls the read API and renders runs + stats. */
2
+ export const PAGE_HTML = `<!doctype html>
3
+ <html lang="en">
4
+ <head>
5
+ <meta charset="utf-8" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
7
+ <title>ghostrail board</title>
8
+ <style>
9
+ :root { color-scheme: light dark; }
10
+ body { font: 14px/1.5 system-ui, sans-serif; margin: 0; padding: 1.5rem; }
11
+ h1 { font-size: 1.1rem; margin: 0 0 1rem; }
12
+ .stats { display: flex; gap: 1rem; flex-wrap: wrap; margin-bottom: 1rem; }
13
+ .stat { border: 1px solid #8884; border-radius: 8px; padding: .5rem .75rem; }
14
+ .stat b { display: block; font-size: 1.3rem; }
15
+ table { border-collapse: collapse; width: 100%; }
16
+ th, td { text-align: left; padding: .4rem .6rem; border-bottom: 1px solid #8883; }
17
+ .state { font-weight: 600; }
18
+ .done { color: #2a9d3a; } .failed { color: #d33; } .blocked { color: #d90; }
19
+ .noop, .skipped { opacity: .6; } .muted { opacity: .6; }
20
+ a { color: inherit; }
21
+ </style>
22
+ </head>
23
+ <body>
24
+ <h1>ghostrail board</h1>
25
+ <div class="stats" id="stats"></div>
26
+ <table><thead><tr><th>Run</th><th>Item</th><th>State</th><th>Backend</th><th>Gate</th><th>PR</th><th>When</th></tr></thead>
27
+ <tbody id="rows"></tbody></table>
28
+ <script>
29
+ const esc = (s) => String(s ?? "").replace(/[&<>]/g, (c) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;" }[c]));
30
+ async function refresh() {
31
+ const [runs, stats] = await Promise.all([
32
+ fetch("api/runs").then((r) => r.json()),
33
+ fetch("api/stats").then((r) => r.json()),
34
+ ]);
35
+ document.getElementById("stats").innerHTML = [
36
+ ["runs", stats.total],
37
+ ["success", (stats.successRate * 100).toFixed(0) + "%"],
38
+ ["PRs", stats.prCount],
39
+ ].map(([k, v]) => '<div class="stat"><b>' + esc(v) + "</b>" + esc(k) + "</div>").join("");
40
+ document.getElementById("rows").innerHTML = runs.map((r) => {
41
+ const gate = (r.gate || []).map((s) => (s.exitCode === 0 ? "✓" : "✗")).join("");
42
+ const pr = r.prUrl ? '<a href="' + esc(r.prUrl) + '">#' + esc(r.prNumber) + "</a>" : "";
43
+ const when = r.startedAt ? new Date(r.startedAt).toLocaleString() : "";
44
+ const state = esc(r.state || "in-progress");
45
+ return "<tr><td class=muted>" + esc(r.runId.slice(0, 8)) + "</td><td>" + esc(r.title || r.itemId || "") +
46
+ '</td><td class="state ' + state + '">' + state + "</td><td>" + esc(r.backend || "") +
47
+ "</td><td>" + gate + "</td><td>" + pr + "</td><td class=muted>" + esc(when) + "</td></tr>";
48
+ }).join("");
49
+ }
50
+ refresh();
51
+ setInterval(refresh, 5000);
52
+ </script>
53
+ </body>
54
+ </html>`;
55
+ //# sourceMappingURL=page.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page.js","sourceRoot":"","sources":["../../src/board/page.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,MAAM,CAAC,MAAM,SAAS,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAoDjB,CAAC"}
@@ -0,0 +1,36 @@
1
+ import { type Server } from "node:http";
2
+ import type { FileStore } from "../store/file-store.js";
3
+ export type Route = {
4
+ kind: "page";
5
+ } | {
6
+ kind: "runs";
7
+ } | {
8
+ kind: "run";
9
+ id: string;
10
+ } | {
11
+ kind: "events";
12
+ id: string;
13
+ } | {
14
+ kind: "stats";
15
+ } | {
16
+ kind: "artifact";
17
+ hash: string;
18
+ } | {
19
+ kind: "notfound";
20
+ };
21
+ /** Map a request pathname to a board route. Pure. */
22
+ export declare function parseRoute(pathname: string): Route;
23
+ export interface BoardOptions {
24
+ /** Address to bind. Defaults to loopback. */
25
+ bind?: string;
26
+ /** When set, requests must present this token (header `x-ghostrail-token` or `?token=`). */
27
+ token?: string;
28
+ }
29
+ /**
30
+ * Build the board's HTTP server over the store: a static page plus a small read
31
+ * API (`/api/runs`, `/api/runs/:id`, `/api/runs/:id/events`, `/api/stats`,
32
+ * `/api/artifacts/:hash`). When a token is configured (required whenever the
33
+ * bind is not loopback), every request must present it.
34
+ */
35
+ export declare function createBoardServer(store: FileStore, options?: BoardOptions): Server;
36
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/board/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,KAAK,MAAM,EAAqC,MAAM,WAAW,CAAC;AACjG,OAAO,KAAK,EAAE,SAAS,EAAa,MAAM,wBAAwB,CAAC;AAInE,MAAM,MAAM,KAAK,GACb;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC3B;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC;AAEzB,qDAAqD;AACrD,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,KAAK,CAiBlD;AAED,MAAM,WAAW,YAAY;IAC3B,6CAA6C;IAC7C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,4FAA4F;IAC5F,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAYD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,GAAE,YAAiB,GAAG,MAAM,CAWtF"}
@@ -0,0 +1,110 @@
1
+ import { createServer } from "node:http";
2
+ import { PAGE_HTML } from "./page.js";
3
+ import { computeStats } from "./stats.js";
4
+ /** Map a request pathname to a board route. Pure. */
5
+ export function parseRoute(pathname) {
6
+ if (pathname === "/" || pathname === "")
7
+ return { kind: "page" };
8
+ const parts = pathname.split("/").filter((p) => p.length > 0);
9
+ if (parts[0] !== "api")
10
+ return { kind: "notfound" };
11
+ if (parts[1] === "runs") {
12
+ if (parts.length === 2)
13
+ return { kind: "runs" };
14
+ const id = decodeURIComponent(parts[2] ?? "");
15
+ if (parts.length === 3)
16
+ return { kind: "run", id };
17
+ if (parts.length === 4 && parts[3] === "events")
18
+ return { kind: "events", id };
19
+ return { kind: "notfound" };
20
+ }
21
+ if (parts[1] === "stats" && parts.length === 2)
22
+ return { kind: "stats" };
23
+ if (parts[1] === "artifacts" && parts.length === 3) {
24
+ return { kind: "artifact", hash: decodeURIComponent(parts[2] ?? "") };
25
+ }
26
+ return { kind: "notfound" };
27
+ }
28
+ function isLoopback(bind) {
29
+ return bind === "127.0.0.1" || bind === "::1" || bind === "localhost";
30
+ }
31
+ function sendJson(res, status, data) {
32
+ const body = JSON.stringify(data);
33
+ res.writeHead(status, { "content-type": "application/json" });
34
+ res.end(body);
35
+ }
36
+ /**
37
+ * Build the board's HTTP server over the store: a static page plus a small read
38
+ * API (`/api/runs`, `/api/runs/:id`, `/api/runs/:id/events`, `/api/stats`,
39
+ * `/api/artifacts/:hash`). When a token is configured (required whenever the
40
+ * bind is not loopback), every request must present it.
41
+ */
42
+ export function createBoardServer(store, options = {}) {
43
+ const bind = options.bind ?? "127.0.0.1";
44
+ if (!isLoopback(bind) && options.token === undefined) {
45
+ throw new Error("a token is required to bind the board to a non-loopback address");
46
+ }
47
+ return createServer((req, res) => {
48
+ handle(store, options, req, res).catch(() => {
49
+ if (!res.headersSent)
50
+ sendJson(res, 500, { error: "internal error" });
51
+ });
52
+ });
53
+ }
54
+ async function handle(store, options, req, res) {
55
+ const url = new URL(req.url ?? "/", "http://localhost");
56
+ if (options.token !== undefined) {
57
+ const presented = req.headers["x-ghostrail-token"] ?? url.searchParams.get("token") ?? "";
58
+ if (presented !== options.token) {
59
+ sendJson(res, 401, { error: "unauthorized" });
60
+ return;
61
+ }
62
+ }
63
+ const route = parseRoute(url.pathname);
64
+ switch (route.kind) {
65
+ case "page":
66
+ res.writeHead(200, { "content-type": "text/html; charset=utf-8" });
67
+ res.end(PAGE_HTML);
68
+ return;
69
+ case "runs": {
70
+ const filter = {};
71
+ const state = url.searchParams.get("state");
72
+ const since = url.searchParams.get("since");
73
+ if (state !== null)
74
+ filter.state = state;
75
+ if (since !== null && Number.isFinite(Number(since)))
76
+ filter.since = Number(since);
77
+ sendJson(res, 200, await store.listRuns(filter));
78
+ return;
79
+ }
80
+ case "run": {
81
+ const row = await store.getRun(route.id);
82
+ if (row === undefined) {
83
+ sendJson(res, 404, { error: "not found" });
84
+ return;
85
+ }
86
+ sendJson(res, 200, { row, events: await store.getEvents(route.id) });
87
+ return;
88
+ }
89
+ case "events":
90
+ sendJson(res, 200, await store.getEvents(route.id));
91
+ return;
92
+ case "stats":
93
+ sendJson(res, 200, computeStats(await store.listRuns()));
94
+ return;
95
+ case "artifact": {
96
+ const blob = await store.getArtifact(route.hash);
97
+ if (blob === undefined) {
98
+ sendJson(res, 404, { error: "not found" });
99
+ return;
100
+ }
101
+ res.writeHead(200, { "content-type": "application/octet-stream" });
102
+ res.end(blob);
103
+ return;
104
+ }
105
+ case "notfound":
106
+ sendJson(res, 404, { error: "not found" });
107
+ return;
108
+ }
109
+ }
110
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/board/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import type { RunRow } from "../store/events.js";
2
+ export interface Stats {
3
+ total: number;
4
+ /** Count of runs per outcome state; runs with no state yet are "in-progress". */
5
+ byState: Record<string, number>;
6
+ /** Runs that opened a PR. */
7
+ prCount: number;
8
+ /** done / (runs that reached a terminal state), 0 when there are none. */
9
+ successRate: number;
10
+ /** Median finishedAt-startedAt over runs that have both, or null. */
11
+ medianDurationMs: number | null;
12
+ /** Gate step names that failed, with counts, most-frequent first. */
13
+ gateFailures: {
14
+ name: string;
15
+ count: number;
16
+ }[];
17
+ }
18
+ /**
19
+ * Aggregate run rows into board statistics. Pure: depends only on the rows.
20
+ * `byState` counts each row's state (a row with no state yet is "in-progress").
21
+ * `successRate` is done over the runs that reached a terminal state.
22
+ * `medianDurationMs` is over rows with both a start and finish. `gateFailures`
23
+ * counts non-zero gate steps by name, most frequent first (ties broken by name).
24
+ */
25
+ export declare function computeStats(rows: readonly RunRow[]): Stats;
26
+ //# sourceMappingURL=stats.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stats.d.ts","sourceRoot":"","sources":["../../src/board/stats.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAEjD,MAAM,WAAW,KAAK;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,iFAAiF;IACjF,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,6BAA6B;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,WAAW,EAAE,MAAM,CAAC;IACpB,qEAAqE;IACrE,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,qEAAqE;IACrE,YAAY,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACjD;AAaD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,KAAK,CAqC3D"}
@@ -0,0 +1,57 @@
1
+ /** Median of a numeric list (average of the two middles for even length); null if empty. */
2
+ function median(values) {
3
+ if (values.length === 0)
4
+ return null;
5
+ const sorted = [...values].sort((a, b) => a - b);
6
+ const mid = Math.floor(sorted.length / 2);
7
+ if (sorted.length % 2 === 1)
8
+ return sorted[mid] ?? null;
9
+ const lo = sorted[mid - 1];
10
+ const hi = sorted[mid];
11
+ return lo !== undefined && hi !== undefined ? (lo + hi) / 2 : null;
12
+ }
13
+ /**
14
+ * Aggregate run rows into board statistics. Pure: depends only on the rows.
15
+ * `byState` counts each row's state (a row with no state yet is "in-progress").
16
+ * `successRate` is done over the runs that reached a terminal state.
17
+ * `medianDurationMs` is over rows with both a start and finish. `gateFailures`
18
+ * counts non-zero gate steps by name, most frequent first (ties broken by name).
19
+ */
20
+ export function computeStats(rows) {
21
+ const byState = {};
22
+ const durations = [];
23
+ const gateFailCounts = new Map();
24
+ let prCount = 0;
25
+ let terminal = 0;
26
+ let done = 0;
27
+ for (const row of rows) {
28
+ const state = row.state ?? "in-progress";
29
+ byState[state] = (byState[state] ?? 0) + 1;
30
+ if (row.prNumber !== undefined)
31
+ prCount++;
32
+ if (row.state !== undefined) {
33
+ terminal++;
34
+ if (row.state === "done")
35
+ done++;
36
+ }
37
+ if (row.startedAt !== undefined && row.finishedAt !== undefined) {
38
+ durations.push(row.finishedAt - row.startedAt);
39
+ }
40
+ for (const step of row.gate) {
41
+ if (step.exitCode !== 0)
42
+ gateFailCounts.set(step.name, (gateFailCounts.get(step.name) ?? 0) + 1);
43
+ }
44
+ }
45
+ const gateFailures = [...gateFailCounts.entries()]
46
+ .map(([name, count]) => ({ name, count }))
47
+ .sort((a, b) => b.count - a.count || a.name.localeCompare(b.name));
48
+ return {
49
+ total: rows.length,
50
+ byState,
51
+ prCount,
52
+ successRate: terminal === 0 ? 0 : done / terminal,
53
+ medianDurationMs: median(durations),
54
+ gateFailures,
55
+ };
56
+ }
57
+ //# sourceMappingURL=stats.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stats.js","sourceRoot":"","sources":["../../src/board/stats.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ export interface CommandStreams {
2
+ out: (text: string) => void;
3
+ err: (text: string) => void;
4
+ }
5
+ export interface CommandFlags {
6
+ config: string;
7
+ repo: string;
8
+ }
9
+ /**
10
+ * Parse the flags shared by `run` and `respond`: `--config`/`-c <path>` and
11
+ * `--repo`/`-C <path>`, starting from the given defaults. Unknown tokens are
12
+ * ignored. A flag missing its value is ignored.
13
+ */
14
+ export declare function parseCommandFlags(argv: readonly string[], defaults: CommandFlags): CommandFlags;
15
+ interface CommandEnv {
16
+ [key: string]: string | undefined;
17
+ }
18
+ /** `ghostrail run`: drain eligible work once. */
19
+ export declare function cmdRun(argv: readonly string[], streams: CommandStreams, env?: CommandEnv, cwd?: string): Promise<number>;
20
+ /** `ghostrail respond`: fold new human PR comments back into their branches. */
21
+ export declare function cmdRespond(argv: readonly string[], streams: CommandStreams, env?: CommandEnv, cwd?: string): Promise<number>;
22
+ interface BoardFlags {
23
+ repo: string;
24
+ port: number;
25
+ bind: string;
26
+ token?: string;
27
+ }
28
+ /** Parse `board` flags: `--repo`, `--port`, `--bind`, `--token`. */
29
+ export declare function parseBoardFlags(argv: readonly string[], defaults: BoardFlags): BoardFlags;
30
+ /** `ghostrail board`: serve the run store as a dashboard. Runs until stopped. */
31
+ export declare function cmdBoard(argv: readonly string[], streams: CommandStreams, env?: CommandEnv, cwd?: string): Promise<number>;
32
+ /** `ghostrail artifacts`: list the shared artifacts available in the global store. */
33
+ export declare function cmdArtifacts(argv: readonly string[], streams: CommandStreams, env?: CommandEnv): Promise<number>;
34
+ /** The quickstart templates bundled with the package. */
35
+ export declare const TEMPLATES: readonly ["fix-bugs-local", "content-loop"];
36
+ /** `ghostrail init <template>`: scaffold a repo from a quickstart template. */
37
+ export declare function cmdInit(argv: readonly string[], streams: CommandStreams, cwd?: string): Promise<number>;
38
+ export {};
39
+ //# sourceMappingURL=commands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/cli/commands.ts"],"names":[],"mappings":"AAiBA,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,QAAQ,EAAE,YAAY,GAAG,YAAY,CAc/F;AAED,UAAU,UAAU;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CACnC;AAkDD,iDAAiD;AACjD,wBAAsB,MAAM,CAC1B,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,OAAO,EAAE,cAAc,EACvB,GAAG,GAAE,UAAwB,EAC7B,GAAG,SAAgB,GAClB,OAAO,CAAC,MAAM,CAAC,CAyBjB;AAED,gFAAgF;AAChF,wBAAsB,UAAU,CAC9B,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,OAAO,EAAE,cAAc,EACvB,GAAG,GAAE,UAAwB,EAC7B,GAAG,SAAgB,GAClB,OAAO,CAAC,MAAM,CAAC,CAwBjB;AAED,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,oEAAoE;AACpE,wBAAgB,eAAe,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,QAAQ,EAAE,UAAU,GAAG,UAAU,CAqBzF;AAED,iFAAiF;AACjF,wBAAgB,QAAQ,CACtB,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,OAAO,EAAE,cAAc,EACvB,GAAG,GAAE,UAAwB,EAC7B,GAAG,SAAgB,GAClB,OAAO,CAAC,MAAM,CAAC,CA6BjB;AAED,sFAAsF;AACtF,wBAAsB,YAAY,CAChC,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,OAAO,EAAE,cAAc,EACvB,GAAG,GAAE,UAAwB,GAC5B,OAAO,CAAC,MAAM,CAAC,CAejB;AAED,yDAAyD;AACzD,eAAO,MAAM,SAAS,6CAA8C,CAAC;AAMrE,+EAA+E;AAC/E,wBAAsB,OAAO,CAC3B,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,OAAO,EAAE,cAAc,EACvB,GAAG,SAAgB,GAClB,OAAO,CAAC,MAAM,CAAC,CAiCjB"}
@@ -0,0 +1,224 @@
1
+ import { cp, readFile } from "node:fs/promises";
2
+ import { homedir } from "node:os";
3
+ import { isAbsolute, join } from "node:path";
4
+ import process from "node:process";
5
+ import { fileURLToPath } from "node:url";
6
+ import { createBoardServer } from "../board/server.js";
7
+ import { parseMergedConfig } from "../config/load.js";
8
+ import { STORE_DIR, buildLoopDeps, buildRespondDeps } from "../factory/build.js";
9
+ import { GlobalStore, resolveGlobalDir } from "../global/store.js";
10
+ import { FileLock } from "../lock/file-lock.js";
11
+ import { runTick } from "../loop/engine.js";
12
+ import { respondTick } from "../respond/respond.js";
13
+ import { redactSecrets } from "../secrets/redact.js";
14
+ import { FileStore } from "../store/file-store.js";
15
+ /**
16
+ * Parse the flags shared by `run` and `respond`: `--config`/`-c <path>` and
17
+ * `--repo`/`-C <path>`, starting from the given defaults. Unknown tokens are
18
+ * ignored. A flag missing its value is ignored.
19
+ */
20
+ export function parseCommandFlags(argv, defaults) {
21
+ const flags = { ...defaults };
22
+ for (let i = 0; i < argv.length; i++) {
23
+ const arg = argv[i];
24
+ const next = argv[i + 1];
25
+ if ((arg === "--config" || arg === "-c") && next !== undefined) {
26
+ flags.config = next;
27
+ i++;
28
+ }
29
+ else if ((arg === "--repo" || arg === "-C") && next !== undefined) {
30
+ flags.repo = next;
31
+ i++;
32
+ }
33
+ }
34
+ return flags;
35
+ }
36
+ function makeLogger(streams, secrets) {
37
+ return {
38
+ info: (message) => streams.out(`${redactSecrets(message, secrets)}\n`),
39
+ warn: (message) => streams.err(`${redactSecrets(message, secrets)}\n`),
40
+ };
41
+ }
42
+ /**
43
+ * Load the repo config layered over the global account settings, and resolve the
44
+ * global store. Prints errors and returns undefined on failure.
45
+ */
46
+ async function loadConfig(flags, streams, env) {
47
+ const configPath = isAbsolute(flags.config) ? flags.config : join(flags.repo, flags.config);
48
+ let repoToml;
49
+ try {
50
+ repoToml = await readFile(configPath, "utf8");
51
+ }
52
+ catch {
53
+ streams.err(`cannot read config file: ${configPath}\n`);
54
+ return undefined;
55
+ }
56
+ const globalStore = new GlobalStore(resolveGlobalDir({ GHOSTRAIL_HOME: env.GHOSTRAIL_HOME, XDG_CONFIG_HOME: env.XDG_CONFIG_HOME }, homedir()));
57
+ const globalToml = await globalStore.readSettings();
58
+ const parsed = parseMergedConfig(repoToml, globalToml);
59
+ if (!parsed.ok) {
60
+ for (const error of parsed.errors) {
61
+ streams.err(`config error at ${error.path || "(root)"}: ${error.message}\n`);
62
+ }
63
+ return undefined;
64
+ }
65
+ return { config: parsed.value, globalStore };
66
+ }
67
+ /** `ghostrail run`: drain eligible work once. */
68
+ export async function cmdRun(argv, streams, env = process.env, cwd = process.cwd()) {
69
+ const flags = parseCommandFlags(argv, { config: "ghostrail.toml", repo: cwd });
70
+ const loaded = await loadConfig(flags, streams, env);
71
+ if (loaded === undefined)
72
+ return 1;
73
+ const { config, globalStore } = loaded;
74
+ const linearApiKey = env.LINEAR_API_KEY;
75
+ if (linearApiKey === undefined || linearApiKey.length === 0) {
76
+ streams.err("LINEAR_API_KEY is not set\n");
77
+ return 1;
78
+ }
79
+ const secrets = [linearApiKey];
80
+ const lock = new FileLock(join(flags.repo, ".factory", "lock"), config.guardrails.claimTtlMs);
81
+ const deps = buildLoopDeps(config, {
82
+ repoPath: flags.repo,
83
+ linearApiKey,
84
+ lock,
85
+ globalStore,
86
+ logger: makeLogger(streams, secrets),
87
+ });
88
+ const result = await runTick(deps, config);
89
+ streams.out(`${redactSecrets(JSON.stringify(result, null, 2), secrets)}\n`);
90
+ return result.results.some((r) => r.state === "failed") ? 1 : 0;
91
+ }
92
+ /** `ghostrail respond`: fold new human PR comments back into their branches. */
93
+ export async function cmdRespond(argv, streams, env = process.env, cwd = process.cwd()) {
94
+ const flags = parseCommandFlags(argv, { config: "ghostrail.toml", repo: cwd });
95
+ const loaded = await loadConfig(flags, streams, env);
96
+ if (loaded === undefined)
97
+ return 1;
98
+ const { config } = loaded;
99
+ const linearApiKey = env.LINEAR_API_KEY ?? "";
100
+ const secrets = linearApiKey.length > 0 ? [linearApiKey] : [];
101
+ const selfLogins = (env.GHOSTRAIL_SELF_LOGINS ?? "")
102
+ .split(",")
103
+ .map((login) => login.trim())
104
+ .filter((login) => login.length > 0);
105
+ const { deps, config: respondConfig } = buildRespondDeps(config, {
106
+ repoPath: flags.repo,
107
+ linearApiKey,
108
+ lock: { acquire: async () => true, release: async () => { } },
109
+ selfLogins,
110
+ logger: makeLogger(streams, secrets),
111
+ });
112
+ const results = await respondTick(deps, respondConfig);
113
+ streams.out(`${redactSecrets(JSON.stringify(results, null, 2), secrets)}\n`);
114
+ return results.some((r) => r.state === "failed") ? 1 : 0;
115
+ }
116
+ /** Parse `board` flags: `--repo`, `--port`, `--bind`, `--token`. */
117
+ export function parseBoardFlags(argv, defaults) {
118
+ const flags = { ...defaults };
119
+ for (let i = 0; i < argv.length; i++) {
120
+ const arg = argv[i];
121
+ const next = argv[i + 1];
122
+ if (next === undefined)
123
+ continue;
124
+ if (arg === "--repo" || arg === "-C") {
125
+ flags.repo = next;
126
+ i++;
127
+ }
128
+ else if (arg === "--port" || arg === "-p") {
129
+ if (Number.isFinite(Number(next)))
130
+ flags.port = Number(next);
131
+ i++;
132
+ }
133
+ else if (arg === "--bind") {
134
+ flags.bind = next;
135
+ i++;
136
+ }
137
+ else if (arg === "--token") {
138
+ flags.token = next;
139
+ i++;
140
+ }
141
+ }
142
+ return flags;
143
+ }
144
+ /** `ghostrail board`: serve the run store as a dashboard. Runs until stopped. */
145
+ export function cmdBoard(argv, streams, env = process.env, cwd = process.cwd()) {
146
+ const flags = parseBoardFlags(argv, {
147
+ repo: cwd,
148
+ port: 4369,
149
+ bind: "127.0.0.1",
150
+ ...(env.GHOSTRAIL_BOARD_TOKEN === undefined ? {} : { token: env.GHOSTRAIL_BOARD_TOKEN }),
151
+ });
152
+ const store = new FileStore(join(flags.repo, STORE_DIR));
153
+ let server;
154
+ try {
155
+ server = createBoardServer(store, {
156
+ bind: flags.bind,
157
+ ...(flags.token === undefined ? {} : { token: flags.token }),
158
+ });
159
+ }
160
+ catch (error) {
161
+ streams.err(`${error instanceof Error ? error.message : String(error)}\n`);
162
+ return Promise.resolve(1);
163
+ }
164
+ return new Promise((resolve) => {
165
+ server.on("error", (error) => {
166
+ streams.err(`board error: ${error.message}\n`);
167
+ resolve(1);
168
+ });
169
+ server.listen(flags.port, flags.bind, () => {
170
+ streams.out(`ghostrail board on http://${flags.bind}:${flags.port}/\n`);
171
+ });
172
+ });
173
+ }
174
+ /** `ghostrail artifacts`: list the shared artifacts available in the global store. */
175
+ export async function cmdArtifacts(argv, streams, env = process.env) {
176
+ const dir = resolveGlobalDir({ GHOSTRAIL_HOME: env.GHOSTRAIL_HOME, XDG_CONFIG_HOME: env.XDG_CONFIG_HOME }, homedir());
177
+ const names = await new GlobalStore(dir).listArtifacts();
178
+ streams.out(`global store: ${dir}\n`);
179
+ if (names.length === 0) {
180
+ streams.out(`no artifacts yet. add .md files under ${join(dir, "artifacts")}/ to share them.\n`);
181
+ return 0;
182
+ }
183
+ streams.out(`artifacts:\n${names.map((name) => ` ${name}`).join("\n")}\n`);
184
+ return 0;
185
+ }
186
+ /** The quickstart templates bundled with the package. */
187
+ export const TEMPLATES = ["fix-bugs-local", "content-loop"];
188
+ function templatesDir() {
189
+ return fileURLToPath(new URL("../../templates", import.meta.url));
190
+ }
191
+ /** `ghostrail init <template>`: scaffold a repo from a quickstart template. */
192
+ export async function cmdInit(argv, streams, cwd = process.cwd()) {
193
+ let template;
194
+ let repo = cwd;
195
+ for (let i = 0; i < argv.length; i++) {
196
+ const arg = argv[i];
197
+ const next = argv[i + 1];
198
+ if ((arg === "--repo" || arg === "-C") && next !== undefined) {
199
+ repo = next;
200
+ i++;
201
+ }
202
+ else if (arg !== undefined && !arg.startsWith("-")) {
203
+ template ??= arg;
204
+ }
205
+ }
206
+ if (template === undefined || !TEMPLATES.includes(template)) {
207
+ streams.err(`usage: ghostrail init <template> [--repo <path>]\ntemplates: ${TEMPLATES.join(", ")}\n`);
208
+ return 1;
209
+ }
210
+ try {
211
+ await cp(join(templatesDir(), template), repo, {
212
+ recursive: true,
213
+ force: false,
214
+ errorOnExist: false,
215
+ });
216
+ }
217
+ catch (error) {
218
+ streams.err(`init failed: ${error instanceof Error ? error.message : String(error)}\n`);
219
+ return 1;
220
+ }
221
+ streams.out(`initialized ${template} in ${repo}\n`);
222
+ return 0;
223
+ }
224
+ //# sourceMappingURL=commands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commands.js","sourceRoot":"","sources":["../../src/cli/commands.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACjF,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAE5C,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAYnD;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAuB,EAAE,QAAsB;IAC/E,MAAM,KAAK,GAAiB,EAAE,GAAG,QAAQ,EAAE,CAAC;IAC5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACzB,IAAI,CAAC,GAAG,KAAK,UAAU,IAAI,GAAG,KAAK,IAAI,CAAC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YAC/D,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC;YACpB,CAAC,EAAE,CAAC;QACN,CAAC;aAAM,IAAI,CAAC,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,CAAC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACpE,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;YAClB,CAAC,EAAE,CAAC;QACN,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAMD,SAAS,UAAU,CAAC,OAAuB,EAAE,OAA0B;IACrE,OAAO;QACL,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC;QACtE,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC;KACvE,CAAC;AACJ,CAAC;AAOD;;;GAGG;AACH,KAAK,UAAU,UAAU,CACvB,KAAmB,EACnB,OAAuB,EACvB,GAAe;IAEf,MAAM,UAAU,GAAG,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC5F,IAAI,QAAgB,CAAC;IACrB,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,GAAG,CAAC,4BAA4B,UAAU,IAAI,CAAC,CAAC;QACxD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,WAAW,GAAG,IAAI,WAAW,CACjC,gBAAgB,CACd,EAAE,cAAc,EAAE,GAAG,CAAC,cAAc,EAAE,eAAe,EAAE,GAAG,CAAC,eAAe,EAAE,EAC5E,OAAO,EAAE,CACV,CACF,CAAC;IACF,MAAM,UAAU,GAAG,MAAM,WAAW,CAAC,YAAY,EAAE,CAAC;IAEpD,MAAM,MAAM,GAAG,iBAAiB,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IACvD,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACf,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YAClC,OAAO,CAAC,GAAG,CAAC,mBAAmB,KAAK,CAAC,IAAI,IAAI,QAAQ,KAAK,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;QAC/E,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,KAAK,EAAE,WAAW,EAAE,CAAC;AAC/C,CAAC;AAED,iDAAiD;AACjD,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,IAAuB,EACvB,OAAuB,EACvB,MAAkB,OAAO,CAAC,GAAG,EAC7B,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAEnB,MAAM,KAAK,GAAG,iBAAiB,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,gBAAgB,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;IAC/E,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;IACrD,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,CAAC,CAAC;IACnC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,CAAC;IAEvC,MAAM,YAAY,GAAG,GAAG,CAAC,cAAc,CAAC;IACxC,IAAI,YAAY,KAAK,SAAS,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5D,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;QAC3C,OAAO,CAAC,CAAC;IACX,CAAC;IAED,MAAM,OAAO,GAAG,CAAC,YAAY,CAAC,CAAC;IAC/B,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;IAC9F,MAAM,IAAI,GAAG,aAAa,CAAC,MAAM,EAAE;QACjC,QAAQ,EAAE,KAAK,CAAC,IAAI;QACpB,YAAY;QACZ,IAAI;QACJ,WAAW;QACX,MAAM,EAAE,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC;KACrC,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC3C,OAAO,CAAC,GAAG,CAAC,GAAG,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5E,OAAO,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAClE,CAAC;AAED,gFAAgF;AAChF,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,IAAuB,EACvB,OAAuB,EACvB,MAAkB,OAAO,CAAC,GAAG,EAC7B,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAEnB,MAAM,KAAK,GAAG,iBAAiB,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,gBAAgB,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;IAC/E,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;IACrD,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,CAAC,CAAC;IACnC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IAE1B,MAAM,YAAY,GAAG,GAAG,CAAC,cAAc,IAAI,EAAE,CAAC;IAC9C,MAAM,OAAO,GAAG,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9D,MAAM,UAAU,GAAG,CAAC,GAAG,CAAC,qBAAqB,IAAI,EAAE,CAAC;SACjD,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;SAC5B,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAEvC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,GAAG,gBAAgB,CAAC,MAAM,EAAE;QAC/D,QAAQ,EAAE,KAAK,CAAC,IAAI;QACpB,YAAY;QACZ,IAAI,EAAE,EAAE,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC,EAAE;QAC5D,UAAU;QACV,MAAM,EAAE,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC;KACrC,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;IACvD,OAAO,CAAC,GAAG,CAAC,GAAG,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7E,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC3D,CAAC;AASD,oEAAoE;AACpE,MAAM,UAAU,eAAe,CAAC,IAAuB,EAAE,QAAoB;IAC3E,MAAM,KAAK,GAAe,EAAE,GAAG,QAAQ,EAAE,CAAC;IAC1C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACzB,IAAI,IAAI,KAAK,SAAS;YAAE,SAAS;QACjC,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACrC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;YAClB,CAAC,EAAE,CAAC;QACN,CAAC;aAAM,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YAC5C,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBAAE,KAAK,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;YAC7D,CAAC,EAAE,CAAC;QACN,CAAC;aAAM,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;YAC5B,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;YAClB,CAAC,EAAE,CAAC;QACN,CAAC;aAAM,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YAC7B,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC;YACnB,CAAC,EAAE,CAAC;QACN,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,QAAQ,CACtB,IAAuB,EACvB,OAAuB,EACvB,MAAkB,OAAO,CAAC,GAAG,EAC7B,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAEnB,MAAM,KAAK,GAAG,eAAe,CAAC,IAAI,EAAE;QAClC,IAAI,EAAE,GAAG;QACT,IAAI,EAAE,IAAI;QACV,IAAI,EAAE,WAAW;QACjB,GAAG,CAAC,GAAG,CAAC,qBAAqB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,qBAAqB,EAAE,CAAC;KACzF,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,IAAI,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC;IACzD,IAAI,MAA4C,CAAC;IACjD,IAAI,CAAC;QACH,MAAM,GAAG,iBAAiB,CAAC,KAAK,EAAE;YAChC,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC;SAC7D,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC3E,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAC5B,CAAC;IAED,OAAO,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,EAAE;QACrC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YAC3B,OAAO,CAAC,GAAG,CAAC,gBAAgB,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;YAC/C,OAAO,CAAC,CAAC,CAAC,CAAC;QACb,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,GAAG,EAAE;YACzC,OAAO,CAAC,GAAG,CAAC,6BAA6B,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC;QAC1E,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,sFAAsF;AACtF,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,IAAuB,EACvB,OAAuB,EACvB,MAAkB,OAAO,CAAC,GAAG;IAE7B,MAAM,GAAG,GAAG,gBAAgB,CAC1B,EAAE,cAAc,EAAE,GAAG,CAAC,cAAc,EAAE,eAAe,EAAE,GAAG,CAAC,eAAe,EAAE,EAC5E,OAAO,EAAE,CACV,CAAC;IACF,MAAM,KAAK,GAAG,MAAM,IAAI,WAAW,CAAC,GAAG,CAAC,CAAC,aAAa,EAAE,CAAC;IACzD,OAAO,CAAC,GAAG,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;IACtC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CACT,yCAAyC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,oBAAoB,CACpF,CAAC;QACF,OAAO,CAAC,CAAC;IACX,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,eAAe,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5E,OAAO,CAAC,CAAC;AACX,CAAC;AAED,yDAAyD;AACzD,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,gBAAgB,EAAE,cAAc,CAAU,CAAC;AAErE,SAAS,YAAY;IACnB,OAAO,aAAa,CAAC,IAAI,GAAG,CAAC,iBAAiB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AACpE,CAAC;AAED,+EAA+E;AAC/E,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,IAAuB,EACvB,OAAuB,EACvB,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAEnB,IAAI,QAA4B,CAAC;IACjC,IAAI,IAAI,GAAG,GAAG,CAAC;IACf,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACzB,IAAI,CAAC,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,CAAC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YAC7D,IAAI,GAAG,IAAI,CAAC;YACZ,CAAC,EAAE,CAAC;QACN,CAAC;aAAM,IAAI,GAAG,KAAK,SAAS,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACrD,QAAQ,KAAK,GAAG,CAAC;QACnB,CAAC;IACH,CAAC;IAED,IAAI,QAAQ,KAAK,SAAS,IAAI,CAAE,SAA+B,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QACnF,OAAO,CAAC,GAAG,CACT,gEAAgE,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CACzF,CAAC;QACF,OAAO,CAAC,CAAC;IACX,CAAC;IAED,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,QAAQ,CAAC,EAAE,IAAI,EAAE;YAC7C,SAAS,EAAE,IAAI;YACf,KAAK,EAAE,KAAK;YACZ,YAAY,EAAE,KAAK;SACpB,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,GAAG,CAAC,gBAAgB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACxF,OAAO,CAAC,CAAC;IACX,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,eAAe,QAAQ,OAAO,IAAI,IAAI,CAAC,CAAC;IACpD,OAAO,CAAC,CAAC;AACX,CAAC"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,16 @@
1
+ /** Minimal stream sink so `run` can be driven and observed in tests. */
2
+ export interface Streams {
3
+ out: (text: string) => void;
4
+ err: (text: string) => void;
5
+ }
6
+ /**
7
+ * Execute the ghostrail CLI for the given arguments (argv with the node binary
8
+ * and script path already stripped) and resolve the intended process exit code.
9
+ * Subcommands (`run`, `respond`) dispatch to their handlers; otherwise the
10
+ * top-level flags (`help`, `version`) are handled here.
11
+ *
12
+ * `run` performs no process-level side effects beyond writing to the provided
13
+ * streams and whatever the dispatched command does.
14
+ */
15
+ export declare function run(argv: readonly string[], streams?: Streams): Promise<number>;
16
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAMA,wEAAwE;AACxE,MAAM,WAAW,OAAO;IACtB,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B;AAOD;;;;;;;;GAQG;AACH,wBAAsB,GAAG,CACvB,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,OAAO,GAAE,OAAwB,GAChC,OAAO,CAAC,MAAM,CAAC,CAqBjB"}