@lumpcode/core 0.1.1 → 0.3.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/README.md CHANGED
@@ -248,23 +248,25 @@ type GitCommitMessageFn = (input: {
248
248
 
249
249
  Maps a context to its normalized git commit message. **The returned message must be unique per context** -- it is the source of truth used to track whether a context has already been processed (see [Context Tracking with Git Commits](#context-tracking-with-git-commits)).
250
250
 
251
- ### `gitAddCommandFn`
251
+ ### `gitAddCommitFn`
252
252
 
253
- **Type:** `GitAddCommandFn` -- **Default:** `git add .`
253
+ **Type:** `GitAddCommitFn` -- **Default:** ``git add . && git commit --allow-empty -m <commitMessage>``
254
254
 
255
- Customize the git add command. Receives `{ baseBranch, branchName, contextList, workspacePath, context }` and is invoked **once per context**, right before that context's commit.
255
+ Per-context add+commit. Receives `{ baseBranch, branchName, workspacePath, context, commitMessage }` (no `contextList`) and returns a `Success` / `Failure` result:
256
256
 
257
- ### `gitCommitCommandFn`
257
+ | Return | Behavior |
258
+ | --- | --- |
259
+ | `success(string)` | Core runs that shell string with `cwd: workspacePath` |
260
+ | `success(null \| undefined)` | No-op (injector already did the work, or intentional skip) |
261
+ | `success('')` / `failure(msg)` / throw | Hard-fail the run with `reason: 'gitAddCommitFailed'` |
258
262
 
259
- **Type:** `GitCommitCommandFn` -- **Default:** ``git commit -m "${commitMessage}"``
263
+ Invoked **once per context** after `teardownFn`, producing exactly one commit per context on the work branch.
260
264
 
261
- Customize the git commit command. Receives the same input as `gitAddCommandFn` plus `{ commitMessage }`. Invoked **once per context**, producing exactly one commit per context on the work branch.
265
+ ### `gitPushFn`
262
266
 
263
- ### `gitPushCommandFn`
267
+ **Type:** `GitPushFn` -- **Default:** ``git push origin <branchName>``
264
268
 
265
- **Type:** `GitPushCommandFn` -- **Default:** ``git push origin ${branchName}``
266
-
267
- Customize the git push command. Invoked **once per branch**, after all per-context commits are made.
269
+ Once-per-branch push after all per-context add+commits succeed. Same Success / Failure payload rules as `gitAddCommitFn`, except failures are **log-only** (the run stays successful).
268
270
 
269
271
  ### `setupWorkspaceFn`
270
272
 
@@ -275,7 +277,7 @@ Prepares the workspace before prompt execution. It returns an object with two fi
275
277
  - `command` — the shell command to run (e.g. checkout the base branch, fetch, create the work branch).
276
278
  - `workspacePath` — the directory where all subsequent operations (prompt execution, git add/commit/push) will take place. The default implementation returns `'.'`, so those commands run with `cwd: '.'` (the **host process's current working directory**). If your process's cwd is not `projectRoot`, pass an absolute path (e.g. `projectRoot` or a worktree path) so behavior is unambiguous.
277
279
 
278
- > **Where commands run:** `setupWorkspaceFn` is the only function whose returned `command` runs at `projectRoot`. All other function parameters that return commands (`gitAddCommandFn`, `gitCommitCommandFn`, `gitPushCommandFn`, `commandFn`, `teardownWorkspaceFn`) execute their commands at `workspacePath`.
280
+ > **Where commands run:** `setupWorkspaceFn` is the only function whose returned `command` runs at `projectRoot`. All other function parameters that return commands (`gitAddCommitFn`, `gitPushFn`, `commandFn`, `teardownWorkspaceFn`) execute their commands at `workspacePath`.
279
281
 
280
282
  The default implementation command checks out the base branch, fetches, pulls, deletes and re-creates the work branch (with `cwd: projectRoot` for this setup command only):
281
283
 
@@ -510,10 +512,10 @@ flowchart TD
510
512
  LoopStart --> Setup["setupFn()"]
511
513
  Setup --> ExecPrompts["Execute steps sequentially"]
512
514
  ExecPrompts --> Teardown["teardownFn()"]
513
- Teardown --> AddCommit["git add + git commit -m gitCommitMessageFn(context)"]
515
+ Teardown --> AddCommit["gitAddCommitFn (commitMessage from gitCommitMessageFn)"]
514
516
  AddCommit --> LoopCheck{"More contexts?"}
515
517
  LoopCheck -->|Yes| LoopStart
516
- LoopCheck -->|No| Push["gitPushCommandFn (branch only)"]
518
+ LoopCheck -->|No| Push["gitPushFn (branch only)"]
517
519
  Push --> TeardownWorkspace["teardownWorkspaceFn()"]
518
520
  TeardownWorkspace --> Done["Return Success or Failure"]
519
521
  ```
@@ -1,14 +1,19 @@
1
- export declare function execAsync(command: string, options?: {
2
- cwd?: string;
3
- }): Promise<import("../..").Failure<{
1
+ import type { Failure, Success } from '../../types';
2
+ export type ExecAsyncFailureReason = 'timeout' | 'exit';
3
+ export type ExecAsyncFailure = {
4
4
  message: string;
5
+ reason: ExecAsyncFailureReason;
5
6
  info: {
6
7
  command: string;
7
- stdout: any;
8
- stderr: any;
8
+ stdout: unknown;
9
+ stderr: unknown;
9
10
  };
10
- }> | import("../..").Success<{
11
- stdout: any;
12
- stderr: any;
13
- }>>;
11
+ };
12
+ export declare function execAsync(command: string, options?: {
13
+ cwd?: string;
14
+ timeoutMillis?: number;
15
+ }): Promise<Success<{
16
+ stdout: string;
17
+ stderr: string;
18
+ }> | Failure<ExecAsyncFailure>>;
14
19
  //# sourceMappingURL=main.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../../src/helpers/execAsync/main.ts"],"names":[],"mappings":"AAMA,wBAAsB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE;;;;;;;;;;IA4B1E"}
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../../src/helpers/execAsync/main.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAQpD,MAAM,MAAM,sBAAsB,GAAG,SAAS,GAAG,MAAM,CAAC;AAExD,MAAM,MAAM,gBAAgB,GAAG;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,sBAAsB,CAAC;IAC/B,IAAI,EAAE;QACF,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,OAAO,CAAC;QAChB,MAAM,EAAE,OAAO,CAAC;KACnB,CAAC;CACL,CAAC;AAoBF,wBAAsB,SAAS,CAC3B,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,GACnD,OAAO,CAAC,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC,CA4BlF"}
@@ -1,19 +1,14 @@
1
- import { ContextList, ContextRunState, ExecuteStepsFailureData, Failure, Logger, LumpVariables, StepVariables } from "../../types";
1
+ import { ContextList, ContextRunState, Failure, Logger, LumpVariables, StepVariables, Success } from "../../types";
2
2
  import type { RunLumpInput } from '../../usages';
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'>> & {
3
+ export type ExecuteStepsForContextListParams<V extends LumpVariables = LumpVariables, SV extends StepVariables = StepVariables> = Required<Pick<RunLumpInput<V, SV>, 'baseBranch' | 'branchFn' | 'lumpVariables' | 'steps' | 'setupFn' | 'teardownFn' | 'gitAddCommitFn' | 'gitPushFn' | 'gitCommitMessageFn' | 'projectRoot' | 'setupWorkspaceFn' | 'teardownWorkspaceFn' | 'getKeepHistoryFilePathFn'>> & {
4
4
  contextList: ContextList;
5
5
  logger?: Logger;
6
6
  /** When aborted, in-flight commands are killed and the step walk stops (ignores continueOnError). */
7
7
  signal?: AbortSignal;
8
8
  };
9
- 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, signal, }: ExecuteStepsForContextListParams<V, SV>): Promise<Failure<{
9
+ export declare function executeStepsForContextList<V extends LumpVariables = LumpVariables, SV extends StepVariables = StepVariables>({ baseBranch, branchFn, lumpVariables, contextList, gitAddCommitFn, gitPushFn, gitCommitMessageFn, projectRoot, steps, setupFn, setupWorkspaceFn, teardownFn, teardownWorkspaceFn, getKeepHistoryFilePathFn, logger: loggerInput, signal, }: ExecuteStepsForContextListParams<V, SV>): Promise<Failure<{
10
10
  message: string;
11
- info: {
12
- command: string;
13
- stdout: any;
14
- stderr: any;
15
- };
16
- }> | Failure<ExecuteStepsFailureData> | import("../..").Success<{
11
+ }> | Success<{
17
12
  branchName: string;
18
13
  contextNames: string[];
19
14
  contextRunStateList: ContextRunState[];
@@ -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,uBAAuB,EACvB,OAAO,EACP,MAAM,EACN,aAAa,EAMb,aAAa,EAChB,MAAM,aAAa,CAAC;AASrB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AA0FjD,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;IAChB,qGAAqG;IACrG,MAAM,CAAC,EAAE,WAAW,CAAC;CACxB,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,EACnB,MAAM,GACT,EAAE,gCAAgC,CAAC,CAAC,EAAE,EAAE,CAAC;;;;;;;;;;;IAkWzC;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,EAEf,OAAO,EACP,MAAM,EACN,aAAa,EAMb,aAAa,EACb,OAAO,EACV,MAAM,aAAa,CAAC;AASrB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAuGjD,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,gBAAgB,GAChB,WAAW,GACX,oBAAoB,GACpB,aAAa,GACb,kBAAkB,GAClB,qBAAqB,GACrB,0BAA0B,CAC/B,CAAC,GAAG;IACD,WAAW,EAAE,WAAW,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qGAAqG;IACrG,MAAM,CAAC,EAAE,WAAW,CAAC;CACxB,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,cAAc,EACd,SAAS,EACT,kBAAkB,EAClB,WAAW,EACX,KAAK,EACL,OAAO,EACP,gBAAgB,EAChB,UAAU,EACV,mBAAmB,EACnB,wBAAwB,EACxB,MAAM,EAAE,WAAW,EACnB,MAAM,GACT,EAAE,gCAAgC,CAAC,CAAC,EAAE,EAAE,CAAC;;;;;;IA6VzC;AAED,MAAM,MAAM,gCAAgC,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,0BAA0B,CAAC,CAAC,CAAC"}
package/dist/index.cjs CHANGED
@@ -3605,32 +3605,54 @@ async function killProcessTree(input) {
3605
3605
  }
3606
3606
 
3607
3607
  const execAsyncBase = node_util.promisify(node_child_process.exec);
3608
+ /** Same signal Node's `exec` `timeout` option uses by default. */
3609
+ const EXEC_TIMEOUT_KILL_SIGNAL = 'SIGTERM';
3610
+ function isExecTimeout(error, timeoutMillis) {
3611
+ if (timeoutMillis === undefined) {
3612
+ return false;
3613
+ }
3614
+ if (typeof error !== 'object' || error === null) {
3615
+ return false;
3616
+ }
3617
+ const execError = error;
3618
+ if (execError.killed !== true) {
3619
+ return false;
3620
+ }
3621
+ // Windows has no POSIX signals; Node force-kills and `signal` is often null.
3622
+ if (process.platform === 'win32') {
3623
+ return true;
3624
+ }
3625
+ return execError.signal === EXEC_TIMEOUT_KILL_SIGNAL;
3626
+ }
3608
3627
  async function execAsync(command, options) {
3609
- const { stdout, stderr, hasErrored } = await execAsyncBase(command, { cwd: options?.cwd })
3610
- .then(result => ({
3611
- stdout: result.stdout,
3612
- stderr: result.stderr,
3613
- hasErrored: false,
3614
- }))
3615
- .catch(e => ({
3616
- stderr: e,
3617
- stdout: e,
3618
- hasErrored: true,
3619
- }));
3620
- if (hasErrored) {
3628
+ const timeoutMillis = options?.timeoutMillis;
3629
+ try {
3630
+ const result = await execAsyncBase(command, {
3631
+ cwd: options?.cwd,
3632
+ ...(timeoutMillis !== undefined
3633
+ ? { timeout: timeoutMillis, killSignal: EXEC_TIMEOUT_KILL_SIGNAL }
3634
+ : {}),
3635
+ });
3636
+ return success({
3637
+ stdout: String(result.stdout),
3638
+ stderr: String(result.stderr),
3639
+ });
3640
+ }
3641
+ catch (e) {
3642
+ const timedOut = isExecTimeout(e, timeoutMillis);
3643
+ const reason = timedOut ? 'timeout' : 'exit';
3621
3644
  return failure({
3622
- message: `Command ${command} failed with error: ${stderr}`,
3645
+ message: timedOut
3646
+ ? `Command ${command} timed out after ${timeoutMillis}ms`
3647
+ : `Command ${command} failed with error: ${e}`,
3648
+ reason,
3623
3649
  info: {
3624
3650
  command,
3625
- stdout,
3626
- stderr,
3651
+ stdout: e,
3652
+ stderr: e,
3627
3653
  },
3628
3654
  });
3629
3655
  }
3630
- return success({
3631
- stdout,
3632
- stderr,
3633
- });
3634
3656
  }
3635
3657
 
3636
3658
  function execBinary(input) {
@@ -3848,28 +3870,37 @@ async function awaitUnlessAborted(work, signal) {
3848
3870
  });
3849
3871
  });
3850
3872
  }
3851
- async function runOptionalGitCommand(input) {
3852
- const { label, getCommand, cwd, logger } = input;
3873
+ /**
3874
+ * Result-aware runner for `gitAddCommitFn` / `gitPushFn`.
3875
+ * nullish Success → no-op; empty string / Failure / throw / exec fail → failed.
3876
+ */
3877
+ async function runGitResultHook(input) {
3878
+ const { getResult, cwd, logger, execLabel } = input;
3853
3879
  try {
3854
- const command = await getCommand();
3855
- if (command == null || command === '') {
3856
- return 'ok';
3857
- }
3858
- const result = await execAsync(command, { cwd });
3859
- logger.verbose(`${label} ${JSON.stringify(result)}`);
3880
+ const result = await getResult();
3860
3881
  if (!result.success) {
3861
- logger.error(formatExecFailureMessage({ label, failure: result }));
3862
- return 'failed';
3882
+ return { status: 'failed', detail: result.data };
3883
+ }
3884
+ const command = result.data;
3885
+ if (command == null) {
3886
+ return { status: 'ok' };
3887
+ }
3888
+ if (command === '') {
3889
+ return { status: 'failed', detail: 'empty command string' };
3890
+ }
3891
+ const execResult = await execAsync(command, { cwd });
3892
+ logger.verbose(`${execLabel} ${JSON.stringify(execResult)}`);
3893
+ if (!execResult.success) {
3894
+ return { status: 'failed', detail: execResult.data.message };
3863
3895
  }
3864
- return 'ok';
3896
+ return { status: 'ok' };
3865
3897
  }
3866
3898
  catch (error) {
3867
3899
  const message = error instanceof Error ? error.message : String(error);
3868
- logger.error(`Failed to run ${label}: ${message}`);
3869
- return 'failed';
3900
+ return { status: 'failed', detail: message };
3870
3901
  }
3871
3902
  }
3872
- async function executeStepsForContextList({ baseBranch, branchFn, lumpVariables, contextList, gitAddCommandFn, gitCommitCommandFn, gitPushCommandFn, gitCommitMessageFn, projectRoot, steps, setupFn, setupWorkspaceFn, teardownFn, teardownWorkspaceFn, getKeepHistoryFilePathFn, logger: loggerInput, signal, }) {
3903
+ async function executeStepsForContextList({ baseBranch, branchFn, lumpVariables, contextList, gitAddCommitFn, gitPushFn, gitCommitMessageFn, projectRoot, steps, setupFn, setupWorkspaceFn, teardownFn, teardownWorkspaceFn, getKeepHistoryFilePathFn, logger: loggerInput, signal, }) {
3873
3904
  const logger = loggerInput ?? createConsoleLogger({});
3874
3905
  const contextNames = contextList.map(context => context.name);
3875
3906
  logger.verbose(`contextNames ${JSON.stringify(contextNames)}`);
@@ -3895,7 +3926,9 @@ async function executeStepsForContextList({ baseBranch, branchFn, lumpVariables,
3895
3926
  });
3896
3927
  logger.verbose(`setupWorkspaceCommandExec ${JSON.stringify(setupWorkspaceCommandExec)}`);
3897
3928
  if (!setupWorkspaceCommandExec.success) {
3898
- return set(setupWorkspaceCommandExec, ['data', 'message'], `Failed to setup the workspace: ${setupWorkspaceCommandExec.data.message}`);
3929
+ return failure({
3930
+ message: `Failed to setup the workspace: ${setupWorkspaceCommandExec.data.message}`,
3931
+ });
3899
3932
  }
3900
3933
  if (afterExec) {
3901
3934
  await afterExec({ workspacePath });
@@ -4077,43 +4110,42 @@ async function executeStepsForContextList({ baseBranch, branchFn, lumpVariables,
4077
4110
  runFailure = stepWalkFailure;
4078
4111
  break;
4079
4112
  }
4080
- const perContextInput = {
4081
- ...injectedGitAndWorkspaceFnsInput,
4082
- context,
4083
- };
4084
- const addOutcome = await runOptionalGitCommand({
4085
- label: `git add for context ${context.name}`,
4086
- getCommand: () => gitAddCommandFn(perContextInput),
4113
+ const commitMessage = gitCommitMessageFn({ context, lumpVariables, baseBranch });
4114
+ const addCommitExecLabel = `git add+commit for context ${context.name}`;
4115
+ const addCommitOutcome = await runGitResultHook({
4116
+ getResult: () => gitAddCommitFn({
4117
+ ...injectedGitAndWorkspaceFnsInput,
4118
+ context,
4119
+ commitMessage,
4120
+ }),
4087
4121
  cwd: workspacePath,
4088
4122
  logger,
4123
+ execLabel: addCommitExecLabel,
4089
4124
  });
4090
- if (addOutcome === 'failed') {
4125
+ if (addCommitOutcome.status === 'failed') {
4126
+ const message = `Failed to add and commit for context ${context.name}: ${addCommitOutcome.detail}`;
4127
+ logger.error(message);
4091
4128
  runFailure = {
4092
4129
  success: false,
4093
4130
  data: {
4094
- message: `Failed to add the changes for context ${context.name}`,
4131
+ message,
4132
+ reason: 'gitAddCommitFailed',
4095
4133
  },
4096
4134
  };
4097
4135
  break;
4098
4136
  }
4099
- const commitMessage = gitCommitMessageFn({ context, lumpVariables, baseBranch });
4100
- await runOptionalGitCommand({
4101
- label: `git commit for context ${context.name}`,
4102
- getCommand: () => gitCommitCommandFn({
4103
- ...perContextInput,
4104
- commitMessage,
4105
- }),
4106
- cwd: workspacePath,
4107
- logger,
4108
- });
4109
4137
  }
4110
4138
  if (!runFailure) {
4111
- await runOptionalGitCommand({
4112
- label: `git push on branch ${branchName}`,
4113
- getCommand: () => gitPushCommandFn(injectedGitAndWorkspaceFnsInput),
4139
+ const pushExecLabel = `git push on branch ${branchName}`;
4140
+ const pushOutcome = await runGitResultHook({
4141
+ getResult: () => gitPushFn(injectedGitAndWorkspaceFnsInput),
4114
4142
  cwd: workspacePath,
4115
4143
  logger,
4144
+ execLabel: pushExecLabel,
4116
4145
  });
4146
+ if (pushOutcome.status === 'failed') {
4147
+ logger.error(`Failed to ${pushExecLabel}: ${pushOutcome.detail}`);
4148
+ }
4117
4149
  }
4118
4150
  }
4119
4151
  finally {
@@ -4378,14 +4410,11 @@ const contextStatus = ['toDo', 'branchPushed', 'finished'];
4378
4410
  const defaultGitCommitMessageFn = ({ context }) => {
4379
4411
  return `LUMP:${context.name}`;
4380
4412
  };
4381
- const defaultGitPushCommandFn = (input) => {
4382
- return `git push origin ${shellSingleQuote(input.branchName)}`;
4383
- };
4384
- const defaultGitAddCommandFn = () => {
4385
- return `git add .`;
4413
+ const defaultGitAddCommitFn = (input) => {
4414
+ return success(`git add . && git commit --allow-empty -m ${shellSingleQuote(input.commitMessage)}`);
4386
4415
  };
4387
- const defaultGitCommitCommandFn = (input) => {
4388
- return `git commit --allow-empty -m ${shellSingleQuote(input.commitMessage)}`;
4416
+ const defaultGitPushFn = (input) => {
4417
+ return success(`git push origin ${shellSingleQuote(input.branchName)}`);
4389
4418
  };
4390
4419
  const defaultSetupWorkspaceFn = async (input) => {
4391
4420
  const { baseBranch, branchName } = input;
@@ -4423,7 +4452,7 @@ const defaultSetupWorkspaceFnWithWorktree = async (input) => {
4423
4452
  };
4424
4453
 
4425
4454
  async function runLump(input) {
4426
- 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, signal, refreshRemoteTrackingRefsFn, } = input;
4455
+ const { baseBranch, branchFn, lumpVariables: lumpVariablesInput, getContextListFn, gitAddCommitFn = defaultGitAddCommitFn, gitCommitMessageFn = defaultGitCommitMessageFn, gitPushFn = defaultGitPushFn, numberOfContextsPerBranch = 1, projectRoot, steps, setupFn = () => ({ contextRunState: {} }), setupWorkspaceFn = defaultSetupWorkspaceFn, teardownFn = () => undefined, teardownWorkspaceFn = defaultTeardownWorkspaceFn, getKeepHistoryFilePathFn = () => undefined, logger: loggerInput, signal, refreshRemoteTrackingRefsFn, } = input;
4427
4456
  const lumpVariables = (lumpVariablesInput ?? {});
4428
4457
  const logger = loggerInput ?? createConsoleLogger({});
4429
4458
  const contextListToDoResult = await getToDoContextList({
@@ -4458,10 +4487,9 @@ async function runLump(input) {
4458
4487
  branchFn: branchFn,
4459
4488
  lumpVariables: lumpVariables,
4460
4489
  contextList: nextContextsForBranchList,
4461
- gitAddCommandFn,
4462
- gitCommitCommandFn,
4490
+ gitAddCommitFn,
4463
4491
  gitCommitMessageFn,
4464
- gitPushCommandFn,
4492
+ gitPushFn,
4465
4493
  projectRoot,
4466
4494
  steps,
4467
4495
  setupFn,
@@ -4486,10 +4514,9 @@ exports.collectStepsForContext = collectStepsForContext;
4486
4514
  exports.commitMessageIncludesMarker = commitMessageIncludesMarker;
4487
4515
  exports.contextStatus = contextStatus;
4488
4516
  exports.createConsoleLogger = createConsoleLogger;
4489
- exports.defaultGitAddCommandFn = defaultGitAddCommandFn;
4490
- exports.defaultGitCommitCommandFn = defaultGitCommitCommandFn;
4517
+ exports.defaultGitAddCommitFn = defaultGitAddCommitFn;
4491
4518
  exports.defaultGitCommitMessageFn = defaultGitCommitMessageFn;
4492
- exports.defaultGitPushCommandFn = defaultGitPushCommandFn;
4519
+ exports.defaultGitPushFn = defaultGitPushFn;
4493
4520
  exports.defaultSetupWorkspaceFn = defaultSetupWorkspaceFn;
4494
4521
  exports.defaultSetupWorkspaceFnWithWorktree = defaultSetupWorkspaceFnWithWorktree;
4495
4522
  exports.defaultTeardownWorkspaceFn = defaultTeardownWorkspaceFn;