codeharness 0.28.2 → 0.29.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.28.2" : "0.0.0-dev";
2898
+ var HARNESS_VERSION = true ? "0.29.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-WGRLLVWV.js";
19
+ } from "./chunk-PTHST5Z7.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-WGRLLVWV.js";
43
+ } from "./chunk-PTHST5Z7.js";
44
44
 
45
45
  // src/index.ts
46
46
  import { Command } from "commander";
@@ -1879,31 +1879,6 @@ function getDriver(name) {
1879
1879
  function listDrivers() {
1880
1880
  return [...registry.keys()];
1881
1881
  }
1882
- function suggestCheaperDriver(driverName, requiredCaps) {
1883
- const current = registry.get(driverName);
1884
- if (!current) return null;
1885
- let cheapestName = null;
1886
- let cheapestTier = Infinity;
1887
- for (const [name, driver] of registry) {
1888
- let satisfies = true;
1889
- for (const [key, value] of Object.entries(requiredCaps)) {
1890
- if (typeof value === "boolean" && value === true) {
1891
- if (!driver.capabilities[key]) {
1892
- satisfies = false;
1893
- break;
1894
- }
1895
- }
1896
- }
1897
- if (satisfies && driver.capabilities.costTier < cheapestTier) {
1898
- cheapestTier = driver.capabilities.costTier;
1899
- cheapestName = name;
1900
- }
1901
- }
1902
- if (cheapestName && cheapestTier < current.capabilities.costTier) {
1903
- return cheapestName;
1904
- }
1905
- return null;
1906
- }
1907
1882
 
1908
1883
  // src/lib/agent-resolver.ts
1909
1884
  import { readFileSync as readFileSync8, existsSync as existsSync9, readdirSync as readdirSync2 } from "fs";
@@ -2542,21 +2517,6 @@ function checkCapabilityConflicts(workflow) {
2542
2517
  message: `Task "${taskName}" requires plugins but driver "${driverName}" does not support plugins (supportsPlugins: false)`
2543
2518
  });
2544
2519
  }
2545
- const requiredCaps = {
2546
- ...hasPlugins ? { supportsPlugins: true } : {}
2547
- };
2548
- const cheaper = suggestCheaperDriver(driverName, requiredCaps);
2549
- if (cheaper) {
2550
- const cheaperDriver = getDriver(cheaper);
2551
- if (driver.capabilities.costTier > 2 * cheaperDriver.capabilities.costTier) {
2552
- warnings.push({
2553
- taskName,
2554
- driverName,
2555
- capability: "costTier",
2556
- message: `Advisory: task "${taskName}" uses ${driverName} \u2014 ${cheaper} could handle this task at lower cost`
2557
- });
2558
- }
2559
- }
2560
2520
  }
2561
2521
  return warnings;
2562
2522
  }
