mainflow 0.36.0 → 0.38.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.
@@ -1,4 +1,4 @@
1
- import { $ as OFFSET, A as SURVEY_SECTION, B as issueSchema, C as REF_EXAMPLES, D as SESSION_STATUS, E as SESSION_ID, F as configSchema, G as parseRef, H as opsEntrySchema, I as decisionSchema, J as refMainline, K as parseUntil, L as findingSchema, M as TASK_SECTIONS, N as UNTIL_FORMS, O as SLUG, P as WORK_STATUS, Q as waitingForRef, R as formatOpsEntry, S as PRIORITIES, T as SERVES_REF, U as parseActionRef, V as mainlineSchema, W as parseOpsLine, X as taskSchema, Y as sessionSchema, Z as waitingForAction, a as DECISION_SECTIONS, at as grantCovers, b as MAINLINE_STATUS, ct as parseGrantTarget, et as stampMs, f as GROUP_SECTIONS, h as ISSUE_SECTIONS, i as DECISION_BASES, it as describeRequest, j as TASK_REQUIRED_SECTIONS, k as SURVEY_LINES, l as FINDING_SECTIONS, n as CLOSED_STATUS, ot as grantForm, p as GROUP_STATUS, q as refExample, r as DECIDERS, s as DEFAULT_CATEGORIES, st as grantRepo, u as FINDING_STATUS, v as MAINLINE_ROLES, w as RESERVED_HUB_NAMES, x as MERGE_STATES, y as MAINLINE_SECTIONS, z as groupSchema } from "./dist-ud09dzZo.js";
1
+ import { A as TASK_SECTIONS, B as opsEntrySchema, C as SERVES_REF, D as SURVEY_LINES, E as SLUG, F as findingSchema, G as refExample, H as parseOpsLine, I as formatOpsEntry, J as taskSchema, K as refMainline, L as groupSchema, M as WORK_STATUS, N as configSchema, O as SURVEY_SECTION, P as decisionSchema, Q as stampMs, R as issueSchema, S as RESERVED_HUB_NAMES, T as SESSION_STATUS, U as parseRef, V as parseActionRef, W as parseUntil, X as waitingForRef, Y as waitingForAction, Z as OFFSET, _ as MAINLINE_SECTIONS, a as DECISION_SECTIONS, at as grantRepo, b as PRIORITIES, c as FINDING_SECTIONS, d as GROUP_SECTIONS, f as GROUP_STATUS, i as DECISION_BASES, it as grantForm, j as UNTIL_FORMS, k as TASK_REQUIRED_SECTIONS, l as FINDING_STATUS, m as ISSUE_SECTIONS, n as CLOSED_STATUS, nt as describeRequest, ot as parseGrantTarget, q as sessionSchema, r as DECIDERS, rt as grantCovers, s as DEFAULT_CATEGORIES, v as MAINLINE_STATUS, w as SESSION_ID, x as REF_EXAMPLES, y as MERGE_STATES, z as mainlineSchema } from "./dist-CZYL5PJ4.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";
@@ -137,6 +137,91 @@ const offlineIds = {
137
137
  next: (request) => fresh(request, true)
138
138
  };
139
139
  //#endregion
