mainflow 0.11.0 → 0.11.1

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-iTpj7MPD.js";
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";
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-BMuk7UvN.js";
6
+ import { c as CLI_VERSION, r as launchUi, s as startUiInBackground } from "./launch-B9QrvwZQ.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-iTpj7MPD.js";
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";
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
@@ -55,8 +55,9 @@ const settleOnEnd = (root, { payload }) => {
55
55
  /** How a hub's interface is linked from a reply: through its /open route, which shows the address in the app. */
56
56
  const openLink = (hub) => (path) => `https://${hostName(hub)}/open${path}`;
57
57
  /**
58
- * MessageDisplay: link the references in the lines about to be shown and expand a trailing end marker into the
59
- * current action line. Display only, so the model keeps reading what it wrote. Text with nothing to change
58
+ * MessageDisplay: link the references in the lines about to be shown and expand the trailing header line into
59
+ * the mainline › task › action its ids name, titles included, whatever state that action is in now. Display
60
+ * only, so the model keeps reading what it wrote. Text with nothing to change
60
61
  * returns before the hub is loaded, because Claude Code holds every batch until the hook answers.
61
62
  */
62
63
  const displayReply = (root, { payload }) => {
@@ -936,31 +936,54 @@ function linkMentions(text, context) {
936
936
  return path ? `[${ref}](${context.link(path)})` : all;
937
937
  })).join("");
938
938
  }
