mainflow 0.29.0 → 0.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
- import { $ as nowMinute, G as loadHub, H as applyOperation, Q as requireSlug, S as readSession, U as checkHubName, W as HubError, X as MAINLINE_FILE, Z as TASK_FILE, _ as untilState, d as retroReportFromReceiver, f as receiverFromEnv, g as initHub, l as migrateHub, ot as DATA_DIR, p as RETRY_RULES, rt as findHubRoot, st as WriteError, tt as nodeStorage, u as retroReport, v as duplicateClaimLines, x as loadSessions, y as sessionBriefing } from "./host-BJnrv8xF.js";
3
- import { B as parseRef, H as refExample, V as parseUntil, k as UNTIL_FORMS } from "./dist-BbamrIPW.js";
2
+ import { B as parseRef, H as refExample, V as parseUntil, Y as stampMs, k as UNTIL_FORMS } from "./dist-IdbnCDqM.js";
3
+ import { B as checkHubName, H as loadHub, J as TASK_FILE, Q as nodeStorage, S as readSession, V as HubError, X as nowMinute, Y as requireSlug, _ as untilState, d as retroReportFromReceiver, f as receiverFromEnv, g as initHub, l as migrateHub, ot as DATA_DIR, p as RETRY_RULES, q as MAINLINE_FILE, rt as findHubRoot, st as WriteError, u as retroReport, v as duplicateClaimLines, x as loadSessions, y as sessionBriefing, z as applyOperation } from "./host-DmVNYRql.js";
4
4
  import { t as listProgress } from "./progress-1BfPg2zN.js";
5
- import { C as ServerError, S as ServerApi, _ as silentHint, a as remoteMode, c as syncSettings, d as startDaemon, f as DaemonRunning, g as readDaemon, h as probeDaemon, i as queuedCount, l as hookAnswer, m as callDaemon, n as hubWriter, o as ENV, p as DaemonUnavailable, r as writtenLines, s as hubName, t as CONFIRM_MS, u as planFlush, v as SETTINGS_FILE, x as syncPaths } from "./operation-Bp4U2bx3.js";
5
+ import { C as ServerError, S as ServerApi, _ as silentHint, a as remoteMode, c as syncSettings, d as startDaemon, f as DaemonRunning, g as readDaemon, h as probeDaemon, i as queuedCount, l as hookAnswer, m as callDaemon, n as hubWriter, o as ENV, p as DaemonUnavailable, r as writtenLines, s as hubName, t as CONFIRM_MS, u as planFlush, v as SETTINGS_FILE, x as syncPaths } from "./operation-BQiUL0eq.js";
6
6
  import { COMMAND_SPECS, OPTIONS } from "./facts.js";
7
7
  import { hookFallback, parsePayload, runHook } from "./hooks.js";
8
- import { c as watchHubGone, l as CLI_VERSION, r as launchUi, s as startUiInBackground } from "./launch-DefacJEL.js";
8
+ import { c as watchHubGone, l as CLI_VERSION, r as launchUi, s as startUiInBackground } from "./launch-DHug6eli.js";
9
9
  import { randomBytes } from "node:crypto";
10
10
  import { existsSync, readFileSync, realpathSync, rmSync, statSync } from "node:fs";
11
11
  import { basename, join, relative, resolve } from "node:path";
@@ -56,7 +56,7 @@ async function syncRun(root) {
56
56
  });
57
57
  await daemon.stop();
58
58
  forgetStarted(root);
59
- return 0;
59
+ process.exit(0);
60
60
  }
61
61
  /** Clear the record of a background start when it names this process. */
62
62
  function forgetStarted(root) {
@@ -900,8 +900,12 @@ const RUNS = {
900
900
  },
901
901
  "ops list": ({ root, opts }) => {
902
902
  const covers = (ref) => !opts.ref || ref !== void 0 && (ref === opts.ref || ref.startsWith(`${opts.ref}/`) || ref.startsWith(`${opts.ref}#`));
903
- const shown = loadHub(root).ops.filter((o) => (!opts.month || o.at.startsWith(opts.month)) && covers(o.ref));
904
- for (const o of shown) console.log(` ${o.at} ${o.target} ${o.operation} ${o.result}${o.ref ? ` ${o.ref}` : ""}`);
903
+ const local = (at) => {
904
+ const d = new Date(stampMs(at));
905
+ return `${d.toLocaleDateString("sv-SE")}T${d.toTimeString().slice(0, 5)}`;
906
+ };
907
+ const shown = loadHub(root).ops.filter((o) => (!opts.month || local(o.at).startsWith(opts.month)) && covers(o.ref));
908
+ for (const o of shown) console.log(` ${local(o.at)} ${o.target} ${o.operation} ${o.result}${o.ref ? ` ${o.ref}` : ""}`);
905
909
  return done(`${shown.length} operations`);
906
910
  },
907
911
  retro: ({ root, args, opts }) => {
@@ -344,8 +344,29 @@ function satisfies(version, range) {
344
344
  });
345
345
  }
346
346
  //#endregion
347
+ //#region ../schema/dist/stamp.js
348
+ /** An offset from UTC: `Z` for UTC itself, otherwise ±HH:mm with hours 00 to 23 and minutes 00 to 59. */
349
+ const OFFSET = "(?:Z|[+-](?:[01]\\d|2[0-3]):[0-5]\\d)";
350
+ /** A time to the minute: the local minute and, since format 3, its offset from UTC. One without an offset was written before format 3. */
351
+ const DATETIME = new RegExp(`^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}${OFFSET}?$`);
352
+ /** A day, or a day with the time when the moment matters. */
353
+ const DATE_OR_TIME = new RegExp(`^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}${OFFSET}?)?$`);
354
+ const STAMP = new RegExp(`^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2})(${OFFSET})?$`);
355
+ /**
356
+ * The instant a time-to-the-minute stamp names, in epoch milliseconds. A stamp with an offset names one instant
357
+ * everywhere; a stamp without one (written before format 3) is read as the reader's local time. NaN when `stamp` is
358
+ * not in that form.
359
+ */
360
+ function stampMs(stamp) {
361
+ const m = STAMP.exec(stamp);
362
+ if (!m) return NaN;
363
+ const [, y, mo, d, hh, mm, offset] = m;
364
+ if (offset) return Date.parse(`${y}-${mo}-${d}T${hh}:${mm}:00${offset}`);
365
+ return new Date(Number(y), Number(mo) - 1, Number(d), Number(hh), Number(mm)).getTime();
366
+ }
367
+ //#endregion
347
368
  //#region ../schema/dist/index.js