@@ -3397,6 +3357,7 @@ ${coverageDedup}`;
3397
3357
  ...task.plugins ?? definition.plugins ? { plugins: task.plugins ?? definition.plugins } : {},
3398
3358
  ...task.max_budget_usd != null ? { timeout: task.max_budget_usd } : {}
3399
3359
  };
3360
+ info(`[${taskName}] ${storyKey} \u2014 dispatching via ${driverName} (model: ${model})`);
3400
3361
  let output = "";
3401
3362
  let resultSessionId = "";
3402
3363
  let cost = 0;
@@ -3866,6 +3827,10 @@ async function executeWorkflow(config) {
3866
3827
  durationMs: 0
3867
3828
  };
3868
3829
  }
3830
+ if (state.phase === "error" || state.phase === "failed") {
3831
+ const errorCount = state.tasks_completed.filter((t) => t.error).length;
3832
+ info(`Resuming from ${state.phase} state \u2014 ${errorCount} previous error(s), retrying failed tasks`);
3833
+ }
3869
3834
  state = {
3870
3835
  ...state,
3871
3836
  phase: "executing",
@@ -4072,7 +4037,9 @@ function recordErrorInState(state, taskName, storyKey, error) {
4072
4037
  task_name: taskName,
4073
4038
  story_key: storyKey,
4074
4039
  completed_at: (/* @__PURE__ */ new Date()).toISOString(),
4075
- error: true
4040
+ error: true,
4041
+ error_message: error.message,
4042
+ error_code: error.code
4076
4043
  };
4077
4044
  return {
4078
4045
  ...state,
@@ -9907,7 +9874,7 @@ function registerTeardownCommand(program) {
9907
9874
  } else if (otlpMode === "remote-routed") {
9908
9875
  if (!options.keepDocker) {
9909
9876
  try {
9910
- const { stopCollectorOnly: stopCollectorOnly2 } = await import("./docker-77PSA3RN.js");
9877
+ const { stopCollectorOnly: stopCollectorOnly2 } = await import("./docker-32GRDQOK.js");
9911
9878
  stopCollectorOnly2();
9912
9879
  result.docker.stopped = true;
9913
9880
  if (!isJson) {
@@ -9939,7 +9906,7 @@ function registerTeardownCommand(program) {
9939
9906
  info("Shared stack: kept running (other projects may use it)");
9940
9907
  }
9941
9908
  } else if (isLegacyStack) {
9942
- const { isStackRunning: isStackRunning2, stopStack } = await import("./docker-77PSA3RN.js");
9909
+ const { isStackRunning: isStackRunning2, stopStack } = await import("./docker-32GRDQOK.js");
9943
9910
  let stackRunning = false;
9944
9911
  try {
9945
9912
  stackRunning = isStackRunning2(composeFile);
@@ -12817,7 +12784,7 @@ function registerDriversCommand(program) {
12817
12784
  }
12818
12785
 
12819
12786
  // src/index.ts
12820
- var VERSION = true ? "0.28.2" : "0.0.0-dev";
12787
+ var VERSION = true ? "0.29.0" : "0.0.0-dev";
12821
12788
  function createProgram() {
12822
12789
  const program = new Command();
12823
12790
  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.28.2",
3
+ "version": "0.29.0",
4
4
  "type": "module",
5
5
  "description": "CLI for codeharness — makes autonomous coding agents produce software that actually works",
6
6
  "bin": {
@@ -0,0 +1,53 @@
1
+ name: story-creator
2
+ role:
3
+ title: Story Creator
4
+ purpose: Create implementation-ready story files from epic specifications with clear ACs, task breakdowns, and dev notes
5
+ persona:
6
+ identity: |
7
+ Technical scrum master who creates detailed, unambiguous story specs.
8
+ Reads epic definitions, architecture docs, and existing code to produce
9
+ stories that a developer agent can execute without clarification.
10
+ communication_style: "Precise, structured. Every AC is testable. Every task maps to an AC. No ambiguity."
11
+ principles:
12
+ - Every acceptance criterion must be independently verifiable
13
+ - Tasks must be ordered by dependency — no circular references
14
+ - Dev notes must cite specific files, modules, and patterns from the codebase
15
+ - Story scope must match the epic definition exactly — no scope creep, no missing requirements
16
+ - Reference architecture decisions and constraints that affect implementation
17
+ prompt_template: |
18
+ ## Role
19
+
20
+ You are creating an implementation-ready story file. The developer agent will execute this story without asking questions — every detail must be explicit.
21
+
22
+ ## Input
23
+
24
+ 1. Read the sprint plan / epic definitions to find the next story to create
25
+ 2. Read architecture docs for technical constraints
26
+ 3. Read the existing codebase to understand current patterns, naming conventions, and module structure
27
+ 4. Read any previous story files in this epic for consistency
28
+
29
+ ## Story Creation Process
30
+
31
+ 1. **Identify the story** from the sprint plan — find the next unwritten story
32
+ 2. **Read all referenced source material** — PRD sections, architecture decisions, UX specs cited in the epic
33
+ 3. **Scan the codebase** — understand existing patterns, file structure, test conventions
34
+ 4. **Write the story file** using the project's story template
35
+
36
+ ## Story Quality Requirements
37
+
38
+ - **Acceptance Criteria**: Each AC must be a concrete, testable condition. Use Given/When/Then or equivalent. Number them sequentially.
39
+ - **Tasks/Subtasks**: Ordered implementation steps. Each task references which AC(s) it satisfies. Include test-writing tasks.
40
+ - **Dev Notes**: Cite specific files to modify, patterns to follow, architecture constraints. Include file paths.
41
+ - **Testing Requirements**: Specify what to test, expected coverage, test file locations.
42
+
43
+ ## Anti-Patterns to Avoid
44
+
45
+ - Vague ACs like "system should handle errors gracefully" — specify WHICH errors and HOW
46
+ - Tasks without AC mapping — every task must trace to at least one AC
47
+ - Missing edge cases — think about failure modes, not just happy path
48
+ - Ignoring existing code patterns — the dev agent must follow established conventions
49
+
50
+ ## Output
51
+
52
+ Write the story file to the implementation artifacts directory following the project's naming convention.
53
+ Mark the story as `ready-for-dev` in the sprint status.
@@ -1,4 +1,10 @@
1
1
  tasks:
2
+ create-story:
3
+ agent: story-creator
4
+ scope: per-story
5
+ session: fresh
6
+ source_access: true
7
+ model: claude-opus-4-6-20250514
2
8
  implement:
3
9
  agent: dev
4
10
  scope: per-story
@@ -31,6 +37,7 @@ tasks:
31
37
  model: claude-opus-4-6-20250514
32
38
 
33
39
  flow:
40
+ - create-story
34
41
  - implement
35
42
  - review
36
43
  - verify