mainflow 0.11.1 → 0.11.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
- import { A as setSessionStatus, C as updateTask, D as readSession, F as sessionBriefing, G as planIssue, H as closeIssue, J as setFindingStatus, K as reopenIssue, M as startSession, O as setSessionArchived, P as updateAction, S as supersedeDecision, U as createFinding, V as appendOps, W as createIssue, X as HubError, Y as setIssueArchived, Z as loadHub, _ as setArchived, b as setMainlineStatus, c as migrateHub, d as addRepo, et as MAINLINE_FILE, f as createDecision, g as initHub, h as dropChecklistItem, l as acceptDecision, m as createTask, ot as findHubRoot, p as createMainline, q as setFindingArchived, rt as WriteError, tt as TASK_FILE, u as addHub, v as setChecklistItem, w as addAction, y as setCriterion } from "./host-ByGN9mGS.js";
2
+ import { C as supersedeDecision, F as updateAction, G as createIssue, H as appendOps, I as sessionBriefing, J as setFindingArchived, K as planIssue, N as startSession, O as readSession, Q as loadHub, T as addAction, U as closeIssue, W as createFinding, X as setIssueArchived, Y as setFindingStatus, Z as HubError, _ as initHub, b as setCriterion, d as addHub, f as addRepo, g as dropChecklistItem, h as createTask, it as WriteError, j as setSessionStatus, k as setSessionArchived, l as migrateHub, m as createMainline, nt as TASK_FILE, p as createDecision, q as reopenIssue, st as findHubRoot, tt as MAINLINE_FILE, u as acceptDecision, v as setArchived, w as updateTask, x as setMainlineStatus, y as setChecklistItem } from "./host-C3MyDGB_.js";
3
3
  import { t as listProgress } from "./progress-1BfPg2zN.js";
4
4
  import { COMMAND_SPECS, OPTIONS } from "./facts.js";
5
5
  import { runHook } from "./hooks.js";
6
- import { c as CLI_VERSION, r as launchUi, s as startUiInBackground } from "./launch-B9QrvwZQ.js";
6
+ import { l as CLI_VERSION, r as launchUi, s as startUiInBackground } from "./launch-T0sXbTgT.js";
7
7
  import { readFileSync, realpathSync } from "node:fs";
8
8
  import { join, relative } from "node:path";
9
9
  import { fileURLToPath } from "node:url";
package/dist/hooks.js CHANGED
@@ -1,4 +1,4 @@
1
- import { A as setSessionStatus, B as mayDecorate, D as readSession, F as sessionBriefing, I as turnReminder, L as decorateReply, R as endsWithMarker, T as ensureSession, X as HubError, Z as loadHub, at as currentBranch, i as hostName, it as DATA_DIR, j as settleSession, k as setSessionInfo, ot as findHubRoot, st as worktreesOf, z as headerLine } from "./host-ByGN9mGS.js";
1
+ import { A as setSessionInfo, B as headerLine, E as ensureSession, I as sessionBriefing, L as turnReminder, M as settleSession, O as readSession, Q as loadHub, R as decorateReply, V as mayDecorate, Z as HubError, at as DATA_DIR, ct as worktreesOf, i as hostName, j as setSessionStatus, ot as currentBranch, st as findHubRoot, z as endsWithMarker } from "./host-C3MyDGB_.js";
2
2
  import { appendFileSync, existsSync, readFileSync } from "node:fs";
3
3
  import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
4
4
  //#region src/hooks.ts
@@ -1842,6 +1842,20 @@ async function syncHost(root, hub, port, options = {}) {
1842
1842
  };
1843
1843
  return { url: `https://${hostName(hub)}` };
1844
1844
  }
