codeharness 0.11.0 → 0.12.1

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 +58 -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.1" : "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,12 @@ var INTEGRATION_KEYWORDS = [
2596
2596
  "integration test",
2597
2597
  "manual verification"
2598
2598
  ];
2599
+ var ESCALATE_KEYWORDS = [
2600
+ "physical hardware",
2601
+ "manual human",
2602
+ "visual inspection by human",
2603
+ "paid external service"
2604
+ ];
2599
2605
  function classifyVerifiability(description) {
2600
2606
  const lower = description.toLowerCase();
2601
2607
  for (const kw of INTEGRATION_KEYWORDS) {
@@ -2603,6 +2609,13 @@ function classifyVerifiability(description) {
2603
2609
  }
2604
2610
  return "cli-verifiable";
2605
2611
  }
2612
+ function classifyStrategy(description) {
2613
+ const lower = description.toLowerCase();
2614
+ for (const kw of ESCALATE_KEYWORDS) {
2615
+ if (lower.includes(kw)) return "escalate";
2616
+ }
2617
+ return "docker";
2618
+ }
2606
2619
  var VERIFICATION_TAG_PATTERN = /<!--\s*verification:\s*(cli-verifiable|integration-required)\s*-->/;
2607
2620
  function parseVerificationTag(text) {
2608
2621
  const match = VERIFICATION_TAG_PATTERN.exec(text);
@@ -2659,11 +2672,13 @@ function parseStoryACs(storyFilePath) {
2659
2672
  if (description) {
2660
2673
  const tag = parseVerificationTag(description);
2661
2674
  const verifiability = tag ?? classifyVerifiability(description);
2675
+ const strategy = classifyStrategy(description);
2662
2676
  acs.push({
2663
2677
  id: currentId,
2664
2678
  description,
2665
2679
  type: classifyAC(description),
2666
- verifiability
2680
+ verifiability,
2681
+ strategy
2667
2682
  });
2668
2683
  } else {
2669
2684
  warn(`Skipping malformed AC #${currentId}: empty description`);
@@ -3300,25 +3315,50 @@ function validateProofQuality(proofPath) {
3300
3315
  const content = readFileSync10(proofPath, "utf-8");
3301
3316
  const acHeaderPattern = /^## AC ?(\d+):/gm;
3302
3317
  const matches = [...content.matchAll(acHeaderPattern)];
3303
- if (matches.length === 0) {
3304
- return { verified: 0, pending: 0, escalated: 0, total: 0, passed: false };
3305
- }
3306
3318
  let verified = 0;
3307
3319
  let pending = 0;
3308
3320
  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;
3321
+ if (matches.length > 0) {
3322
+ for (let i = 0; i < matches.length; i++) {
3323
+ const start = matches[i].index;
3324
+ const end = i + 1 < matches.length ? matches[i + 1].index : content.length;
3325
+ const section = content.slice(start, end);
3326
+ if (section.includes("[ESCALATE]")) {
3327
+ escalated++;
3328
+ continue;
3329
+ }
3330
+ const hasEvidence = section.includes("<!-- /showboat exec -->") || section.includes("<!-- showboat image:") || /```(?:bash|shell)\n[\s\S]*?```\n+```output\n/m.test(section);
3331
+ if (hasEvidence) {
3332
+ verified++;
3333
+ } else {
3334
+ pending++;
3335
+ }
3316
3336
  }
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++;
3337
+ } else {
3338
+ const inlineAcPattern = /--- AC ?(\d+):/g;
3339
+ const inlineMatches = [...content.matchAll(inlineAcPattern)];
3340
+ const acNumbers = new Set(inlineMatches.map((m) => m[1]));
3341
+ if (acNumbers.size === 0) {
3342
+ return { verified: 0, pending: 0, escalated: 0, total: 0, passed: false };
3343
+ }
3344
+ for (const acNum of acNumbers) {
3345
+ const acPattern = new RegExp(`--- AC ?${acNum}:`, "g");
3346
+ const acIdx = content.search(acPattern);
3347
+ if (acIdx === -1) {
3348
+ pending++;
3349
+ continue;
3350
+ }
3351
+ const nextAcPattern = new RegExp(`--- AC ?(?!${acNum})\\d+:`, "g");
3352
+ nextAcPattern.lastIndex = acIdx + 1;
3353
+ const nextMatch = nextAcPattern.exec(content);
3354
+ const section = content.slice(acIdx, nextMatch ? nextMatch.index : content.length);
3355
+ if (section.includes("[ESCALATE]")) {
3356
+ escalated++;
3357
+ } else if (/```output\n/m.test(section)) {
3358
+ verified++;
3359
+ } else {
3360
+ pending++;
3361
+ }
3322
3362
  }
3323
3363
  }
3324
3364
  const total = verified + pending + escalated;
@@ -6787,7 +6827,7 @@ function registerGithubImportCommand(program) {
6787
6827
  }
6788
6828
 
6789
6829
  // src/index.ts
6790
- var VERSION = true ? "0.11.0" : "0.0.0-dev";
6830
+ var VERSION = true ? "0.12.1" : "0.0.0-dev";
6791
6831
  function createProgram() {
6792
6832
  const program = new Command();
6793
6833
  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.1",
4
4
  "type": "module",
5
5
  "description": "CLI for codeharness — makes autonomous coding agents produce software that actually works",
6
6
  "bin": {