@kody-ade/kody-engine 0.1.4 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin/cli.mjs CHANGED
@@ -7965,10 +7965,16 @@ async function runPipeline(ctx, pipeline, hooks, rebuildPipeline) {
7965
7965
  }
7966
7966
  if (!ctx.input.dryRun && !ctx.input.local) {
7967
7967
  try {
7968
- const currentBranch = execFileSync13("git", ["branch", "--show-current"], {
7969
- encoding: "utf-8"
7970
- }).trim();
7971
- const isFeatureBranch = !["dev", "main", "master"].includes(currentBranch);
7968
+ const currentBranch = execFileSync13(
7969
+ "git",
7970
+ ["branch", "--show-current"],
7971
+ {
7972
+ encoding: "utf-8"
7973
+ }
7974
+ ).trim();
7975
+ const isFeatureBranch = !["dev", "main", "master"].includes(
7976
+ currentBranch
7977
+ );
7972
7978
  if (isFeatureBranch) {
7973
7979
  commitPipelineFiles({
7974
7980
  taskDir: ctx.taskDir,
@@ -7981,7 +7987,10 @@ async function runPipeline(ctx, pipeline, hooks, rebuildPipeline) {
7981
7987
  logger.info(" \u2713 Pushed fresh running status.json to branch");
7982
7988
  }
7983
7989
  } catch (earlyPushErr) {
7984
- logger.warn({ err: earlyPushErr }, "Early status push failed (non-fatal)");
7990
+ logger.warn(
7991
+ { err: earlyPushErr },
7992
+ "Early status push failed (non-fatal)"
7993
+ );
7985
7994
  }
7986
7995
  }
7987
7996
  } else {
@@ -8002,7 +8011,9 @@ async function runPipeline(ctx, pipeline, hooks, rebuildPipeline) {
8002
8011
  }
8003
8012
  }
8004
8013
  if (state.state === "paused") {
8005
- const anyPausedStage = Object.values(state.stages).some((s) => s.state === "paused");
8014
+ const anyPausedStage = Object.values(state.stages).some(
8015
+ (s) => s.state === "paused"
8016
+ );
8006
8017
  if (!anyPausedStage) {
8007
8018
  state = {
8008
8019
  ...state,
@@ -8035,7 +8046,11 @@ async function runPipeline(ctx, pipeline, hooks, rebuildPipeline) {
8035
8046
  const recoveredState = recoverStaleStages(currentState);
8036
8047
  if (recoveredState !== currentState) {
8037
8048
  logger.info("\u26A0\uFE0F Periodic recovery: reset stale running stages");
8038
- logRecovery("stale-stage-recovery", ctx.taskId, "Reset stale running stages");
8049
+ logRecovery(
8050
+ "stale-stage-recovery",
8051
+ ctx.taskId,
8052
+ "Reset stale running stages"
8053
+ );
8039
8054
  state = recoveredState;
8040
8055
  writeState(ctx.taskId, state);
8041
8056
  }
@@ -8047,7 +8062,10 @@ async function runPipeline(ctx, pipeline, hooks, rebuildPipeline) {
8047
8062
  const newOrder = flattenPipelineOrder(pipeline.order);
8048
8063
  for (const stageName of newOrder) {
8049
8064
  if (!state.stages[stageName]) {
8050
- state = updateStage(state, stageName, { state: "pending", retries: 0 });
8065
+ state = updateStage(state, stageName, {
8066
+ state: "pending",
8067
+ retries: 0
8068
+ });
8051
8069
  }
8052
8070
  }
8053
8071
  writeState(ctx.taskId, state);
@@ -8088,7 +8106,9 @@ async function runPipeline(ctx, pipeline, hooks, rebuildPipeline) {
8088
8106
  const stageState = failedStage?.[1];
8089
8107
  const stageOutcome = stageState?.state || "unknown";
8090
8108
  const stageError = stageState?.error ? `: ${stageState.error}` : "";
8091
- throw new Error(`Pipeline failed at stage: ${stageName} (${stageOutcome})${stageError}`);
8109
+ throw new Error(
8110
+ `Pipeline failed at stage: ${stageName} (${stageOutcome})${stageError}`
8111
+ );
8092
8112
  }
8093
8113
  return state;
8094
8114
  }
@@ -8134,7 +8154,10 @@ async function executeSingleStep(ctx, pipeline, state, stageName) {
8134
8154
  logger.info(` ${stageName} already completed, skipping`);
8135
8155
  return state;
8136
8156
  }
8137
- state = updateStage(state, stageName, { state: "running", startedAt: (/* @__PURE__ */ new Date()).toISOString() });
8157
+ state = updateStage(state, stageName, {
8158
+ state: "running",
8159
+ startedAt: (/* @__PURE__ */ new Date()).toISOString()
8160
+ });
8138
8161
  writeState(ctx.taskId, state);
8139
8162
  logStageStart(stageName, ctx.taskId);
8140
8163
  if (ctx.input.dryRun) {
@@ -8156,7 +8179,35 @@ async function executeSingleStep(ctx, pipeline, state, stageName) {
8156
8179
  const handler = getHandler(def.name, def.type);
8157
8180
  const result = await handler.execute(ctx, def);
8158
8181
  ciGroupEnd();
8159
- return await handleStageResult(ctx, pipeline, state, stageName, result, def);
8182
+ if (result.outcome === "failed" || result.outcome === "timed_out") {
8183
+ if (def.postActions && !ctx.input.dryRun) {
8184
+ try {
8185
+ for (const action of def.postActions) {
8186
+ await executePostAction(ctx, action, state);
8187
+ }
8188
+ } catch (postError) {
8189
+ logger.error(
8190
+ { err: postError },
8191
+ ` Post-action failed for ${stageName}:`
8192
+ );
8193
+ }
8194
+ }
8195
+ const errorMessage = `${stageName} ${result.outcome === "timed_out" ? "timed out" : "failed"}: ${result.reason || "unknown"}`;
8196
+ throw new StageError(
8197
+ errorMessage,
8198
+ stageName,
8199
+ void 0,
8200
+ result.sessionId
8201
+ );
8202
+ }
8203
+ return await handleStageResult(
8204
+ ctx,
8205
+ pipeline,
8206
+ state,
8207
+ stageName,
8208
+ result,
8209
+ def
8210
+ );
8160
8211
  } catch (error) {
8161
8212
  ciGroupEnd();
8162
8213
  if (error instanceof PipelinePausedError) {
@@ -8166,14 +8217,16 @@ async function executeSingleStep(ctx, pipeline, state, stageName) {
8166
8217
  const errorMessage = error instanceof Error ? error.message : String(error);
8167
8218
  logger.error({ err: error }, ` \u274C ${stageName} failed:`);
8168
8219
  logStageFail(stageName, ctx.taskId, errorMessage);
8169
- const canObserve = ctx.serverUrl && ctx.lastSessionId && !ctx.input.dryRun;
8220
+ const stageSessionId = error instanceof StageError ? error.sessionId : void 0;
8221
+ const effectiveSessionId = stageSessionId || ctx.lastSessionId;
8222
+ const canObserve = ctx.serverUrl && effectiveSessionId && !ctx.input.dryRun;
8170
8223
  if (canObserve && !def.advisory) {
8171
8224
  try {
8172
8225
  const observer = new PipelineObserver(
8173
8226
  ctx.taskId,
8174
8227
  ctx.taskDir,
8175
8228
  ctx.serverUrl,
8176
- ctx.lastSessionId,
8229
+ effectiveSessionId,
8177
8230
  ctx.taskDir
8178
8231
  // dataDir is taskDir/opencode-data derived in Observer
8179
8232
  );
@@ -8214,7 +8267,10 @@ async function executeSingleStep(ctx, pipeline, state, stageName) {
8214
8267
  return completeState(state, "failed");
8215
8268
  }
8216
8269
  } catch (observerError) {
8217
- logger.error({ err: observerError }, `[StateMachine] Observer error, falling back`);
8270
+ logger.error(
8271
+ { err: observerError },
8272
+ `[StateMachine] Observer error, falling back`
8273
+ );
8218
8274
  state = updateStage(state, stageName, {
8219
8275
  state: "failed",
8220
8276
  error: errorMessage
@@ -8261,7 +8317,10 @@ async function executeParallelStep(ctx, pipeline, state, stageNames) {
8261
8317
  stagesToRun.map(async (stageName) => {
8262
8318
  const def = pipeline.stages.get(stageName);
8263
8319
  if (!def) {
8264
- throw new StageError(`Stage '${stageName}' not found in pipeline definitions`, stageName);
8320
+ throw new StageError(
8321
+ `Stage '${stageName}' not found in pipeline definitions`,
8322
+ stageName
8323
+ );
8265
8324
  }
8266
8325
  if (def.shouldSkip) {
8267
8326
  const skipResult = def.shouldSkip(ctx);
@@ -8360,7 +8419,10 @@ async function executeParallelStep(ctx, pipeline, state, stageNames) {
8360
8419
  pausedStage = stageName;
8361
8420
  continue;
8362
8421
  }
8363
- logger.error({ err: postError }, ` Post-action failed for parallel stage ${stageName}:`);
8422
+ logger.error(
8423
+ { err: postError },
8424
+ ` Post-action failed for parallel stage ${stageName}:`
8425
+ );
8364
8426
  const postErrorMsg = postError instanceof Error ? postError.message : String(postError);
8365
8427
  state = updateStage(state, stageName, {
8366
8428
  state: "failed",
@@ -8386,7 +8448,10 @@ async function executeParallelStep(ctx, pipeline, state, stageNames) {
8386
8448
  error: stageResult.reason || "timed out"
8387
8449
  });
8388
8450
  if (!isAdvisory) {
8389
- criticalFailures.push({ name: stageName, reason: stageResult.reason || "timed out" });
8451
+ criticalFailures.push({
8452
+ name: stageName,
8453
+ reason: stageResult.reason || "timed out"
8454
+ });
8390
8455
  }
8391
8456
  } else if (stageResult.outcome === "failed") {
8392
8457
  const isAdvisory = pipeline.stages.get(stageName)?.advisory === true;
@@ -8395,20 +8460,28 @@ async function executeParallelStep(ctx, pipeline, state, stageNames) {
8395
8460
  state: "failed",
8396
8461
  error: stageResult.reason || "failed"
8397
8462
  });
8398
- advisoryFailures.push({ name: stageName, reason: stageResult.reason || "failed" });
8463
+ advisoryFailures.push({
8464
+ name: stageName,
8465
+ reason: stageResult.reason || "failed"
8466
+ });
8399
8467
  } else {
8400
8468
  state = updateStage(state, stageName, {
8401
8469
  state: "failed",
8402
8470
  error: stageResult.reason || "failed"
8403
8471
  });
8404
- criticalFailures.push({ name: stageName, reason: stageResult.reason || "failed" });
8472
+ criticalFailures.push({
8473
+ name: stageName,
8474
+ reason: stageResult.reason || "failed"
8475
+ });
8405
8476
  }
8406
8477
  }
8407
8478
  }
8408
8479
  if (criticalFailures.length > 0) {
8409
8480
  const errors = criticalFailures.map((f) => f.reason).join("; ");
8410
8481
  const names = criticalFailures.map((f) => f.name);
8411
- logger.error(` \u274C Parallel stages [${names.join(", ")}] failed: ${errors}`);
8482
+ logger.error(
8483
+ ` \u274C Parallel stages [${names.join(", ")}] failed: ${errors}`
8484
+ );
8412
8485
  if (ctx.input.issueNumber) {
8413
8486
  setLifecycleLabel(ctx.input.issueNumber, "kody:failed");
8414
8487
  }
@@ -8434,7 +8507,12 @@ async function handleStageResult(ctx, pipeline, state, stageName, result, def) {
8434
8507
  cost: result.cost,
8435
8508
  sessionId: result.sessionId
8436
8509
  });
8437
- logStageComplete(stageName, ctx.taskId, "completed", elapsed ? elapsed * 1e3 : void 0);
8510
+ logStageComplete(
8511
+ stageName,
8512
+ ctx.taskId,
8513
+ "completed",
8514
+ elapsed ? elapsed * 1e3 : void 0
8515
+ );
8438
8516
  if (result.sessionId) {
8439
8517
  ctx.lastSessionId = result.sessionId;
8440
8518
  }
@@ -8526,11 +8604,13 @@ var init_state_machine = __esm({
8526
8604
  StageError = class extends Error {
8527
8605
  stageName;
8528
8606
  cause;
8529
- constructor(message, stageName, cause) {
8607
+ sessionId;
8608
+ constructor(message, stageName, cause, sessionId) {
8530
8609
  super(message);
8531
8610
  this.name = "StageError";
8532
8611
  this.stageName = stageName;
8533
8612
  this.cause = cause;
8613
+ this.sessionId = sessionId;
8534
8614
  }
8535
8615
  };
8536
8616
  }