1845
+ /**
1846
+ * Remove {hub}.mainflow.localhost when the hub rooted at `root` is gone, so a dangling link does not stop Caddy
1847
+ * from loading every other site. Only a link that points into `root` is removed; the reload failure, if any,
1848
+ * is returned for the caller to log.
1849
+ */
1850
+ function removeHostLink(root, hub, reload = reloadCaddy) {
1851
+ const sites = caddySites();
1852
+ if (!sites) return null;
1853
+ const link = join(sites, `mainflow-${hub}.caddy`);
1854
+ if (!lstatSync(link, { throwIfNoEntry: false })?.isSymbolicLink()) return null;
1855
+ if (!resolve(dirname(link), readlinkSync(link)).startsWith(resolve(root) + "/")) return null;
1856
+ rmSync(link);
1857
+ return reload(sites);
1858
+ }
1845
1859
  /** The macOS app's bundle identifier, from apps/macos/scripts/package.sh. */
1846
1860
  const APP_BUNDLE_ID = "space.carlos.mainflow";
1847
1861
  /** Close the tabs Safari and Chrome opened on this hub's /open route; each browser only when it is running. */
@@ -1874,4 +1888,4 @@ function openInApp(hub, target, closeAfterMs = 150) {
1874
1888
  return true;
1875
1889
  }
1876
1890
  //#endregion