348
- const FORMAT_VERSION = 2;
369
+ const FORMAT_VERSION = 3;
349
370
  const ID_PATTERNS = {
350
371
  mainline: /^m\d{3}$/,
351
372
  task: /^t\d{3}$/,
@@ -362,7 +383,6 @@ const CHECKLIST_REF = /^m\d{3}\/t\d{3}#c\d{3}$/;
362
383
  const SERVES_REF = /^m\d{3}(?:\/t\d{3}#c\d{3}|#r\d{3})$/;
363
384
  const SLUG = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
364
385
  const DATE = /^\d{4}-\d{2}-\d{2}$/;
365
- const DATETIME = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}$/;
366
386
  /** A hub name: kebab-case, also the first label of {hub}.mainflow.localhost and the prefix of a cross-hub reference. */
367
387
  const HUB_NAME = SLUG;
368
388
  /** Prefixes the web interface already uses in its own references, so no registered hub may take them. */
@@ -482,7 +502,7 @@ const id = (kind) => z.string().regex(ID_PATTERNS[kind]);
482
502
  const date = z.string().regex(DATE);
483
503
  const datetime = z.string().regex(DATETIME);
484
504
  /** A day, or a day with the time when the moment matters (who decided what, and when). */
485
- const dateOrTime = z.string().regex(/^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2})?$/);
505
+ const dateOrTime = z.string().regex(DATE_OR_TIME);
486
506
  const text = z.string().min(1);
487
507
  /** Any reference parseRef understands, in this hub or, with a `{hub}:` prefix, in another one. */
488
508
  const anyRef = z.string().refine((s) => parseRef(s) !== null, `expected a reference like ${REF_EXAMPLES}`);
@@ -1020,4 +1040,4 @@ function parseOpsLine(line) {
1020
1040
  return parsed.success ? parsed.data : null;
1021
1041
  }
1022
1042
  //#endregion
1023
- export { grantForm as $, WORK_STATUS as A, parseRef as B, SESSION_STATUS as C, TASK_REQUIRED_SECTIONS as D, SURVEY_SECTION as E, issueSchema as F, taskSchema as G, refExample as H, mainlineSchema as I, GRANT_ACTIONS as J, waitingForAction as K, opsEntrySchema as L, decisionSchema as M, findingSchema as N, TASK_SECTIONS as O, formatOpsEntry as P, grantCovers as Q, parseActionRef as R, SESSION_ID as S, SURVEY_LINES as T, refMainline as U, parseUntil as V, sessionSchema as W, GRANT_TARGET_FORMS as X, GRANT_FORMS as Y, describeRequest as Z, MERGE_STATES as _, DECISION_SECTIONS as a, RESERVED_HUB_NAMES as b, FINDING_SECTIONS as c, ID_PATTERNS as d, grantRepo as et, ISSUE_SECTIONS as f, MAINLINE_STATUS as g, MAINLINE_SECTIONS as h, DECISION_BASES as i, configSchema as j, UNTIL_FORMS as k, FINDING_STATUS as l, LINK_RELS as m, CLOSED_STATUS as n, DECISION_STATUS as o, ISSUE_STATUS as p, waitingForRef as q, DECIDERS as r, DEFAULT_CATEGORIES as s, CHECKLIST_REF as t, parseGrantTarget as tt, FORMAT_VERSION as u, PRIORITIES as v, SLUG as w, SERVES_REF as x, REF_EXAMPLES as y, parseOpsLine as z };
1043
+ export { describeRequest as $, WORK_STATUS as A, parseRef as B, SESSION_STATUS as C, TASK_REQUIRED_SECTIONS as D, SURVEY_SECTION as E, issueSchema as F, taskSchema as G, refExample as H, mainlineSchema as I, OFFSET as J, waitingForAction as K, opsEntrySchema as L, decisionSchema as M, findingSchema as N, TASK_SECTIONS as O, formatOpsEntry as P, GRANT_TARGET_FORMS as Q, parseActionRef as R, SESSION_ID as S, SURVEY_LINES as T, refMainline as U, parseUntil as V, sessionSchema as W, GRANT_ACTIONS as X, stampMs as Y, GRANT_FORMS as Z, MERGE_STATES as _, DECISION_SECTIONS as a, RESERVED_HUB_NAMES as b, FINDING_SECTIONS as c, ID_PATTERNS as d, grantCovers as et, ISSUE_SECTIONS as f, MAINLINE_STATUS as g, MAINLINE_SECTIONS as h, DECISION_BASES as i, configSchema as j, UNTIL_FORMS as k, FINDING_STATUS as l, LINK_RELS as m, CLOSED_STATUS as n, grantRepo as nt, DECISION_STATUS as o, ISSUE_STATUS as p, waitingForRef as q, DECIDERS as r, parseGrantTarget as rt, DEFAULT_CATEGORIES as s, CHECKLIST_REF as t, grantForm as tt, FORMAT_VERSION as u, PRIORITIES as v, SLUG as w, SERVES_REF as x, REF_EXAMPLES as y, parseOpsLine as z };
package/dist/facts.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { _ as Until, c as ID_PATTERNS, f as SERVES_REF, h as SurveyLine, o as FORMAT_VERSION, p as SLUG, r as CHECKLIST_REF } from "./index-DV6Gqu8K.js";
1
+ import { _ as Until, c as ID_PATTERNS, f as SERVES_REF, h as SurveyLine, o as FORMAT_VERSION, p as SLUG, r as CHECKLIST_REF } from "./index-ihgXABQc.js";
2
2
  //#region src/facts.d.ts
