@pmelab/gtd 26.0.0 → 27.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 (66) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +21 -3
  3. package/dist/chunks/{Schema-B5yK7QrT.mjs → Schema-CyImoHTj.mjs} +56 -3
  4. package/dist/chunks/{reserved-6pAgFGgB.mjs → reserved-BL9krPao.mjs} +1 -1
  5. package/dist/chunks/{wire-DA7q2ikx.mjs → wire-BY1S-obW.mjs} +5 -2
  6. package/dist/flows.mjs +15 -1
  7. package/dist/gtd.bundle.mjs +219 -34
  8. package/dist/testkit.mjs +447 -72
  9. package/dist/wire.mjs +2 -2
  10. package/dist/workflows/feature.mjs +1 -1
  11. package/dist/workflows/fix.mjs +1 -1
  12. package/dist/workflows/review.mjs +1 -1
  13. package/package.json +2 -2
  14. package/src/cli/Cli.test.ts +56 -4
  15. package/src/cli/Cli.ts +48 -6
  16. package/src/cli/History.test.ts +2 -2
  17. package/src/cli/Output.ts +3 -1
  18. package/src/cli/Program.test.ts +11 -12
  19. package/src/cli/Program.ts +28 -7
  20. package/src/cli/Strays.test.ts +88 -0
  21. package/src/cli/Strays.ts +56 -0
  22. package/src/edge/Edge.test.ts +113 -16
  23. package/src/edge/Edge.ts +22 -6
  24. package/src/emit/GitScript.test.ts +65 -2
  25. package/src/emit/GitScript.ts +34 -1
  26. package/src/emit/index.ts +1 -0
  27. package/src/flags/index.ts +0 -1
  28. package/src/flows/runtime.test.ts +33 -0
  29. package/src/flows/runtime.ts +31 -0
  30. package/src/platform/Git.test.ts +96 -1
  31. package/src/platform/Git.ts +24 -0
  32. package/src/platform/RetainedHistory.test.ts +9 -0
  33. package/src/platform/RetainedHistory.ts +3 -0
  34. package/src/platform/Workspace.test.ts +1 -1
  35. package/src/platform/index.ts +1 -0
  36. package/src/replay/RefName.test.ts +40 -0
  37. package/src/replay/RefName.ts +19 -0
  38. package/src/replay/Replay.test.ts +193 -2
  39. package/src/replay/Replay.ts +51 -6
  40. package/src/replay/Trailers.test.ts +26 -0
  41. package/src/replay/Trailers.ts +8 -0
  42. package/src/replay/index.ts +1 -0
  43. package/src/step/LandStep.ts +1 -0
  44. package/src/step/RepoSnapshot.ts +2 -0
  45. package/src/step/index.ts +1 -0
  46. package/src/step/planStart.test.ts +5 -5
  47. package/src/step/planStep.test.ts +53 -0
  48. package/src/step/planStep.ts +7 -1
  49. package/src/step/strayPaths.test.ts +17 -0
  50. package/src/step/strayPaths.ts +8 -0
  51. package/src/testkit/EmittedScriptRecognizer.test.ts +57 -29
  52. package/src/testkit/EmittedScriptRecognizer.ts +26 -4
  53. package/src/testkit/EmittedScripts.test.ts +182 -0
  54. package/src/testkit/FakeGitOperations.ts +10 -2
  55. package/src/testkit/GitTiers.ts +170 -25
  56. package/src/testkit/InMemRepo.ts +64 -12
  57. package/src/testkit/Layers.test.ts +34 -1
  58. package/src/testkit/Layers.ts +21 -1
  59. package/src/testkit/TestRepo.ts +3 -3
  60. package/src/wire/ExitCodes.test.ts +11 -3
  61. package/src/wire/ExitCodes.ts +3 -0
  62. package/src/wire/Glob.test.ts +35 -0
  63. package/src/wire/Glob.ts +1 -1
  64. package/src/workflow/Workflow.ts +1 -0
  65. package/src/workflow/discovery.test.ts +1 -1
  66. package/src/workflows/shared/text.fixture.ts +1 -0
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gtd",
3
- "version": "26.0.0",
3
+ "version": "27.0.0",
4
4
  "description": "Drive the gtd loop inside Claude Code: agent turns run as subagents, gtd decides every beat",
