mainflow 0.26.0 → 0.27.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,14 +1,64 @@
1
1
  #!/usr/bin/env node
2
- import { $ as createIssue, A as sessionBriefing, C as setCriterionText, D as updateTask, E as supersedeDecision, F as loadSessions, I as readSession, L as setSessionArchived, M as addAction, O as untilState, P as handoffSession, Q as createFinding, S as setCriterion, U as updateAction, V as startSession, X as appendOps, Z as closeIssue, _ as createTask, at as HubError, b as setArchived, dt as MAINLINE_FILE, et as planIssue, f as acceptDecision, ft as TASK_FILE, g as createMainline, h as createDecision, it as setIssueArchived, k as duplicateClaimLines, l as migrateHub, m as addRepo, mt as WriteError, nt as setFindingArchived, ot as loadHub, p as addHub, rt as setFindingStatus, tt as reopenIssue, v as dropChecklistItem, vt as findHubRoot, w as setMainlineStatus, x as setChecklistItem, y as initHub, z as setSessionStatus } from "./host-Dr0bCHd8.js";
3
- import { B as parseUntil, O as UNTIL_FORMS, V as refExample, z as parseRef } from "./dist-DlmecRLf.js";
2
+ import { $ as createFinding, A as duplicateClaimLines, B as setSessionStatus, C as setCriterion, D as supersedeDecision, F as handoffSession, H as startSession, I as loadSessions, L as readSession, N as addAction, O as updateTask, Q as closeIssue, R as setSessionArchived, S as setChecklistItem, T as setMainlineStatus, W as updateAction, Z as appendOps, _ as createMainline, at as setIssueArchived, b as initHub, et as createIssue, ft as MAINLINE_FILE, g as createDecision, h as addRepo, ht as WriteError, it as setFindingStatus, j as sessionBriefing, k as untilState, l as migrateHub, m as addHub, nt as reopenIssue, ot as HubError, p as acceptDecision, pt as TASK_FILE, rt as setFindingArchived, st as loadHub, tt as planIssue, u as retroReport, v as createTask, w as setCriterionText, x as setArchived, y as dropChecklistItem, yt as findHubRoot } from "./host-sSWrUJeC.js";
3
+ import { B as parseRef, H as refExample, V as parseUntil, k as UNTIL_FORMS } from "./dist-CBGKXsoi.js";
4
4
  import { t as listProgress } from "./progress-1BfPg2zN.js";
5
5
  import { COMMAND_SPECS, OPTIONS } from "./facts.js";
6
6
  import { hookFallback, parsePayload, runHook } from "./hooks.js";
7
- import { l as CLI_VERSION, r as launchUi, s as startUiInBackground } from "./launch-lnD-Z3hb.js";
7
+ import { l as CLI_VERSION, r as launchUi, s as startUiInBackground } from "./launch-1i4OAsD6.js";
8
8
  import { readFileSync, realpathSync } from "node:fs";
9
- import { join, relative } from "node:path";
9
+ import { basename, join, relative } from "node:path";
10
10
  import { fileURLToPath } from "node:url";
11
11
  import { parseArgs } from "node:util";