3
3
  export interface CommandSpec {
4
4
  usage: string;
package/dist/facts.js CHANGED
@@ -1,4 +1,4 @@
1
- import { A as WORK_STATUS, C as SESSION_STATUS, D as TASK_REQUIRED_SECTIONS, E as SURVEY_SECTION, J as GRANT_ACTIONS, O as TASK_SECTIONS, T as SURVEY_LINES, X as GRANT_TARGET_FORMS, Y as GRANT_FORMS, _ as MERGE_STATES, a as DECISION_SECTIONS, c as FINDING_SECTIONS, d as ID_PATTERNS, f as ISSUE_SECTIONS, g as MAINLINE_STATUS, h as MAINLINE_SECTIONS, i as DECISION_BASES, k as UNTIL_FORMS, l as FINDING_STATUS, m as LINK_RELS, n as CLOSED_STATUS, o as DECISION_STATUS, p as ISSUE_STATUS, r as DECIDERS, s as DEFAULT_CATEGORIES, t as CHECKLIST_REF, u as FORMAT_VERSION, v as PRIORITIES, w as SLUG, x as SERVES_REF } from "./dist-BbamrIPW.js";
1
+ import { A as WORK_STATUS, C as SESSION_STATUS, D as TASK_REQUIRED_SECTIONS, E as SURVEY_SECTION, O as TASK_SECTIONS, Q as GRANT_TARGET_FORMS, T as SURVEY_LINES, X as GRANT_ACTIONS, Z as GRANT_FORMS, _ as MERGE_STATES, a as DECISION_SECTIONS, c as FINDING_SECTIONS, d as ID_PATTERNS, f as ISSUE_SECTIONS, g as MAINLINE_STATUS, h as MAINLINE_SECTIONS, i as DECISION_BASES, k as UNTIL_FORMS, l as FINDING_STATUS, m as LINK_RELS, n as CLOSED_STATUS, o as DECISION_STATUS, p as ISSUE_STATUS, r as DECIDERS, s as DEFAULT_CATEGORIES, t as CHECKLIST_REF, u as FORMAT_VERSION, v as PRIORITIES, w as SLUG, x as SERVES_REF } from "./dist-IdbnCDqM.js";
2
2
  import { a as LABEL_ROLES, i as FINDING_SEVERITIES, n as FINDING_CLASSES, r as FINDING_FIELDS, t as FINDINGS_FENCE } from "./retro-formats-ECy0gGOL.js";
3
3
  //#region src/facts.ts
4
4
  const COMMAND_SPECS = {
@@ -1,4 +1,4 @@
1
- import "./index-DV6Gqu8K.js";
1
+ import "./index-ihgXABQc.js";
2
2
  //#region ../schema/dist/grants.d.ts
3
3
  /** An operation about to run, resolved to what a grant is written against. */
4
4
  type GrantRequest = {
@@ -1,4 +1,4 @@
1
- import { Y as GRANT_FORMS } from "./dist-BbamrIPW.js";
1
+ import { Z as GRANT_FORMS } from "./dist-IdbnCDqM.js";
2
2
  import { closeSync, constants, fstatSync, openSync, readFileSync, realpathSync } from "node:fs";
3
3
  import { isAbsolute, join, relative, resolve } from "node:path";
4
4
  import { spawnSync } from "node:child_process";
package/dist/hooks.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as Decision, d as OpsEntry, g as Task, i as ChecklistItem, l as Issue, m as Session, n as ActionBlock, s as Finding, t as Action, u as Mainline } from "./index-DV6Gqu8K.js";
1
+ import { a as Decision, d as OpsEntry, g as Task, i as ChecklistItem, l as Issue, m as Session, n as ActionBlock, s as Finding, t as Action, u as Mainline } from "./index-ihgXABQc.js";
2
2
  import { z } from "zod";
3
3
  //#region ../core/dist/ids/allocators.d.ts
4
4
  /** The letters ids start with. */
@@ -29,9 +29,9 @@ interface IdAllocator {
29
29
  /** What an operation needs from its caller besides its input. */
30
30
  interface OpContext {
31
31
  /**
32
- * The caller's local time to the minute, like 2026-09-24T15:30. Dates and times an operation writes come
33
- * from it, so an operation run where the clock is in another time zone, such as UTC in Workers, writes the
34
- * same dates as one run on the caller's machine.
32
+ * The caller's local time to the minute with its offset from UTC, like 2026-09-24T15:30+08:00 (`Z` for UTC).
33
+ * Dates and times an operation writes come from it, so an operation run where the clock is in another time
34
+ * zone, such as UTC in Workers, writes the caller's dates, and its times keep the caller's offset.
35
35
  */
36
36
  now: string;
37
37
  /** Who numbers new entries (src/ids/); without one, the next free id, final at once */
package/dist/hooks.js CHANGED
@@ -1,6 +1,6 @@
1
- import { D as endsWithMarker, E as decorateReply, G as loadHub, O as headerLine, S as readSession, T as matchGrants, W as HubError, b as turnReminder, et as readYaml, i as hostName, it as worktreesOf, k as mayDecorate, nt as currentBranch, ot as DATA_DIR, rt as findHubRoot, w as grantScope, x as loadSessions, y as sessionBriefing } from "./host-BJnrv8xF.js";
2
- import { Z as describeRequest, j as configSchema } from "./dist-BbamrIPW.js";
3
- import { n as hubWriter, r as writtenLines } from "./operation-Bp4U2bx3.js";
1
+ import { $ as describeRequest, j as configSchema } from "./dist-IdbnCDqM.js";
2
+ import { D as endsWithMarker, E as decorateReply, H as loadHub, O as headerLine, S as readSession, T as matchGrants, V as HubError, Z as readYaml, b as turnReminder, i as hostName, it as worktreesOf, k as mayDecorate, nt as currentBranch, ot as DATA_DIR, rt as findHubRoot, w as grantScope, x as loadSessions, y as sessionBriefing } from "./host-DmVNYRql.js";
3
+ import { n as hubWriter, r as writtenLines } from "./operation-BQiUL0eq.js";
4
4
  import { resolveFixed, scanCommand, scopedCwd } from "./grant-commands.js";
5
5
  import { appendFileSync, existsSync, readFileSync } from "node:fs";
6
6
  import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
@@ -1,4 +1,4 @@
1
- import { $ as grantForm, A as WORK_STATUS, B as parseRef, C as SESSION_STATUS, D as TASK_REQUIRED_SECTIONS, E as SURVEY_SECTION, F as issueSchema, G as taskSchema, H as refExample, I as mainlineSchema, K as waitingForAction, L as opsEntrySchema, M as decisionSchema, N as findingSchema, O as TASK_SECTIONS, P as formatOpsEntry, Q as grantCovers, R as parseActionRef, S as SESSION_ID, T as SURVEY_LINES, U as refMainline, V as parseUntil, W as sessionSchema, Z as describeRequest, _ as MERGE_STATES, a as DECISION_SECTIONS, b as RESERVED_HUB_NAMES, c as FINDING_SECTIONS, et as grantRepo, f as ISSUE_SECTIONS, g as MAINLINE_STATUS, h as MAINLINE_SECTIONS, i as DECISION_BASES, j as configSchema, l as FINDING_STATUS, n as CLOSED_STATUS, q as waitingForRef, r as DECIDERS, s as DEFAULT_CATEGORIES, tt as parseGrantTarget, w as SLUG, x as SERVES_REF, y as REF_EXAMPLES, z as parseOpsLine } from "./dist-BbamrIPW.js";
1
+ import { $ as describeRequest, A as WORK_STATUS, B as parseRef, C as SESSION_STATUS, D as TASK_REQUIRED_SECTIONS, E as SURVEY_SECTION, F as issueSchema, G as taskSchema, H as refExample, I as mainlineSchema, J as OFFSET, K as waitingForAction, L as opsEntrySchema, M as decisionSchema, N as findingSchema, O as TASK_SECTIONS, P as formatOpsEntry, R as parseActionRef, S as SESSION_ID, T as SURVEY_LINES, U as refMainline, V as parseUntil, W as sessionSchema, Y as stampMs, _ as MERGE_STATES, a as DECISION_SECTIONS, b as RESERVED_HUB_NAMES, c as FINDING_SECTIONS, et as grantCovers, f as ISSUE_SECTIONS, g as MAINLINE_STATUS, h as MAINLINE_SECTIONS, i as DECISION_BASES, j as configSchema, l as FINDING_STATUS, n as CLOSED_STATUS, nt as grantRepo, q as waitingForRef, r as DECIDERS, rt as parseGrantTarget, s as DEFAULT_CATEGORIES, tt as grantForm, w as SLUG, x as SERVES_REF, y as REF_EXAMPLES, z as parseOpsLine } from "./dist-IdbnCDqM.js";
2
2
  import { a as LABEL_ROLES, i as FINDING_SEVERITIES, n as FINDING_CLASSES, r as FINDING_FIELDS, t as FINDINGS_FENCE } from "./retro-formats-ECy0gGOL.js";
3
3
  import { createHash } from "node:crypto";
4
4
  import { appendFileSync, closeSync, existsSync, lstatSync, mkdirSync, openSync, readFileSync, readSync, readdirSync, readlinkSync, realpathSync, renameSync, rmSync, rmdirSync, statSync, symlinkSync, writeFileSync, writeSync } from "node:fs";
@@ -34,10 +34,10 @@ function splitFrontMatter(source) {
34
34
  };
35
35
  }
36
36
  const contentHash = (text) => createHash("sha1").update(text).digest("hex");
37
- const MINUTE$1 = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}$/;
38
- /** The day and the minute of the context's time, after checking its form. */
37
+ const MINUTE$1 = new RegExp(`^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}${OFFSET}?$`);
38
+ /** The day and the minute of the context's time, after checking its form. The minute keeps the offset the context has. */
39
39
  function stamps(ctx) {
40
- if (!MINUTE$1.test(ctx.now)) throw new WriteError(`the operation time must look like 2026-09-24T15:30, got "${ctx.now}"`);
40
+ if (!MINUTE$1.test(ctx.now)) throw new WriteError(`the operation time must look like 2026-09-24T15:30+08:00, got "${ctx.now}"`);
41
41
  return {
42
42
  day: ctx.now.slice(0, 10),
43
43
  minute: ctx.now
@@ -310,6 +310,36 @@ function editFrontMatter(draft, path, schema, mutate, expectedVersion) {
310
310
  return next;
311
311
  }
312
312
  //#endregion
313
+ //#region ../core/dist/ops/protocol.js
314
+ /** `now` of a request: a local minute and its offset from UTC, `Z` for UTC itself. */
315
+ const REQUEST_TIME = new RegExp(`^(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2})(${OFFSET})$`);
316
+ /** The local minute of a request's `now` without its offset, like 2026-10-06T15:30; null when `now` is not REQUEST_TIME. Operations stamp the whole `now` (stampOf in apply.ts). */
317
+ function requestMinute(now) {
318
+ return typeof now === "string" ? REQUEST_TIME.exec(now)?.[1] ?? null : null;
319
+ }
320
+ /** `instant` as a request's `now`: the minute it is in this machine's time zone, with that zone's offset. */
321
+ function requestTime(instant = /* @__PURE__ */ new Date()) {
322
+ const pad = (n) => String(n).padStart(2, "0");
323
+ const minute = `${instant.getFullYear()}-${pad(instant.getMonth() + 1)}-${pad(instant.getDate())}T${pad(instant.getHours())}:${pad(instant.getMinutes())}`;
324
+ const offset = -instant.getTimezoneOffset();
325
+ if (offset === 0) return `${minute}Z`;
326
+ const abs = Math.abs(offset);
327
+ return `${minute}${offset > 0 ? "+" : "-"}${pad(Math.floor(abs / 60))}:${pad(abs % 60)}`;
328
+ }
329
+ /** The routes, below the server's origin. `{hub}` is the hub's name, like carlos-space. */
330
+ const ROUTES = {
331
+ /** GET, without a token: the protocol version this server speaks, `{ protocol }` */
332
+ version: "/version",
333
+ /** POST one request (SyncRequest), answered with its response and broadcast to the hub's connections when applied */
334
+ request: (hub) => `/hub/${hub}/request`,
335
+ /** GET `?protocol=2`: every file and directory of the hub (Snapshot). PUT: upload a whole hub (UploadRequest) */
336
+ snapshot: (hub) => `/hub/${hub}/snapshot`,
337
+ /** GET `?protocol=2` with `Upgrade: websocket`: receive every broadcast of the hub (ServerBroadcast) */
338
+ socket: (hub) => `/hub/${hub}/ws`
339
+ };
340
+ /** Every route below /hub/ needs this header as `Bearer <token>`, with the token of that hub. */
341
+ const AUTHORIZATION = "authorization";
342
+ //#endregion
313
343
  //#region ../core/dist/storage/node.js
314
344
  const LOCK_WAIT_MS = 5e3;
315
345
  const LOCK_STALE_MS = 3e4;
@@ -336,6 +366,7 @@ function removeIfEmpty(dir) {
336
366
  function holdLock(dir, fn) {
337
367
  const lock = join(dir, "write.lock");
338
368
  const deadline = Date.now() + LOCK_WAIT_MS;
369
+ let vanished = 0;
339
370
  for (;;) try {
340
371
  const fd = openSync(lock, "wx");
341
372
  writeSync(fd, String(process.pid));
@@ -347,12 +378,13 @@ function holdLock(dir, fn) {
347
378
  continue;
348
379
  }
349
380
  if (error.code !== "EEXIST") throw error;
350
- if (Date.now() - statSync(lock, { throwIfNoEntry: false }).mtimeMs > LOCK_STALE_MS) {
381
+ const held = statSync(lock, { throwIfNoEntry: false });
382
+ if (held && Date.now() - held.mtimeMs > LOCK_STALE_MS) {
351
383
  rmSync(lock, { force: true });
352
384
  continue;
353
385
  }
354
386
  if (Date.now() > deadline) throw new WriteError(`hub is locked by another writer (${lock}); retry in a moment`);
355
- sleep(50);
387
+ sleep(held ? 50 : Math.min(2 ** vanished++, 50));
356
388
  }
357
389
  try {
358
390
  return fn();
@@ -402,18 +434,8 @@ function nodeStorage(root) {
402
434
  }
403
435
  //#endregion
404
436
  //#region ../core/dist/io.js
405
- /** Local time to the minute, the form sessions, actions and decisions use: 2026-09-24T15:30. */
406
- const nowMinute = () => {
407
- const d = /* @__PURE__ */ new Date();
408
- return `${d.toLocaleDateString("sv-SE")}T${d.toTimeString().slice(0, 5)}`;
409
- };
410
- /** Epoch milliseconds of a stamp in that form, read as local time. */
411
- const minuteMs = (stamp) => {
412
- const [date = "", time = ""] = stamp.split("T");
413
- const [y, m, d] = date.split("-").map(Number);
414
- const [hh, mm] = time.split(":").map(Number);
415
- return new Date(y, m - 1, d, hh, mm).getTime();
416
- };
437
+ /** The time now to the minute with this machine's offset from UTC, the form sessions, actions and decisions use: 2026-09-24T15:30+08:00, or 2026-09-24T07:30Z in UTC. */
438
+ const nowMinute = () => requestTime();
417
439
  /** The context an operation run from this machine gets: the local time, which is the user's. */
418
440
  const localContext = () => ({ now: nowMinute() });
419
441
  /** Run an operation on the hub at `root` under its write lock, apply its changes and return what it reports. */
@@ -866,7 +888,7 @@ function loadHub(root, options = {}) {
866
888
  };
867
889
  const config = read(join(dataDir, "config.yaml"), configSchema);
868
890
  if (!config) throw new HubError("invalid config.yaml", problems);
869
- if (config.formatVersion !== 2) throw new HubError(config.formatVersion < 2 ? `data format version ${config.formatVersion} is older than this CLI's (2); run "mainflow migrate --dry-run" to preview the conversion, then "mainflow migrate"` : `data format version ${config.formatVersion} is newer than this CLI supports (2); install the matching mainflow version in this hub`, problems);
891
+ if (config.formatVersion !== 3) throw new HubError(config.formatVersion < 3 ? `data format version ${config.formatVersion} is older than this CLI's (3); run "mainflow migrate --dry-run" to preview the conversion, then "mainflow migrate"` : `data format version ${config.formatVersion} is newer than this CLI supports (3); install the matching mainflow version in this hub`, problems);
870
892
  problems.push(...repoPathProblems(root, config));
871
893
  const categories = /* @__PURE__ */ new Set([...DEFAULT_CATEGORIES, ...config.categories ?? []]);
872
894
  /** Read a Markdown document's front matter against `schema`, with the attributes every document shares. */
@@ -1394,7 +1416,7 @@ function initHub$1(hub, input) {
1394
1416
  if (hub.read("config.yaml") !== null) throw new WriteError(`${hub.where("")} already holds a hub`);
1395
1417
  const config = validate(configSchema, {
1396
1418
  hub: input.name,
1397
- formatVersion: 2,
1419
+ formatVersion: 3,
1398
1420
  repos: {}
1399
1421
  }, CONFIG_FILE);
1400
1422
  const draft = new Draft(hub);
@@ -2493,7 +2515,7 @@ function migrateListItem(item) {
2493
2515
  }
2494
2516
  const openItem = (item) => !item.done && !item.dropped;
2495
2517
  /**
2496
- * Convert a format 1 hub to the current format. The report lists what the changes write and remove; a dry
2518
+ * Convert a format 1 or 2 hub to the current format. Times already written are never changed. The report lists what the changes write and remove; a dry
2497
2519
  * run reports them without applying them.
2498
2520
  */
2499
2521
  function migrateHub$1(hub) {
@@ -2507,94 +2529,103 @@ function migrateHub$1(hub) {
2507
2529
  const markdownIn = (dir) => hub.list(dir).map((e) => e.name).filter((n) => n.endsWith(".md"));
2508
2530
  const config = parse$1(read(CONFIG_FILE));
2509
2531
  const from = Number(config.formatVersion);
2510
- if (from === 2) throw new WriteError(`${rel(CONFIG_FILE)} is already format 2; nothing to migrate`);
2511
- if (from !== 1) throw new WriteError(`cannot migrate from format ${String(config.formatVersion)}; this CLI migrates format 1 to 2`);
2532
+ if (from === 3) throw new WriteError(`${rel(CONFIG_FILE)} is already format 3; nothing to migrate`);
2533
+ if (from !== 1 && from !== 2) throw new WriteError(`cannot migrate from format ${String(config.formatVersion)}; this CLI migrates format 1 or 2 to 3`);
2512
2534
  const writes = /* @__PURE__ */ new Map();
2513
2535
  const removes = [];
2514
2536
  const missing = [];
2515
2537
  const document = (file, schema, data, body) => {
2516
2538
  writes.set(file, frontMatterText(validate(schema, data, rel(file)), body));
2517
2539
  };
2518
- for (const mainlineDir of subdirs(MAINLINES_DIR)) {
2519
- const yamlFile = `${mainlineDir}/mainline.yaml`;
2520
- const yamlText = hub.read(yamlFile);
2521
- if (yamlText === null) continue;
2522
- const m = parse$1(yamlText);
2523
- dropNull(m, "archivedAt");
2524
- if (isClosed("mainline", m.status) && m.archivedAt) m.closedAt = m.archivedAt;
2525
- const criteria = (m.criteria ?? []).map(migrateListItem);
2526
- m.criteria = criteria;
2527
- const id = String(m.id);
2528
- const open = !isClosed("mainline", m.status);
2529
- if (open) {
2530
- for (const c of criteria) if (openItem(c) && !c.doneWhen) missing.push(`${id}#${c.id} doneWhen`);
2531
- }
2532
- const contextFile = `${mainlineDir}/context.md`;
2533
- const contextText = hub.read(contextFile);
2534
- const context = contextText === null ? "" : withoutTitle(contextText);
2535
- document(`${mainlineDir}/${MAINLINE_FILE}`, mainlineSchema, m, `\n${context.trimEnd()}\n`);
2536
- removes.push(yamlFile, ...contextText === null ? [] : [contextFile]);
2537
- for (const taskDir of subdirs(`${mainlineDir}/tasks`)) {
2538
- const taskYaml = `${taskDir}/task.yaml`;
2539
- const taskText = hub.read(taskYaml);
2540
- if (taskText === null) continue;
2541
- const t = parse$1(taskText);
2542
- const content = typeof t.content === "string" ? t.content.trim() : "";
2543
- drop(t, "content");
2544
- dropNull(t, "parent", "repo");
2545
- t.created ??= m.created;
2546
- const checklist = (t.checklist ?? []).map(migrateListItem);
2547
- t.checklist = checklist;
2548
- const doneDays = checklist.map((c) => c.doneAt).filter((d) => typeof d === "string").sort();
2549
- if (isClosed("task", t.status) && doneDays.length) t.closedAt = doneDays.at(-1);
2550
- let body = content ? withSection(TASK_BODY, "目標", content) : TASK_BODY;
2551
- const notesFile = `${taskDir}/notes.md`;
2552
- const notes = hub.read(notesFile);
2553
- if (notes !== null) {
2554
- body = foldNotes(body, notes);
2555
- removes.push(notesFile);
2540
+ /** Format 1 to 2: documents are rewritten in their new shape and the old files removed. */
2541
+ const convertFormat1 = () => {
2542
+ for (const mainlineDir of subdirs(MAINLINES_DIR)) {
2543
+ const yamlFile = `${mainlineDir}/mainline.yaml`;
2544
+ const yamlText = hub.read(yamlFile);
2545
+ if (yamlText === null) continue;
2546
+ const m = parse$1(yamlText);
2547
+ dropNull(m, "archivedAt");
2548
+ if (isClosed("mainline", m.status) && m.archivedAt) m.closedAt = m.archivedAt;
2549
+ const criteria = (m.criteria ?? []).map(migrateListItem);
2550
+ m.criteria = criteria;
2551
+ const id = String(m.id);
2552
+ const open = !isClosed("mainline", m.status);
2553
+ if (open) {
2554
+ for (const c of criteria) if (openItem(c) && !c.doneWhen) missing.push(`${id}#${c.id} doneWhen`);
2556
2555
  }
2557
- const taskRef = `${id}/${String(t.id)}`;
2558
- if (open && !isClosed("task", t.status)) {
2559
- for (const section of TASK_REQUIRED_SECTIONS) if (!sectionText(body, section)) missing.push(`${taskRef} ${section}`);
2560
- for (const c of checklist) if (openItem(c) && !c.doneWhen) missing.push(`${taskRef}#${c.id} doneWhen`);
2556
+ const contextFile = `${mainlineDir}/context.md`;
2557
+ const contextText = hub.read(contextFile);
2558
+ const context = contextText === null ? "" : withoutTitle(contextText);
2559
+ document(`${mainlineDir}/${MAINLINE_FILE}`, mainlineSchema, m, `\n${context.trimEnd()}\n`);
2560
+ removes.push(yamlFile, ...contextText === null ? [] : [contextFile]);
2561
+ for (const taskDir of subdirs(`${mainlineDir}/tasks`)) {
2562
+ const taskYaml = `${taskDir}/task.yaml`;
2563
+ const taskText = hub.read(taskYaml);
2564
+ if (taskText === null) continue;
2565
+ const t = parse$1(taskText);
2566
+ const content = typeof t.content === "string" ? t.content.trim() : "";
2567
+ drop(t, "content");
2568
+ dropNull(t, "parent", "repo");
2569
+ t.created ??= m.created;
2570
+ const checklist = (t.checklist ?? []).map(migrateListItem);
2571
+ t.checklist = checklist;
2572
+ const doneDays = checklist.map((c) => c.doneAt).filter((d) => typeof d === "string").sort();
2573
+ if (isClosed("task", t.status) && doneDays.length) t.closedAt = doneDays.at(-1);
2574
+ let body = content ? withSection(TASK_BODY, "目標", content) : TASK_BODY;
2575
+ const notesFile = `${taskDir}/notes.md`;
2576
+ const notes = hub.read(notesFile);
2577
+ if (notes !== null) {
2578
+ body = foldNotes(body, notes);
2579
+ removes.push(notesFile);
2580
+ }
2581
+ const taskRef = `${id}/${String(t.id)}`;
2582
+ if (open && !isClosed("task", t.status)) {
2583
+ for (const section of TASK_REQUIRED_SECTIONS) if (!sectionText(body, section)) missing.push(`${taskRef} ${section}`);
2584
+ for (const c of checklist) if (openItem(c) && !c.doneWhen) missing.push(`${taskRef}#${c.id} doneWhen`);
2585
+ }
2586
+ document(`${taskDir}/${TASK_FILE}`, taskSchema, t, body);
2587
+ removes.push(taskYaml);
2588
+ }
2589
+ const decisionsDir = `${mainlineDir}/decisions`;
2590
+ for (const name of markdownIn(decisionsDir)) {
2591
+ const file = `${decisionsDir}/${name}`;
2592
+ const { data, body } = splitFrontMatter(read(file));
2593
+ const d = data;
2594
+ rename(d, "date", "created");
2595
+ if (d.status !== "proposed") d.decidedAt = d.created;
2596
+ dropNull(d, "supersededBy");
2597
+ rename(d, "blocks", "affects");
2598
+ document(file, decisionSchema, d, body);
2561
2599
  }
2562
- document(`${taskDir}/${TASK_FILE}`, taskSchema, t, body);
2563
- removes.push(taskYaml);
2564
- }
2565
- const decisionsDir = `${mainlineDir}/decisions`;
2566
- for (const name of markdownIn(decisionsDir)) {
2567
- const file = `${decisionsDir}/${name}`;
2568
- const { data, body } = splitFrontMatter(read(file));
2569
- const d = data;
2570
- rename(d, "date", "created");
2571
- if (d.status !== "proposed") d.decidedAt = d.created;
2572
- dropNull(d, "supersededBy");
2573
- rename(d, "blocks", "affects");
2574
- document(file, decisionSchema, d, body);
2575
- }
2576
- }
2577
- const hubDocs = (dir, migrate, schema) => {
2578
- for (const name of markdownIn(dir)) {
2579
- const file = `${dir}/${name}`;
2580
- const { data, body } = splitFrontMatter(read(file));
2581
- migrate(data);
2582
- document(file, schema, data, body);
2583
2600
  }
2601
+ const hubDocs = (dir, migrate, schema) => {
2602
+ for (const name of markdownIn(dir)) {
2603
+ const file = `${dir}/${name}`;
2604
+ const { data, body } = splitFrontMatter(read(file));
2605
+ migrate(data);
2606
+ document(file, schema, data, body);
2607
+ }
2608
+ };
2609
+ hubDocs(ISSUES_DIR, (i) => rename(i, "closedBy", "resolution"), issueSchema);
2610
+ hubDocs(FINDINGS_DIR, (f) => {
2611
+ rename(f, "date", "created");
2612
+ rename(f, "tags", "labels");
2613
+ }, findingSchema);
2584
2614
  };
2585
- hubDocs(ISSUES_DIR, (i) => rename(i, "closedBy", "resolution"), issueSchema);
2586
- hubDocs(FINDINGS_DIR, (f) => {
2587
- rename(f, "date", "created");
2588
- rename(f, "tags", "labels");
2589
- }, findingSchema);
2590
- config.formatVersion = 2;
2591
- writes.set(CONFIG_FILE, toYaml(validate(configSchema, config, rel(CONFIG_FILE))));
2615
+ if (from === 1) convertFormat1();
2616
+ const configText = read(CONFIG_FILE);
2617
+ const versionLine = /^formatVersion:[ \t]*2[ \t]*$/m;
2618
+ config.formatVersion = 3;
2619
+ if (from === 2 && versionLine.test(configText)) {
2620
+ validate(configSchema, config, rel(CONFIG_FILE));
2621
+ writes.set(CONFIG_FILE, configText.replace(versionLine, `formatVersion: 3`));
2622
+ } else writes.set(CONFIG_FILE, toYaml(validate(configSchema, config, rel(CONFIG_FILE))));
2592
2623
  const draft = new Draft(hub);
2593
2624
  for (const [file, text] of writes) draft.write(file, text);
2594
2625
  for (const file of removes) draft.remove(file);
2595
2626
  return draft.result({
2596
2627
  from,
2597
- to: 2,
2628
+ to: 3,
2598
2629
  written: [...writes.keys()].map(rel),
2599
2630
  removed: removes.map(rel),
2600
2631
  missingDefinitions: missing
@@ -2656,36 +2687,6 @@ function applyOperation(storage, name, input, ctx) {
2656
2687
  return applyOp(storage, (hub) => operation(hub, input, ctx));
2657
2688
  }
2658
2689
  //#endregion
2659
- //#region ../core/dist/ops/protocol.js
2660
- /** `now` of a request: a local minute and its offset from UTC, `Z` for UTC itself. */
2661
- const REQUEST_TIME = /^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2})(Z|[+-]\d{2}:\d{2})$/;
2662
- /** The local minute of a request's `now`, like 2026-10-06T15:30, which an operation stamps; null when `now` is not REQUEST_TIME. */
2663
- function requestMinute(now) {
2664
- return typeof now === "string" ? REQUEST_TIME.exec(now)?.[1] ?? null : null;
2665
- }
2666
- /** `instant` as a request's `now`: the minute it is in this machine's time zone, with that zone's offset. */
2667
- function requestTime(instant = /* @__PURE__ */ new Date()) {
2668
- const pad = (n) => String(n).padStart(2, "0");
2669
- const minute = `${instant.getFullYear()}-${pad(instant.getMonth() + 1)}-${pad(instant.getDate())}T${pad(instant.getHours())}:${pad(instant.getMinutes())}`;
2670
- const offset = -instant.getTimezoneOffset();
2671
- if (offset === 0) return `${minute}Z`;
2672
- const abs = Math.abs(offset);
2673
- return `${minute}${offset > 0 ? "+" : "-"}${pad(Math.floor(abs / 60))}:${pad(abs % 60)}`;
2674
- }
2675
- /** The routes, below the server's origin. `{hub}` is the hub's name, like carlos-space. */
2676
- const ROUTES = {
2677
- /** GET, without a token: the protocol version this server speaks, `{ protocol }` */
2678
- version: "/version",
2679
- /** POST one request (SyncRequest), answered with its response and broadcast to the hub's connections when applied */
2680
- request: (hub) => `/hub/${hub}/request`,
2681
- /** GET `?protocol=2`: every file and directory of the hub (Snapshot). PUT: upload a whole hub (UploadRequest) */
2682
- snapshot: (hub) => `/hub/${hub}/snapshot`,
2683
- /** GET `?protocol=2` with `Upgrade: websocket`: receive every broadcast of the hub (ServerBroadcast) */
2684
- socket: (hub) => `/hub/${hub}/ws`
2685
- };
2686
- /** Every route below /hub/ needs this header as `Bearer <token>`, with the token of that hub. */
2687
- const AUTHORIZATION = "authorization";
2688
- //#endregion
2689
2690
  //#region ../core/dist/ids/renumber.js
2690
2691
  /** The id at the end of a reference: c003 in m001/t002#c003, a002 in claude-code-1a2b3c4d#a002. */
2691
2692
  const lastId = (ref) => /([a-z]\d{3})$/.exec(ref)?.[1] ?? "";
@@ -2791,11 +2792,10 @@ function renumberFiles(hub, paths, renumbered) {
2791
2792
  }
2792
2793
  //#endregion
2793
2794
  //#region ../core/dist/ops/apply.js
2794
- /** The local minute an operation stamps, from a request's `now`; a `now` without its offset is refused. */
2795
- function minuteOf(now) {
2796
- const minute = requestMinute(now);
2797
- if (minute === null) throw new WriteError(`the request time must be a local minute with its offset from UTC, like 2026-10-06T15:30+08:00 (${REQUEST_TIME.source}); got "${String(now)}"`);
2798
- return minute;
2795
+ /** The time an operation stamps, from a request's `now`: the sender's local minute with its offset, UTC as `Z`. A `now` without the offset is refused. */
2796
+ function stampOf(now) {
2797
+ if (requestMinute(now) === null) throw new WriteError(`the request time must be a local minute with its offset from UTC, like 2026-10-06T15:30+08:00 (${REQUEST_TIME.source}); got "${String(now)}"`);
2798
+ return now.replace(/[+-]00:00$/, "Z");
2799
2799
  }
2800
2800
  /**
2801
2801
  * Apply a request to an offline copy of the hub, numbering new entries provisionally, and return the request to
@@ -2804,7 +2804,7 @@ function minuteOf(now) {
2804
2804
  */
2805
2805
  function applyOffline(storage, request) {
2806
2806
  const result = applyOperation(storage, request.op, request.input, {
2807
- now: minuteOf(request.now),
2807
+ now: stampOf(request.now),
2808
2808
  ids: offlineIds
2809
2809
  });
2810
2810
  return {
@@ -3034,8 +3034,8 @@ function summarize$1(entries) {
3034
3034
  function attributeTrace(trace, actions, now = Date.now()) {
3035
3035
  const windows = actions.filter((a) => a.startedAt).map((a) => ({
3036
3036
  id: a.id,
3037
- from: minuteMs(a.startedAt),
3038
- to: a.doneAt ? minuteMs(a.doneAt) + 6e4 : now
3037
+ from: stampMs(a.startedAt),
3038
+ to: a.doneAt ? stampMs(a.doneAt) + 6e4 : now
3039
3039
  }));
3040
3040
  const grouped = {};
3041
3041
  const rest = [];
@@ -4803,13 +4803,13 @@ function actionTimeline(session, stamps) {
4803
4803
  if (a.status !== "todo" && a.startedAt && !stamped(a, ["doing"])) events.push({
4804
4804
  action: a.id,
4805
4805
  status: "doing",
4806
- at: minuteMs(a.startedAt),
4806
+ at: stampMs(a.startedAt),
4807
4807
  order: events.length
4808
4808
  });
4809
4809
  if (a.doneAt && (a.status === "done" || a.status === "dropped") && !stamped(a, ["done", "dropped"])) events.push({
4810
4810
  action: a.id,
4811
4811
  status: a.status,
4812
- at: minuteMs(a.doneAt) + MINUTE,
4812
+ at: stampMs(a.doneAt) + MINUTE,
4813
4813
  order: events.length
4814
4814
  });
4815
4815
  }
@@ -7297,4 +7297,4 @@ function openInApp(hub, target, closeAfterMs = 150) {
7297
7297
  return true;
7298
7298
  }
7299
7299
  //#endregion
7300
- export { nowMinute as $, attributeTrace as A, ROUTES as B, transcriptPath as C, endsWithMarker as D, decorateReply as E, renumberFiles as F, loadHub as G, applyOperation as H, renumberPath as I, linksInto as J, dependencyGraph as K, renumberText as L, transcriptTitle as M, applyOffline as N, headerLine as O, renumberRequest as P, requireSlug as Q, scopeOfPath as R, readSession as S, matchGrants as T, checkHubName as U, requestTime as V, HubError as W, MAINLINE_FILE as X, refIndex as Y, TASK_FILE as Z, untilState as _, openInApp as a, ConflictError as at, turnReminder as b, syncHost as c, contentHash as ct, retroReportFromReceiver as d, readYaml as et, receiverFromEnv as f, initHub as g, setArchivedMany as h, hostName as i, worktreesOf as it, traceTranscript as j, mayDecorate as k, migrateHub as l, ARCHIVE_KINDS as m, DEFAULT_UI_PORT as n, currentBranch as nt, removeHostLink as o, DATA_DIR as ot, RETRY_RULES as p, mainlineEdges as q, caddySites as r, findHubRoot as rt, siteBlock as s, WriteError as st, APP_BUNDLE_ID as t, nodeStorage as tt, retroReport as u, duplicateClaimLines as v, grantScope as w, loadSessions as x, sessionBriefing as y, AUTHORIZATION as z };
7300
+ export { AUTHORIZATION as $, attributeTrace as A, checkHubName as B, transcriptPath as C, endsWithMarker as D, decorateReply as E, renumberFiles as F, linksInto as G, loadHub as H, renumberPath as I, TASK_FILE as J, refIndex as K, renumberText as L, transcriptTitle as M, applyOffline as N, headerLine as O, renumberRequest as P, nodeStorage as Q, scopeOfPath as R, readSession as S, matchGrants as T, dependencyGraph as U, HubError as V, mainlineEdges as W, nowMinute as X, requireSlug as Y, readYaml as Z, untilState as _, openInApp as a, ConflictError as at, turnReminder as b, syncHost as c, contentHash as ct, retroReportFromReceiver as d, ROUTES as et, receiverFromEnv as f, initHub as g, setArchivedMany as h, hostName as i, worktreesOf as it, traceTranscript as j, mayDecorate as k, migrateHub as l, ARCHIVE_KINDS as m, DEFAULT_UI_PORT as n, currentBranch as nt, removeHostLink as o, DATA_DIR as ot, RETRY_RULES as p, MAINLINE_FILE as q, caddySites as r, findHubRoot as rt, siteBlock as s, WriteError as st, APP_BUNDLE_ID as t, requestTime as tt, retroReport as u, duplicateClaimLines as v, grantScope as w, loadSessions as x, sessionBriefing as y, applyOperation as z };
package/dist/host.js CHANGED
@@ -1,2 +1,2 @@
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-BJnrv8xF.js";
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-DmVNYRql.js";
2
2
  export { APP_BUNDLE_ID, DEFAULT_UI_PORT, caddySites, hostName, openInApp, removeHostLink, siteBlock, syncHost };
@@ -1,6 +1,6 @@
1
1
  import { z } from "zod";
2
2
  //#region ../schema/dist/index.d.ts
3
- declare const FORMAT_VERSION = 2;
3
+ declare const FORMAT_VERSION = 3;
4
4
  declare const ID_PATTERNS: {
5
5
  readonly mainline: RegExp;
6
6
  readonly task: RegExp;
@@ -1,4 +1,4 @@
1
- import { c as syncHost, i as hostName, n as DEFAULT_UI_PORT, o as removeHostLink, ot as DATA_DIR, st as WriteError } from "./host-BJnrv8xF.js";
1
+ import { c as syncHost, i as hostName, n as DEFAULT_UI_PORT, o as removeHostLink, ot as DATA_DIR, st as WriteError } from "./host-DmVNYRql.js";
2
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";
@@ -176,7 +176,7 @@ async function launchUi(root, hub, configured, options) {
176
176
  }
177
177
  let server;
178
178
  if (!reuse) {
179
- const { serveUi } = await import("./ui-CiapFoik.js");
179
+ const { serveUi } = await import("./ui-BqRmaHXn.js");
180
180
  server = await serveUi(root, choice.port);
181
181
  writeUiRecord(root, {
182
182
  port: choice.port,
package/dist/launch.js CHANGED
@@ -1,2 +1,2 @@
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-DefacJEL.js";
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-DHug6eli.js";
2
2
  export { PORT_SPAN, choosePort, launchUi, networkProbe, portCandidates, readUiRecord, startUiInBackground, watchHubGone };
Binary file