140
+ //#region ../core/dist/ops/unknown.js
141
+ const isPlain = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
142
+ const idOf = (value) => isPlain(value) && typeof value.id === "string" ? value.id : void 0;
143
+ /** Keys that would reach the prototype instead of the data when assigned. */
144
+ const UNSAFE_KEYS = /* @__PURE__ */ new Set([
145
+ "__proto__",
146
+ "constructor",
147
+ "prototype"
148
+ ]);
149
+ function diff(raw, parsed) {
150
+ if (isPlain(raw) && isPlain(parsed)) {
151
+ const fields = /* @__PURE__ */ new Map();
152
+ for (const [key, value] of Object.entries(raw)) if (!Object.hasOwn(parsed, key)) fields.set(key, {
153
+ kind: "value",
154
+ value
155
+ });
156
+ else {
157
+ const inner = diff(value, parsed[key]);
158
+ if (inner) fields.set(key, inner);
159
+ }
160
+ return fields.size > 0 ? {
161
+ kind: "object",
162
+ fields
163
+ } : void 0;
164
+ }
165
+ if (Array.isArray(raw) && Array.isArray(parsed)) {
166
+ const counts = /* @__PURE__ */ new Map();
167
+ for (const element of raw) {
168
+ const id = idOf(element);
169
+ if (id !== void 0) counts.set(id, (counts.get(id) ?? 0) + 1);
170
+ }
171
+ const byId = /* @__PURE__ */ new Map();
172
+ for (const element of raw) {
173
+ const id = idOf(element);
174
+ if (id === void 0 || counts.get(id) !== 1) continue;
175
+ const matches = parsed.filter((p) => idOf(p) === id);
176
+ if (matches.length !== 1) continue;
177
+ const inner = diff(element, matches[0]);
178
+ if (inner) byId.set(id, inner);
179
+ }
180
+ return byId.size > 0 ? {
181
+ kind: "array",
182
+ byId
183
+ } : void 0;
184
+ }
185
+ }
186
+ /** The parts of `raw`, as it was read, that validation left out of `parsed`; undefined when nothing was dropped. */
187
+ function strippedOf(raw, parsed) {
188
+ return diff(raw, parsed);
189
+ }
190
+ function put(target, stripped) {
191
+ if (stripped.kind === "object" && isPlain(target)) for (const [key, inner] of stripped.fields) {
192
+ if (UNSAFE_KEYS.has(key)) {
193
+ if (inner.kind === "value" && !Object.hasOwn(target, key)) Object.defineProperty(target, key, {
194
+ value: structuredClone(inner.value),
195
+ enumerable: true,
196
+ writable: true,
197
+ configurable: true
198
+ });
199
+ continue;
200
+ }
201
+ if (inner.kind === "value") {
202
+ if (!Object.hasOwn(target, key)) target[key] = structuredClone(inner.value);
203
+ } else if (Object.hasOwn(target, key)) put(target[key], inner);
204
+ }
205
+ else if (stripped.kind === "array" && Array.isArray(target)) {
206
+ const counts = /* @__PURE__ */ new Map();
207
+ for (const element of target) {
208
+ const id = idOf(element);
209
+ if (id !== void 0) counts.set(id, (counts.get(id) ?? 0) + 1);
210
+ }
211
+ for (const element of target) {
212
+ const id = idOf(element);
213
+ const inner = id === void 0 || counts.get(id) !== 1 ? void 0 : stripped.byId.get(id);
214
+ if (inner) put(element, inner);
215
+ }
216
+ }
217
+ }
218
+ /** A copy of `next` with the stripped parts put back where the data has no value of its own. */
219
+ function graft(next, stripped) {
220
+ const copy = structuredClone(next);
221
+ if (stripped) put(copy, stripped);
222
+ return copy;
223
+ }
224
+ //#endregion
140
225
  //#region ../core/dist/ops/draft.js
141
226
  const normalize$1 = (path) => path.split("/").filter(Boolean).join("/");
142
227
  const parentOf = (path) => normalize$1(path).split("/").slice(0, -1).join("/");
@@ -263,7 +348,11 @@ function commit(storage, changes) {
263
348
  case "remove": storage.remove(change.path);
264
349
  }
265
350
  }
