codeharness 0.11.0 → 0.12.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.
Files changed (2) hide show
  1. package/dist/index.js +84 -18
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1348,7 +1348,7 @@ function importStoriesToBeads(stories, opts, beadsFns) {
1348
1348
  }
1349
1349
 
1350
1350
  // src/commands/init.ts
1351
- var HARNESS_VERSION = true ? "0.11.0" : "0.0.0-dev";
1351
+ var HARNESS_VERSION = true ? "0.12.0" : "0.0.0-dev";
1352
1352
  function getStackLabel(stack) {
1353
1353
  if (stack === "nodejs") return "Node.js (package.json)";
1354
1354
  if (stack === "python") return "Python";
@@ -2596,6 +2596,32 @@ var INTEGRATION_KEYWORDS = [
2596
2596
  "integration test",
2597
2597
  "manual verification"
2598
2598
  ];
2599
+ var DOCKER_SESSION_KEYWORDS = [
2600
+ "agent tool",
2601
+ "subagent",
2602
+ "via agent",
2603
+ "invoke",
2604
+ "/create-story",
2605
+ "/bmad-dev-story",
2606
+ "/bmad-code-review",
2607
+ "/harness-run",
2608
+ "/retrospective",
2609
+ "sprint execution",
2610
+ "fresh context",
2611
+ "spawns",
2612
+ "code review workflow",
2613
+ "dev-story workflow",
2614
+ "automatically proceeds",
2615
+ "retries the current story",
2616
+ "halts with status",
2617
+ "prints summary"
2618
+ ];
2619
+ var ESCALATE_KEYWORDS = [
2620
+ "physical hardware",
2621
+ "manual human",
2622
+ "visual inspection by human",
2623
+ "paid external service"
2624
+ ];
2599
2625
  function classifyVerifiability(description) {
2600
2626
  const lower = description.toLowerCase();
2601
2627
  for (const kw of INTEGRATION_KEYWORDS) {
@@ -2603,6 +2629,19 @@ function classifyVerifiability(description) {
2603
2629
  }
2604
2630
  return "cli-verifiable";
2605
2631
  }
2632
+ function classifyStrategy(description) {
2633
+ const lower = description.toLowerCase();
2634
+ for (const kw of ESCALATE_KEYWORDS) {
2635
+ if (lower.includes(kw)) return "escalate";
2636
+ }
2637
+ for (const kw of DOCKER_SESSION_KEYWORDS) {
2638
+ if (lower.includes(kw)) return "docker-session";
2639
+ }
2640
+ for (const kw of INTEGRATION_KEYWORDS) {
2641
+ if (lower.includes(kw)) return "docker-session";
2642
+ }
2643
+ return "cli-direct";
2644
+ }
2606
2645
  var VERIFICATION_TAG_PATTERN = /<!--\s*verification:\s*(cli-verifiable|integration-required)\s*-->/;
2607
2646
  function parseVerificationTag(text) {
2608
2647
  const match = VERIFICATION_TAG_PATTERN.exec(text);
@@ -2659,11 +2698,13 @@ function parseStoryACs(storyFilePath) {
2659
2698
  if (description) {
2660
2699
  const tag = parseVerificationTag(description);
2661
2700
  const verifiability = tag ?? classifyVerifiability(description);
2701
+ const strategy = classifyStrategy(description);
2662
2702
  acs.push({
2663
2703
  id: currentId,
2664
2704
  description,
2665
2705
  type: classifyAC(description),
2666
- verifiability
2706
+ verifiability,
2707
+ strategy
2667
2708
  });
2668
2709
  } else {
2669
2710
  warn(`Skipping malformed AC #${currentId}: empty description`);
@@ -3300,25 +3341,50 @@ function validateProofQuality(proofPath) {
3300
3341
  const content = readFileSync10(proofPath, "utf-8");
3301
3342
  const acHeaderPattern = /^## AC ?(\d+):/gm;
3302
3343
  const matches = [...content.matchAll(acHeaderPattern)];
3303
- if (matches.length === 0) {
3304
- return { verified: 0, pending: 0, escalated: 0, total: 0, passed: false };
3305
- }
3306
3344
  let verified = 0;
3307
3345
  let pending = 0;
3308
3346
  let escalated = 0;
3309
- for (let i = 0; i < matches.length; i++) {
3310
- const start = matches[i].index;
3311
- const end = i + 1 < matches.length ? matches[i + 1].index : content.length;
3312
- const section = content.slice(start, end);
3313
- if (section.includes("[ESCALATE]")) {
3314
- escalated++;
3315
- continue;
3347
+ if (matches.length > 0) {
3348
+ for (let i = 0; i < matches.length; i++) {
3349
+ const start = matches[i].index;
3350
+ const end = i + 1 < matches.length ? matches[i + 1].index : content.length;
3351
+ const section = content.slice(start, end);
3352
+ if (section.includes("[ESCALATE]")) {
3353
+ escalated++;
3354
+ continue;
3355
+ }
3356
+ const hasEvidence = section.includes("<!-- /showboat exec -->") || section.includes("<!-- showboat image:") || /```(?:bash|shell)\n[\s\S]*?```\n+```output\n/m.test(section);
3357
+ if (hasEvidence) {
3358
+ verified++;
3359
+ } else {
3360
+ pending++;
3361
+ }
3316
3362
  }
3317
- const hasEvidence = section.includes("<!-- /showboat exec -->") || section.includes("<!-- showboat image:") || /```(?:bash|shell)\n[\s\S]*?```\n+```output\n/m.test(section);
3318
- if (hasEvidence) {
3319
- verified++;
3320
- } else {
3321
- pending++;
3363
+ } else {
3364
+ const inlineAcPattern = /--- AC ?(\d+):/g;
3365
+ const inlineMatches = [...content.matchAll(inlineAcPattern)];
3366
+ const acNumbers = new Set(inlineMatches.map((m) => m[1]));
3367
+ if (acNumbers.size === 0) {
3368
+ return { verified: 0, pending: 0, escalated: 0, total: 0, passed: false };
3369
+ }
3370
+ for (const acNum of acNumbers) {
3371
+ const acPattern = new RegExp(`--- AC ?${acNum}:`, "g");
3372
+ const acIdx = content.search(acPattern);
3373
+ if (acIdx === -1) {
3374
+ pending++;
3375
+ continue;
3376
+ }
3377
+ const nextAcPattern = new RegExp(`--- AC ?(?!${acNum})\\d+:`, "g");
3378
+ nextAcPattern.lastIndex = acIdx + 1;
3379
+ const nextMatch = nextAcPattern.exec(content);
3380
+ const section = content.slice(acIdx, nextMatch ? nextMatch.index : content.length);
3381
+ if (section.includes("[ESCALATE]")) {
3382
+ escalated++;
3383
+ } else if (/```output\n/m.test(section)) {
3384
+ verified++;
3385
+ } else {
3386
+ pending++;
3387
+ }
3322
3388
  }
3323
3389
  }
3324
3390
  const total = verified + pending + escalated;
@@ -6787,7 +6853,7 @@ function registerGithubImportCommand(program) {
6787
6853
  }
6788
6854
 
6789
6855
  // src/index.ts
6790
- var VERSION = true ? "0.11.0" : "0.0.0-dev";
6856
+ var VERSION = true ? "0.12.0" : "0.0.0-dev";
6791
6857
  function createProgram() {
6792
6858
  const program = new Command();
6793
6859
  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.11.0",
3
+ "version": "0.12.0",
4
4
  "type": "module",
5
5
  "description": "CLI for codeharness — makes autonomous coding agents produce software that actually works",
6
6
  "bin": {