939
- /** `▸ m001 title › t001 title › a001 do`, each id linked; null when the session has no action in progress. */
940
- function currentActionLine(context) {
941
- const action = context.session?.actions.find((a) => a.status === "doing");
942
- if (!context.session || !action) return null;
939
+ /** `▸ m001 title › t001 title › a001 do` for the given ids, each linked; titles come from the hub and the session. */
940
+ function headerLineFor(ids, context) {
943
941
  const index = refIndex(context.hub);
944
942
  const parts = [];
945
- const served = action.serves.map((s) => parseRef(s)).find((r) => r !== null);
946
- if (served && "mainline" in served) {
947
- const mainline = index.get(served.mainline);
948
- parts.push(`[${served.mainline}](${context.link(`/mainlines/${served.mainline}`)}) ${mainline?.title ?? ""}`.trimEnd());
949
- if ("task" in served) {
950
- const ref = `${served.mainline}/${served.task}`;
951
- parts.push(`[${served.task}](${context.link(`/mainlines/${served.mainline}/tasks/${served.task}`)}) ${index.get(ref)?.title ?? ""}`.trimEnd());
943
+ if (ids.mainline) {
944
+ parts.push(`[${ids.mainline}](${context.link(`/mainlines/${ids.mainline}`)}) ${index.get(ids.mainline)?.title ?? ""}`.trimEnd());
945
+ if (ids.task) {
946
+ const ref = `${ids.mainline}/${ids.task}`;
947
+ parts.push(`[${ids.task}](${context.link(`/mainlines/${ids.mainline}/tasks/${ids.task}`)}) ${index.get(ref)?.title ?? ""}`.trimEnd());
952
948
  }
953
949
  }
954
- parts.push(`[${action.id}](${context.link(sessionPath(context.session.id))}) ${action.do}`);
950
+ const action = context.session?.actions.find((a) => a.id === ids.action);
951
+ parts.push(context.session ? `[${ids.action}](${context.link(sessionPath(context.session.id))}) ${action?.do ?? ""}`.trimEnd() : ids.action);
955
952
  return `▸ ${parts.join(" › ")}`;
956
953
  }
957
- /** The header line the model writes at the end of a turn, e.g. `▸ m001/t001 · a001`; null without an action in progress. */
958
- function headerLine(session) {
954
+ /** The ids of the session's action in progress; null when there is none. */
955
+ function currentIds(session) {
959
956
  const action = session?.actions.find((a) => a.status === "doing");
960
957
  if (!action) return null;
961
958
  const served = action.serves.map((s) => parseRef(s)).find((r) => r !== null);
962
- const where = served && "mainline" in served ? "task" in served ? `${served.mainline}/${served.task}` : served.mainline : null;
963
- return `▸ ${where ? `${where} · ` : ""}${action.id}`;
959
+ if (served && "mainline" in served) return {
960
+ mainline: served.mainline,
961
+ task: "task" in served ? served.task : void 0,
962
+ action: action.id
963
+ };
964
+ return { action: action.id };
965
+ }
966
+ /** The current action line for a bare marker; null when the session has no action in progress. */
967
+ function currentActionLine(context) {
968
+ const ids = currentIds(context.session);
969
+ return ids ? headerLineFor(ids, context) : null;
970
+ }
971
+ /** The header line the model writes at the end of a turn, e.g. `▸ m001/t001 · a001`; null without an action in progress. */
972
+ function headerLine(session) {
973
+ const ids = currentIds(session);
974
+ if (!ids) return null;
975
+ const where = ids.mainline ? ids.task ? `${ids.mainline}/${ids.task}` : ids.mainline : null;
976
+ return `▸ ${where ? `${where} · ` : ""}${ids.action}`;
977
+ }
978
+ /** The ids in a header line the model wrote, or null for a bare marker or a line that does not parse. */
979
+ const WRITTEN = new RegExp(`^\\s*▸\\s+(?:(m\\d{3})(?:\\/(t\\d{3}))?\\s*·\\s*)?(a\\d{3})\\s*$`);
980
+ function parseHeader(line) {
981
+ const m = WRITTEN.exec(line);
982
+ return m ? {
983
+ mainline: m[1],
984
+ task: m[2],
985
+ action: m[3]
986
+ } : null;
964
987
  }
965
988
  /** A line that is the header: the marker alone, or the marker followed by the ids the model copied. */
966
989
  const HEADER = new RegExp(`^[ \\t]*▸(?:[ \\t].*)?$`);
@@ -973,14 +996,15 @@ const lastHeader = (text) => {
973
996
  const endsWithMarker = (text) => lastHeader(text) !== null;
974
997
  /**
975
998
  * The text to display for a piece of a reply: mentions linked, and a trailing header line replaced with the
976
- * session's current action line, titles and links included. Without an action in progress the line the model
977
- * wrote stays, its ids linked; a bare marker is dropped. Returns the input unchanged when there is nothing to do.
999
+ * mainline › task › action it names, titles and links included. A bare marker names the session's action in
1000
+ * progress and is dropped without one. Returns the input unchanged when there is nothing to do.
978
1001
  */
979
1002
  function decorateReply(text, context) {
980
1003
  const header = lastHeader(text);
981
1004
  if (header === null) return linkMentions(text, context);
982
1005
  const body = linkMentions(text.trimEnd().slice(0, -header.length).trimEnd(), context);
983
- const line = currentActionLine(context) ?? (header.trim() === "▸" ? null : linkMentions(header.trim(), context));
1006
+ const written = parseHeader(header);
1007
+ const line = written ? headerLineFor(written, context) : header.trim() === "▸" ? currentActionLine(context) : linkMentions(header.trim(), context);
984
1008
  return line ? `${body}\n\n${line}\n` : `${body}\n`;
985
1009
  }
986
1010
  /** Cheap test for text that decorateReply could change, so a display hook can skip loading the hub. */
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-iTpj7MPD.js";
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
2
  export { APP_BUNDLE_ID, DEFAULT_UI_PORT, caddySites, hostName, openInApp, siteBlock, syncHost };
@@ -1,4 +1,4 @@
1
- import { it as DATA_DIR, n as DEFAULT_UI_PORT, rt as WriteError, s as syncHost } from "./host-iTpj7MPD.js";
1
+ import { it as DATA_DIR, n as DEFAULT_UI_PORT, rt as WriteError, s as syncHost } from "./host-ByGN9mGS.js";
2
2
  import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
3
3
  import { join } from "node:path";
4
4
  import { spawn, spawnSync } from "node:child_process";
@@ -162,7 +162,7 @@ async function launchUi(root, hub, configured, options) {
162
162
  }
163
163
  let server;
164
164
  if (!reuse) {
165
- const { serveUi } = await import("./ui-DNLdjWwd.js");
165
+ const { serveUi } = await import("./ui-BY65lR7x.js");
166
166
  server = await serveUi(root, choice.port);
167
167
  writeUiRecord(root, {
168
168
  port: choice.port,
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-BMuk7UvN.js";
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
2
  export { PORT_SPAN, choosePort, launchUi, networkProbe, portCandidates, readUiRecord, startUiInBackground };
@@ -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-iTpj7MPD.js";
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";
2
2
  import { t as listProgress } from "./progress-1BfPg2zN.js";
3
- import { c as CLI_VERSION } from "./launch-BMuk7UvN.js";
3
+ import { c as CLI_VERSION } from "./launch-B9QrvwZQ.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.0",
3
+ "version": "0.11.1",
4
4
  "description": "本機多 AI 協作的主脈絡任務管理:CLI 與介面",
5
5
  "license": "MIT",
6
6
  "type": "module",