5
5
  "author": {
6
6
  "name": "Philipp Melab"
package/README.md CHANGED
@@ -552,6 +552,19 @@ unknown key. `gtd.config.ts` is the only repository config: gtd 23 removed the
552
552
  home directory — fails every command until you delete it. See
553
553
  [Migrating from `.gtdrc`](https://github.com/pmelab/gtd/blob/main/docs/configuration.md#migrating-from-gtdrc).
554
554
 
555
+ ## Checking a range for stray files
556
+
557
+ ```sh
558
+ gtd strays main..HEAD 'src/**' '*.md' # files the range touched outside the globs
559
+ ```
560
+
561
+ Prints a sorted JSON array of every file the range's committed diff touched that
562
+ matches none of the globs, and exits `10` when there are any (`0` when none).
563
+ stderr gets a summary; `--verbose` adds one `stray:` line per path. `--json=<n>`
564
+ picks one entry (nothing when past the end). Symlinks count as paths and are
565
+ never followed; a submodule counts as its path, whatever `diff.ignoreSubmodules`
566
+ or `.gitmodules` `ignore` say. Works in any git repository, no process needed.
567
+
555
568
  ## Process history
556
569
 
557
570
  When a process finishes, the landing that closes it also keeps the whole run
@@ -576,6 +589,11 @@ git config --add remote.origin.fetch 'refs/gtd/history/*:refs/gtd/history/*'
576
589
  The second line makes every plain `git fetch` include them. It has no leading
577
590
  `+`, so a conflicting local ref fails instead of being overwritten.
578
591
 
592
+ A step declared with `keep: true` files its turn under `refs/gtd/kept/` instead
593
+ of on the branch (see [Kept tips](docs/configuration.md#kept-tips)). Those refs
594
+ are not process history: `gtd history` does not list them, and the
595
+ `refs/gtd/history/*` refspecs above neither push nor fetch them.
596
+
579
597
  ## Entrypoints
580
598
 
581
599
  gtd is one package, `@pmelab/gtd`, and every entrypoint shares its version and
@@ -597,9 +615,9 @@ install for any of these but `./testkit`: gtd resolves a `gtd.config.ts`'s
597
615
 
598
616
  The `gtd` bin's commands — `next`, `land`, `abandon`, `restore`, `validate`,
599
617
  `check`, `uncheck`, `install`, `summary`, `base`, `door`, `doors`, `version`,
600
- `help`, `history list`, `history show`, `history fetch`, and the tools `ui`,
601
- `lsp`, `loop` and `judge` (`judge answer`, `judge run`) — are listed in the
602
- [CLI reference](https://github.com/pmelab/gtd/blob/main/docs/cli.md).
618
+ `help`, `history list`, `history show`, `history fetch`, `strays`, and the tools
619
+ `ui`, `lsp`, `loop` and `judge` (`judge answer`, `judge run`) — are listed in
620
+ the [CLI reference](https://github.com/pmelab/gtd/blob/main/docs/cli.md).
603
621
 
604
622
  ## License
605
623
 
@@ -10197,7 +10197,7 @@ const catchAll$1 = /*#__PURE__*/ dual(2, (self, f) => matchEffect$1(self, {
10197
10197
  onFailure: f,
10198
10198
  onSuccess: succeed$5
10199
10199
  }));
10200
- const catchIf = /*#__PURE__*/ dual(3, (self, predicate, f) => catchAllCause$1(self, (cause) => {
10200
+ const catchIf$1 = /*#__PURE__*/ dual(3, (self, predicate, f) => catchAllCause$1(self, (cause) => {
10201
10201
  const either = failureOrCause$1(cause);
10202
10202
  switch (either._tag) {
10203
10203
  case "Left": return predicate(either.left) ? f(either.left) : failCause$3(cause);
@@ -12202,7 +12202,7 @@ const catchTag$1 = /*#__PURE__*/ dual((args) => isEffect$1(args[0]), (self, ...a
12202
12202
  for (let i = 0; i < args.length - 1; i++) if (args[i] === tag) return true;
12203
12203
  return false;
12204
12204
  };
12205
- return catchIf(self, predicate, f);
12205
+ return catchIf$1(self, predicate, f);
12206
12206
  });
12207
12207
  const diffFiberRefs = (self) => summarized(self, fiberRefs, diff$2);
12208
12208
  const bind = /*#__PURE__*/ bind$1(map$5, flatMap$3);
@@ -18757,6 +18757,59 @@ const catchAll = catchAll$1;
18757
18757
  */
18758
18758
  const catchAllCause = catchAllCause$1;
18759
18759
  /**
18760
+ * Recovers from specific errors based on a predicate.
18761
+ *
18762
+ * **When to Use**
18763
+ *
18764
+ * `catchIf` works similarly to {@link catchSome}, but it allows you to
18765
+ * recover from errors by providing a predicate function. If the predicate
18766
+ * matches the error, the recovery effect is applied. This function doesn't
18767
+ * alter the error type, so the resulting effect still carries the original
18768
+ * error type unless a user-defined type guard is used to narrow the type.
18769
+ *
18770
+ * **Example** (Catching Specific Errors with a Predicate)
18771
+ *
18772
+ * ```ts
18773
+ * import { Effect, Random } from "effect"
18774
+ *
18775
+ * class HttpError {
18776
+ * readonly _tag = "HttpError"
18777
+ * }
18778
+ *
18779
+ * class ValidationError {
18780
+ * readonly _tag = "ValidationError"
18781
+ * }
18782
+ *
18783
+ * // ┌─── Effect<string, HttpError | ValidationError, never>
18784
+ * // ▼
18785
+ * const program = Effect.gen(function* () {
18786
+ * const n1 = yield* Random.next
18787
+ * const n2 = yield* Random.next
18788
+ * if (n1 < 0.5) {
18789
+ * yield* Effect.fail(new HttpError())
18790
+ * }
18791
+ * if (n2 < 0.5) {
18792
+ * yield* Effect.fail(new ValidationError())
18793
+ * }
18794
+ * return "some result"
18795
+ * })
18796
+ *
18797
+ * // ┌─── Effect<string, ValidationError, never>
18798
+ * // ▼
18799
+ * const recovered = program.pipe(
18800
+ * Effect.catchIf(
18801
+ * // Only handle HttpError errors
18802
+ * (error) => error._tag === "HttpError",
18803
+ * () => Effect.succeed("Recovering from HttpError")
18804
+ * )
18805
+ * )
18806
+ * ```
18807
+ *
18808
+ * @since 2.0.0
18809
+ * @category Error handling
18810
+ */
18811
+ const catchIf = catchIf$1;
18812
+ /**
18760
18813
  * Catches and handles specific errors by their `_tag` field, which is used as a
18761
18814
  * discriminator.
18762
18815
  *
@@ -25396,4 +25449,4 @@ Struct({
25396
25449
  description: "Represents an issue returned by the ArrayFormatter formatter"
25397
25450
  });
25398
25451
  //#endregion
25399
- export { makeSemaphore as $, toJSON as $i, mapBoth$2 as $n, none$2 as $r, provideMerge as $t, catchTag as A, getOption as Ai, scopeTag as An, interrupt$2 as Ar, sync as At, flatten as B, isSome as Bi, make$12 as Bn, tap$1 as Br, unsafeMakeSemaphore as Bt, all as C, unsafeFromArray as Ci, isInterruptedOnly as Cn, exitFailCause$1 as Cr, scope as Ct, async as D, Tag as Di, ensuring$1 as Dn, fiberId as Dr, serviceOption as Dt, asVoid as E, GenericTag as Ei, squash as En, exitZipRight as Er, scopedWith as Et, exit as F, filter$3 as Fi, sequential$1 as Fn, onInterrupt as Fr, tryPromise as Ft, forkScoped as G, isLeft as Gi, Class as Gn, withFiberRuntime$1 as Gr, zipRight as Gt, forEach as H, match$6 as Hi, set as Hn, uninterruptibleMask$2 as Hr, withFiberRuntime as Ht, fail$1 as I, flatMap$6 as Ii, bind as In, scopeClose as Ir, try_ as It, interrupt as J, right as Ji, die$2 as Jn, empty$15 as Jr, TaggedError$1 as Jt, gen as K, left as Ki, spanTag as Kn, zipRight$2 as Kr, zipWith as Kt, failCause as L, fromNullable as Li, bindTo as Ln, succeed$5 as Lr, uninterruptible as Lt, dieMessage as M, empty$22 as Mi, inheritAll as Mn, interruptFiber as Mr, tapErrorCause as Mt, either as N, fromIterable$6 as Ni, interruptAllAs as Nn, interruptible$2 as Nr, timeout as Nt, catchAll as O, add$2 as Oi, forEachConcurrentDiscard as On, fiberRefLocally as Or, succeed$1 as Ot, ensuring as P, splitAt as Pi, join as Pn, map$5 as Pr, tryMap as Pt, logWarning as Q, format$4 as Qi, map$4 as Qn, make$20 as Qr, provide$1 as Qt, fiberIdWith as R, getOrElse as Ri, sleep as Rn, suspend$3 as Rr, uninterruptibleMask as Rt, addFinalizer as S, toArray$1 as Si, isInterrupted as Sn, exitFail as Sr, sandbox as St, as as T, unsafeHead as Ti, reduceWithContext as Tn, exitVoid$1 as Tr, scoped as Tt, forkDaemon as U, none$4 as Ui, update$1 as Un, void_$2 as Ur, zip as Ut, fnUntraced as V, map$11 as Vi, modify as Vn, uninterruptible$1 as Vr, when as Vt, forkIn as W, some as Wi, TypeId$4 as Wn, whenEffect as Wr, zipLeft as Wt, intoDeferred as X, BaseProto as Xi, failCause$2 as Xn, combineAll as Xr, fromEffect as Xt, interruptible as Y, pipeArguments as Yi, fail$4 as Yn, combine$5 as Yr, tagged as Yt, isEffect as Z, NodeInspectSymbol as Zi, isFailure as Zn, ids as Zr, mergeAll as Zt, decodeSync as _, prepend$1 as _i, failureOrCause as _n, deferredMake as _r, repeat as _t, Literal as a, constVoid as aa, decode as ai, forkIn$1 as an, as$1 as ar, matchCauseEffect as at, acquireRelease as b, take as bi, interruptors as bn, deferredUnsafeMake as br, runPromiseExit as bt, String$ as c, pipe as ca, appendAll$1 as ci, addFinalizer$1 as cn, catchAll$1 as cr, onError as ct, Union as d, filter$1 as di, extend$1 as dn, deferredComplete as dr, orElseSucceed as dt, equals$2 as ea, get$4 as ei, scoped$1 as en, match$3 as er, map$1 as et, between as f, fromIterable$5 as fi, fork as fn, deferredFail as fr, promise as ft, standardSchemaV1 as g, of$1 as gi, fail$2 as gn, deferredIsDone as gr, raceWith as gt, optionalWith as h, map$9 as hi, die$1 as hn, deferredInterruptWith as hr, race as ht, Defect as i, constUndefined as ia, size$2 as ii, updateContext as in, zipRight$1 as ir, matchCause as it, die as j, omit$1 as ji, _await as jn, interruptAsFiber as jr, tap as jt, catchAllCause as k, get$7 as ki, scopeMake as kn, flatMap$3 as kr, suspend$1 as kt, Struct as l, drop as li, addFinalizerExit as ln, currentContext as lr, orDie as lt, optional as m, isEmpty$5 as mi, NoSuchElementException as mn, deferredInterrupt as mr, provideService as mt, Boolean$ as n, constFalse as na, set$3 as ni, unsafeFork as nn, void_$1 as nr, mapError$1 as nt, Never as o, dual as oa, isFinite as oi, unsafeMakeSemaphore$1 as on, asVoid$1 as or, matchEffect as ot, decodeUnknown as p, isChunk as pi, make$2 as pn, deferredFailCause as pr, provide as pt, ignore as q, match$7 as qi, all$2 as qn, DeferredTypeId as qr, spaced as qt, Cause as r, constTrue as ra, has$1 as ri, unsafeRunPromiseExit as rn, zip$1 as rr, match as rt, Number$ as s, identity as sa, append as si, Scope as sn, asyncInterrupt as sr, negate as st, Array$ as t, hasProperty as ta, make$22 as ti, succeed$2 as tn, succeed$4 as tr, mapBoth$1 as tt, TaggedError as u, empty$19 as ui, close as un, deferredAwait as ur, orElse$1 as ut, encodeSync as v, reduce$6 as vi, flipCauseOption as vn, deferredSucceed as vr, retry as vt, annotateLogs as w, unsafeGet as wi, map$3 as wn, exitSucceed$1 as wr, scopeWith as wt, acquireUseRelease as x, takeRight as xi, isDieType as xn, exitAs as xr, runtime as xt, _void as y, reverse$1 as yi, interrupt$1 as yn, deferredUnsafeDone as yr, runPromise as yt, flatMap$1 as z, isNone as zi, get as zn, sync$1 as zr, unsafeMakeLatch as zt };
25452
+ export { logWarning as $, format$4 as $i, map$4 as $n, make$20 as $r, provide$1 as $t, catchIf as A, get$7 as Ai, scopeMake as An, flatMap$3 as Ar, suspend$1 as At, flatMap$1 as B, isNone as Bi, get as Bn, sync$1 as Br, unsafeMakeLatch as Bt, all as C, toArray$1 as Ci, isInterrupted as Cn, exitFail as Cr, sandbox as Ct, async as D, GenericTag as Di, squash as Dn, exitZipRight as Dr, scopedWith as Dt, asVoid as E, unsafeHead as Ei, reduceWithContext as En, exitVoid$1 as Er, scoped as Et, ensuring as F, splitAt as Fi, join as Fn, map$5 as Fr, tryMap as Ft, forkIn as G, some as Gi, TypeId$4 as Gn, whenEffect as Gr, zipLeft as Gt, fnUntraced as H, map$11 as Hi, modify as Hn, uninterruptible$1 as Hr, when as Ht, exit as I, filter$3 as Ii, sequential$1 as In, onInterrupt as Ir, tryPromise as It, ignore as J, match$7 as Ji, all$2 as Jn, DeferredTypeId as Jr, spaced as Jt, forkScoped as K, isLeft as Ki, Class as Kn, withFiberRuntime$1 as Kr, zipRight as Kt, fail$1 as L, flatMap$6 as Li, bind as Ln, scopeClose as Lr, try_ as Lt, die as M, omit$1 as Mi, _await as Mn, interruptAsFiber as Mr, tap as Mt, dieMessage as N, empty$22 as Ni, inheritAll as Nn, interruptFiber as Nr, tapErrorCause as Nt, catchAll as O, Tag as Oi, ensuring$1 as On, fiberId as Or, serviceOption as Ot, either as P, fromIterable$6 as Pi, interruptAllAs as Pn, interruptible$2 as Pr, timeout as Pt, isEffect as Q, NodeInspectSymbol as Qi, isFailure as Qn, ids as Qr, mergeAll as Qt, failCause as R, fromNullable as Ri, bindTo as Rn, succeed$5 as Rr, uninterruptible as Rt, addFinalizer as S, takeRight as Si, isDieType as Sn, exitAs as Sr, runtime as St, as as T, unsafeGet as Ti, map$3 as Tn, exitSucceed$1 as Tr, scopeWith as Tt, forEach as U, match$6 as Ui, set as Un, uninterruptibleMask$2 as Ur, withFiberRuntime as Ut, flatten as V, isSome as Vi, make$12 as Vn, tap$1 as Vr, unsafeMakeSemaphore as Vt, forkDaemon as W, none$4 as Wi, update$1 as Wn, void_$2 as Wr, zip as Wt, interruptible as X, pipeArguments as Xi, fail$4 as Xn, combine$5 as Xr, tagged as Xt, interrupt as Y, right as Yi, die$2 as Yn, empty$15 as Yr, TaggedError$1 as Yt, intoDeferred as Z, BaseProto as Zi, failCause$2 as Zn, combineAll as Zr, fromEffect as Zt, decodeSync as _, of$1 as _i, fail$2 as _n, deferredIsDone as _r, raceWith as _t, Literal as a, constUndefined as aa, size$2 as ai, updateContext as an, zipRight$1 as ar, matchCause as at, acquireRelease as b, reverse$1 as bi, interrupt$1 as bn, deferredUnsafeDone as br, runPromise as bt, String$ as c, identity as ca, append as ci, Scope as cn, asyncInterrupt as cr, negate as ct, Union as d, empty$19 as di, close as dn, deferredAwait as dr, orElse$1 as dt, toJSON as ea, none$2 as ei, provideMerge as en, mapBoth$2 as er, makeSemaphore as et, between as f, filter$1 as fi, extend$1 as fn, deferredComplete as fr, orElseSucceed as ft, standardSchemaV1 as g, map$9 as gi, die$1 as gn, deferredInterruptWith as gr, race as gt, optionalWith as h, isEmpty$5 as hi, NoSuchElementException as hn, deferredInterrupt as hr, provideService as ht, Defect as i, constTrue as ia, has$1 as ii, unsafeRunPromiseExit as in, zip$1 as ir, match as it, catchTag as j, getOption as ji, scopeTag as jn, interrupt$2 as jr, sync as jt, catchAllCause as k, add$2 as ki, forEachConcurrentDiscard as kn, fiberRefLocally as kr, succeed$1 as kt, Struct as l, pipe as la, appendAll$1 as li, addFinalizer$1 as ln, catchAll$1 as lr, onError as lt, optional as m, isChunk as mi, make$2 as mn, deferredFailCause as mr, provide as mt, Boolean$ as n, hasProperty as na, make$22 as ni, succeed$2 as nn, succeed$4 as nr, mapBoth$1 as nt, Never as o, constVoid as oa, decode as oi, forkIn$1 as on, as$1 as or, matchCauseEffect as ot, decodeUnknown as p, fromIterable$5 as pi, fork as pn, deferredFail as pr, promise as pt, gen as q, left as qi, spanTag as qn, zipRight$2 as qr, zipWith as qt, Cause as r, constFalse as ra, set$3 as ri, unsafeFork as rn, void_$1 as rr, mapError$1 as rt, Number$ as s, dual as sa, isFinite as si, unsafeMakeSemaphore$1 as sn, asVoid$1 as sr, matchEffect as st, Array$ as t, equals$2 as ta, get$4 as ti, scoped$1 as tn, match$3 as tr, map$1 as tt, TaggedError as u, drop as ui, addFinalizerExit as un, currentContext as ur, orDie as ut, encodeSync as v, prepend$1 as vi, failureOrCause as vn, deferredMake as vr, repeat as vt, annotateLogs as w, unsafeFromArray as wi, isInterruptedOnly as wn, exitFailCause$1 as wr, scope as wt, acquireUseRelease as x, take as xi, interruptors as xn, deferredUnsafeMake as xr, runPromiseExit as xt, _void as y, reduce$6 as yi, flipCauseOption as yn, deferredSucceed as yr, retry as yt, fiberIdWith as z, getOrElse as zi, sleep as zn, suspend$3 as zr, uninterruptibleMask as zt };
@@ -1,6 +1,6 @@
1
1
  import { accessFor, agent, answered, changesSince, check, codeThreads, defineWorkflow, env, head, human, judge, numeric, quote, read, refuse, removeScript, run, scope, showScript, skillsFor, start, vars } from "../flows.mjs";
2
2
  import { escalation as escalation$1, fixFindings, gate as gate$1, healthy as healthy$1, lensScopes, lensesOf, qualityLap as qualityLap$1, removedAssertions, reviewToHandOff } from "../workflow-kit.mjs";
3
- import { c as String$, g as standardSchemaV1, h as optionalWith, l as Struct } from "./Schema-B5yK7QrT.mjs";
3
+ import { c as String$, g as standardSchemaV1, h as optionalWith, l as Struct } from "./Schema-CyImoHTj.mjs";
4
4
  //#region src/workflows/shared/prose.ts
5
5
  const skillsPreamble = `- Load whatever's listed here that your harness actually has installed,
6
6
  skip anything it doesn't — silently, never stopping or asking about a
@@ -22,6 +22,8 @@ const EXIT_OK = 0;
22
22
  const EXIT_RUNTIME_ERROR = 1;
23
23
  /** gtd was invoked wrong — an unknown option/command, bad arity, a scope violation, a decode failure. */
24
24
  const EXIT_USAGE_ERROR = 2;
25
+ /** `gtd strays` found touched paths outside the allowlist — that command's only, and it carries no other meaning. */
26
+ const EXIT_STRAYS_FOUND = 10;
25
27
  const EXIT_SIGINT = 130;
26
28
  const EXIT_SIGTERM = 143;
27
29
  /** Frozen: adding a code is a driver-protocol break, the same as removing a wire field. */
@@ -29,6 +31,7 @@ const EXIT_CODES = /* @__PURE__ */ new Set([
29
31
  0,
30
32
  1,
31
33
  2,
34
+ 10,
32
35
  130,
33
36
  143
34
37
  ]);
@@ -466,8 +469,8 @@ const compile = (glob) => {
466
469
  i += 2;
467
470
  }
468
471
  }
469
- return new RegExp(`${pattern}$`);
472
+ return new RegExp(`${pattern}$`, "s");
470
473
  };
471
474
  const globMatches = (path, glob) => compile(glob).test(path);
472
475
  //#endregion
473
- export { EXIT_SIGTERM as C, WIRE_SCHEMA as D, UNATTRIBUTED_MODEL as E, renderFormat as O, EXIT_SIGINT as S, ACCESS_REFUSAL as T, demandOf as _, landFields as a, EXIT_OK as b, renderLandJson as c, renderBeatPlain as d, beatDocument as f, beatKindOf as g, BEAT_KINDS as h, judgeJson as i, renderLandPlain as l, statusOf as m, resolveSession as n, landProseText as o, renderBeatJson as p, selectPath as r, noopText as s, globMatches as t, DEMAND_BRIEFING as u, stallDiagnosis as v, EXIT_USAGE_ERROR as w, EXIT_RUNTIME_ERROR as x, EXIT_CODES as y };
476
+ export { EXIT_SIGTERM as C, UNATTRIBUTED_MODEL as D, ACCESS_REFUSAL as E, WIRE_SCHEMA as O, EXIT_SIGINT as S, EXIT_USAGE_ERROR as T, demandOf as _, landFields as a, EXIT_OK as b, renderLandJson as c, renderBeatPlain as d, beatDocument as f, beatKindOf as g, BEAT_KINDS as h, judgeJson as i, renderFormat as k, renderLandPlain as l, statusOf as m, resolveSession as n, landProseText as o, renderBeatJson as p, selectPath as r, noopText as s, globMatches as t, DEMAND_BRIEFING as u, stallDiagnosis as v, EXIT_STRAYS_FOUND as w, EXIT_RUNTIME_ERROR as x, EXIT_CODES as y };
package/dist/flows.mjs CHANGED
@@ -109,6 +109,19 @@ const changesSince = (hash, pattern) => {
109
109
  const all = context.changesSince(hash);
110
110
  return toChanges(pattern === void 0 ? all : all.filter((c) => context.matches(c.path, pattern)));
111
111
  };
112
+ /**
113
+ * The latest kept tip of step `name` (scoped from here, same as `agent()`) in
114
+ * this episode, or `undefined` when none.
115
+ */
116
+ const kept = (name) => {
117
+ const context = ctx();
118
+ if (typeof context.kept !== "function") throw new Error("gtd: kept() needs a newer gtd — upgrade the gtd that runs it");
119
+ const tip = context.kept(name);
120
+ return tip === void 0 ? void 0 : {
121
+ hash: tip.hash,
122
+ changes: toChanges(tip.changes)
123
+ };
124
+ };
112
125
  /** The commit the process stands on at this point of the flow. */
113
126
  const head = () => ctx().head();
114
127
  /** The process's diff base: the commit before it began, or the base `gtd --workflow` fixed. */
@@ -502,6 +515,7 @@ var flows_exports = /* @__PURE__ */ __exportAll({
502
515
  installContext: () => installContext,
503
516
  isFactoryWorkflow: () => isFactoryWorkflow,
504
517
  judge: () => judge,
518
+ kept: () => kept,
505
519
  moveScript: () => moveScript,
506
520
  numeric: () => numeric,
507
521
  openQuestions: () => openQuestions,
@@ -530,4 +544,4 @@ var flows_exports = /* @__PURE__ */ __exportAll({
530
544
  wrote: () => wrote
531
545
  });
532
546
  //#endregion
533
- export { FLOWS_PROTOCOL, FlowsProtocolError, accessFor, agent, answered, changes, changesSince, check, checkScript, codeChanges, codeThreads, configProblems, configure, defineConfig, defineWorkflow, env, glob, hasThreadFor, head, human, installContext, isFactoryWorkflow, judge, moveScript, numeric, openQuestions, protocolMismatch, quote, read, refuse, removeScript, requireAnswers, requireProgress, requireReplies, requireRevert, requireThreadsClosed, restart, restoreScript, revertScript, run, scope, sectionBodies, sections, showScript, skillsFor, start, flows_exports as t, threads, vars, wrote };
547
+ export { FLOWS_PROTOCOL, FlowsProtocolError, accessFor, agent, answered, changes, changesSince, check, checkScript, codeChanges, codeThreads, configProblems, configure, defineConfig, defineWorkflow, env, glob, hasThreadFor, head, human, installContext, isFactoryWorkflow, judge, kept, moveScript, numeric, openQuestions, protocolMismatch, quote, read, refuse, removeScript, requireAnswers, requireProgress, requireReplies, requireRevert, requireThreadsClosed, restart, restoreScript, revertScript, run, scope, sectionBodies, sections, showScript, skillsFor, start, flows_exports as t, threads, vars, wrote };