1877
- export { refIndex as $, setSessionStatus as A, mayDecorate as B, updateTask as C, readSession as D, loadSessions as E, sessionBriefing as F, planIssue as G, closeIssue as H, turnReminder as I, setFindingStatus as J, reopenIssue as K, decorateReply as L, startSession as M, transcriptPath as N, setSessionArchived as O, updateAction as P, linksInto as Q, endsWithMarker as R, supersedeDecision as S, ensureSession as T, createFinding as U, appendOps as V, createIssue as W, HubError as X, setIssueArchived as Y, loadHub as Z, setArchived as _, openInApp as a, currentBranch as at, setMainlineStatus as b, migrateHub as c, addRepo as d, MAINLINE_FILE as et, createDecision as f, initHub as g, dropChecklistItem as h, hostName as i, DATA_DIR as it, settleSession as j, setSessionInfo as k, acceptDecision as l, createTask as m, DEFAULT_UI_PORT as n, ConflictError as nt, siteBlock as o, findHubRoot as ot, createMainline as p, setFindingArchived as q, caddySites as r, WriteError as rt, syncHost as s, worktreesOf as st, APP_BUNDLE_ID as t, TASK_FILE as tt, addHub as u, setChecklistItem as v, addAction as w, setMainlineTitle as x, setCriterion as y, headerLine as z };
1891
+ export { linksInto as $, setSessionInfo as A, headerLine as B, supersedeDecision as C, loadSessions as D, ensureSession as E, updateAction as F, createIssue as G, appendOps as H, sessionBriefing as I, setFindingArchived as J, planIssue as K, turnReminder as L, settleSession as M, startSession as N, readSession as O, transcriptPath as P, loadHub as Q, decorateReply as R, setMainlineTitle as S, addAction as T, closeIssue as U, mayDecorate as V, createFinding as W, setIssueArchived as X, setFindingStatus as Y, HubError as Z, initHub as _, openInApp as a, DATA_DIR as at, setCriterion as b, syncHost as c, worktreesOf as ct, addHub as d, refIndex as et, addRepo as f, dropChecklistItem as g, createTask as h, hostName as i, WriteError as it, setSessionStatus as j, setSessionArchived as k, migrateHub as l, createMainline as m, DEFAULT_UI_PORT as n, TASK_FILE as nt, removeHostLink as o, currentBranch as ot, createDecision as p, reopenIssue as q, caddySites as r, ConflictError as rt, siteBlock as s, findHubRoot as st, APP_BUNDLE_ID as t, MAINLINE_FILE as tt, acceptDecision as u, setArchived as v, updateTask as w, setMainlineStatus as x, setChecklistItem as y, endsWithMarker as z };
package/dist/host.d.ts CHANGED
@@ -21,6 +21,12 @@ export type HostResult = {
21
21
  * different hub of the same name stops here: overwriting it would silently take that hub's host name.
22
22
  */
23
23
  export declare function syncHost(root: string, hub: string, port: number, options?: HostOptions): Promise<HostResult>;
24
+ /**
25
+ * Remove {hub}.mainflow.localhost when the hub rooted at `root` is gone, so a dangling link does not stop Caddy
26
+ * from loading every other site. Only a link that points into `root` is removed; the reload failure, if any,
27
+ * is returned for the caller to log.
28
+ */
29
+ export declare function removeHostLink(root: string, hub: string, reload?: (sites: string) => string | null): string | null;
24
30
  /** The macOS app's bundle identifier, from apps/macos/scripts/package.sh. */
25
31
  export declare const APP_BUNDLE_ID = "space.carlos.mainflow";
26
32
  /**
package/dist/host.js CHANGED
@@ -1,2 +1,2 @@
1
- import { a as openInApp, i as hostName, n as DEFAULT_UI_PORT, o as siteBlock, r as caddySites, s as syncHost, t as APP_BUNDLE_ID } from "./host-ByGN9mGS.js";
2
- export { APP_BUNDLE_ID, DEFAULT_UI_PORT, caddySites, hostName, openInApp, siteBlock, syncHost };
1
+ import { a as openInApp, c as syncHost, i as hostName, n as DEFAULT_UI_PORT, o as removeHostLink, r as caddySites, s as siteBlock, t as APP_BUNDLE_ID } from "./host-C3MyDGB_.js";
2
+ export { APP_BUNDLE_ID, DEFAULT_UI_PORT, caddySites, hostName, openInApp, removeHostLink, siteBlock, syncHost };
@@ -1,5 +1,5 @@
1
- import { it as DATA_DIR, n as DEFAULT_UI_PORT, rt as WriteError, s as syncHost } from "./host-ByGN9mGS.js";
2
- import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
1
+ import { at as DATA_DIR, c as syncHost, i as hostName, it as WriteError, n as DEFAULT_UI_PORT, o as removeHostLink } from "./host-C3MyDGB_.js";
2
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
3
3
  import { join } from "node:path";
4
4
  import { spawn, spawnSync } from "node:child_process";
5
5
  import { createServer } from "node:net";
@@ -111,7 +111,7 @@ async function choosePort(hub, candidates, probe = networkProbe) {
111
111
  */
112
112
  function startUiInBackground(root) {
113
113
  const cli = process.argv[1];
114
- if (!cli) return;
114
+ if (!cli || process.env.MAINFLOW_NO_BACKGROUND_UI === "1") return;
115
115
  spawn(process.execPath, [
116
116
  cli,
117
117
  "ui",
@@ -122,6 +122,20 @@ function startUiInBackground(root) {
122
122
  stdio: "ignore"
123
123
  }).on("error", () => {}).unref();
124
124
  }
125
+ /**
126
+ * Call `onGone` once the hub's config.yaml disappears, checking every `everyMs`. A server started for a hub in a
127
+ * directory that is later deleted, such as a test's, then stops instead of holding its port forever. The timer
128
+ * does not keep the process alive by itself.
129
+ */
130
+ function watchHubGone(root, onGone, everyMs = 3e4) {
131
+ const timer = setInterval(() => {
132
+ if (existsSync(join(root, ".mainflow", "config.yaml"))) return;
133
+ clearInterval(timer);
134
+ onGone();
135
+ }, everyMs);
136
+ timer.unref();
137
+ return timer;
138
+ }
125
139
  /** Open a URL in the default browser without waiting for it. */
126
140
  function openUrl(url) {
127
141
  const [command, ...args] = process.platform === "darwin" ? ["open", url] : process.platform === "win32" ? [
@@ -162,13 +176,20 @@ async function launchUi(root, hub, configured, options) {
162
176
  }
163
177
  let server;
164
178
  if (!reuse) {
165
- const { serveUi } = await import("./ui-BY65lR7x.js");
179
+ const { serveUi } = await import("./ui-BTLe6I--.js");
166
180
  server = await serveUi(root, choice.port);
167
181
  writeUiRecord(root, {
168
182
  port: choice.port,
169
183
  pid: process.pid,
170
184
  version: CLI_VERSION
171
185
  });
186
+ const started = server;
187
+ watchHubGone(root, () => {
188
+ const failure = removeHostLink(root, hub);
189
+ if (failure) log(`! caddy reload failed after removing ${hostName(hub)}: ${failure}`);
190
+ started.close();
191
+ process.exit(0);
192
+ });
172
193
  }
173
194
  const host = await syncHost(root, hub, choice.port, options.host);
174
195
  if (host.url === null) log(`! host name not available: ${host.reason}`);
@@ -181,4 +202,4 @@ async function launchUi(root, hub, configured, options) {
181
202
  };
182
203
  }
183
204
  //#endregion
184
- export { portCandidates as a, CLI_VERSION as c, networkProbe as i, choosePort as n, readUiRecord as o, launchUi as r, startUiInBackground as s, PORT_SPAN as t };
205
+ export { portCandidates as a, watchHubGone as c, networkProbe as i, CLI_VERSION as l, choosePort as n, readUiRecord as o, launchUi as r, startUiInBackground as s, PORT_SPAN as t };
package/dist/launch.d.ts CHANGED
@@ -51,6 +51,12 @@ export declare function choosePort(hub: string, candidates: number[], probe?: Po
51
51
  * pinned version serves its interface.
52
52
  */
53
53
  export declare function startUiInBackground(root: string): void;
54
+ /**
55
+ * Call `onGone` once the hub's config.yaml disappears, checking every `everyMs`. A server started for a hub in a
56
+ * directory that is later deleted, such as a test's, then stops instead of holding its port forever. The timer
57
+ * does not keep the process alive by itself.
58
+ */
59
+ export declare function watchHubGone(root: string, onGone: () => void, everyMs?: number): NodeJS.Timeout;
54
60
  export interface LaunchOptions {
55
61
  port?: string;
56
62
  open: boolean;
package/dist/launch.js CHANGED
@@ -1,2 +1,2 @@
1
- import { a as portCandidates, i as networkProbe, n as choosePort, o as readUiRecord, r as launchUi, s as startUiInBackground, t as PORT_SPAN } from "./launch-B9QrvwZQ.js";
2
- export { PORT_SPAN, choosePort, launchUi, networkProbe, portCandidates, readUiRecord, startUiInBackground };
1
+ import { a as portCandidates, c as watchHubGone, i as networkProbe, n as choosePort, o as readUiRecord, r as launchUi, s as startUiInBackground, t as PORT_SPAN } from "./launch-T0sXbTgT.js";
2
+ export { PORT_SPAN, choosePort, launchUi, networkProbe, portCandidates, readUiRecord, startUiInBackground, watchHubGone };
@@ -1,6 +1,6 @@
1
- import { $ as refIndex, C as updateTask, D as readSession, E as loadSessions, N as transcriptPath, O as setSessionArchived, Q as linksInto, Y as setIssueArchived, Z as loadHub, _ as setArchived, a as openInApp, b as setMainlineStatus, it as DATA_DIR, nt as ConflictError, q as setFindingArchived, rt as WriteError, v as setChecklistItem, x as setMainlineTitle, y as setCriterion } from "./host-ByGN9mGS.js";
1
+ import { $ as linksInto, D as loadSessions, J as setFindingArchived, O as readSession, P as transcriptPath, Q as loadHub, S as setMainlineTitle, X as setIssueArchived, a as openInApp, at as DATA_DIR, b as setCriterion, et as refIndex, it as WriteError, k as setSessionArchived, rt as ConflictError, v as setArchived, w as updateTask, x as setMainlineStatus, y as setChecklistItem } from "./host-C3MyDGB_.js";
2
2
  import { t as listProgress } from "./progress-1BfPg2zN.js";
3
- import { c as CLI_VERSION } from "./launch-B9QrvwZQ.js";
3
+ import { l as CLI_VERSION } from "./launch-T0sXbTgT.js";
4
4
  import { createRequire } from "node:module";
5
5
  import { closeSync, existsSync, openSync, readFileSync, readSync, statSync, watch } from "node:fs";
6
6
  import { basename, dirname, extname, join, normalize, relative, sep } from "node:path";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mainflow",
3
- "version": "0.11.1",
3
+ "version": "0.11.2",
4
4
  "description": "本機多 AI 協作的主脈絡任務管理:CLI 與介面",
5
5
  "license": "MIT",
6
6
  "type": "module",