@pmelab/gtd 64.2.0 → 65.0.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.
Files changed (59) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +36 -26
  3. package/claude/hooks/assist.ts +9 -35
  4. package/claude/hooks/doors.ts +4 -4
  5. package/claude/hooks/git.ts +56 -0
  6. package/claude/hooks/handoff.ts +11 -11
  7. package/claude/hooks/jobs.ts +8 -8
  8. package/claude/hooks/pr.ts +8 -8
  9. package/claude/hooks/register.tsx +16 -78
  10. package/claude/hooks/tools.ts +7 -20
  11. package/claude/hooks/wording.ts +3 -3
  12. package/dist/chunks/{flows-dnIE_qbe.mjs → flows-DGs0W3HI.mjs} +19 -2
  13. package/dist/chunks/{testkit-BwCH8ky6.mjs → testkit-CgrLmpdJ.mjs} +741 -80
  14. package/dist/chunks/{wire-CaPJ9Tme.mjs → wire-BNS8ciNu.mjs} +5 -3
  15. package/dist/flows.mjs +1 -1
  16. package/dist/gtd.bundle.mjs +565 -114
  17. package/dist/gtd.core.mjs +132 -129
  18. package/dist/testkit/gherkin.mjs +1 -1
  19. package/dist/testkit.mjs +2 -2
  20. package/dist/web/main.js +2 -2
  21. package/dist/wire.mjs +1 -1
  22. package/dist/workflow-kit.mjs +1 -1
  23. package/package.json +1 -1
  24. package/src/cli/Cli.ts +5 -5
  25. package/src/cli/History.test.ts +10 -8
  26. package/src/cli/Metrics.test.ts +2 -1
  27. package/src/cli/Program.test.ts +4 -2
  28. package/src/cli/Program.ts +87 -5
  29. package/src/edge/Edge.test.ts +37 -16
  30. package/src/edge/Edge.ts +296 -31
  31. package/src/emit/GitScript.ts +116 -15
  32. package/src/emit/index.ts +7 -0
  33. package/src/flows/config.ts +7 -1
  34. package/src/flows/index.test.ts +1 -0
  35. package/src/flows/index.ts +2 -0
  36. package/src/flows/runtime.ts +32 -1
  37. package/src/platform/RetainedHistory.ts +3 -0
  38. package/src/platform/index.ts +1 -0
  39. package/src/replay/Replay.test.ts +9 -0
  40. package/src/replay/Replay.ts +59 -15
  41. package/src/replay/Trailers.ts +14 -0
  42. package/src/replay/index.ts +1 -1
  43. package/src/step/LandStep.ts +12 -0
  44. package/src/step/RepoSnapshot.ts +11 -0
  45. package/src/step/index.ts +1 -0
  46. package/src/step/planStart.test.ts +4 -3
  47. package/src/step/planStart.ts +7 -0
  48. package/src/step/planStep.ts +17 -12
  49. package/src/step/startBranch.ts +54 -0
  50. package/src/twins/EmittedScriptRecognizer.ts +117 -0
  51. package/src/twins/EmittedScripts.test.ts +147 -1
  52. package/src/twins/InMemRepo.ts +116 -0
  53. package/src/wire/Demand.ts +22 -10
  54. package/src/wire/constants.ts +3 -0
  55. package/src/wire/types.ts +4 -0
  56. package/src/workflow/Workflow.ts +1 -0
  57. package/src/workflow/compile.ts +2 -0
  58. package/src/workflow/load.ts +2 -0
  59. package/claude/hooks/ship.ts +0 -730
@@ -25,9 +25,8 @@ import type { Judgment } from "./judge"
25
25
  import { catchFrom, throwTo } from "./handoff"
26
26
  import { jobs } from "./jobs"
27
27
  import { documents, readDocument } from "./schema"
28
- import { READ_ONLY_GIT, ship } from "./ship"
29
28
  import { withRequirements } from "./sketch"
