@lumpcode/core 0.0.12 → 0.0.14

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 (48) hide show
  1. package/README.md +2 -2
  2. package/dist/helpers/executeStepsForContextList/main.d.ts +3 -3
  3. package/dist/helpers/executeStepsForContextList/main.d.ts.map +1 -1
  4. package/dist/helpers/getContextStatus/main.d.ts +3 -3
  5. package/dist/helpers/getContextStatus/main.d.ts.map +1 -1
  6. package/dist/helpers/getToDoContextList/main.d.ts +4 -4
  7. package/dist/helpers/getToDoContextList/main.d.ts.map +1 -1
  8. package/dist/index.cjs +123 -7
  9. package/dist/index.cjs.map +1 -1
  10. package/dist/index.js +123 -7
  11. package/dist/index.js.map +1 -1
  12. package/dist/types/BranchFn.d.ts +2 -2
  13. package/dist/types/BranchFn.d.ts.map +1 -1
  14. package/dist/types/CommandFn.d.ts +3 -3
  15. package/dist/types/CommandFn.d.ts.map +1 -1
  16. package/dist/types/ContextStatus.d.ts +1 -7
  17. package/dist/types/ContextStatus.d.ts.map +1 -1
  18. package/dist/types/GetContextListFn.d.ts +3 -3
  19. package/dist/types/GetContextListFn.d.ts.map +1 -1
  20. package/dist/types/GitCommitMessageFn.d.ts +3 -3
  21. package/dist/types/GitCommitMessageFn.d.ts.map +1 -1
  22. package/dist/types/HistoryEntry.d.ts +3 -3
  23. package/dist/types/HistoryEntry.d.ts.map +1 -1
  24. package/dist/types/PostCommandExecFn.d.ts +5 -4
  25. package/dist/types/PostCommandExecFn.d.ts.map +1 -1
  26. package/dist/types/PromptFn.d.ts +4 -4
  27. package/dist/types/PromptFn.d.ts.map +1 -1
  28. package/dist/types/SetupFn.d.ts +2 -2
  29. package/dist/types/SetupFn.d.ts.map +1 -1
  30. package/dist/types/Step.d.ts +6 -5
  31. package/dist/types/Step.d.ts.map +1 -1
  32. package/dist/types/Steps.d.ts +3 -1
  33. package/dist/types/Steps.d.ts.map +1 -1
  34. package/dist/types/TeardownFn.d.ts +2 -2
  35. package/dist/types/TeardownFn.d.ts.map +1 -1
  36. package/dist/usages/runLump/main.d.ts +9 -9
  37. package/dist/usages/runLump/main.d.ts.map +1 -1
  38. package/dist/utils/resolveSpawnExecutable/index.d.ts +1 -0
  39. package/dist/utils/resolveSpawnExecutable/index.d.ts.map +1 -1
  40. package/dist/utils/resolveSpawnExecutable/main.d.ts +4 -0
  41. package/dist/utils/resolveSpawnExecutable/main.d.ts.map +1 -1
  42. package/dist/utils/resolveSpawnExecutable/npmCmdShimFixture.d.ts +6 -0
  43. package/dist/utils/resolveSpawnExecutable/npmCmdShimFixture.d.ts.map +1 -0
  44. package/dist/utils/resolveSpawnExecutable/windowsNpmCmdShimBody.d.ts +6 -0
  45. package/dist/utils/resolveSpawnExecutable/windowsNpmCmdShimBody.d.ts.map +1 -0
  46. package/dist/utils/resolveSpawnExecutable/windowsNpmCmdShimFixture.d.ts +6 -0
  47. package/dist/utils/resolveSpawnExecutable/windowsNpmCmdShimFixture.d.ts.map +1 -0
  48. package/package.json +1 -1
package/README.md CHANGED
@@ -106,7 +106,7 @@ An array of `Step` objects that are executed sequentially for each context. Each
106
106
  | `promptFn` | `PromptFn | undefined` | Optional. Generates the prompt string from the current context, run state, and variables. When omitted, `commandFn` receives an empty prompt string. |