266
- /** Run an operation on the hub as it is under the lock and apply its changes before the lock is released. */
351
+ /**
352
+ * Run an operation on the hub as it is under the lock and apply its changes before the lock is released. It does not
353
+ * check the hub's data format: migrate must write a hub of another format, and the sync server's text patches
354
+ * keep every field. The entries for operations (`runOp`, `applyOperation`) check it before they call this.
355
+ */
267
356
  function applyOp(storage, run) {
268
357
  return storage.lock(() => {
269
358
  const result = run(storage);
@@ -288,14 +377,20 @@ function readYamlIn(hub, path, schema) {
288
377
  function readFrontMatterIn(hub, path, schema) {
289
378
  return validate(schema, splitFrontMatter(requireText(hub, path)).data, hub.where(path));
290
379
  }
380
+ /** `next` with the fields the YAML document at `path` has beyond its schema put back; `current` is that document as validated. */
381
+ function yamlKeeping(hub, path, current, next) {
382
+ return graft(next, strippedOf(parse$1(requireText(hub, path)), current));
383
+ }
291
384
  /** Mutate, validate and stage a YAML document; `expectedVersion` refuses the change when the file moved on. */
292
385
  function editYaml(draft, path, schema, mutate, expectedVersion) {
293
386
  const text = requireText(draft, path);
294
387
  checkVersion(draft, path, text, expectedVersion);
295
- const data = validate(schema, parse$1(text), draft.where(path));
388
+ const raw = parse$1(text);
389
+ const data = validate(schema, raw, draft.where(path));
390
+ const stripped = strippedOf(raw, data);
296
391
  mutate(data);
297
392
  const next = validate(schema, data, draft.where(path));
298
- draft.write(path, toYaml(next));
393
+ draft.write(path, toYaml(graft(next, stripped)));
299
394
  return next;
300
395
  }
301
396
  /** Mutate, validate and stage the front matter of a Markdown document; the body is kept unless `mutate` returns a new one. */
@@ -304,9 +399,10 @@ function editFrontMatter(draft, path, schema, mutate, expectedVersion) {
304
399
  checkVersion(draft, path, text, expectedVersion);
305
400
  const { data, body } = splitFrontMatter(text);
306
401
  const current = validate(schema, data, draft.where(path));
402
+ const stripped = strippedOf(data, current);
307
403
  const nextBody = mutate(current, body) ?? body;
308
404
  const next = validate(schema, current, draft.where(path));
309
- draft.write(path, frontMatterText(next, nextBody));
405
+ draft.write(path, frontMatterText(graft(next, stripped), nextBody));
310
406
  return next;
311
407
  }
312
408
  //#endregion
@@ -364,6 +460,40 @@ function decisionFileIn(hub, mainline, decision) {
364
460
  }
365
461
  const sessionFileIn = (id) => `${SESSIONS_DIR}/${id}.yaml`;
366
462
  //#endregion
463
+ //#region ../core/dist/ops/format.js
464
+ /** Why a hub whose data format is `found` cannot be written by this CLI; null when it can. */
465
+ function formatMismatch(found) {
466
+ if (found === 3) return null;
467
+ return found < 3 ? `data format version ${found} is older than this CLI's (3); run "mainflow migrate --dry-run" to preview the conversion, then "mainflow migrate"` : `data format version ${found} is newer than this CLI supports (3); install the matching mainflow version in this hub`;
468
+ }
469
+ /**
470
+ * The data format config.yaml declares; null when the hub has no config.yaml or it names no number, which loading
471
+ * the config reports. A config.yaml that is not YAML is a WriteError, so the sync server refuses the request
472
+ * instead of failing on it.
473
+ */
474
+ function hubFormatVersion(hub) {
475
+ const text = hub.read(CONFIG_FILE);
476
+ if (text === null) return null;
477
+ let data;
478
+ try {
479
+ data = parse$1(text);
480
+ } catch (error) {
481
+ throw new WriteError(`refusing to write: ${hub.where(CONFIG_FILE)} cannot be parsed as YAML: ${error.message}`);
482
+ }
483
+ const found = data?.formatVersion;
484
+ return typeof found === "number" ? found : null;
485
+ }
486
+ /**
487
+ * Refuse a write to a hub whose data format is not the one this CLI writes: rewriting a document would drop what
488
+ * another format keeps there. A hub without config.yaml is not checked, since `init` writes it.
489
+ */
490
+ function requireWritableFormat(hub) {
491
+ const found = hubFormatVersion(hub);
492
+ if (found === null) return;
493
+ const reason = formatMismatch(found);
494
+ if (reason) throw new WriteError(`refusing to write: ${reason}`);
495
+ }
496
+ //#endregion
367
497
  //#region ../core/dist/ops/protocol.js
368
498
  /** `now` of a request: a local minute and its offset from UTC, `Z` for UTC itself. */
369
499
  const REQUEST_TIME = new RegExp(`^(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2})(${OFFSET})$`);
@@ -584,7 +714,10 @@ const localContext = () => ({ now: nowMinute() });
584
714
  /** Run an operation on the hub at `root` under its write lock, apply its changes and return what it reports. */
585
715
  function runOp(root, run) {
586
716
  const ctx = localContext();
587
- return applyOp(nodeStorage(root), (hub) => run(hub, ctx)).value;
717
+ return applyOp(nodeStorage(root), (hub) => {
718
+ requireWritableFormat(hub);
719
+ return run(hub, ctx);
720
+ }).value;
588
721
  }
589
722
  /** Run an operation that must not take the lock, such as one creating the hub the lock would live in. */
590
723
  function runUnlocked(root, run) {
@@ -747,7 +880,6 @@ function remoteMembers(remotes, hubName) {
747
880
  kind: "mainline",
748
881
  title: m.title,
749
882
  status: m.status,
750
- role: m.role ?? "impl",
751
883
  archived: Boolean(m.archivedAt),
752
884
  open: !CLOSED_STATUS.mainline.includes(m.status)
753
885
  });
@@ -1031,7 +1163,8 @@ function loadConfig(root) {
1031
1163
  message: issue.message
1032
1164
  })));
1033
1165
  const config = result.data;
1034
- 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`, []);
1166
+ const mismatch = formatMismatch(config.formatVersion);
1167
+ if (mismatch) throw new HubError(mismatch, []);
1035
1168
  return config;
1036
1169
  }
1037
1170
  function loadHub(root, options = {}) {
@@ -1944,7 +2077,6 @@ function listFilesIn(hub, dir) {
1944
2077
  function createMainline(hub, input, ctx) {
1945
2078
  requireSlug(input.slug);
1946
2079
  const group = input.group ? requireGroup(hub, input.group) : void 0;
1947
- const role = input.role ? requireOneOf(input.role, MAINLINE_ROLES, "mainline role") : void 0;
1948
2080
  const priority = input.priority ? requirePriority(input.priority) : void 0;
1949
2081
  const { day } = stamps(ctx);
1950
2082
  const draft = new Draft(hub);
@@ -1961,7 +2093,6 @@ function createMainline(hub, input, ctx) {
1961
2093
  ...priority ? { priority } : {},
1962
2094
  created: day,
1963
2095
  ...group ? { group } : {},
1964
- ...role ? { role } : {},
1965
2096
  criteria: []
1966
2097
  }, MAINLINE_FILE);
1967
2098
  draft.makeDir(`${dir}/tasks`);
@@ -2003,7 +2134,7 @@ function activatePlanning(draft, id) {
2003
2134
  editFrontMatter(draft, path, mainlineSchema, (m) => void (m.status = "active"));
2004
2135
  }
2005
2136
  /**
2006
- * Change a mainline's status, group, role or priority. Done is refused while criteria are open or decisions are
2137
+ * Change a mainline's status, group or priority. Done is refused while criteria are open or decisions are
2007
2138
  * proposed; the other fields change without conditions, in the same write.
2008
2139
  */
2009
2140
  function setMainline(hub, input, ctx) {
@@ -2011,11 +2142,9 @@ function setMainline(hub, input, ctx) {
2011
2142
  if ([
2012
2143
  input.status,
2013
2144
  input.group,
2014
- input.role,
2015
2145
  input.priority
2016
- ].every((v) => v === void 0)) throw new WriteError(`${input.id} needs --status, --group, --role or --priority, e.g. --status paused`);
2146
+ ].every((v) => v === void 0)) throw new WriteError(`${input.id} needs --status, --group or --priority, e.g. --status paused`);
2017
2147
  const next = input.status === void 0 ? void 0 : requireOneOf(input.status, MAINLINE_STATUS, "mainline status");
2018
- const role = input.role === void 0 ? void 0 : requireOneOf(input.role, MAINLINE_ROLES, "mainline role");
2019
2148
  const priority = input.priority === void 0 ? void 0 : requirePriority(input.priority);
2020
2149
  const { day } = stamps(ctx);
2021
2150
  const draft = new Draft(hub);
@@ -2028,7 +2157,6 @@ function setMainline(hub, input, ctx) {
2028
2157
  }
2029
2158
  if (group) m.group = group;
2030
2159
  else if (clearsGroup(input.group)) delete m.group;
2031
- if (role) m.role = role;
2032
2160
  if (priority) m.priority = priority;
2033
2161
  }, input.expectedVersion));
2034
2162
  }
@@ -2591,11 +2719,11 @@ function takeUnfinished(draft, ctx, from, to, existing, at) {
2591
2719
  doneAt: at
2592
2720
  };
2593
2721
  });
2594
- draft.write(previousFile, toYaml(validate(sessionSchema, {
2722
+ draft.write(previousFile, toYaml(yamlKeeping(draft, previousFile, previous, validate(sessionSchema, {
2595
2723
  ...previous,
2596
2724
  status: "handed-off",
2597
2725
  actions: left
2598
- }, draft.where(previousFile))));
2726
+ }, draft.where(previousFile)))));
2599
2727
  return carried;
2600
2728
  }
2601
2729
  /**
@@ -2678,7 +2806,7 @@ function handoffSession(hub, input, ctx) {
2678
2806
  handoffFrom: from,
2679
2807
  actions: [...session.actions, ...carried]
2680
2808
  }, draft.where(file));
2681
- draft.write(file, toYaml(next));
2809
+ draft.write(file, toYaml(yamlKeeping(draft, file, session, next)));
2682
2810
  return draft.result(next);
2683
2811
  }
2684
2812
  function setSessionInfo(hub, input) {
@@ -2721,10 +2849,10 @@ function settleSession(hub, input) {
2721
2849
  if (s.status !== "active" || s.delegatedFrom || removed && s.id === id) continue;
2722
2850
  if (!s.actions.every((a) => a.status === "done" || a.status === "dropped") || subagents(s.id).some((x) => x.status === "active")) continue;
2723
2851
  if (s.id === id && s.actions.length === 0) continue;
2724
- draft.write(sessionFileIn(s.id), toYaml(validate(sessionSchema, {
2852
+ draft.write(sessionFileIn(s.id), toYaml(yamlKeeping(draft, sessionFileIn(s.id), s, validate(sessionSchema, {
2725
2853
  ...s,
2726
2854
  status: "ended"
2727
- }, draft.where(sessionFileIn(s.id)))));
2855
+ }, draft.where(sessionFileIn(s.id))))));
2728
2856
  if (s.id === id) result = "ended";
2729
2857
  }
2730
2858
  return draft.result(result);
@@ -3076,7 +3204,10 @@ const OPERATIONS = {
3076
3204
  function applyOperation(storage, name, input, ctx) {
3077
3205
  const operation = OPERATIONS[name];
3078
3206
  if (!operation) throw new Error(`unknown operation "${String(name)}"`);
3079
- return applyOp(storage, (hub) => operation(hub, input, ctx));
3207
+ return applyOp(storage, (hub) => {
3208
+ requireWritableFormat(hub);
3209
+ return operation(hub, input, ctx);
3210
+ });
3080
3211
  }
3081
3212
  //#endregion
3082
3213
  //#region ../core/dist/ids/renumber.js
@@ -8102,4 +8233,4 @@ function openInApp(hub, target, closeAfterMs = 150) {
8102
8233
  return true;
8103
8234
  }
8104
8235
  //#endregion
8105
- export { nowMinute as $, mayDecorate as A, applyOperation as B, readSession as C, splitFrontMatter as Ct, decorateReply as D, matchGrants as E, renumberRequest as F, sectionText as G, HubError as H, renumberFiles as I, linksInto as J, dependencyGraph as K, renumberPath as L, traceTranscript as M, transcriptTitle as N, endsWithMarker as O, applyOffline as P, unavailableHubs as Q, renumberText as R, loadSessions as S, contentHash as St, grantScope as T, loadConfig as U, checkHubName as V, loadHub as W, refIndex as X, memberOfGroup as Y, remoteMembers as Z, initHub as _, findHubRoot as _t, openInApp as a, MAX_FILE_BYTES as at, sessionBriefing as b, DATA_DIR as bt, siteBlock as c, comparePaths as ct, retroReport as d, requestTime as dt, readYaml as et, retroReportFromReceiver as f, textBytes as ft, setArchivedMany as g, currentBranch as gt, ARCHIVE_KINDS as h, requireSlug as ht, hostName as i, MAX_BLOB_BYTES as it, attributeTrace as j, headerLine as k, syncHost as l, exceedsFileLimit as lt, RETRY_RULES as m, TASK_FILE as mt, DEFAULT_UI_PORT as n, ACCESS_HEADERS as nt, removeDanglingLinks as o, ROUTES as ot, receiverFromEnv as p, MAINLINE_FILE as pt, mainlineEdges as q, caddySites as r, BLOB_HASH as rt, removeHostLink as s, SOCKET_MAX_AGE_CLOSE as st, APP_BUNDLE_ID as t, nodeStorage as tt, migrateHub as u, readsAsText as ut, untilState as v, worktreesOf as vt, transcriptPath as w, turnReminder as x, WriteError as xt, duplicateClaimLines as y, ConflictError as yt, scopeOfPath as z };
8236
+ export { nowMinute as $, mayDecorate as A, applyOperation as B, readSession as C, WriteError as Ct, decorateReply as D, matchGrants as E, renumberRequest as F, sectionText as G, HubError as H, renumberFiles as I, linksInto as J, dependencyGraph as K, renumberPath as L, traceTranscript as M, transcriptTitle as N, endsWithMarker as O, applyOffline as P, unavailableHubs as Q, renumberText as R, loadSessions as S, DATA_DIR as St, grantScope as T, splitFrontMatter as Tt, loadConfig as U, checkHubName as V, loadHub as W, refIndex as X, memberOfGroup as Y, remoteMembers as Z, initHub as _, requireSlug as _t, openInApp as a, MAX_FILE_BYTES as at, sessionBriefing as b, worktreesOf as bt, siteBlock as c, comparePaths as ct, retroReport as d, requestTime as dt, readYaml as et, retroReportFromReceiver as f, textBytes as ft, setArchivedMany as g, TASK_FILE as gt, ARCHIVE_KINDS as h, MAINLINE_FILE as ht, hostName as i, MAX_BLOB_BYTES as it, attributeTrace as j, headerLine as k, syncHost as l, exceedsFileLimit as lt, RETRY_RULES as m, hubFormatVersion as mt, DEFAULT_UI_PORT as n, ACCESS_HEADERS as nt, removeDanglingLinks as o, ROUTES as ot, receiverFromEnv as p, formatMismatch as pt, mainlineEdges as q, caddySites as r, BLOB_HASH as rt, removeHostLink as s, SOCKET_MAX_AGE_CLOSE as st, APP_BUNDLE_ID as t, nodeStorage as tt, migrateHub as u, readsAsText as ut, untilState as v, currentBranch as vt, transcriptPath as w, contentHash as wt, turnReminder as x, ConflictError as xt, duplicateClaimLines as y, findHubRoot as yt, scopeOfPath as z };
package/dist/host.js CHANGED
@@ -1,2 +1,2 @@
1
- import { a as openInApp, c as siteBlock, i as hostName, l as syncHost, n as DEFAULT_UI_PORT, o as removeDanglingLinks, r as caddySites, s as removeHostLink, t as APP_BUNDLE_ID } from "./host-BauijAdm.js";
1
+ import { a as openInApp, c as siteBlock, i as hostName, l as syncHost, n as DEFAULT_UI_PORT, o as removeDanglingLinks, r as caddySites, s as removeHostLink, t as APP_BUNDLE_ID } from "./host-aYx3DYrv.js";
2
2
  export { APP_BUNDLE_ID, DEFAULT_UI_PORT, caddySites, hostName, openInApp, removeDanglingLinks, removeHostLink, siteBlock, syncHost };
@@ -78,10 +78,6 @@ declare const mainlineSchema: z.ZodObject<{
78
78
  P3: "P3";
79
79
  }>>;
80
80
  group: z.ZodOptional<z.ZodString>;
81
- role: z.ZodOptional<z.ZodEnum<{
82
- impl: "impl";
83
- plan: "plan";
84
- }>>;
85
81
  due: z.ZodOptional<z.ZodString>;
86
82
  archivedAt: z.ZodOptional<z.ZodString>;
87
83
  criteria: z.ZodArray<z.ZodObject<{
@@ -423,8 +419,8 @@ declare const findingSchema: z.ZodObject<{
423
419
  }, z.core.$strip>;
424
420
  type Finding = z.infer<typeof findingSchema>;
425
421
  /**
426
- * Front matter of groups/w{NNN}-{slug}.md: mainlines and issues that belong together, such as a plan mainline with the
427
- * impl mainlines it split off, or the issues to take up together when a measurement is fixed. Membership is written
422
+ * Front matter of groups/w{NNN}-{slug}.md: mainlines and issues that belong together, such as the mainlines that split one
423
+ * piece of work, or the issues to take up together when a measurement is fixed. Membership is written
428
424
  * on each member (`group`), so a group file never lists its members and the two cannot disagree. A group is apart
429
425
  * from dependencies: depends-on between groups orders them, and priority and trigger say how urgent and when.
430
426
  */
@@ -1,4 +1,4 @@
1
- import { bt as DATA_DIR, i as hostName, l as syncHost, n as DEFAULT_UI_PORT, s as removeHostLink, xt as WriteError } from "./host-BauijAdm.js";
1
+ import { Ct as WriteError, St as DATA_DIR, i as hostName, l as syncHost, n as DEFAULT_UI_PORT, s as removeHostLink } from "./host-aYx3DYrv.js";
2
2
  import { existsSync, mkdirSync, readFileSync, realpathSync, rmSync, statSync, writeFileSync } from "node:fs";
3
3
  import { join, resolve } from "node:path";
4
4
  import { spawn, spawnSync } from "node:child_process";
@@ -276,7 +276,7 @@ async function launchUi(root, hub, configured, options) {
276
276
  }
277
277
  let server;
278
278
  if (!reuse) {
279
- const { serveUi } = await import("./ui-C-laSyqU.js");
279
+ const { serveUi } = await import("./ui-BwAp_sgf.js");
280
280
  server = await serveUi(root, choice.port);
281
281
  writeUiRecord(root, {
282
282
  port: choice.port,
package/dist/launch.js CHANGED
@@ -1,2 +1,2 @@
1
- import { a as networkProbe, c as realRoot, d as withUiLock, i as launchUi, l as startUiInBackground, n as choosePort, o as portCandidates, r as exitCodeFor, s as readUiRecord, t as PORT_SPAN, u as watchHubGone } from "./launch-n2ZDF0BF.js";
1
+ import { a as networkProbe, c as realRoot, d as withUiLock, i as launchUi, l as startUiInBackground, n as choosePort, o as portCandidates, r as exitCodeFor, s as readUiRecord, t as PORT_SPAN, u as watchHubGone } from "./launch-D38sNgXM.js";
2
2
  export { PORT_SPAN, choosePort, exitCodeFor, launchUi, networkProbe, portCandidates, readUiRecord, realRoot, startUiInBackground, watchHubGone, withUiLock };
@@ -1,4 +1,4 @@
1
- import { $ as nowMinute, B as applyOperation, Ct as splitFrontMatter, F as renumberRequest, I as renumberFiles, L as renumberPath, P as applyOffline, R as renumberText, St as contentHash, at as MAX_FILE_BYTES, bt as DATA_DIR, ct as comparePaths, dt as requestTime, ft as textBytes, it as MAX_BLOB_BYTES, lt as exceedsFileLimit, nt as ACCESS_HEADERS, ot as ROUTES, rt as BLOB_HASH, st as SOCKET_MAX_AGE_CLOSE, tt as nodeStorage, ut as readsAsText, xt as WriteError, yt as ConflictError, z as scopeOfPath } from "./host-BauijAdm.js";
1
+ import { $ as nowMinute, B as applyOperation, Ct as WriteError, F as renumberRequest, I as renumberFiles, L as renumberPath, P as applyOffline, R as renumberText, St as DATA_DIR, Tt as splitFrontMatter, at as MAX_FILE_BYTES, ct as comparePaths, dt as requestTime, ft as textBytes, it as MAX_BLOB_BYTES, lt as exceedsFileLimit, nt as ACCESS_HEADERS, ot as ROUTES, rt as BLOB_HASH, st as SOCKET_MAX_AGE_CLOSE, tt as nodeStorage, ut as readsAsText, wt as contentHash, xt as ConflictError, z as scopeOfPath } from "./host-aYx3DYrv.js";
2
2
  import { createHash, randomBytes } from "node:crypto";
3
3
  import { accessSync, appendFileSync, chmodSync, closeSync, constants, copyFileSync, createReadStream, createWriteStream, existsSync, linkSync, lstatSync, mkdirSync, openSync, readFileSync, readSync, readdirSync, renameSync, rmSync, statSync, watch, writeFileSync } from "node:fs";
4
4
  import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
@@ -1,8 +1,8 @@
1
- import { F as configSchema, f as GROUP_SECTIONS } from "./dist-ud09dzZo.js";
2
- import { C as readSession, G as sectionText, H as HubError, J as linksInto, K as dependencyGraph, M as traceTranscript, N as transcriptTitle, S as loadSessions, U as loadConfig, W as loadHub, X as refIndex, Z as remoteMembers, a as openInApp, bt as DATA_DIR, et as readYaml, g as setArchivedMany, h as ARCHIVE_KINDS, j as attributeTrace, q as mainlineEdges, w as transcriptPath, xt as WriteError, yt as ConflictError } from "./host-BauijAdm.js";
1
+ import { N as configSchema, d as GROUP_SECTIONS } from "./dist-CZYL5PJ4.js";
2
+ import { C as readSession, Ct as WriteError, G as sectionText, H as HubError, J as linksInto, K as dependencyGraph, M as traceTranscript, N as transcriptTitle, S as loadSessions, St as DATA_DIR, U as loadConfig, W as loadHub, X as refIndex, Z as remoteMembers, a as openInApp, et as readYaml, g as setArchivedMany, h as ARCHIVE_KINDS, j as attributeTrace, q as mainlineEdges, w as transcriptPath, xt as ConflictError } from "./host-aYx3DYrv.js";
3
3
  import { t as listProgress } from "./progress-1BfPg2zN.js";
4
- import { A as isSynced, _ as readDaemon, a as remoteMode, b as readRemote, h as callDaemon, j as syncPaths, k as SYNC_DIR, m as DaemonUnavailable, n as hubWriter, r as writtenLines, y as watchTree } from "./operation-DGRH4iBE.js";
5
- import { c as realRoot, f as CLI_VERSION, s as readUiRecord } from "./launch-n2ZDF0BF.js";
4
+ import { A as isSynced, _ as readDaemon, a as remoteMode, b as readRemote, h as callDaemon, j as syncPaths, k as SYNC_DIR, m as DaemonUnavailable, n as hubWriter, r as writtenLines, y as watchTree } from "./operation-1oQ8lA9C.js";
5
+ import { c as realRoot, f as CLI_VERSION, s as readUiRecord } from "./launch-D38sNgXM.js";
6
6
  import { createRequire } from "node:module";
7
7
  import { closeSync, existsSync, lstatSync, openSync, readFileSync, readSync, realpathSync, statSync } from "node:fs";
8
8
  import { basename, dirname, extname, join, normalize, relative, resolve, sep } from "node:path";
@@ -117,7 +117,6 @@ function summarize(m) {
117
117
  labels: m.labels ?? [],
118
118
  due: m.due ?? null,
119
119
  group: m.group ?? null,
120
- role: m.role ?? "impl",
121
120
  updated: [
122
121
  m,
123
122
  ...m.tasks,