30
- import type { Shipped, ShipIo } from "./ship"
29
+ import type { Done, GitIo } from "./git"
31
30
  import { collectAnswer } from "./delegate"
32
31
  import { decideCommand, decideContinue, decideJob, restId, TOOLS } from "./tools"
33
32
  import type { JobName } from "./tools"
@@ -72,7 +71,7 @@ let isDriving = false
72
71
  // bumped by every stop, so a queued continue that was mid-check sees it
73
72
  let stopCount = 0
74
73
  // subagents answering into a file: what each may touch (see tool.call)
75
- const delegates = new Map<string, { file: string; mayRun: RegExp | undefined }>()
74
+ const delegates = new Map<string, { file: string }>()
76
75
  const ours = new Set<string>()
77
76
  // What each turn agent may read and write; reset on every spawn and resume,
78
77
  // since the steering file can differ per step.
@@ -295,8 +294,7 @@ async function wake($: $) {
295
294
  const r = await read($, run)
296
295
  const stop = r.stop
297
296
  if (!stop || !r.rest) return
298
- const branch = stop.kind === "done" ? await shippable($) : undefined
299
- if (!wakes(stop, branch)) return
297
+ if (!wakes(stop)) return
300
298
  const questions = stop.isJudge ? await openQuestions($) : undefined
301
299
  const text = wakePrompt({
302
300
  stop,
@@ -304,7 +302,6 @@ async function wake($: $) {
304
302
  notes: r.notes,
305
303
  isRepeat: r.isRepeat,
306
304
  questions,
307
- branch,
308
305
  })
309
306
  await update($, run, (x) => ({ ...x, notes: undefined }))
310
307
  // Not from inside the hook that started the run: a prompt submitted there
@@ -321,16 +318,6 @@ async function openQuestions($: $) {
321
318
  }
322
319
  }
323
320
 
324
- // The branch a finished process can open its pull request from, if any.
325
- async function shippable($: $) {
326
- const branch = (
327
- await $.process.run(["git", "rev-parse", "--abbrev-ref", "HEAD"], { cwd: root })
328
- ).stdout.trim()
329
- if (["main", "master", "HEAD"].includes(branch)) return undefined
330
- const summary = await $.process.run(["gtd", "summary"], { cwd: root })
331
- return summary.exitCode === 0 ? branch : undefined
332
- }
333
-
334
321
  // A new process starts from the requirements written to the steering file an
335
322
  // idle rest names; the opening beat captures them like a hand-edit.
336
323
  async function begin($: $, requirements: string) {
@@ -440,8 +427,8 @@ function startJob(
440
427
  $: $,
441
428
  job: JobName,
442
429
  isInTurn: boolean,
443
- work: () => Promise<Shipped>,
444
- then?: (outcome: Shipped) => Promise<void>,
430
+ work: () => Promise<Done>,
431
+ then?: (outcome: Done) => Promise<void>,
445
432
  ) {
446
433
  const answer = background.start(job, work, true, async (outcome) => {
447
434
  if (then) await then(outcome)
@@ -457,7 +444,7 @@ function startJob(
457
444
  }
458
445
 
459
446
  async function throwNow($: $, target: string | undefined, isInTurn: boolean) {
460
- const refused = decideJob(await read($, run), "handoff")
447
+ const refused = decideJob(await read($, run))
461
448
  if (refused) return refused
462
449
  return startJob(
463
450
  $,
@@ -474,7 +461,7 @@ async function throwNow($: $, target: string | undefined, isInTurn: boolean) {
474
461
  content: b.content,
475
462
  isIdle: isTrue(b.idle),
476
463
  }
477
- return throwTo(shipIo($), rest, target, new Date().toISOString())
464
+ return throwTo(gitIo($), rest, target, new Date().toISOString())
478
465
  },
479
466
  async (thrown) => {
480
467
  if (!thrown.ok) return
@@ -490,7 +477,7 @@ async function throwNow($: $, target: string | undefined, isInTurn: boolean) {
490
477
 
491
478
  async function enterNow($: $, door: string, args: string[]) {
492
479
  if ((await read($, run)).isRunning) return "Stop the loop first: /gtd stop."
493
- const entered = await enter(shipIo($), door, args)
480
+ const entered = await enter(gitIo($), door, args)
494
481
  if (entered.ok) await start($)
495
482
  return entered.text
496
483
  }
@@ -511,7 +498,7 @@ async function prNow($: $) {
511
498
  if (r.pr && !isReviewGate(r.stop)) {
512
499
  return "Review threads from an earlier /gtd pr wait for the review's first review gate."
513
500
  }
514
- const io = shipIo($)
501
+ const io = gitIo($)
515
502
  const pr = await currentPr(io)
516
503
  if (typeof pr === "string") return pr
517
504
  const threads = await unresolvedThreads(io, pr)
@@ -585,7 +572,7 @@ async function prRest($: $, stop: Stop) {
585
572
  async function replyThreads($: $, stop: Stop) {
586
573
  const pr = (await read($, run)).pr
587
574
  if (!pr?.importedAt) return
588
- const io = shipIo($)
575
+ const io = gitIo($)
589
576
  const found = await decided(
590
577
  io,
591
578
  pr.importedAt,
@@ -618,7 +605,7 @@ async function replyThreads($: $, stop: Stop) {
618
605
  // shown to the catcher first, never landed unseen.
619
606
  async function catchNow($: $, ref: string) {
620
607
  if ((await read($, run)).isRunning) return "Stop the loop first: /gtd stop."
621
- const caught = await catchFrom(shipIo($), ref)
608
+ const caught = await catchFrom(gitIo($), ref)
622
609
  if (!caught.ok) return caught.text
623
610
  await findRoot($)
624
611
  const b = await docs($).next()
@@ -636,27 +623,11 @@ async function catchNow($: $, ref: string) {
636
623
  return caught.text
637
624
  }
638
625
 
639
- // Ship's text turns need git to read the process, so they run as a subagent.
640
- // Its answer is a file, not its hand-back: a hand-back never reaches a mod.
641
- // `mayRun`: the only shell commands the subagent may run; none when absent.
642
626
  type Delegate = {
643
627
  name: string
644
628
  description: string
645
629
  system: string
646
630
  tools: string[]
647
- mayRun?: RegExp
648
- }
649
-
650
- const SHIPPER: Delegate = {
651
- name: "shipper",
652
- description:
653
- "Writes commit messages and pull requests for gtd's ship, spawned by the gtd mod only",
654
- system:
655
- "You write commit messages and pull-request descriptions for gtd's ship command. Read the repository with git and the file tools as the instructions ask. Never modify the repository: no commits, no checkouts, no pushes.",
656
- tools: ["Bash", "Read", "Grep", "Glob", "Write", "Skill"],
657
- // It reads commit messages anyone on the branch wrote: read-only git, and
658
- // no shell syntax to chain anything else onto it.
659
- mayRun: READ_ONLY_GIT,
660
631
  }
661
632
 
662
633
  // gtd's llm judge persona; writing its answer file is its one tool.
@@ -693,7 +664,7 @@ async function delegate($: $, who: Delegate, prompt: string, model: string, deli
693
664
  const id = spawned.agentId
694
665
  if (!id) return undefined
695
666
  ours.add(id)
696
- delegates.set(id, { file, mayRun: who.mayRun })
667
+ delegates.set(id, { file })
697
668
  // A timed-out agent may still be running: it keeps its tool limits until its
698
669
  // turn ends, where turn.complete drops them.
699
670
  return collectAnswer({
@@ -704,11 +675,6 @@ async function delegate($: $, who: Delegate, prompt: string, model: string, deli
704
675
  })
705
676
  }
706
677
 
707
- async function writer($: $, prompt: string) {
708
- const model = (await $.env.get("GTD_PLANNERMODEL")) ?? "opus"
709
- return delegate($, SHIPPER, prompt, model, "Your final answer, exactly as you would print it.")
710
- }
711
-
712
678
  // Where `gtd judge run` would pick its llm, a judge gate is put to a small
713
679
  // model as that provider does, but as a subagent of this session. Any doubt leaves the
714
680
  // gate to the person, which routes the workflow its cautious way.
@@ -729,39 +695,19 @@ async function judgeInSession($: $, j: Judgment) {
729
695
  }
730
696
  }
731
697
 
732
- function shipIo($: $): ShipIo {
698
+ function gitIo($: $): GitIo {
733
699
  return {
734
700
  run: async (argv, stdin) => {
735
701
  const r = await $.process.run(argv, { cwd: root, stdin, timeoutMs: TEN_MINUTES })
736
702
  return { code: r.exitCode, out: r.stdout, err: r.stderr }
737
703
  },
738
- complete: (prompt) => writer($, prompt),
739
704
  log: (line) => {
740
705
  for (const l of line.split("\n")) $.ui.log(l)
741
706
  if (background.busy()) $.ui.status(line.split("\n")[0]!)
742
707
  },
743
- today: () => new Date().toISOString().slice(0, 10),
744
708
  }
745
709
  }
746
710
 
747
- async function shipNow($: $, isDry: boolean, isInTurn: boolean) {
748
- const refused = decideJob(await read($, run), "ship")
749
- if (refused) return refused
750
- return startJob(
751
- $,
752
- "ship",
753
- isInTurn,
754
- async () => {
755
- $.ui.status(isDry ? "previewing the pull request…" : "opening the pull request…")
756
- return ship(shipIo($), isDry)
757
- },
758
- async (shipped) => {
759
- // a failed ship leaves the run as it was; a dry run changes nothing
760
- if (shipped.ok && !isDry) await dismiss($)
761
- },
762
- )
763
- }
764
-
765
711
  // Turns a missing CLI or a wrong directory into an instruction, not a stack trace.
766
712
  // The plugin is gtd's own npm package, so it runs the gtd it ships and the mod
767
713
  // and the CLI never disagree. A checkout without a build falls back to PATH.
@@ -986,8 +932,6 @@ async function command($: $, arg: string): Promise<string | undefined> {
986
932
  return rest[0]
987
933
  ? catchNow($, rest[0])
988
934
  : "Name the pull request or branch: /gtd catch <number|branch>."
989
- case "ship":
990
- return shipNow($, rest[0] === "-n" || rest[0] === "--dry-run", false)
991
935
  case "":
992
936
  return resume($)
993
937
  default:
@@ -997,7 +941,7 @@ async function command($: $, arg: string): Promise<string | undefined> {
997
941
 
998
942
  // A door wins over the bare `pr` verb; anything else is requirements.
999
943
  async function routed($: $, verb: string, rest: string[], arg: string) {
1000
- if (doorFor(await doors(shipIo($)), verb, rest)) return enterNow($, verb, rest)
944
+ if (doorFor(await doors(gitIo($)), verb, rest)) return enterNow($, verb, rest)
1001
945
  return verb === "pr" && rest.length === 0 ? prNow($) : begin($, arg)
1002
946
  }
1003
947
 
@@ -1067,12 +1011,9 @@ function subagentDenial(agentId: string, e: Record<string, unknown>) {
1067
1011
  if (denial) return denial
1068
1012
  const delegated = delegates.get(agentId)
1069
1013
  if (!delegated) return undefined
1070
- if (e.tool === "Write" && e.file_path !== delegated.file) {
1014
+ if ((e.tool === "Write" && e.file_path !== delegated.file) || e.tool === "Bash") {
1071
1015
  return `Write only your answer, to ${delegated.file}.`
1072
1016
  }
1073
- if (e.tool === "Bash" && !delegated.mayRun?.test(String(e.command).trim())) {
1074
- return "Only read-only git commands, without shell syntax, are allowed here."
1075
- }
1076
1017
  return undefined
1077
1018
  }
1078
1019
 
@@ -1111,7 +1052,7 @@ export const register: Register = (on) => {
1111
1052
  name: "gtd",
1112
1053
  description: "Drive gtd until it rests on you; pass requirements to start a new process",
1113
1054
  argumentHint:
1114
- "[requirements | <door> [args] | stop | status | ui | ship [-n] | pr | throw [@user] | catch <pr|branch>]",
1055
+ "[requirements | <door> [args] | stop | status | ui | pr | throw [@user] | catch <pr|branch>]",
1115
1056
  immediate: true,
1116
1057
  })
1117
1058
  return next(e)
@@ -1191,9 +1132,6 @@ export const register: Register = (on) => {
1191
1132
  on("tool.call", { tool: "mcp__gtd__handoff" }, async ($, e) =>
1192
1133
  answer(await throwNow($, typeof e.to === "string" && e.to ? e.to : undefined, true), true),
1193
1134
  )
1194
- on("tool.call", { tool: "mcp__gtd__ship" }, async ($, e) =>
1195
- answer(await shipNow($, e.dryRun === true, true), true),
1196
- )
1197
1135
  on("tool.call", { tool: "mcp__gtd__browser" }, async ($) => answer(await browse($), true))
1198
1136
 
1199
1137
  on("agent.offer", ($, e, next) => (e.agent.startsWith("gtd:") ? { isOffered: false } : next(e)))
@@ -10,7 +10,6 @@ export const TOOL = {
10
10
  continue: "mcp__gtd__continue",
11
11
  note: "mcp__gtd__note",
12
12
  handoff: "mcp__gtd__handoff",
13
- ship: "mcp__gtd__ship",
14
13
  browser: "mcp__gtd__browser",
15
14
  } as const
16
15
 
@@ -44,12 +43,6 @@ export const TOOLS = [
44
43
  "Hands the gtd process to someone else: pushes the branch and opens or refreshes a draft pull request assigned to them. Call it only when the person asks. `to`: their GitHub username; omit it to leave the process for anyone.",
45
44
  inputSchema: { type: "object", properties: { to: { type: "string" } } },
46
45
  },
47
- {
48
- name: "ship",
49
- description:
50
- "Combines the finished gtd process into one commit, pushes it and opens or updates its pull request. Call it only after the person agreed. `dryRun` previews without writing anything.",
51
- inputSchema: { type: "object", properties: { dryRun: { type: "boolean" } } },
52
- },
53
46
  {
54
47
  name: "browser",
55
48
  description:
@@ -71,21 +64,21 @@ export type ContinueIo = {
71
64
  // the rest's own `gtd validate` script, run; ok when there is nothing to check
72
65
  validate(): Promise<{ ok: boolean; out: string }>
73
66
  judgment(): Promise<Judgment | undefined>
74
- // a ship or hand-off running or queued: it writes the tree the driver would
67
+ // a hand-off running or queued: it writes the tree the driver would
75
68
  busy?: JobName
76
69
  }
77
70
 
78
- export type JobName = "ship" | "handoff"
71
+ export type JobName = "handoff"
79
72
 
80
- export const JOB_NAME: Record<JobName, string> = { ship: "ship", handoff: "hand-off" }
73
+ export const JOB_NAME: Record<JobName, string> = { handoff: "hand-off" }
81
74
 
82
75
  const busyText = (job: JobName) => `A ${JOB_NAME[job]} is still running: wait for its report.`
83
76
 
84
- // Only these leave the tree alone (ship and throw refuse for themselves); any
77
+ // Only these leave the tree alone (throw refuses for itself); any
85
78
  // other verb, unknown ones included, may switch branch or write .gtd/. `stop`
86
79
  // is not here: `command` takes the bare word itself, and `stop <words>` is a
87
80
  // requirement. `ui` is not: its page writes steering files.
88
- const WHILE_BUSY = new Set(["status", "throw", "ship"])
81
+ const WHILE_BUSY = new Set(["status", "throw"])
89
82
 
90
83
  export function decideCommand(arg: string, busy: JobName | undefined): string | undefined {
91
84
  if (!busy) return undefined
@@ -94,13 +87,9 @@ export function decideCommand(arg: string, busy: JobName | undefined): string |
94
87
  }
95
88
 
96
89
  // Pure: a refused job leaves the run, and so `continue`, as it was.
97
- export function decideJob(run: Run, job: JobName): string | undefined {
90
+ export function decideJob(run: Run): string | undefined {
98
91
  if (run.isRunning) return "gtd is running a step: wait for it to rest."
99
92
  if (run.pending) return "A continue is already waiting for this turn to end."
100
- const kind = run.stop?.kind
101
- if (job === "ship" && (kind === "gate" || kind === "stalled" || kind === "error")) {
102
- return "gtd still waits on the person at this step: answer it with continue first."
103
- }
104
93
  return undefined
105
94
  }
106
95
 
@@ -116,9 +105,7 @@ export async function decideContinue(
116
105
  if (io.busy) return { refuse: busyText(io.busy) }
117
106
  const stop = run.stop
118
107
  if (!stop) return { refuse: "Nothing is waiting: gtd has no rest open. /gtd drives it." }
119
- if (stop.kind === "done") {
120
- return { refuse: `The process is finished: ${TOOL.ship} opens its pull request.` }
121
- }
108
+ if (stop.kind === "done") return { refuse: "The process is finished: nothing waits here." }
122
109
  if (rest !== undefined && rest !== run.rest) {
123
110
  return {
124
111
  refuse: "gtd has moved on from that step; it no longer waits there. Nothing was changed.",
@@ -2,7 +2,7 @@
2
2
 
3
3
  import type { Stop } from "../types"
4
4
  import type { Beat } from "./drive"
5
- import type { Shipped } from "./ship"
5
+ import type { Done } from "./git"
6
6
  import { JOB_NAME } from "./tools"
7
7
  import type { JobName } from "./tools"
8
8
 
@@ -61,8 +61,8 @@ export function pushText(stop: Stop, repo: string, url?: string) {
61
61
 
62
62
  const capitalised = (s: string) => s[0]!.toUpperCase() + s.slice(1)
63
63
 
64
- export const jobHeadline = (job: JobName, outcome: Shipped) =>
64
+ export const jobHeadline = (job: JobName, outcome: Done) =>
65
65
  `${outcome.ok ? "✔" : "✘"} ${capitalised(JOB_NAME[job])} ${outcome.ok ? "finished" : "failed"}`
66
66
 
67
- export const jobPushText = (job: JobName, outcome: Shipped, repo: string) =>
67
+ export const jobPushText = (job: JobName, outcome: Done, repo: string) =>
68
68
  `${repo}: ${JOB_NAME[job]} ${outcome.ok ? "finished" : "failed"}. ${outcome.text}`.trim()
@@ -60,6 +60,17 @@ const run = (name, body, options = {}) => ctx().step({
60
60
  body,
61
61
  options
62
62
  });
63
+ /**
64
+ * Squashes HEAD's tree, with `.gtd/` as the user's branch has it, into one commit on the user's branch
65
+ * with `message`, and moves that branch there; HEAD stays on `gtd/<b>`.
66
+ * Resolves to the new commit's hash, or `undefined` when nothing shipped.
67
+ */
68
+ const ship = (name, message, options = {}) => ctx().step({
69
+ kind: "ship",
70
+ name,
71
+ message,
72
+ options
73
+ });
63
74
  /** A judge gate: resolves to what the judge answered, for the flow to decide on. */
64
75
  const judge = (name, spec) => {
65
76
  const { questions, evidence, ...options } = spec;
@@ -551,7 +562,8 @@ const CONFIG_KEYS = [
551
562
  "modes",
552
563
  "ui",
553
564
  "skills",
554
- "access"
565
+ "access",
566
+ "historyRemote"
555
567
  ];
556
568
  const MODE_KEYS = ["format", "validate"];
557
569
  const UI_KEYS = [
@@ -622,6 +634,10 @@ const configProblems = (value) => {
622
634
  ...unknownKeys(value, CONFIG_KEYS, []),
623
635
  ...value.modes === void 0 ? [] : recordOf(value.modes, ["modes"], "modes", modeProblems),
624
636
  ...value.ui === void 0 ? [] : uiProblems(value.ui, ["ui"]),
637
+ ...value.historyRemote === void 0 || typeof value.historyRemote === "string" && value.historyRemote.trim() !== "" ? [] : [{
638
+ path: ["historyRemote"],
639
+ message: "must be a non-empty remote name"
640
+ }],
625
641
  ...value.skills === void 0 ? [] : recordOf(value.skills, ["skills"], "skill-name arrays", (v, path) => isStringArray(v) ? [] : [{
626
642
  path,
627
643
  message: "must be an array of skill names"
@@ -690,6 +706,7 @@ var flows_exports = /* @__PURE__ */ __exportAll({
690
706
  sections: () => sections,
691
707
  settings: () => settings,
692
708
  settingsOf: () => settingsOf,
709
+ ship: () => ship,
693
710
  showScript: () => showScript,
694
711
  skillsFor: () => skillsFor,
695
712
  start: () => start,
@@ -698,4 +715,4 @@ var flows_exports = /* @__PURE__ */ __exportAll({
698
715
  writeScript: () => writeScript,
699
716
  wrote: () => wrote
700
717
  });
701
- export { run as $, FLOWS_PROTOCOL as A, head as B, moveScript as C, revertScript as D, restoreScript as E, changesSince as F, mark as G, installContext as H, codeThreads as I, openQuestions as J, markedOptions as K, envSettings as L, accessFor as M, agent as N, showScript as O, changes as P, restart as Q, envSettingsOf as R, checkScript as S, removeScript as T, judge as U, human as V, kept as W, read as X, protocolMismatch as Y, refuse as Z, requireRevert as _, defineWorkflow as a, skillsFor as at, wrote as b, check as c, workflow as ct, hasThreadFor as d, scope as et, judgeDiffShape as f, requireReplies as g, requireProgress as h, configure as i, settingsOf as it, FlowsProtocolError as j, writeScript as k, codeChanges as l, requireAnswers as m, configProblems as n, sections as nt, isFactoryWorkflow as o, start as ot, numeric as p, matches as q, defineConfig as r, settings as rt, answered as s, threads as st, flows_exports as t, sectionBodies as tt, displayPath as u, requireThreadsClosed as v, quote as w, applyScript as x, seamGate as y, glob as z };
718
+ export { run as $, FLOWS_PROTOCOL as A, head as B, moveScript as C, revertScript as D, restoreScript as E, changesSince as F, mark as G, installContext as H, codeThreads as I, openQuestions as J, markedOptions as K, envSettings as L, accessFor as M, agent as N, showScript as O, changes as P, restart as Q, envSettingsOf as R, checkScript as S, removeScript as T, judge as U, human as V, kept as W, read as X, protocolMismatch as Y, refuse as Z, requireRevert as _, defineWorkflow as a, ship as at, wrote as b, check as c, threads as ct, hasThreadFor as d, scope as et, judgeDiffShape as f, requireReplies as g, requireProgress as h, configure as i, settingsOf as it, FlowsProtocolError as j, writeScript as k, codeChanges as l, workflow as lt, requireAnswers as m, configProblems as n, sections as nt, isFactoryWorkflow as o, skillsFor as ot, numeric as p, matches as q, defineConfig as r, settings as rt, answered as s, start as st, flows_exports as t, sectionBodies as tt, displayPath as u, requireThreadsClosed as v, quote as w, applyScript as x, seamGate as y, glob as z };