codeharness 0.29.4 → 0.30.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.
@@ -2895,7 +2895,7 @@ function generateDockerfileTemplate(projectDir, stackOrDetections) {
2895
2895
  }
2896
2896
 
2897
2897
  // src/modules/infra/init-project.ts
2898
- var HARNESS_VERSION = true ? "0.29.4" : "0.0.0-dev";
2898
+ var HARNESS_VERSION = true ? "0.30.0" : "0.0.0-dev";
2899
2899
  function failResult(opts, error) {
2900
2900
  return {
2901
2901
  status: "fail",
@@ -16,7 +16,7 @@ import {
16
16
  stopCollectorOnly,
17
17
  stopSharedStack,
18
18
  stopStack
19
- } from "./chunk-KVKEUNEB.js";
19
+ } from "./chunk-S3RKDJMC.js";
20
20
  export {
21
21
  checkRemoteEndpoint,
22
22
  cleanupOrphanedContainers,
package/dist/index.js CHANGED
@@ -40,7 +40,7 @@ import {
40
40
  validateDockerfile,
41
41
  warn,
42
42
  writeState
43
- } from "./chunk-KVKEUNEB.js";
43
+ } from "./chunk-S3RKDJMC.js";
44
44
 
45
45
  // src/index.ts
46
46
  import { Command } from "commander";
@@ -3882,75 +3882,165 @@ async function executeWorkflow(config) {
3882
3882
  let halted = false;
3883
3883
  let lastOutputContract = null;
3884
3884
  let accumulatedCostUsd = 0;
3885
- for (const step of config.workflow.storyFlow) {
3886
- if (halted) break;
3887
- if (config.abortSignal?.aborted) {
3888
- info("Execution interrupted \u2014 saving state");
3889
- state = { ...state, phase: "interrupted" };
3890
- writeWorkflowState(state, projectDir);
3891
- halted = true;
3892
- break;
3893
- }
3894
- if (isLoopBlock(step)) {
3895
- const loopResult = await executeLoopBlock(step, state, config, workItems, lastOutputContract);
3896
- state = loopResult.state;
3897
- errors.push(...loopResult.errors);
3898
- tasksCompleted += loopResult.tasksCompleted;
3899
- lastOutputContract = loopResult.lastContract;
3900
- for (const item of workItems) {
3901
- processedStories.add(item.key);
3885
+ if (config.storyPipeline) {
3886
+ const preTasks = [];
3887
+ let loopIdx = -1;
3888
+ for (let i = 0; i < config.workflow.storyFlow.length; i++) {
3889
+ const s = config.workflow.storyFlow[i];
3890
+ if (isLoopBlock(s)) {
3891
+ loopIdx = i;
3892
+ break;
3902
3893
  }
3903
- if (loopResult.halted) {
3894
+ if (typeof s === "string") preTasks.push(s);
3895
+ }
3896
+ for (const item of workItems) {
3897
+ if (halted || config.abortSignal?.aborted) {
3898
+ if (config.abortSignal?.aborted) {
3899
+ info("Execution interrupted \u2014 saving state");
3900
+ state = { ...state, phase: "interrupted" };
3901
+ writeWorkflowState(state, projectDir);
3902
+ }
3904
3903
  halted = true;
3904
+ break;
3905
3905
  }
3906
- if (state.phase === "max-iterations" || state.phase === "circuit-breaker") {
3907
- halted = true;
3906
+ processedStories.add(item.key);
3907
+ for (const taskName of preTasks) {
3908
+ if (halted || config.abortSignal?.aborted) {
3909
+ halted = true;
3910
+ break;
3911
+ }
3912
+ const task = config.workflow.tasks[taskName];
3913
+ if (!task || task.agent === null) continue;
3914
+ const definition = config.agents[task.agent];
3915
+ if (!definition) {
3916
+ warn(`workflow-engine: agent "${task.agent}" not found for "${taskName}"`);
3917
+ continue;
3918
+ }
3919
+ if (isTaskCompleted(state, taskName, item.key)) continue;
3920
+ try {
3921
+ const dr = await dispatchTaskWithResult(task, taskName, item.key, definition, state, config, void 0, lastOutputContract ?? void 0);
3922
+ state = dr.updatedState;
3923
+ lastOutputContract = dr.contract;
3924
+ propagateVerifyFlags(taskName, dr.contract, projectDir);
3925
+ accumulatedCostUsd += dr.contract?.cost_usd ?? 0;
3926
+ tasksCompleted++;
3927
+ } catch (err) {
3928
+ const engineError = handleDispatchError(err, taskName, item.key);
3929
+ errors.push(engineError);
3930
+ if (config.onEvent) {
3931
+ config.onEvent({ type: "dispatch-error", taskName, storyKey: item.key, error: { code: engineError.code, message: engineError.message } });
3932
+ } else {
3933
+ warn(`[${taskName}] ${item.key} \u2014 ERROR: [${engineError.code}] ${engineError.message}`);
3934
+ }
3935
+ state = recordErrorInState(state, taskName, item.key, engineError);
3936
+ writeWorkflowState(state, projectDir);
3937
+ if (err instanceof DispatchError && HALT_ERROR_CODES.has(err.code)) {
3938
+ halted = true;
3939
+ }
3940
+ break;
3941
+ }
3908
3942
  }
3909
- continue;
3910
3943
  }
3911
- const taskName = step;
3912
- const task = config.workflow.tasks[taskName];
3913
- if (!task) {
3914
- warn(`workflow-engine: task "${taskName}" not found in workflow tasks, skipping`);
3915
- continue;
3916
- }
3917
- if (task.agent === null) {
3918
- if (task.scope === "per-run") {
3919
- if (isTaskCompleted(state, taskName, PER_RUN_SENTINEL)) {
3920
- warn(`workflow-engine: skipping completed task ${taskName} for ${PER_RUN_SENTINEL}`);
3921
- continue;
3944
+ const remaining = loopIdx >= 0 ? config.workflow.storyFlow.slice(loopIdx) : [];
3945
+ for (const step of remaining) {
3946
+ if (halted || config.abortSignal?.aborted) {
3947
+ halted = true;
3948
+ break;
3949
+ }
3950
+ if (isLoopBlock(step)) {
3951
+ const loopResult = await executeLoopBlock(step, state, config, workItems, lastOutputContract);
3952
+ state = loopResult.state;
3953
+ errors.push(...loopResult.errors);
3954
+ tasksCompleted += loopResult.tasksCompleted;
3955
+ lastOutputContract = loopResult.lastContract;
3956
+ for (const item of workItems) processedStories.add(item.key);
3957
+ if (loopResult.halted || state.phase === "max-iterations" || state.phase === "circuit-breaker") {
3958
+ halted = true;
3922
3959
  }
3960
+ continue;
3961
+ }
3962
+ const taskName = step;
3963
+ const task = config.workflow.tasks[taskName];
3964
+ if (!task) continue;
3965
+ if (task.agent === null) continue;
3966
+ const definition = config.agents[task.agent];
3967
+ if (!definition) continue;
3968
+ if (task.scope === "per-run" || task.scope === "per-epic") {
3969
+ if (isTaskCompleted(state, taskName, PER_RUN_SENTINEL)) continue;
3923
3970
  try {
3924
- const nullResult = await executeNullTask(
3925
- task,
3926
- taskName,
3927
- PER_RUN_SENTINEL,
3928
- state,
3929
- config,
3930
- lastOutputContract ?? void 0,
3931
- accumulatedCostUsd
3932
- );
3933
- state = nullResult.updatedState;
3934
- lastOutputContract = nullResult.contract;
3971
+ const dr = await dispatchTaskWithResult(task, taskName, PER_RUN_SENTINEL, definition, state, config, void 0, lastOutputContract ?? void 0);
3972
+ state = dr.updatedState;
3973
+ lastOutputContract = dr.contract;
3935
3974
  tasksCompleted++;
3936
3975
  } catch (err) {
3937
- const engineError = isEngineError(err) ? err : handleDispatchError(err, taskName, PER_RUN_SENTINEL);
3976
+ const engineError = handleDispatchError(err, taskName, PER_RUN_SENTINEL);
3938
3977
  errors.push(engineError);
3939
3978
  state = recordErrorInState(state, taskName, PER_RUN_SENTINEL, engineError);
3940
3979
  writeWorkflowState(state, projectDir);
3941
3980
  }
3942
3981
  } else {
3982
+ for (const item of workItems) {
3983
+ if (halted || config.abortSignal?.aborted) break;
3984
+ if (isTaskCompleted(state, taskName, item.key)) continue;
3985
+ try {
3986
+ const dr = await dispatchTaskWithResult(task, taskName, item.key, definition, state, config, void 0, lastOutputContract ?? void 0);
3987
+ state = dr.updatedState;
3988
+ lastOutputContract = dr.contract;
3989
+ tasksCompleted++;
3990
+ } catch (err) {
3991
+ const engineError = handleDispatchError(err, taskName, item.key);
3992
+ errors.push(engineError);
3993
+ state = recordErrorInState(state, taskName, item.key, engineError);
3994
+ writeWorkflowState(state, projectDir);
3995
+ }
3996
+ }
3997
+ }
3998
+ }
3999
+ }
4000
+ if (!config.storyPipeline)
4001
+ for (const step of config.workflow.storyFlow) {
4002
+ if (halted) break;
4003
+ if (config.abortSignal?.aborted) {
4004
+ info("Execution interrupted \u2014 saving state");
4005
+ state = { ...state, phase: "interrupted" };
4006
+ writeWorkflowState(state, projectDir);
4007
+ halted = true;
4008
+ break;
4009
+ }
4010
+ if (isLoopBlock(step)) {
4011
+ const loopResult = await executeLoopBlock(step, state, config, workItems, lastOutputContract);
4012
+ state = loopResult.state;
4013
+ errors.push(...loopResult.errors);
4014
+ tasksCompleted += loopResult.tasksCompleted;
4015
+ lastOutputContract = loopResult.lastContract;
3943
4016
  for (const item of workItems) {
3944
4017
  processedStories.add(item.key);
3945
- if (isTaskCompleted(state, taskName, item.key)) {
3946
- warn(`workflow-engine: skipping completed task ${taskName} for ${item.key}`);
4018
+ }
4019
+ if (loopResult.halted) {
4020
+ halted = true;
4021
+ }
4022
+ if (state.phase === "max-iterations" || state.phase === "circuit-breaker") {
4023
+ halted = true;
4024
+ }
4025
+ continue;
4026
+ }
4027
+ const taskName = step;
4028
+ const task = config.workflow.tasks[taskName];
4029
+ if (!task) {
4030
+ warn(`workflow-engine: task "${taskName}" not found in workflow tasks, skipping`);
4031
+ continue;
4032
+ }
4033
+ if (task.agent === null) {
4034
+ if (task.scope === "per-run") {
4035
+ if (isTaskCompleted(state, taskName, PER_RUN_SENTINEL)) {
4036
+ warn(`workflow-engine: skipping completed task ${taskName} for ${PER_RUN_SENTINEL}`);
3947
4037
  continue;
3948
4038
  }
3949
4039
  try {
3950
4040
  const nullResult = await executeNullTask(
3951
4041
  task,
3952
4042
  taskName,
3953
- item.key,
4043
+ PER_RUN_SENTINEL,
3954
4044
  state,
3955
4045
  config,
3956
4046
  lastOutputContract ?? void 0,
@@ -3960,71 +4050,56 @@ async function executeWorkflow(config) {
3960
4050
  lastOutputContract = nullResult.contract;
3961
4051
  tasksCompleted++;
3962
4052
  } catch (err) {
3963
- const engineError = isEngineError(err) ? err : handleDispatchError(err, taskName, item.key);
4053
+ const engineError = isEngineError(err) ? err : handleDispatchError(err, taskName, PER_RUN_SENTINEL);
3964
4054
  errors.push(engineError);
3965
- state = recordErrorInState(state, taskName, item.key, engineError);
4055
+ state = recordErrorInState(state, taskName, PER_RUN_SENTINEL, engineError);
3966
4056
  writeWorkflowState(state, projectDir);
3967
4057
  }
4058
+ } else {
4059
+ for (const item of workItems) {
4060
+ processedStories.add(item.key);
4061
+ if (isTaskCompleted(state, taskName, item.key)) {
4062
+ warn(`workflow-engine: skipping completed task ${taskName} for ${item.key}`);
4063
+ continue;
4064
+ }
4065
+ try {
4066
+ const nullResult = await executeNullTask(
4067
+ task,
4068
+ taskName,
4069
+ item.key,
4070
+ state,
4071
+ config,
4072
+ lastOutputContract ?? void 0,
4073
+ accumulatedCostUsd
4074
+ );
4075
+ state = nullResult.updatedState;
4076
+ lastOutputContract = nullResult.contract;
4077
+ tasksCompleted++;
4078
+ } catch (err) {
4079
+ const engineError = isEngineError(err) ? err : handleDispatchError(err, taskName, item.key);
4080
+ errors.push(engineError);
4081
+ state = recordErrorInState(state, taskName, item.key, engineError);
4082
+ writeWorkflowState(state, projectDir);
4083
+ }
4084
+ }
3968
4085
  }
3969
- }
3970
- continue;
3971
- }
3972
- const definition = config.agents[task.agent];
3973
- if (!definition) {
3974
- warn(`workflow-engine: agent "${task.agent}" not found for task "${taskName}", skipping`);
3975
- continue;
3976
- }
3977
- if (task.scope === "per-run") {
3978
- if (isTaskCompleted(state, taskName, PER_RUN_SENTINEL)) {
3979
- warn(`workflow-engine: skipping completed task ${taskName} for ${PER_RUN_SENTINEL}`);
3980
4086
  continue;
3981
4087
  }
3982
- try {
3983
- const dispatchResult = await dispatchTaskWithResult(
3984
- task,
3985
- taskName,
3986
- PER_RUN_SENTINEL,
3987
- definition,
3988
- state,
3989
- config,
3990
- void 0,
3991
- lastOutputContract ?? void 0
3992
- );
3993
- state = dispatchResult.updatedState;
3994
- lastOutputContract = dispatchResult.contract;
3995
- propagateVerifyFlags(taskName, dispatchResult.contract, projectDir);
3996
- accumulatedCostUsd += dispatchResult.contract?.cost_usd ?? 0;
3997
- tasksCompleted++;
3998
- } catch (err) {
3999
- const engineError = handleDispatchError(err, taskName, PER_RUN_SENTINEL);
4000
- errors.push(engineError);
4001
- if (config.onEvent) {
4002
- config.onEvent({ type: "dispatch-error", taskName, storyKey: PER_RUN_SENTINEL, error: { code: engineError.code, message: engineError.message } });
4003
- } else {
4004
- warn(`[${taskName}] ${PER_RUN_SENTINEL} \u2014 ERROR: [${engineError.code}] ${engineError.message}`);
4005
- }
4006
- state = recordErrorInState(state, taskName, PER_RUN_SENTINEL, engineError);
4007
- writeWorkflowState(state, projectDir);
4008
- if (err instanceof DispatchError && HALT_ERROR_CODES.has(err.code)) {
4009
- halted = true;
4010
- }
4088
+ const definition = config.agents[task.agent];
4089
+ if (!definition) {
4090
+ warn(`workflow-engine: agent "${task.agent}" not found for task "${taskName}", skipping`);
4091
+ continue;
4011
4092
  }
4012
- } else {
4013
- for (const item of workItems) {
4014
- if (config.abortSignal?.aborted) {
4015
- halted = true;
4016
- break;
4017
- }
4018
- processedStories.add(item.key);
4019
- if (isTaskCompleted(state, taskName, item.key)) {
4020
- warn(`workflow-engine: skipping completed task ${taskName} for ${item.key}`);
4093
+ if (task.scope === "per-run") {
4094
+ if (isTaskCompleted(state, taskName, PER_RUN_SENTINEL)) {
4095
+ warn(`workflow-engine: skipping completed task ${taskName} for ${PER_RUN_SENTINEL}`);
4021
4096
  continue;
4022
4097
  }
4023
4098
  try {
4024
4099
  const dispatchResult = await dispatchTaskWithResult(
4025
4100
  task,
4026
4101
  taskName,
4027
- item.key,
4102
+ PER_RUN_SENTINEL,
4028
4103
  definition,
4029
4104
  state,
4030
4105
  config,
@@ -4037,24 +4112,65 @@ async function executeWorkflow(config) {
4037
4112
  accumulatedCostUsd += dispatchResult.contract?.cost_usd ?? 0;
4038
4113
  tasksCompleted++;
4039
4114
  } catch (err) {
4040
- const engineError = handleDispatchError(err, taskName, item.key);
4115
+ const engineError = handleDispatchError(err, taskName, PER_RUN_SENTINEL);
4041
4116
  errors.push(engineError);
4042
4117
  if (config.onEvent) {
4043
- config.onEvent({ type: "dispatch-error", taskName, storyKey: item.key, error: { code: engineError.code, message: engineError.message } });
4118
+ config.onEvent({ type: "dispatch-error", taskName, storyKey: PER_RUN_SENTINEL, error: { code: engineError.code, message: engineError.message } });
4044
4119
  } else {
4045
- warn(`[${taskName}] ${item.key} \u2014 ERROR: [${engineError.code}] ${engineError.message}`);
4120
+ warn(`[${taskName}] ${PER_RUN_SENTINEL} \u2014 ERROR: [${engineError.code}] ${engineError.message}`);
4046
4121
  }
4047
- state = recordErrorInState(state, taskName, item.key, engineError);
4122
+ state = recordErrorInState(state, taskName, PER_RUN_SENTINEL, engineError);
4048
4123
  writeWorkflowState(state, projectDir);
4049
4124
  if (err instanceof DispatchError && HALT_ERROR_CODES.has(err.code)) {
4050
4125
  halted = true;
4126
+ }
4127
+ }
4128
+ } else {
4129
+ for (const item of workItems) {
4130
+ if (config.abortSignal?.aborted) {
4131
+ halted = true;
4051
4132
  break;
4052
4133
  }
4053
- continue;
4134
+ processedStories.add(item.key);
4135
+ if (isTaskCompleted(state, taskName, item.key)) {
4136
+ warn(`workflow-engine: skipping completed task ${taskName} for ${item.key}`);
4137
+ continue;
4138
+ }
4139
+ try {
4140
+ const dispatchResult = await dispatchTaskWithResult(
4141
+ task,
4142
+ taskName,
4143
+ item.key,
4144
+ definition,
4145
+ state,
4146
+ config,
4147
+ void 0,
4148
+ lastOutputContract ?? void 0
4149
+ );
4150
+ state = dispatchResult.updatedState;
4151
+ lastOutputContract = dispatchResult.contract;
4152
+ propagateVerifyFlags(taskName, dispatchResult.contract, projectDir);
4153
+ accumulatedCostUsd += dispatchResult.contract?.cost_usd ?? 0;
4154
+ tasksCompleted++;
4155
+ } catch (err) {
4156
+ const engineError = handleDispatchError(err, taskName, item.key);
4157
+ errors.push(engineError);
4158
+ if (config.onEvent) {
4159
+ config.onEvent({ type: "dispatch-error", taskName, storyKey: item.key, error: { code: engineError.code, message: engineError.message } });
4160
+ } else {
4161
+ warn(`[${taskName}] ${item.key} \u2014 ERROR: [${engineError.code}] ${engineError.message}`);
4162
+ }
4163
+ state = recordErrorInState(state, taskName, item.key, engineError);
4164
+ writeWorkflowState(state, projectDir);
4165
+ if (err instanceof DispatchError && HALT_ERROR_CODES.has(err.code)) {
4166
+ halted = true;
4167
+ break;
4168
+ }
4169
+ continue;
4170
+ }
4054
4171
  }
4055
4172
  }
4056
4173
  }
4057
- }
4058
4174
  if (state.phase === "interrupted") {
4059
4175
  } else if (errors.length === 0 && state.phase !== "max-iterations" && state.phase !== "circuit-breaker") {
4060
4176
  state = { ...state, phase: "completed" };
@@ -5430,14 +5546,17 @@ function LaneActivityHeader({ activeLaneId, laneCount }) {
5430
5546
  if (laneCount <= 1 || !activeLaneId) return null;
5431
5547
  return /* @__PURE__ */ jsx7(Text7, { children: /* @__PURE__ */ jsx7(Text7, { color: "cyan", children: `[Lane ${activeLaneId} \u25B8]` }) });
5432
5548
  }
5433
- function App({ state, onCycleLane }) {
5549
+ function App({ state, onCycleLane, onQuit }) {
5434
5550
  const lanes = state.lanes;
5435
5551
  const laneCount = lanes?.length ?? 0;
5436
5552
  const terminalWidth = process.stdout.columns || 80;
5437
- useInput((_input, key) => {
5438
- if (key.ctrl && _input === "l" && onCycleLane && laneCount > 1) {
5553
+ useInput((input, key) => {
5554
+ if (key.ctrl && input === "l" && onCycleLane && laneCount > 1) {
5439
5555
  onCycleLane();
5440
5556
  }
5557
+ if (input === "q" && onQuit) {
5558
+ onQuit();
5559
+ }
5441
5560
  }, { isActive: typeof process.stdin.setRawMode === "function" });
5442
5561
  const activeLaneCount = state.laneCount ?? 0;
5443
5562
  return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
@@ -5661,7 +5780,8 @@ function startRenderer(options) {
5661
5780
  let lastStoryKey = state.sprintInfo?.storyKey ?? null;
5662
5781
  const pendingStoryCosts = /* @__PURE__ */ new Map();
5663
5782
  let cleaned = false;
5664
- const inkInstance = inkRender(/* @__PURE__ */ jsx9(App, { state, onCycleLane: () => cycleLane() }), {
5783
+ const onQuit = options?.onQuit;
5784
+ const inkInstance = inkRender(/* @__PURE__ */ jsx9(App, { state, onCycleLane: () => cycleLane(), onQuit: onQuit ? () => onQuit() : void 0 }), {
5665
5785
  exitOnCtrlC: false,
5666
5786
  patchConsole: !options?._forceTTY,
5667
5787
  maxFps: 15
@@ -5669,7 +5789,7 @@ function startRenderer(options) {
5669
5789
  function rerender() {
5670
5790
  if (!cleaned) {
5671
5791
  state = { ...state };
5672
- inkInstance.rerender(/* @__PURE__ */ jsx9(App, { state, onCycleLane: () => cycleLane() }));
5792
+ inkInstance.rerender(/* @__PURE__ */ jsx9(App, { state, onCycleLane: () => cycleLane(), onQuit: onQuit ? () => onQuit() : void 0 }));
5673
5793
  }
5674
5794
  }
5675
5795
  const heartbeat = setInterval(() => {
@@ -6175,17 +6295,8 @@ function registerRunCommand(program) {
6175
6295
  }
6176
6296
  }
6177
6297
  const abortController = new AbortController();
6178
- const renderer = startRenderer({
6179
- quiet: !!options.quiet || isJson,
6180
- sprintState: {
6181
- storyKey: "",
6182
- phase: "executing",
6183
- done: counts.done,
6184
- total: counts.total,
6185
- totalCost: 0
6186
- }
6187
- });
6188
6298
  let interrupted = false;
6299
+ let renderer;
6189
6300
  const onInterrupt = () => {
6190
6301
  if (interrupted) {
6191
6302
  process.exit(1);
@@ -6195,6 +6306,17 @@ function registerRunCommand(program) {
6195
6306
  abortController.abort();
6196
6307
  info("Interrupted \u2014 waiting for current task to finish...", outputOpts);
6197
6308
  };
6309
+ renderer = startRenderer({
6310
+ quiet: !!options.quiet || isJson,
6311
+ sprintState: {
6312
+ storyKey: "",
6313
+ phase: "executing",
6314
+ done: counts.done,
6315
+ total: counts.total,
6316
+ totalCost: 0
6317
+ },
6318
+ onQuit: () => onInterrupt()
6319
+ });
6198
6320
  process.on("SIGINT", onInterrupt);
6199
6321
  process.on("SIGTERM", onInterrupt);
6200
6322
  const sessionStartMs = Date.now();
@@ -6286,6 +6408,7 @@ function registerRunCommand(program) {
6286
6408
  runId: `run-${Date.now()}`,
6287
6409
  projectDir,
6288
6410
  abortSignal: abortController.signal,
6411
+ storyPipeline: true,
6289
6412
  maxIterations,
6290
6413
  onEvent
6291
6414
  };
@@ -11167,7 +11290,7 @@ function registerTeardownCommand(program) {
11167
11290
  } else if (otlpMode === "remote-routed") {
11168
11291
  if (!options.keepDocker) {
11169
11292
  try {
11170
- const { stopCollectorOnly: stopCollectorOnly2 } = await import("./docker-PYH5XATT.js");
11293
+ const { stopCollectorOnly: stopCollectorOnly2 } = await import("./docker-7QONH2B5.js");
11171
11294
  stopCollectorOnly2();
11172
11295
  result.docker.stopped = true;
11173
11296
  if (!isJson) {
@@ -11199,7 +11322,7 @@ function registerTeardownCommand(program) {
11199
11322
  info("Shared stack: kept running (other projects may use it)");
11200
11323
  }
11201
11324
  } else if (isLegacyStack) {
11202
- const { isStackRunning: isStackRunning2, stopStack } = await import("./docker-PYH5XATT.js");
11325
+ const { isStackRunning: isStackRunning2, stopStack } = await import("./docker-7QONH2B5.js");
11203
11326
  let stackRunning = false;
11204
11327
  try {
11205
11328
  stackRunning = isStackRunning2(composeFile);
@@ -14095,7 +14218,7 @@ function registerDriversCommand(program) {
14095
14218
  }
14096
14219
 
14097
14220
  // src/index.ts
14098
- var VERSION = true ? "0.29.4" : "0.0.0-dev";
14221
+ var VERSION = true ? "0.30.0" : "0.0.0-dev";
14099
14222
  function createProgram() {
14100
14223
  const program = new Command();
14101
14224
  program.name("codeharness").description("Makes autonomous coding agents produce software that actually works").version(VERSION).option("--json", "Output in machine-readable JSON format");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeharness",
3
- "version": "0.29.4",
3
+ "version": "0.30.0",
4
4
  "type": "module",
5
5
  "description": "CLI for codeharness — makes autonomous coding agents produce software that actually works",
6
6
  "bin": {