12
+ //#region src/retro.ts
13
+ const int = (n) => n.toLocaleString("en-US");
14
+ const usd = (n) => `$${n.toFixed(2)}`;
15
+ const pct = (n) => n === null ? "–" : `${(n * 100).toFixed(1)}%`;
16
+ /** A transcript timestamp in local time, to the minute. */
17
+ const local = (iso) => {
18
+ const d = new Date(iso);
19
+ return Number.isNaN(d.getTime()) ? iso : `${d.toLocaleDateString("sv-SE")} ${d.toTimeString().slice(0, 5)}`;
20
+ };
21
+ const tokens = (u) => `輸入 ${int(u.input)}、快取寫 5m ${int(u.cacheWrite5m)}、快取寫 1h ${int(u.cacheWrite1h)}、快取讀 ${int(u.cacheRead)}、輸出 ${int(u.output)}`;
22
+ const costOf = (t) => `${usd(t.cost)}${t.unknownPriceModels.length ? `(另有未知單價:${t.unknownPriceModels.join("、")})` : ""}`;
23
+ const byCount = (r) => Object.entries(r).sort((a, b) => b[1] - a[1]).map(([k, v]) => `${k} ${v}`).join("、");
24
+ const COMMAND_SHOWN = 100;
25
+ function retroText(report) {
26
+ const { mainline, cost, precision } = report;
27
+ return [
28
+ `retro ${mainline.id} ${mainline.title}(${mainline.status})`,
29
+ `Claude Code 版本:${report.versions.join("、") || "(對話紀錄沒有版本欄位)"}`,
30
+ `費用為依牌價的估算:${report.pricing.url}(${report.pricing.date},${report.pricing.unit})`,
31
+ `無法解析的列:${int(report.unreadable)}`,
32
+ `對話紀錄:${cost.sessions.length} 場會話、${cost.subagents.length} 個子代理`,
33
+ "",
34
+ "== 費用 ==",
35
+ `估算合計:${usd(cost.total)}${cost.unknownPriceModels.length ? `,不含未知單價的 ${cost.unknownPriceModels.join("、")}` : ""}`,
36
+ `快取命中率:${pct(cost.cacheHitRate)}(快取讀 ÷ 全部上下文)`,
37
+ "各模型:",
38
+ ...cost.models.map((m) => `- ${m.model}:呼叫 ${int(m.calls)},${tokens(m.usage)},${m.cost === null ? "未知單價" : usd(m.cost)}`),
39
+ "會話:",
40
+ ...cost.sessions.map((s) => s.missing ? `- ${s.session}:沒有讀到對話紀錄(${s.missing})` : `- ${s.session}:開場上下文 ${s.openingContext === null ? "–" : int(s.openingContext)} tokens,呼叫 ${int(s.calls)},快取命中率 ${pct(s.cacheHitRate)},${costOf(s)}`),
41
+ "子代理:",
42
+ ...cost.subagents.length === 0 ? ["- 無"] : cost.subagents.map((a) => {
43
+ const who = [a.agentType, a.description].filter(Boolean).join(":");
44
+ return `- ${basename(a.file, ".jsonl")}${who ? `(${who})` : ""},委派自 ${a.parent}:${a.models.join("、") || "沒有回覆"},呼叫 ${int(a.calls)},${tokens(a.usage)},開場上下文 ${a.openingContext === null ? "–" : int(a.openingContext)},${costOf(a)}`;
45
+ }),
46
+ "hook 注入:",
47
+ ...cost.hooks.length === 0 ? ["- 無"] : cost.hooks.map((h) => `- ${h.event}:${int(h.injections)} 次,${int(h.chars)} 字${h.blocked ? `,擋下 ${h.blocked} 次` : ""}`),
48
+ "",
49
+ "== 精準度候選 ==",
50
+ `工具錯誤:${precision.toolErrors.total}${precision.toolErrors.total ? `(${byCount(precision.toolErrors.byTool)})` : ""}`,
51
+ `同一個 Bash 指令重跑:${precision.bashReruns.total} 次`,
52
+ ...precision.bashReruns.commands.slice(0, 10).map((c) => `- ${c.runs} 次(${c.session}):${c.command.length > COMMAND_SHOWN ? `${c.command.slice(0, 99)}…` : c.command}`.replace(/\n/g, " ")),
53
+ `誤觸候選(hook 注入後,下一則回覆沒有任何工具呼叫):${precision.misfireCandidates.total}${precision.misfireCandidates.total ? `(${byCount(precision.misfireCandidates.byEvent)})` : ""}`,
54
+ `被 hook 擋下:${precision.blocked.total}${precision.blocked.total ? `(${byCount(precision.blocked.byEvent)})` : ""}`,
55
+ `超過 5 分鐘的間隔:${precision.gaps.length}`,
56
+ ...precision.gaps.map((g) => `- ${local(g.from)} → ${local(g.to)},${g.minutes} 分鐘,${g.waitingForUser ? "等使用者" : "工具或子代理執行中"}(${g.session})`),
57
+ `主脈絡:解決條件 ${mainline.criteria} 條,任務 ${mainline.tasks} 個,完成檢查未過 ${precision.failedChecks.length} 行`,
58
+ ...precision.failedChecks.map((f) => `- ${f.task}:${f.line}`)
59
+ ].join("\n");
60
+ }
61
+ //#endregion
12
62
  //#region src/cli.ts