107
107
  | `commandFn` | `CommandFn` | Required. Returns `{ executable, args, env? }` to run a subprocess, or `null` / `undefined` to skip execution while still running `postCommandExecFn`. Optional `env` merges over the parent process environment for that command only. |
108
108
  | `stepVariables` | `StepVariables | undefined` | Optional extra variables passed into `promptFn`, `commandFn`, and `postCommandExecFn`. |
109
- | `postCommandExecFn` | `PostCommandExecFn | undefined` | Optional hook called after the command finishes, receiving the command output. |
109
+ | `postCommandExecFn` | `PostCommandExecFn | undefined` | Optional hook called after the command finishes, receiving the command output. May return `void` / `undefined` / `[]` (no-op) or a `Steps` array to run nested follow-on steps under this leaf. |
110
110
  | `timeoutMillis` | `number | undefined` | Maximum time in milliseconds allowed for the command execution. Defaults to `1800000` (30 minutes). |
111
111
 
112
112
 
@@ -350,7 +350,7 @@ type Steps = Array<
350
350
  >;
351
351
  ```
352
352
 
353
- When the engine encounters a concrete `Step`, it runs optional `promptFn`, then `commandFn`, then `postCommandExecFn` (if provided). When `commandFn` returns `null`, `undefined`, or nothing, the subprocess is skipped and `postCommandExecFn` still runs with an empty `commandResult`. When it encounters a **function**, it calls it and recursively executes the returned `Steps` before moving to the next element. The returned array can itself contain more functions, allowing arbitrary nesting depth. An empty returned array is a no-op.
353
+ When the engine encounters a concrete `Step`, it runs optional `promptFn`, then `commandFn`, then `postCommandExecFn` (if provided). When `commandFn` returns `null`, `undefined`, or nothing, the subprocess is skipped and `postCommandExecFn` still runs with an empty `commandResult`. When `postCommandExecFn` returns a non-empty `Steps` array, those steps are executed recursively nested under the leaf (same `stepIndex` path rules as function-form children) before the walk continues with any remaining siblings. When the engine encounters a **function**, it calls it and recursively executes the returned `Steps` before moving to the next element. The returned array can itself contain more functions, allowing arbitrary nesting depth. An empty returned array is a no-op.
354
354
 
355
355
  This makes it possible to build dynamic prompt chains: a function can inspect the current context, run state, or variables and decide at runtime how many prompts to produce, what they contain, or whether to skip entirely by returning an empty array.
356
356
 
@@ -1,10 +1,10 @@
1
- import { ContextList, ContextRunState, Failure, Logger } from "../../types";
1
+ import { ContextList, ContextRunState, Failure, Logger, LumpVariables, StepVariables } from "../../types";
2
2
  import type { RunLumpInput } from '../../usages';
3
- export type ExecuteStepsForContextListParams = Required<Pick<RunLumpInput, 'baseBranch' | 'branchFn' | 'lumpVariables' | 'steps' | 'setupFn' | 'teardownFn' | 'gitAddCommandFn' | 'gitCommitCommandFn' | 'gitPushCommandFn' | 'gitCommitMessageFn' | 'projectRoot' | 'setupWorkspaceFn' | 'teardownWorkspaceFn' | 'getKeepHistoryFilePathFn'>> & {
3
+ export type ExecuteStepsForContextListParams<V extends LumpVariables = LumpVariables, SV extends StepVariables = StepVariables> = Required<Pick<RunLumpInput<V, SV>, 'baseBranch' | 'branchFn' | 'lumpVariables' | 'steps' | 'setupFn' | 'teardownFn' | 'gitAddCommandFn' | 'gitCommitCommandFn' | 'gitPushCommandFn' | 'gitCommitMessageFn' | 'projectRoot' | 'setupWorkspaceFn' | 'teardownWorkspaceFn' | 'getKeepHistoryFilePathFn'>> & {
4
4
  contextList: ContextList;
5
5
  logger?: Logger;
6
6
  };
7
- export declare function executeStepsForContextList({ baseBranch, branchFn, lumpVariables, contextList, gitAddCommandFn, gitCommitCommandFn, gitPushCommandFn, gitCommitMessageFn, projectRoot, steps, setupFn, setupWorkspaceFn, teardownFn, teardownWorkspaceFn, getKeepHistoryFilePathFn, logger: loggerInput, }: ExecuteStepsForContextListParams): Promise<Failure<{
7
+ export declare function executeStepsForContextList<V extends LumpVariables = LumpVariables, SV extends StepVariables = StepVariables>({ baseBranch, branchFn, lumpVariables, contextList, gitAddCommandFn, gitCommitCommandFn, gitPushCommandFn, gitCommitMessageFn, projectRoot, steps, setupFn, setupWorkspaceFn, teardownFn, teardownWorkspaceFn, getKeepHistoryFilePathFn, logger: loggerInput, }: ExecuteStepsForContextListParams<V, SV>): Promise<Failure<{
8
8
  message: string;
9
9
  }> | import("../..").Success<{
10
10
  branchName: string;
@@ -1 +1 @@
1
- {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../../src/helpers/executeStepsForContextList/main.ts"],"names":[],"mappings":"AAEA,OAAO,EACH,WAAW,EACX,eAAe,EACf,OAAO,EACP,MAAM,EAIT,MAAM,aAAa,CAAC;AAUrB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,MAAM,MAAM,gCAAgC,GAAG,QAAQ,CAAC,IAAI,CACxD,YAAY,EACV,YAAY,GACZ,UAAU,GACV,eAAe,GACf,OAAO,GACP,SAAS,GACT,YAAY,GACZ,iBAAiB,GACjB,oBAAoB,GACpB,kBAAkB,GAClB,oBAAoB,GACpB,aAAa,GACb,kBAAkB,GAClB,qBAAqB,GACrB,0BAA0B,CAC/B,CAAC,GAAG;IACD,WAAW,EAAE,WAAW,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB,CAAA;AAED,wBAAsB,0BAA0B,CAAC,EAC7C,UAAU,EACV,QAAQ,EACR,aAAa,EACb,WAAW,EACX,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,WAAW,EACX,KAAK,EACL,OAAO,EACP,gBAAgB,EAChB,UAAU,EACV,mBAAmB,EACnB,wBAAwB,EACxB,MAAM,EAAE,WAAW,GACtB,EAAE,gCAAgC;aAqEa,MAAM;;;;;IAqOrD;AAED,MAAM,MAAM,gCAAgC,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,0BAA0B,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../../src/helpers/executeStepsForContextList/main.ts"],"names":[],"mappings":"AAEA,OAAO,EACH,WAAW,EACX,eAAe,EACf,OAAO,EACP,MAAM,EACN,aAAa,EAIb,aAAa,EAChB,MAAM,aAAa,CAAC;AAUrB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,MAAM,MAAM,gCAAgC,CACxC,CAAC,SAAS,aAAa,GAAG,aAAa,EACvC,EAAE,SAAS,aAAa,GAAG,aAAa,IACxC,QAAQ,CAAC,IAAI,CACb,YAAY,CAAC,CAAC,EAAE,EAAE,CAAC,EACjB,YAAY,GACZ,UAAU,GACV,eAAe,GACf,OAAO,GACP,SAAS,GACT,YAAY,GACZ,iBAAiB,GACjB,oBAAoB,GACpB,kBAAkB,GAClB,oBAAoB,GACpB,aAAa,GACb,kBAAkB,GAClB,qBAAqB,GACrB,0BAA0B,CAC/B,CAAC,GAAG;IACD,WAAW,EAAE,WAAW,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB,CAAA;AAED,wBAAsB,0BAA0B,CAC5C,CAAC,SAAS,aAAa,GAAG,aAAa,EACvC,EAAE,SAAS,aAAa,GAAG,aAAa,EAC1C,EACE,UAAU,EACV,QAAQ,EACR,aAAa,EACb,WAAW,EACX,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,WAAW,EACX,KAAK,EACL,OAAO,EACP,gBAAgB,EAChB,UAAU,EACV,mBAAmB,EACnB,wBAAwB,EACxB,MAAM,EAAE,WAAW,GACtB,EAAE,gCAAgC,CAAC,CAAC,EAAE,EAAE,CAAC;aAqEM,MAAM;;;;;IAwOrD;AAED,MAAM,MAAM,gCAAgC,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,0BAA0B,CAAC,CAAC,CAAC"}
@@ -1,11 +1,11 @@
1
1
  import { ContextStatus, Logger, LumpVariables } from "../../types";
2
2
  import { GitCommitMessageFn } from "../../types/GitCommitMessageFn";
3
- export declare function getContextStatus(params: {
3
+ export declare function getContextStatus<V extends LumpVariables = LumpVariables>(params: {
4
4
  contextName: string;
5
- gitCommitMessageFn: GitCommitMessageFn;
5
+ gitCommitMessageFn: GitCommitMessageFn<V>;
6
6
  projectRoot: string;
7
7
  baseBranch: string;
8
- lumpVariables?: LumpVariables;
8
+ lumpVariables?: V;
9
9
  contextVariables?: Record<string, string>;
10
10
  remoteName?: string;
11
11
  logger?: Logger;
@@ -1 +1 @@
1
- {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../../src/helpers/getContextStatus/main.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAIpE,wBAAsB,gBAAgB,CAAC,MAAM,EAAE;IAC3C,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,aAAa,CAAC,CAmEzB"}
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../../src/helpers/getContextStatus/main.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAIpE,wBAAsB,gBAAgB,CAAC,CAAC,SAAS,aAAa,GAAG,aAAa,EAAE,MAAM,EAAE;IACpF,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,kBAAkB,CAAC,CAAC,CAAC,CAAC;IAC1C,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,CAAC,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,aAAa,CAAC,CAoEzB"}
@@ -1,9 +1,9 @@
1
1
  import { GetContextListFn, Logger, LumpVariables } from "../../types";
2
2
  import { GitCommitMessageFn } from "../../types/GitCommitMessageFn";
3
- export declare function getToDoContextList(params: {
4
- getContextListFn: GetContextListFn;
5
- lumpVariables: LumpVariables;
6
- gitCommitMessageFn: GitCommitMessageFn;
3
+ export declare function getToDoContextList<V extends LumpVariables = LumpVariables>(params: {
4
+ getContextListFn: GetContextListFn<V>;
5
+ lumpVariables: V;
6
+ gitCommitMessageFn: GitCommitMessageFn<V>;
7
7
  projectRoot: string;
8
8
  baseBranch: string;
9
9
  logger?: Logger;
@@ -1 +1 @@
1
- {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../../src/helpers/getToDoContextList/main.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAGpE,wBAAsB,kBAAkB,CAAC,MAAM,EAAE;IAC7C,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,aAAa,EAAE,aAAa,CAAC;IAC7B,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;;oGA8DA"}
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../../src/helpers/getToDoContextList/main.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAGpE,wBAAsB,kBAAkB,CAAC,CAAC,SAAS,aAAa,GAAG,aAAa,EAAE,MAAM,EAAE;IACtF,gBAAgB,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAC;IACtC,aAAa,EAAE,CAAC,CAAC;IACjB,kBAAkB,EAAE,kBAAkB,CAAC,CAAC,CAAC,CAAC;IAC1C,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;;oGA8DA"}
package/dist/index.cjs CHANGED
@@ -6,7 +6,6 @@ var fs = require('node:fs');
6
6
  var path = require('node:path');
7
7
  var fs$1 = require('node:fs/promises');
8
8
  var ignore = require('ignore');
9
- var z = require('zod');
10
9
 
11
10
  function _interopNamespaceDefault(e) {
12
11
  var n = Object.create(null);
@@ -86,6 +85,10 @@ const DEFAULT_WINDOWS_PATHEXT = [
86
85
  '.WSH',
87
86
  '.MSC',
88
87
  ];
88
+ /** Matches a quoted script path using %dp0% / %~dp0 relative to a Windows .cmd shim. */
89
+ const WINDOWS_DP0_SCRIPT_RE = /"(?:%dp0%|%~dp0)\\?((?:[^"\r\n])+?\.(?:js|mjs|cjs))"/i;
90
+ /** Absolute Windows path to a Node script in quotes. */
91
+ const WINDOWS_ABS_SCRIPT_RE = /"([A-Za-z]:\\[^"\r\n]+\.(?:js|mjs|cjs))"/i;
89
92
  function windowsPathext() {
90
93
  const fromEnv = process.env.PATHEXT?.split(';').map((entry) => entry.trim()).filter(Boolean);
91
94
  return fromEnv?.length ? fromEnv : DEFAULT_WINDOWS_PATHEXT;
@@ -151,9 +154,83 @@ function wrapWindowsCmdShim(resolvedPath, args) {
151
154
  args: ['/d', '/s', '/c', resolvedPath, ...args],
152
155
  };
153
156
  }
157
+ function resolveWindowsJsPathFromShim(shimDir, relativeOrAbsolute) {
158
+ if (/^[A-Za-z]:[\\/]/.test(relativeOrAbsolute)) {
159
+ return path__namespace.resolve(relativeOrAbsolute);
160
+ }
161
+ // Normalize Windows separators so stubbed-win32 tests on POSIX still resolve.
162
+ const parts = relativeOrAbsolute.replace(/^[\\/]+/, '').split(/[/\\]+/).filter(Boolean);
163
+ return path__namespace.resolve(shimDir, ...parts);
164
+ }
165
+ /**
166
+ * Prefer a real Node binary — never a .cmd/.bat shim (those reintroduce cmd.exe),
167
+ * and never the host SEA/`lumpcode` binary via process.execPath.
168
+ * Returns bare `"node"` as last resort so spawn fails with ENOENT instead of
169
+ * silently falling back to cmd.exe after a Node entry was identified.
170
+ */
171
+ function resolveNodeExecutable(preferredDir) {
172
+ if (preferredDir != null) {
173
+ const bundledNode = path__namespace.join(preferredDir, 'node.exe');
174
+ if (fileExists(bundledNode)) {
175
+ return bundledNode;
176
+ }
177
+ }
178
+ for (const name of ['node.exe', 'node']) {
179
+ const found = resolveOnPath(name);
180
+ if (!found)
181
+ continue;
182
+ const ext = path__namespace.extname(found).toLowerCase();
183
+ if (ext === '.cmd' || ext === '.bat')
184
+ continue;
185
+ return found;
186
+ }
187
+ const base = path__namespace.basename(process.execPath).toLowerCase();
188
+ if (base === 'node' || base === 'node.exe') {
189
+ return process.execPath;
190
+ }
191
+ return 'node';
192
+ }
193
+ /**
194
+ * Parse an npm/yarn-style Windows `.cmd` shim to `node <script.js>`.
195
+ * Returns null only when the file is not a recognizable Node cmd-shim
196
+ * (caller may wrap with cmd.exe). Once a script path is found, never falls
197
+ * back to cmd.exe — missing Node uses bare `"node"` for a clear spawn failure.
198
+ */
199
+ function tryUnwrapWindowsNpmCmdShim(cmdPath) {
200
+ let body;
201
+ try {
202
+ body = fs__namespace.readFileSync(cmdPath, 'utf8');
203
+ }
204
+ catch {
205
+ return null;
206
+ }
207
+ const shimDir = path__namespace.dirname(cmdPath);
208
+ const lines = body.split(/\r?\n/);
209
+ // Windows npm-cmd-shim ends with `%*` pass-through; prefer that line for the script path.
210
+ const passThroughLine = [...lines].reverse().find((line) => /%\*\s*$/.test(line));
211
+ const searchOrder = passThroughLine != null ? [passThroughLine, body] : [body];
212
+ for (const searchIn of searchOrder) {
213
+ const dp0Match = searchIn.match(WINDOWS_DP0_SCRIPT_RE);
214
+ if (dp0Match?.[1]) {
215
+ const candidate = resolveWindowsJsPathFromShim(shimDir, dp0Match[1]);
216
+ if (fileExists(candidate)) {
217
+ return { scriptPath: candidate };
218
+ }
219
+ }
220
+ const absMatch = searchIn.match(WINDOWS_ABS_SCRIPT_RE);
221
+ if (absMatch?.[1] && fileExists(absMatch[1])) {
222
+ return { scriptPath: absMatch[1] };
223
+ }
224
+ }
225
+ return null;
226
+ }
154
227
  /**
155
228
  * Resolves bare executable names on Windows so npm-style `.cmd` shims and
156
229
  * extensionless Node entrypoints work with `child_process.spawn` (no shell).
230
+ *
231
+ * For Node agent CLIs installed via npm (copilot.cmd, cursor-agent.cmd, …),
232
+ * unwraps the shim to `node <entry.js> …args` so prompt argv is not mangled by
233
+ * cmd.exe / `%*`. Unrecognized `.cmd`/`.bat` files still wrap through cmd.exe.
157
234
  */
158
235
  function resolveSpawnExecutable(executable, args) {
159
236
  if (process.platform !== 'win32') {
@@ -174,17 +251,52 @@ function resolveSpawnExecutable(executable, args) {
174
251
  }
175
252
  const ext = path__namespace.extname(resolved).toLowerCase();
176
253
  if (ext === '.cmd' || ext === '.bat') {
254
+ const unwrapped = tryUnwrapWindowsNpmCmdShim(resolved);
255
+ if (unwrapped != null) {
256
+ return {
257
+ executable: resolveNodeExecutable(path__namespace.dirname(resolved)),
258
+ args: [unwrapped.scriptPath, ...args],
259
+ };
260
+ }
177
261
  return wrapWindowsCmdShim(resolved, args);
178
262
  }
179
263
  if (isNodeScript(resolved)) {
180
264
  return {
181
- executable: process.execPath,
265
+ executable: resolveNodeExecutable(path__namespace.dirname(resolved)),
182
266
  args: [resolved, ...args],
183
267
  };
184
268
  }
185
269
  return { executable: resolved, args };
186
270
  }
187
271
 
272
+ /**
273
+ * Minimal Windows npm-cmd-shim `.cmd` body (modern `"%_prog%"` + `"%dp0%\\…\\.js" %*` form).
274
+ * Shared by core spawn tests and CLI e2e path-agent install — do not duplicate.
275
+ */
276
+ function windowsNpmCmdShimBody(relativeJsFromShimDir) {
277
+ const target = relativeJsFromShimDir.replace(/\//g, '\\');
278
+ return [
279
+ '@ECHO off',
280
+ 'GOTO start',
281
+ ':find_dp0',
282
+ 'SET dp0=%~dp0',
283
+ 'EXIT /b',
284
+ ':start',
285
+ 'SETLOCAL',
286
+ 'CALL :find_dp0',
287
+ '',
288
+ 'IF EXIST "%dp0%\\node.exe" (',
289
+ ' SET "_prog=%dp0%\\node.exe"',
290
+ ') ELSE (',
291
+ ' SET "_prog=node"',
292
+ ' SET PATHEXT=%PATHEXT:;.JS;=;%',
293
+ ')',
294
+ '',
295
+ `endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & set PATHEXT=%PATHEXT:;.JS;=;% & "%_prog%" "%dp0%\\${target}" %*`,
296
+ '',
297
+ ].join('\r\n');
298
+ }
299
+
188
300
  function formatMessage(prefix, message) {
189
301
  if (!prefix)
190
302
  return message;
@@ -3612,7 +3724,10 @@ async function executeStepsForContextList({ baseBranch, branchFn, lumpVariables,
3612
3724
  }
3613
3725
  }
3614
3726
  if (postCommandExecFn) {
3615
- await postCommandExecFn(postCommandExecFnInput);
3727
+ const returnedSteps = await postCommandExecFn(postCommandExecFnInput);
3728
+ if (returnedSteps != null && returnedSteps.length > 0) {
3729
+ await walkAndExecuteSteps(returnedSteps, nextCallHeadIndex);
3730
+ }
3616
3731
  }
3617
3732
  }
3618
3733
  }
@@ -3751,7 +3866,8 @@ async function scanDirectory({ dirPath, allPaths, gitignoresMap, projectRoot, lo
3751
3866
  }
3752
3867
 
3753
3868
  async function getContextStatus(params) {
3754
- const { contextName, gitCommitMessageFn, projectRoot, baseBranch, lumpVariables = {}, contextVariables = {}, remoteName = "origin", logger, } = params;
3869
+ const { contextName, gitCommitMessageFn, projectRoot, baseBranch, lumpVariables: lumpVariablesInput, contextVariables = {}, remoteName = "origin", logger, } = params;
3870
+ const lumpVariables = (lumpVariablesInput ?? {});
3755
3871
  const commitMessage = gitCommitMessageFn({
3756
3872
  context: { name: contextName, variables: contextVariables },
3757
3873
  lumpVariables,
@@ -3871,7 +3987,6 @@ async function getToDoContextList(params) {
3871
3987
  }
3872
3988
 
3873
3989
  const contextStatus = ['toDo', 'branchPushed', 'finished'];
3874
- const contextStatusSchema = z.enum(contextStatus);
3875
3990
 
3876
3991
  const defaultGitCommitMessageFn = ({ context }) => {
3877
3992
  return `LUMP:${context.name}`;
@@ -3921,7 +4036,8 @@ const defaultSetupWorkspaceFnWithWorktree = async (input) => {
3921
4036
  };
3922
4037
 
3923
4038
  async function runLump(input) {
3924
- const { baseBranch, branchFn, lumpVariables = {}, getContextListFn, gitAddCommandFn = defaultGitAddCommandFn, gitCommitCommandFn = defaultGitCommitCommandFn, gitCommitMessageFn = defaultGitCommitMessageFn, gitPushCommandFn = defaultGitPushCommandFn, numberOfContextsPerBranch = 1, projectRoot, steps, setupFn = () => ({ contextRunState: {} }), setupWorkspaceFn = defaultSetupWorkspaceFn, teardownFn = () => undefined, teardownWorkspaceFn = defaultTeardownWorkspaceFn, getKeepHistoryFilePathFn = () => undefined, logger: loggerInput, } = input;
4039
+ const { baseBranch, branchFn, lumpVariables: lumpVariablesInput, getContextListFn, gitAddCommandFn = defaultGitAddCommandFn, gitCommitCommandFn = defaultGitCommitCommandFn, gitCommitMessageFn = defaultGitCommitMessageFn, gitPushCommandFn = defaultGitPushCommandFn, numberOfContextsPerBranch = 1, projectRoot, steps, setupFn = () => ({ contextRunState: {} }), setupWorkspaceFn = defaultSetupWorkspaceFn, teardownFn = () => undefined, teardownWorkspaceFn = defaultTeardownWorkspaceFn, getKeepHistoryFilePathFn = () => undefined, logger: loggerInput, } = input;
4040
+ const lumpVariables = (lumpVariablesInput ?? {});
3925
4041
  const logger = loggerInput ?? createConsoleLogger({});
3926
4042
  const contextListToDoResult = await getToDoContextList({
3927
4043
  getContextListFn,
@@ -3978,7 +4094,6 @@ async function runLump(input) {
3978
4094
  exports.appendHistoryEntry = appendHistoryEntry;
3979
4095
  exports.collectStepsForContext = collectStepsForContext;
3980
4096
  exports.contextStatus = contextStatus;
3981
- exports.contextStatusSchema = contextStatusSchema;
3982
4097
  exports.createConsoleLogger = createConsoleLogger;
3983
4098
  exports.defaultGitAddCommandFn = defaultGitAddCommandFn;
3984
4099
  exports.defaultGitCommitCommandFn = defaultGitCommitCommandFn;
@@ -4006,5 +4121,6 @@ exports.set = set;
4006
4121
  exports.shellSingleQuote = shellSingleQuote;
4007
4122
  exports.success = success;
4008
4123
  exports.validateContextListNames = validateContextListNames;
4124
+ exports.windowsNpmCmdShimBody = windowsNpmCmdShimBody;
4009
4125
  exports.writeHistoryFile = writeHistoryFile;
4010
4126
  //# sourceMappingURL=index.cjs.map