13
63
  const RUNS = {
14
64
  init: ({ root, args }) => done(`created ${relative(root, initHub(root, args[0]))}`),
@@ -275,6 +325,10 @@ const RUNS = {
275
325
  const d = supersedeDecision(root, args[0], required(opts, "by", "--by d002"));
276
326
  return done(`superseded ${args[0]} by ${d.supersededBy}`);
277
327
  },
328
+ retro: ({ root, args, opts }) => {
329
+ const report = retroReport(root, args[0]);
330
+ return done(opts.json ? JSON.stringify(report, null, 2) : retroText(report));
331
+ },
278
332
  "decision list": ({ root, args }) => {
279
333
  const mainline = findMainline(loadHub(root), args[0]);
280
334
  for (const d of mainline.decisions) console.log(` ${mainline.id}/${d.id} ${d.status.padEnd(10)} ${d.title}`);
@@ -358,6 +358,8 @@ const ID_PATTERNS = {
358
358
  grant: /^g\d{3}$/
359
359
  };
360
360
  const CHECKLIST_REF = /^m\d{3}\/t\d{3}#c\d{3}$/;
361
+ /** What an action may serve: a checklist item, or a mainline's criterion while the mainline has no task for it yet. */
362
+ const SERVES_REF = /^m\d{3}(?:\/t\d{3}#c\d{3}|#r\d{3})$/;
361
363
  const SLUG = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
362
364
  const DATE = /^\d{4}-\d{2}-\d{2}$/;
363
365
  const DATETIME = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}$/;
@@ -773,6 +775,11 @@ const taskSchema = z.object({
773
775
  /** Tasks that must be done before this one starts */
774
776
  dependsOn: z.array(id("task")).optional(),
775
777
  repo: z.string().min(1).nullable().optional(),
778
+ /**
779
+ * Paths or globs, relative to the root of the task's repo, that the task expects to change. Check warns when
780
+ * open tasks of two open mainlines touch the same paths in one repo with no depends-on between them.
781
+ */
782
+ touches: z.array(text.refine((p) => !p.startsWith("/"), "a touches entry is relative to the root of the task's repo")).optional(),
776
783
  startedAt: date.optional(),
777
784
  checklist: z.array(checklistItemSchema),
778
785
  /**
@@ -885,7 +892,8 @@ const actionSchema = z.object({
885
892
  id: id("action"),
886
893
  do: z.string().min(1),
887
894
  status: z.enum(WORK_STATUS),
888
- serves: z.array(z.string().regex(CHECKLIST_REF)),
895
+ /** Checklist items (m001/t002#c003) or criteria (m001#r001) the action pushes forward */
896
+ serves: z.array(z.string().regex(SERVES_REF)),
889
897
  note: text.optional(),
890
898
  /** Required while blocked, absent otherwise */
891
899
  blockedBy: actionBlockSchema.optional(),
@@ -1010,4 +1018,4 @@ function parseOpsLine(line) {
1010
1018
  return parsed.success ? parsed.data : null;
1011
1019
  }
1012
1020
  //#endregion
1013
- export { grantRepo as $, configSchema as A, parseUntil as B, SLUG as C, TASK_SECTIONS as D, TASK_REQUIRED_SECTIONS as E, mainlineSchema as F, waitingForAction as G, refMainline as H, opsEntrySchema as I, GRANT_FORMS as J, waitingForRef as K, parseActionRef as L, findingSchema as M, formatOpsEntry as N, UNTIL_FORMS as O, issueSchema as P, grantForm as Q, parseOpsLine as R, SESSION_STATUS as S, SURVEY_SECTION as T, sessionSchema as U, refExample as V, taskSchema as W, describeRequest as X, GRANT_TARGET_FORMS as Y, grantCovers as Z, MERGE_STATES as _, DECISION_SECTIONS as a, RESERVED_HUB_NAMES as b, FINDING_SECTIONS as c, ID_PATTERNS as d, parseGrantTarget as et, ISSUE_SECTIONS as f, MAINLINE_STATUS as g, MAINLINE_SECTIONS as h, DECISION_BASES as i, decisionSchema as j, WORK_STATUS as k, FINDING_STATUS as l, LINK_RELS as m, CLOSED_STATUS as n, DECISION_STATUS as o, ISSUE_STATUS as p, GRANT_ACTIONS as q, DECIDERS as r, DEFAULT_CATEGORIES as s, CHECKLIST_REF as t, FORMAT_VERSION as u, PRIORITIES as v, SURVEY_LINES as w, SESSION_ID as x, REF_EXAMPLES as y, parseRef as z };
1021
+ 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 };
package/dist/facts.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as SurveyLine, i as SLUG, n as FORMAT_VERSION, o as Until, r as ID_PATTERNS, t as CHECKLIST_REF } from "./index-D4IIwDGE.js";
1
+ import { a as SLUG, i as SERVES_REF, n as FORMAT_VERSION, o as SurveyLine, r as ID_PATTERNS, s as Until, t as CHECKLIST_REF } from "./index-bIFT1ORw.js";
2
2
  //#region src/facts.d.ts
3
3
  export interface CommandSpec {
4
4
  usage: string;
@@ -97,8 +97,8 @@ export declare const COMMAND_SPECS: {
97
97
  readonly needsHub: true;
98
98
  };
99
99
  readonly 'action add': {
100
- readonly usage: 'action add <text> --serves <m/t#c>[,<m/t#c>] [--before <a>] [--session <session>]';
101
- readonly summary: 'Add an action to the session queue; prints a reminder when another session active in the last 15 minutes is doing an item it serves';
100
+ readonly usage: 'action add <text> --serves <m/t#c|m#r>[,...] [--before <a>] [--session <session>]';
101
+ readonly summary: 'Add an action to the session queue; --serves names checklist items, or criteria while the mainline has no task for them. Prints a reminder when another session active in the last 15 minutes is doing what it serves';
102
102
  readonly args: 1;
103
103
  readonly needsHub: true;
104
104
  };
@@ -307,6 +307,12 @@ export declare const COMMAND_SPECS: {
307
307
  readonly args: 1;
308
308
  readonly needsHub: true;
309
309
  };
310
+ readonly retro: {
311
+ readonly usage: 'retro <m> [--json]';
312
+ readonly summary: 'Read the Claude Code transcripts of the sessions that served a mainline, and their subagents\', into estimated list-price cost (per model, opening context, cache hit rate, hook injections) and candidates for where work went wrong (tool errors, rerun Bash commands, hook injections followed by no tool call, blocks, pauses over 5 minutes, failed completion checks); read-only';
313
+ readonly args: 1;
314
+ readonly needsHub: true;
315
+ };
310
316
  };
311
317
  export type CommandName = keyof typeof COMMAND_SPECS;
312
318
  export declare const OPTIONS: {
@@ -429,6 +435,10 @@ export declare const OPTIONS: {
429
435
  readonly type: 'boolean';
430
436
  readonly default: false;
431
437
  };
438
+ readonly json: {
439
+ readonly type: 'boolean';
440
+ readonly default: false;
441
+ };
432
442
  readonly 'dry-run': {
433
443
  readonly type: 'boolean';
434
444
  readonly default: false;
@@ -575,7 +585,7 @@ export interface FieldSpec {
575
585
  /** Every front matter field of each document and list entry; facts.test keeps it equal to the schema. */
576
586
  export declare const FIELDS: {
577
587
  readonly mainline: readonly [...FieldSpec[], FieldSpec, FieldSpec, FieldSpec, FieldSpec, FieldSpec, FieldSpec];
578
- readonly task: readonly [...FieldSpec[], FieldSpec, FieldSpec, FieldSpec, FieldSpec, FieldSpec, FieldSpec, FieldSpec, FieldSpec, FieldSpec, FieldSpec, FieldSpec, FieldSpec];
588
+ readonly task: readonly [...FieldSpec[], FieldSpec, FieldSpec, FieldSpec, FieldSpec, FieldSpec, FieldSpec, FieldSpec, FieldSpec, FieldSpec, FieldSpec, FieldSpec, FieldSpec, FieldSpec];
579
589
  readonly decision: readonly [...FieldSpec[], FieldSpec, FieldSpec, FieldSpec, FieldSpec, FieldSpec, FieldSpec];
580
590
  readonly issue: readonly [...FieldSpec[], FieldSpec, FieldSpec, FieldSpec, FieldSpec];
581
591
  readonly finding: readonly [...FieldSpec[], FieldSpec, FieldSpec, FieldSpec];
@@ -586,4 +596,4 @@ export declare const FIELDS: {
586
596
  readonly link: readonly [FieldSpec, FieldSpec, FieldSpec];
587
597
  };
588
598
  //#endregion
589
- export { CHECKLIST_REF, FORMAT_VERSION, ID_PATTERNS, SLUG };
599
+ export { CHECKLIST_REF, FORMAT_VERSION, ID_PATTERNS, SERVES_REF, SLUG };
package/dist/facts.js CHANGED
@@ -1,4 +1,4 @@
1
- import { C as SLUG, D as TASK_SECTIONS, E as TASK_REQUIRED_SECTIONS, J as GRANT_FORMS, O as UNTIL_FORMS, S as SESSION_STATUS, T as SURVEY_SECTION, Y as GRANT_TARGET_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 WORK_STATUS, l as FINDING_STATUS, m as LINK_RELS, n as CLOSED_STATUS, o as DECISION_STATUS, p as ISSUE_STATUS, q as GRANT_ACTIONS, r as DECIDERS, s as DEFAULT_CATEGORIES, t as CHECKLIST_REF, u as FORMAT_VERSION, v as PRIORITIES, w as SURVEY_LINES } from "./dist-DlmecRLf.js";
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-CBGKXsoi.js";
2
2
  //#region src/facts.ts
3
3
  const COMMAND_SPECS = {
4
4
  init: {
@@ -88,8 +88,8 @@ const COMMAND_SPECS = {
88
88
  needsHub: true
89
89
  },
90
90
  "action add": {
91
- usage: "action add <text> --serves <m/t#c>[,<m/t#c>] [--before <a>] [--session <session>]",
92
- summary: "Add an action to the session queue; prints a reminder when another session active in the last 15 minutes is doing an item it serves",
91
+ usage: "action add <text> --serves <m/t#c|m#r>[,...] [--before <a>] [--session <session>]",
92
+ summary: "Add an action to the session queue; --serves names checklist items, or criteria while the mainline has no task for them. Prints a reminder when another session active in the last 15 minutes is doing what it serves",
93
93
  args: 1,
94
94
  needsHub: true
95
95
  },
@@ -297,6 +297,12 @@ const COMMAND_SPECS = {
297
297
  summary: "List a mainline's decisions",
298
298
  args: 1,
299
299
  needsHub: true
300
+ },
301
+ retro: {
302
+ usage: "retro <m> [--json]",
303
+ summary: "Read the Claude Code transcripts of the sessions that served a mainline, and their subagents', into estimated list-price cost (per model, opening context, cache hit rate, hook injections) and candidates for where work went wrong (tool errors, rerun Bash commands, hook injections followed by no tool call, blocks, pauses over 5 minutes, failed completion checks); read-only",
304
+ args: 1,
305
+ needsHub: true
300
306
  }
301
307
  };
302
308
  const OPTIONS = {
@@ -345,6 +351,10 @@ const OPTIONS = {
345
351
  type: "boolean",
346
352
  default: false
347
353
  },
354
+ json: {
355
+ type: "boolean",
356
+ default: false
357
+ },
348
358
  "dry-run": {
349
359
  type: "boolean",
350
360
  default: false
@@ -539,6 +549,7 @@ const FIELDS = {
539
549
  field("order", false, "在主脈絡內的順序,小的在前"),
540
550
  field("dependsOn", false, "開始前必須先完成的任務"),
541
551
  field("repo", false, "主要動到的倉庫,名稱需在 config.yaml 登記"),
552
+ field("touches", false, "預計會改到的路徑或 glob 清單,相對於 repo 的根目錄;兩條進行中的主脈絡各有未結束的任務在同一個 repo 碰到重疊的路徑、彼此又沒有 depends-on 時,check 列出警告"),
542
553
  field("startedAt", false, "第一次轉為 doing 時由 CLI 寫入"),
543
554
  field("checklist", true, "checklist 項目清單,每項的欄位見 checklistItem"),
544
555
  field("blockedBy", false, "卡住時的原因、等待對象與繼續的訊號,blocked 時必填;等待對象整串是參照時(例如 m031/t002)會檢查它存在"),
@@ -581,7 +592,7 @@ const FIELDS = {
581
592
  field("id", true, "會話內不重複的編號 a{NNN},由 action add 配發"),
582
593
  field("do", true, "要做的事,一句話"),
583
594
  field("status", true, "狀態值見 STATUSES,用 action set 改"),
584
- field("serves", true, "推進的 checklist 項目參照清單,可以是空的"),
595
+ field("serves", true, "推進的 checklist 項目(m{NNN}/t{NNN}#c{NNN})或解決條件(m{NNN}#r{NNN})參照清單,可以是空的;主脈絡還沒拆任務時指向解決條件"),
585
596
  field("note", false, "一句備註"),
586
597
  field("blockedBy", false, "卡住時的原因 reason、等待對象 waitingFor 與程式可判斷的條件 until,blocked 時必填,其他狀態不得有;等待對象整串是其他會話的行動(例如 claude-code-1a2b3c4d#a003)時,對方的簡報會列出有人在等它;條件格式見 UNTIL"),
587
598
  field("startedAt", false, "轉為 doing 時由 CLI 寫入"),
@@ -594,4 +605,4 @@ const FIELDS = {
594
605
  ]
595
606
  };
596
607
  //#endregion
597
- export { CHECKLIST_REF, CLASSIFICATION, CLOSED_STATUSES, COMMAND_SPECS, FIELDS, FORMAT_VERSION, GRANTS, ID_PATTERNS, LAYOUT, LINKS, OPTIONS, REFERENCES, SECTIONS, SLUG, STATUSES, SURVEY, UNTIL };
608
+ export { CHECKLIST_REF, CLASSIFICATION, CLOSED_STATUSES, COMMAND_SPECS, FIELDS, FORMAT_VERSION, GRANTS, ID_PATTERNS, LAYOUT, LINKS, OPTIONS, REFERENCES, SECTIONS, SERVES_REF, SLUG, STATUSES, SURVEY, UNTIL };
@@ -1,4 +1,4 @@
1
- import "./index-D4IIwDGE.js";
1
+ import "./index-bIFT1ORw.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 { J as GRANT_FORMS } from "./dist-DlmecRLf.js";
1
+ import { Y as GRANT_FORMS } from "./dist-CBGKXsoi.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.js CHANGED
@@ -1,5 +1,5 @@
1
- import { A as sessionBriefing, B as settleSession, F as loadSessions, G as matchGrants, I as readSession, J as headerLine, K as decorateReply, N as ensureSession, R as setSessionInfo, W as grantScope, X as appendOps, Y as mayDecorate, _t as currentBranch, at as HubError, gt as DATA_DIR, ht as readYaml, i as hostName, j as turnReminder, ot as loadHub, q as endsWithMarker, vt as findHubRoot, yt as worktreesOf, z as setSessionStatus } from "./host-Dr0bCHd8.js";
2
- import { A as configSchema, X as describeRequest } from "./dist-DlmecRLf.js";
1
+ import { B as setSessionStatus, G as grantScope, I as loadSessions, J as endsWithMarker, K as matchGrants, L as readSession, M as turnReminder, P as ensureSession, V as settleSession, X as mayDecorate, Y as headerLine, Z as appendOps, _t as DATA_DIR, bt as worktreesOf, gt as readYaml, i as hostName, j as sessionBriefing, ot as HubError, q as decorateReply, st as loadHub, vt as currentBranch, yt as findHubRoot, z as setSessionInfo } from "./host-sSWrUJeC.js";
2
+ import { Z as describeRequest, j as configSchema } from "./dist-CBGKXsoi.js";
3
3
  import { resolveFixed, scanCommand, scopedCwd } from "./grant-commands.js";
4
4
  import { appendFileSync, existsSync, readFileSync } from "node:fs";
5
5
  import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
@@ -140,7 +140,7 @@ function missingHeaderRequest(root, { payload, cli }) {
140
140
  if (session && session.actions.length > 0) return null;
141
141
  const mainlines = openMainlinesIn(root, message);
142
142
  if (mainlines.length === 0) return null;
143
- return `[mainflow] 這一輪的回覆提到 ${mainlines.join("、")},但這場會話沒有行動,所以回覆結尾沒有標頭。這一輪若在推進它,先用 ${cli} action add "<做法>" --serves <m/t#c> 列出行動並用 ${cli} action set <a編號> --status doing 標為進行中,或用 ${cli} session handoff <會話> 接手上一場沒做完的行動;再只回一則內容為「▸ <m/t> · <a編號>」的訊息,不加其他文字。只是提到、沒有推進時,不必處理。`;
143
+ return `[mainflow] 這一輪的回覆提到 ${mainlines.join("、")},但這場會話沒有行動,所以回覆結尾沒有標頭。這一輪若在推進它,先用 ${cli} action add "<做法>" --serves <m/t#c>(還沒拆任務時用解決條件 <m#r>)列出行動並用 ${cli} action set <a編號> --status doing 標為進行中,或用 ${cli} session handoff <會話> 接手上一場沒做完的行動;再只回一則內容為「▸ <m/t> · <a編號>」的訊息,不加其他文字。只是提到、沒有推進時,不必處理。`;
144
144
  }
145
145
  /**
146
146
  * Stop: ask for what the turn's header needs, then settle the session. Only the model knows which message closes a