strikethroo 3.17.0 → 3.17.2

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 (61) hide show
  1. package/dist-web/assets/{arc-CtIXTnp-.js → arc-C3L1jkFY.js} +1 -1
  2. package/dist-web/assets/{architectureDiagram-3BPJPVTR-DjLBuYL_.js → architectureDiagram-3BPJPVTR-Dc5wdWPF.js} +1 -1
  3. package/dist-web/assets/{blockDiagram-GPEHLZMM-CyUvqZi1.js → blockDiagram-GPEHLZMM-BCqaESV7.js} +1 -1
  4. package/dist-web/assets/{c4Diagram-AAUBKEIU-DbT3qzdM.js → c4Diagram-AAUBKEIU-DNecSAwM.js} +1 -1
  5. package/dist-web/assets/channel-DmY2Krrw.js +1 -0
  6. package/dist-web/assets/{chunk-2J33WTMH-w1zteFnE.js → chunk-2J33WTMH-3QS28848.js} +1 -1
  7. package/dist-web/assets/{chunk-4BX2VUAB-AXaQBlkr.js → chunk-4BX2VUAB-B6R-x-SN.js} +1 -1
  8. package/dist-web/assets/{chunk-55IACEB6-YxIJIoS8.js → chunk-55IACEB6-BYY5vsbu.js} +1 -1
  9. package/dist-web/assets/{chunk-727SXJPM-Ec_YNRXy.js → chunk-727SXJPM-BZxIJIkN.js} +1 -1
  10. package/dist-web/assets/{chunk-AQP2D5EJ-Bq3XSb33.js → chunk-AQP2D5EJ-Dwpt8x10.js} +1 -1
  11. package/dist-web/assets/{chunk-FMBD7UC4-D3hDHEbQ.js → chunk-FMBD7UC4-BkIlqLqc.js} +1 -1
  12. package/dist-web/assets/{chunk-ND2GUHAM-D7qdmfIe.js → chunk-ND2GUHAM-BZAfIvWk.js} +1 -1
  13. package/dist-web/assets/{chunk-QZHKN3VN-CnaHYcq_.js → chunk-QZHKN3VN-wAp9ruCQ.js} +1 -1
  14. package/dist-web/assets/classDiagram-4FO5ZUOK-C91aiCZF.js +1 -0
  15. package/dist-web/assets/classDiagram-v2-Q7XG4LA2-C91aiCZF.js +1 -0
  16. package/dist-web/assets/{cose-bilkent-S5V4N54A-B-C7BPM4.js → cose-bilkent-S5V4N54A-BWhls-Li.js} +1 -1
  17. package/dist-web/assets/{dagre-BM42HDAG-Ce21GDpz.js → dagre-BM42HDAG-D_rm5H8p.js} +1 -1
  18. package/dist-web/assets/{diagram-2AECGRRQ-DHwtwYvI.js → diagram-2AECGRRQ-CgrRz62Y.js} +1 -1
  19. package/dist-web/assets/{diagram-5GNKFQAL-Cz3oNPoV.js → diagram-5GNKFQAL-BRdPFx5y.js} +1 -1
  20. package/dist-web/assets/{diagram-KO2AKTUF-DvTrw4fW.js → diagram-KO2AKTUF-CRkShN2W.js} +1 -1
  21. package/dist-web/assets/{diagram-LMA3HP47-BkoqJsup.js → diagram-LMA3HP47-Bxah1b5X.js} +1 -1
  22. package/dist-web/assets/{diagram-OG6HWLK6-D-g29Bkd.js → diagram-OG6HWLK6-D9gsqeVI.js} +1 -1
  23. package/dist-web/assets/{erDiagram-TEJ5UH35-CTjmf6Xm.js → erDiagram-TEJ5UH35-BxuqpCGH.js} +1 -1
  24. package/dist-web/assets/{flowDiagram-I6XJVG4X-Bw77m94u.js → flowDiagram-I6XJVG4X-CVc346ab.js} +1 -1
  25. package/dist-web/assets/{ganttDiagram-6RSMTGT7-gzA4FOSg.js → ganttDiagram-6RSMTGT7-CoV2q8mu.js} +1 -1
  26. package/dist-web/assets/{gitGraphDiagram-PVQCEYII-BRaUUXaJ.js → gitGraphDiagram-PVQCEYII-DpBtbvUQ.js} +1 -1
  27. package/dist-web/assets/{index-YT2EMDff.js → index-B5AkN942.js} +4 -4
  28. package/dist-web/assets/{index-DJpZGE86.js → index-DXAUzXLU.js} +1 -1
  29. package/dist-web/assets/{index-B_YjLzSw.js → index-qiGGVGhU.js} +1 -1
  30. package/dist-web/assets/{infoDiagram-5YYISTIA-h6n8eqGu.js → infoDiagram-5YYISTIA-Cs1LaltR.js} +1 -1
  31. package/dist-web/assets/{ishikawaDiagram-YF4QCWOH-BiJ3tbak.js → ishikawaDiagram-YF4QCWOH-2dwQITAJ.js} +1 -1
  32. package/dist-web/assets/{journeyDiagram-JHISSGLW-Q31kk_hH.js → journeyDiagram-JHISSGLW-C5NXwRcO.js} +1 -1
  33. package/dist-web/assets/{kanban-definition-UN3LZRKU-ZV5ks__v.js → kanban-definition-UN3LZRKU-D8L4UiFp.js} +1 -1
  34. package/dist-web/assets/{linear-F-j1CAaU.js → linear-BmwJXk2t.js} +1 -1
  35. package/dist-web/assets/{mermaid.core-C6KsMc78.js → mermaid.core-CxfmFJso.js} +4 -4
  36. package/dist-web/assets/{mindmap-definition-RKZ34NQL-D-qRccYa.js → mindmap-definition-RKZ34NQL-CCk10yMr.js} +1 -1
  37. package/dist-web/assets/{pieDiagram-4H26LBE5-y1b8Tbaa.js → pieDiagram-4H26LBE5-CNaROrHh.js} +1 -1
  38. package/dist-web/assets/{quadrantDiagram-W4KKPZXB-BMoept3P.js → quadrantDiagram-W4KKPZXB-C9eBwT_4.js} +1 -1
  39. package/dist-web/assets/{requirementDiagram-4Y6WPE33-BL-2jNsJ.js → requirementDiagram-4Y6WPE33-CuWFUe-Z.js} +1 -1
  40. package/dist-web/assets/{sankeyDiagram-5OEKKPKP-dfD7Fow2.js → sankeyDiagram-5OEKKPKP-xGYYGBDj.js} +1 -1
  41. package/dist-web/assets/{sequenceDiagram-3UESZ5HK-DEkvMHGP.js → sequenceDiagram-3UESZ5HK-Corn4mP3.js} +1 -1
  42. package/dist-web/assets/{stateDiagram-AJRCARHV-4t9PvMom.js → stateDiagram-AJRCARHV-DP1EwgDv.js} +1 -1
  43. package/dist-web/assets/stateDiagram-v2-BHNVJYJU-DQIao4rH.js +1 -0
  44. package/dist-web/assets/{timeline-definition-PNZ67QCA-V1D7tV43.js → timeline-definition-PNZ67QCA-DgVY9v5q.js} +1 -1
  45. package/dist-web/assets/{vennDiagram-CIIHVFJN-Tw5zLG0T.js → vennDiagram-CIIHVFJN-B47n0Ab2.js} +1 -1
  46. package/dist-web/assets/{wardley-L42UT6IY-CrYt_lTh.js → wardley-L42UT6IY-ubK4o7Fl.js} +1 -1
  47. package/dist-web/assets/{wardleyDiagram-YWT4CUSO-CDe_cIHY.js → wardleyDiagram-YWT4CUSO-ChirN_61.js} +1 -1
  48. package/dist-web/assets/{xychartDiagram-2RQKCTM6-DNoNd0tl.js → xychartDiagram-2RQKCTM6-Cf8q2_P7.js} +1 -1
  49. package/dist-web/index.html +1 -1
  50. package/package.json +1 -1
  51. package/templates/harness/skills/st-code-review/SKILL.md +22 -7
  52. package/templates/harness/skills/st-code-review/scripts/code-review.cjs +131 -16
  53. package/templates/harness/skills/st-execute-blueprint/SKILL.md +1 -1
  54. package/templates/harness/skills/st-execute-blueprint/scripts/dispatch-task-execution.cjs +36 -8
  55. package/templates/harness/skills/st-execute-task/scripts/dispatch-task-execution.cjs +36 -8
  56. package/templates/harness/skills/st-full-workflow/SKILL.md +1 -1
  57. package/templates/harness/skills/st-full-workflow/scripts/dispatch-task-execution.cjs +36 -8
  58. package/dist-web/assets/channel-ejrFqLJP.js +0 -1
  59. package/dist-web/assets/classDiagram-4FO5ZUOK-D4kGOS-J.js +0 -1
  60. package/dist-web/assets/classDiagram-v2-Q7XG4LA2-D4kGOS-J.js +0 -1
  61. package/dist-web/assets/stateDiagram-v2-BHNVJYJU-5xE8WrG_.js +0 -1
@@ -37,6 +37,8 @@ __export(code_review_exports, {
37
37
  MAX_REVIEW_ROUNDS: () => MAX_REVIEW_ROUNDS,
38
38
  _decideRound: () => _decideRound,
39
39
  _exitCodeFor: () => _exitCodeFor,
40
+ _extractReviewDocument: () => _extractReviewDocument,
41
+ _makeDeliveryToken: () => _makeDeliveryToken,
40
42
  _readBaseCommit: () => _readBaseCommit,
41
43
  _readCumulativeDiff: () => _readCumulativeDiff,
42
44
  _readPriorAdjudicated: () => _readPriorAdjudicated,
@@ -48,6 +50,7 @@ __export(code_review_exports, {
48
50
  runReviewRound: () => runReviewRound
49
51
  });
50
52
  module.exports = __toCommonJS(code_review_exports);
53
+ var crypto = __toESM(require("crypto"));
51
54
  var fs6 = __toESM(require("fs"));
52
55
  var path6 = __toESM(require("path"));
53
56
 
@@ -382,7 +385,13 @@ var executableOnPath = (executable) => (process.env.PATH ?? "").split(path4.deli
382
385
  return false;
383
386
  }
384
387
  });
385
- var runProcess = (executable, argv, cwd, stdin, inheritOutput = false) => new Promise((resolve3, reject) => {
388
+ var CAPTURED_STDOUT_LIMIT = 262144;
389
+ var STDIO_SLOTS = {
390
+ ignore: { stdout: "ignore" },
391
+ inherit: { stdout: "inherit" },
392
+ capture: { stdout: "pipe" }
393
+ };
394
+ var runProcess = (executable, argv, cwd, stdin, outputMode = "ignore") => new Promise((resolve3, reject) => {
386
395
  let settled = false;
387
396
  const fail = (error) => {
388
397
  if (settled) return;
@@ -394,15 +403,30 @@ var runProcess = (executable, argv, cwd, stdin, inheritOutput = false) => new Pr
394
403
  shell: false,
395
404
  stdio: [
396
405
  stdin === void 0 ? "ignore" : "pipe",
397
- inheritOutput ? "inherit" : "ignore",
398
- inheritOutput ? "inherit" : "ignore"
406
+ STDIO_SLOTS[outputMode].stdout,
407
+ outputMode === "ignore" ? "ignore" : "inherit"
399
408
  ]
400
409
  });
410
+ let captured = "";
411
+ if (outputMode === "capture") {
412
+ child.stdout.setEncoding("utf8");
413
+ child.stdout.once("error", fail);
414
+ child.stdout.on("data", (chunk) => {
415
+ process.stderr.write(chunk);
416
+ captured += chunk;
417
+ if (captured.length > CAPTURED_STDOUT_LIMIT) {
418
+ captured = captured.slice(captured.length - CAPTURED_STDOUT_LIMIT);
419
+ }
420
+ });
421
+ }
401
422
  child.once("error", fail);
402
423
  child.once("close", (code) => {
403
424
  if (settled) return;
404
425
  settled = true;
405
- resolve3({ exitCode: code ?? 1 });
426
+ resolve3({
427
+ exitCode: code ?? 1,
428
+ ...outputMode === "capture" ? { stdout: captured } : {}
429
+ });
406
430
  });
407
431
  if (stdin !== void 0) {
408
432
  child.stdin.once("error", fail);
@@ -430,7 +454,13 @@ var dependencies = {
430
454
  };
431
455
  }
432
456
  },
433
- launch: (commandSpec) => runProcess(commandSpec.executable, commandSpec.argv, commandSpec.cwd, commandSpec.stdin, true)
457
+ launch: (commandSpec, options) => runProcess(
458
+ commandSpec.executable,
459
+ commandSpec.argv,
460
+ commandSpec.cwd,
461
+ commandSpec.stdin,
462
+ options?.captureStdout === true ? "capture" : "inherit"
463
+ )
434
464
  };
435
465
  var errorMessage = (error) => error instanceof Error ? error.message : String(error);
436
466
  var prepareLaunch = async (harness, input, active, guard) => {
@@ -462,11 +492,12 @@ var prepareLaunch = async (harness, input, active, guard) => {
462
492
  }
463
493
  return { kind: "ready", command: commandSpec };
464
494
  };
465
- var launchPrepared = async (prepared, active, label) => {
495
+ var launchPrepared = async (prepared, active, label, captureStdout = false) => {
466
496
  if (prepared.kind === "fallback") return prepared;
467
497
  try {
468
- const launched = await active.launch(prepared.command);
469
- return launched.exitCode === 0 ? { kind: "launched-success", exitCode: 0 } : { kind: "launched-failure", exitCode: launched.exitCode };
498
+ const launched = await active.launch(prepared.command, { captureStdout });
499
+ const stdout = launched.stdout === void 0 ? {} : { stdout: launched.stdout };
500
+ return launched.exitCode === 0 ? { kind: "launched-success", exitCode: 0, ...stdout } : { kind: "launched-failure", exitCode: launched.exitCode, ...stdout };
470
501
  } catch (error) {
471
502
  return {
472
503
  kind: "infrastructure-failure",
@@ -477,7 +508,7 @@ var launchPrepared = async (prepared, active, label) => {
477
508
  var dispatchReview = async (request, overrides = {}) => {
478
509
  const active = { ...dependencies, ...overrides };
479
510
  const prepared = await prepareLaunch(request.harness, reviewCommandRequest(request), active);
480
- return launchPrepared(prepared, active, "review");
511
+ return launchPrepared(prepared, active, "review", true);
481
512
  };
482
513
 
483
514
  // src/skill-scripts/shared/harness-availability.ts
@@ -992,6 +1023,7 @@ var REVIEW_DIR_NAME = "review";
992
1023
  var BASE_COMMIT_FILE_NAME = "base-commit.json";
993
1024
  var REVIEW_FILE_NAME = "review.xml";
994
1025
  var FINDINGS_FILE_NAME = "findings.json";
1026
+ var TRANSCRIPT_FILE_NAME = "reviewer-output.txt";
995
1027
  var SHA_RE = /^[0-9a-f]{40}$/i;
996
1028
  var errorMessage2 = (error) => error instanceof Error ? error.message : String(error);
997
1029
  var readFileOrNull = (filePath) => {
@@ -1001,6 +1033,14 @@ var readFileOrNull = (filePath) => {
1001
1033
  return null;
1002
1034
  }
1003
1035
  };
1036
+ var writeTranscript = (roundDir, transcript) => {
1037
+ if (transcript === void 0 || transcript === "") return;
1038
+ try {
1039
+ fs6.mkdirSync(roundDir, { recursive: true });
1040
+ fs6.writeFileSync(path6.join(roundDir, TRANSCRIPT_FILE_NAME), transcript, "utf8");
1041
+ } catch {
1042
+ }
1043
+ };
1004
1044
  var createFindingsGate = (mandate) => async (context) => {
1005
1045
  const roundDir = path6.dirname(context.reviewFile);
1006
1046
  const findingsFile = path6.join(roundDir, FINDINGS_FILE_NAME);
@@ -1022,11 +1062,25 @@ var createFindingsGate = (mandate) => async (context) => {
1022
1062
  severityFloor: mandate.severityFloor,
1023
1063
  confidenceFloor: mandate.confidenceFloor
1024
1064
  };
1025
- if (!fs6.existsSync(context.reviewFile)) {
1026
- const detail = `The reviewer did not write ${context.reviewFile}. A round with no findings document cannot be read as a round with no findings.`;
1065
+ const delivered = _extractReviewDocument(context.reviewerStdout, context.deliveryToken);
1066
+ if (delivered === null) {
1067
+ const detail = "The reviewer printed no complete findings document between this dispatch's delimiters. A round with no findings document cannot be read as a round with no findings.";
1027
1068
  record({ ...base, status: "findings-absent", detail, actionable: [], recorded: [] });
1028
1069
  return { kind: "findings-absent", detail };
1029
1070
  }
1071
+ try {
1072
+ fs6.mkdirSync(roundDir, { recursive: true });
1073
+ fs6.writeFileSync(
1074
+ context.reviewFile,
1075
+ delivered.endsWith("\n") ? delivered : `${delivered}
1076
+ `,
1077
+ "utf8"
1078
+ );
1079
+ } catch (error) {
1080
+ throw new Error(
1081
+ `The delivered findings document could not be written to ${context.reviewFile}: ` + errorMessage2(error)
1082
+ );
1083
+ }
1030
1084
  const validation = await validateAgainstSchema(context.xsdFile, context.reviewFile);
1031
1085
  if (validation.kind === "validator-unavailable") {
1032
1086
  record({
@@ -1157,13 +1211,33 @@ var renderAdjudicated = (findings) => {
1157
1211
  return `- [${finding.disposition}] ${where}${attributes ? ` (${attributes})` : ""} \u2014 ${finding.summary}`;
1158
1212
  }).join("\n");
1159
1213
  };
1214
+ var _makeDeliveryToken = () => crypto.randomBytes(6).toString("hex");
1215
+ var beginMarker = (token) => `<<<BEGIN REVIEW XML ${token}>>>`;
1216
+ var endMarker = (token) => `<<<END REVIEW XML ${token}>>>`;
1217
+ var ANSI_PATTERN = /\u001b\[[0-9;?]*[ -/]*[@-~]/g;
1218
+ var _extractReviewDocument = (stdout, token) => {
1219
+ const clean = stdout.replace(ANSI_PATTERN, "");
1220
+ const begin = beginMarker(token);
1221
+ const end = endMarker(token);
1222
+ let searchFrom = clean.length;
1223
+ while (searchFrom >= 0) {
1224
+ const endIndex = clean.lastIndexOf(end, searchFrom);
1225
+ if (endIndex === -1) return null;
1226
+ const beginIndex = clean.lastIndexOf(begin, endIndex);
1227
+ if (beginIndex === -1) return null;
1228
+ const inner = clean.slice(beginIndex + begin.length, endIndex).trim();
1229
+ if (inner.startsWith("<?xml") || inner.startsWith("<review")) return inner;
1230
+ searchFrom = beginIndex - 1;
1231
+ }
1232
+ return null;
1233
+ };
1160
1234
  var buildReviewerPrompt = (input) => [
1161
1235
  `Strikethroo code review gate \u2014 Plan ${input.planId}, review round ${input.round}.`,
1162
1236
  "",
1163
1237
  "You are the independent reviewer, running on a different harness than the one",
1164
1238
  "that wrote this code. You detect; you never fix. Do not edit, create, or delete",
1165
1239
  "source files. Do not run formatters. Do not commit. Your entire output is one",
1166
- "review.xml at the path named below, plus a short report of the counts.",
1240
+ "findings document, printed as described below, plus a short report of the counts.",
1167
1241
  "",
1168
1242
  `Repository / workspace root: ${input.workspace}`,
1169
1243
  `Strikethroo workspace root: ${input.strikethrooRoot}`,
@@ -1172,7 +1246,28 @@ var buildReviewerPrompt = (input) => [
1172
1246
  `Findings schema to validate against: ${input.xsdFile}`,
1173
1247
  `Base commit anchoring this plan's scope: ${input.baseCommit}`,
1174
1248
  `Round: ${input.round}`,
1175
- `Write your findings to: ${input.reviewFile}`,
1249
+ "",
1250
+ "## How to deliver your findings",
1251
+ "",
1252
+ "Print the complete findings document as the final thing you print, between these",
1253
+ "exact lines:",
1254
+ "",
1255
+ beginMarker(input.deliveryToken),
1256
+ // The placeholder deliberately does not begin with `<?xml` or `<review`.
1257
+ // `_extractReviewDocument` rejects a region on exactly that test, which is what
1258
+ // stops a reviewer that echoes these instructions back from being read as a
1259
+ // delivered document. A placeholder shaped like a real document would defeat
1260
+ // it — keep this line prose, here and in any mirror of it.
1261
+ "... the complete findings document, beginning with its XML declaration ...",
1262
+ endMarker(input.deliveryToken),
1263
+ "",
1264
+ "Copy those two lines from this dispatch; never invent a token. Print nothing after",
1265
+ "the closing line. Do not write the document to a file \u2014 this channel is the only",
1266
+ "one that is read. The document is validated against the schema named above, so an",
1267
+ "incomplete or invented document fails the round. Being unable to read the",
1268
+ "repository is not a reason to emit this block: a review you could not perform is a",
1269
+ "failed round, and emitting well-formed XML instead of reporting that failure is a",
1270
+ "worse outcome than the failure.",
1176
1271
  "",
1177
1272
  "## Review mandate (authoritative \u2014 it overrides the reviewer instructions below)",
1178
1273
  "",
@@ -1363,6 +1458,18 @@ var runReviewRound = async (request, overrides = {}) => {
1363
1458
  detail: `Could not create the review round directory ${roundDir}: ${errorMessage2(error)}`
1364
1459
  };
1365
1460
  }
1461
+ const staleArtifacts = [reviewFile, path6.join(roundDir, TRANSCRIPT_FILE_NAME)];
1462
+ for (const stale of staleArtifacts) {
1463
+ try {
1464
+ fs6.rmSync(stale, { force: true });
1465
+ } catch (error) {
1466
+ return {
1467
+ kind: "infrastructure-failure",
1468
+ detail: `Could not remove the stale round artifact ${stale}: ${errorMessage2(error)}`
1469
+ };
1470
+ }
1471
+ }
1472
+ const deliveryToken = _makeDeliveryToken();
1366
1473
  const prompt = buildReviewerPrompt({
1367
1474
  planId,
1368
1475
  planFile,
@@ -1373,10 +1480,10 @@ var runReviewRound = async (request, overrides = {}) => {
1373
1480
  xsdFile,
1374
1481
  baseCommit,
1375
1482
  round: request.round,
1376
- reviewFile,
1377
1483
  diff,
1378
1484
  adjudicatedFindings: request.adjudicatedFindings ?? _readPriorAdjudicated(planDir, request.round),
1379
- skillInstructions: readReviewerSkill()
1485
+ skillInstructions: readReviewerSkill(),
1486
+ deliveryToken
1380
1487
  });
1381
1488
  const dispatched = await dependencies2.dispatch({ harness, workspace, prompt });
1382
1489
  if (dispatched.kind === "infrastructure-failure") {
@@ -1392,6 +1499,7 @@ var runReviewRound = async (request, overrides = {}) => {
1392
1499
  };
1393
1500
  }
1394
1501
  if (dispatched.kind === "launched-failure") {
1502
+ writeTranscript(roundDir, dispatched.stdout);
1395
1503
  return {
1396
1504
  kind: "launched-failure",
1397
1505
  harness,
@@ -1406,8 +1514,13 @@ var runReviewRound = async (request, overrides = {}) => {
1406
1514
  reviewFile,
1407
1515
  xsdFile,
1408
1516
  planDir,
1409
- round: request.round
1517
+ round: request.round,
1518
+ reviewerStdout: dispatched.stdout ?? "",
1519
+ deliveryToken
1410
1520
  });
1521
+ if (findingsGate.kind !== "evaluated") {
1522
+ writeTranscript(roundDir, dispatched.stdout);
1523
+ }
1411
1524
  return {
1412
1525
  kind: "reviewed",
1413
1526
  harness,
@@ -1527,6 +1640,8 @@ if (require.main === module) {
1527
1640
  MAX_REVIEW_ROUNDS,
1528
1641
  _decideRound,
1529
1642
  _exitCodeFor,
1643
+ _extractReviewDocument,
1644
+ _makeDeliveryToken,
1530
1645
  _readBaseCommit,
1531
1646
  _readCumulativeDiff,
1532
1647
  _readPriorAdjudicated,
@@ -174,7 +174,7 @@ code-review.cjs <plan-id> <current-harness> <round>
174
174
 
175
175
  `code-review.cjs` ships with the `st-code-review` skill and lives in that skill's own `scripts` directory, a sibling of this one. Resolve it there; it is not bundled with this skill. If the `st-code-review` skill is not installed on this harness, record that as the review outcome in the execution summary and continue to the summary and archival.
176
176
 
177
- `<current-harness>` is the exact supported harness identifier running this skill. `<round>` is `1` on the first invocation, and thereafter the exact `decision.nextRound` the previous round returned. The command emits exactly one JSON line on stdout. Read its `kind`, then — when `kind` is `reviewed` — its `decision.kind`, and do exactly what the matching row states.
177
+ `<current-harness>` is the exact supported harness identifier running this skill. `<round>` is `1` on the first invocation, and thereafter the exact `decision.nextRound` the previous round returned. The command emits exactly one JSON line on stdout. Reviewer output is captured and teed to stderr, so stdout carries the verdict JSON line and nothing else. Read its `kind`, then — when `kind` is `reviewed` — its `decision.kind`, and do exactly what the matching row states.
178
178
 
179
179
  | Result | What you do |
180
180
  | --- | --- |
@@ -3737,7 +3737,13 @@ var executableOnPath = (executable) => (process.env.PATH ?? "").split(path2.deli
3737
3737
  return false;
3738
3738
  }
3739
3739
  });
3740
- var runProcess = (executable, argv, cwd, stdin, inheritOutput = false) => new Promise((resolve3, reject) => {
3740
+ var CAPTURED_STDOUT_LIMIT = 262144;
3741
+ var STDIO_SLOTS = {
3742
+ ignore: { stdout: "ignore" },
3743
+ inherit: { stdout: "inherit" },
3744
+ capture: { stdout: "pipe" }
3745
+ };
3746
+ var runProcess = (executable, argv, cwd, stdin, outputMode = "ignore") => new Promise((resolve3, reject) => {
3741
3747
  let settled = false;
3742
3748
  const fail = (error) => {
3743
3749
  if (settled) return;
@@ -3749,15 +3755,30 @@ var runProcess = (executable, argv, cwd, stdin, inheritOutput = false) => new Pr
3749
3755
  shell: false,
3750
3756
  stdio: [
3751
3757
  stdin === void 0 ? "ignore" : "pipe",
3752
- inheritOutput ? "inherit" : "ignore",
3753
- inheritOutput ? "inherit" : "ignore"
3758
+ STDIO_SLOTS[outputMode].stdout,
3759
+ outputMode === "ignore" ? "ignore" : "inherit"
3754
3760
  ]
3755
3761
  });
3762
+ let captured = "";
3763
+ if (outputMode === "capture") {
3764
+ child.stdout.setEncoding("utf8");
3765
+ child.stdout.once("error", fail);
3766
+ child.stdout.on("data", (chunk) => {
3767
+ process.stderr.write(chunk);
3768
+ captured += chunk;
3769
+ if (captured.length > CAPTURED_STDOUT_LIMIT) {
3770
+ captured = captured.slice(captured.length - CAPTURED_STDOUT_LIMIT);
3771
+ }
3772
+ });
3773
+ }
3756
3774
  child.once("error", fail);
3757
3775
  child.once("close", (code) => {
3758
3776
  if (settled) return;
3759
3777
  settled = true;
3760
- resolve3({ exitCode: code ?? 1 });
3778
+ resolve3({
3779
+ exitCode: code ?? 1,
3780
+ ...outputMode === "capture" ? { stdout: captured } : {}
3781
+ });
3761
3782
  });
3762
3783
  if (stdin !== void 0) {
3763
3784
  child.stdin.once("error", fail);
@@ -3785,7 +3806,13 @@ var dependencies = {
3785
3806
  };
3786
3807
  }
3787
3808
  },
3788
- launch: (commandSpec) => runProcess(commandSpec.executable, commandSpec.argv, commandSpec.cwd, commandSpec.stdin, true)
3809
+ launch: (commandSpec, options2) => runProcess(
3810
+ commandSpec.executable,
3811
+ commandSpec.argv,
3812
+ commandSpec.cwd,
3813
+ commandSpec.stdin,
3814
+ options2?.captureStdout === true ? "capture" : "inherit"
3815
+ )
3789
3816
  };
3790
3817
  var errorMessage = (error) => error instanceof Error ? error.message : String(error);
3791
3818
  var prepareLaunch = async (harness, input, active, guard) => {
@@ -3817,11 +3844,12 @@ var prepareLaunch = async (harness, input, active, guard) => {
3817
3844
  }
3818
3845
  return { kind: "ready", command: commandSpec };
3819
3846
  };
3820
- var launchPrepared = async (prepared, active, label) => {
3847
+ var launchPrepared = async (prepared, active, label, captureStdout = false) => {
3821
3848
  if (prepared.kind === "fallback") return prepared;
3822
3849
  try {
3823
- const launched = await active.launch(prepared.command);
3824
- return launched.exitCode === 0 ? { kind: "launched-success", exitCode: 0 } : { kind: "launched-failure", exitCode: launched.exitCode };
3850
+ const launched = await active.launch(prepared.command, { captureStdout });
3851
+ const stdout = launched.stdout === void 0 ? {} : { stdout: launched.stdout };
3852
+ return launched.exitCode === 0 ? { kind: "launched-success", exitCode: 0, ...stdout } : { kind: "launched-failure", exitCode: launched.exitCode, ...stdout };
3825
3853
  } catch (error) {
3826
3854
  return {
3827
3855
  kind: "infrastructure-failure",
@@ -3737,7 +3737,13 @@ var executableOnPath = (executable) => (process.env.PATH ?? "").split(path2.deli
3737
3737
  return false;
3738
3738
  }
3739
3739
  });
3740
- var runProcess = (executable, argv, cwd, stdin, inheritOutput = false) => new Promise((resolve3, reject) => {
3740
+ var CAPTURED_STDOUT_LIMIT = 262144;
3741
+ var STDIO_SLOTS = {
3742
+ ignore: { stdout: "ignore" },
3743
+ inherit: { stdout: "inherit" },
3744
+ capture: { stdout: "pipe" }
3745
+ };
3746
+ var runProcess = (executable, argv, cwd, stdin, outputMode = "ignore") => new Promise((resolve3, reject) => {
3741
3747
  let settled = false;
3742
3748
  const fail = (error) => {
3743
3749
  if (settled) return;
@@ -3749,15 +3755,30 @@ var runProcess = (executable, argv, cwd, stdin, inheritOutput = false) => new Pr
3749
3755
  shell: false,
3750
3756
  stdio: [
3751
3757
  stdin === void 0 ? "ignore" : "pipe",
3752
- inheritOutput ? "inherit" : "ignore",
3753
- inheritOutput ? "inherit" : "ignore"
3758
+ STDIO_SLOTS[outputMode].stdout,
3759
+ outputMode === "ignore" ? "ignore" : "inherit"
3754
3760
  ]
3755
3761
  });
3762
+ let captured = "";
3763
+ if (outputMode === "capture") {
3764
+ child.stdout.setEncoding("utf8");
3765
+ child.stdout.once("error", fail);
3766
+ child.stdout.on("data", (chunk) => {
3767
+ process.stderr.write(chunk);
3768
+ captured += chunk;
3769
+ if (captured.length > CAPTURED_STDOUT_LIMIT) {
3770
+ captured = captured.slice(captured.length - CAPTURED_STDOUT_LIMIT);
3771
+ }
3772
+ });
3773
+ }
3756
3774
  child.once("error", fail);
3757
3775
  child.once("close", (code) => {
3758
3776
  if (settled) return;
3759
3777
  settled = true;
3760
- resolve3({ exitCode: code ?? 1 });
3778
+ resolve3({
3779
+ exitCode: code ?? 1,
3780
+ ...outputMode === "capture" ? { stdout: captured } : {}
3781
+ });
3761
3782
  });
3762
3783
  if (stdin !== void 0) {
3763
3784
  child.stdin.once("error", fail);
@@ -3785,7 +3806,13 @@ var dependencies = {
3785
3806
  };
3786
3807
  }
3787
3808
  },
3788
- launch: (commandSpec) => runProcess(commandSpec.executable, commandSpec.argv, commandSpec.cwd, commandSpec.stdin, true)
3809
+ launch: (commandSpec, options2) => runProcess(
3810
+ commandSpec.executable,
3811
+ commandSpec.argv,
3812
+ commandSpec.cwd,
3813
+ commandSpec.stdin,
3814
+ options2?.captureStdout === true ? "capture" : "inherit"
3815
+ )
3789
3816
  };
3790
3817
  var errorMessage = (error) => error instanceof Error ? error.message : String(error);
3791
3818
  var prepareLaunch = async (harness, input, active, guard) => {
@@ -3817,11 +3844,12 @@ var prepareLaunch = async (harness, input, active, guard) => {
3817
3844
  }
3818
3845
  return { kind: "ready", command: commandSpec };
3819
3846
  };
3820
- var launchPrepared = async (prepared, active, label) => {
3847
+ var launchPrepared = async (prepared, active, label, captureStdout = false) => {
3821
3848
  if (prepared.kind === "fallback") return prepared;
3822
3849
  try {
3823
- const launched = await active.launch(prepared.command);
3824
- return launched.exitCode === 0 ? { kind: "launched-success", exitCode: 0 } : { kind: "launched-failure", exitCode: launched.exitCode };
3850
+ const launched = await active.launch(prepared.command, { captureStdout });
3851
+ const stdout = launched.stdout === void 0 ? {} : { stdout: launched.stdout };
3852
+ return launched.exitCode === 0 ? { kind: "launched-success", exitCode: 0, ...stdout } : { kind: "launched-failure", exitCode: launched.exitCode, ...stdout };
3825
3853
  } catch (error) {
3826
3854
  return {
3827
3855
  kind: "infrastructure-failure",
@@ -517,7 +517,7 @@ code-review.cjs <plan-id> <current-harness> <round>
517
517
 
518
518
  `code-review.cjs` ships with the `st-code-review` skill and lives in that skill's own `scripts` directory, a sibling of this one. Resolve it there; it is not bundled with this skill. If the `st-code-review` skill is not installed on this harness, record that as the review outcome in the execution summary and continue to the summary and archival.
519
519
 
520
- `<current-harness>` is the exact supported harness identifier running this skill. `<round>` is `1` on the first invocation, and thereafter the exact `decision.nextRound` the previous round returned. The command emits exactly one JSON line on stdout. Read its `kind`, then — when `kind` is `reviewed` — its `decision.kind`, and do exactly what the matching row states.
520
+ `<current-harness>` is the exact supported harness identifier running this skill. `<round>` is `1` on the first invocation, and thereafter the exact `decision.nextRound` the previous round returned. The command emits exactly one JSON line on stdout. Reviewer output is captured and teed to stderr, so stdout carries the verdict JSON line and nothing else. Read its `kind`, then — when `kind` is `reviewed` — its `decision.kind`, and do exactly what the matching row states.
521
521
 
522
522
  | Result | What you do |
523
523
  | --- | --- |
@@ -3737,7 +3737,13 @@ var executableOnPath = (executable) => (process.env.PATH ?? "").split(path2.deli
3737
3737
  return false;
3738
3738
  }
3739
3739
  });
3740
- var runProcess = (executable, argv, cwd, stdin, inheritOutput = false) => new Promise((resolve3, reject) => {
3740
+ var CAPTURED_STDOUT_LIMIT = 262144;
3741
+ var STDIO_SLOTS = {
3742
+ ignore: { stdout: "ignore" },
3743
+ inherit: { stdout: "inherit" },
3744
+ capture: { stdout: "pipe" }
3745
+ };
3746
+ var runProcess = (executable, argv, cwd, stdin, outputMode = "ignore") => new Promise((resolve3, reject) => {
3741
3747
  let settled = false;
3742
3748
  const fail = (error) => {
3743
3749
  if (settled) return;
@@ -3749,15 +3755,30 @@ var runProcess = (executable, argv, cwd, stdin, inheritOutput = false) => new Pr
3749
3755
  shell: false,
3750
3756
  stdio: [
3751
3757
  stdin === void 0 ? "ignore" : "pipe",
3752
- inheritOutput ? "inherit" : "ignore",
3753
- inheritOutput ? "inherit" : "ignore"
3758
+ STDIO_SLOTS[outputMode].stdout,
3759
+ outputMode === "ignore" ? "ignore" : "inherit"
3754
3760
  ]
3755
3761
  });
3762
+ let captured = "";
3763
+ if (outputMode === "capture") {
3764
+ child.stdout.setEncoding("utf8");
3765
+ child.stdout.once("error", fail);
3766
+ child.stdout.on("data", (chunk) => {
3767
+ process.stderr.write(chunk);
3768
+ captured += chunk;
3769
+ if (captured.length > CAPTURED_STDOUT_LIMIT) {
3770
+ captured = captured.slice(captured.length - CAPTURED_STDOUT_LIMIT);
3771
+ }
3772
+ });
3773
+ }
3756
3774
  child.once("error", fail);
3757
3775
  child.once("close", (code) => {
3758
3776
  if (settled) return;
3759
3777
  settled = true;
3760
- resolve3({ exitCode: code ?? 1 });
3778
+ resolve3({
3779
+ exitCode: code ?? 1,
3780
+ ...outputMode === "capture" ? { stdout: captured } : {}
3781
+ });
3761
3782
  });
3762
3783
  if (stdin !== void 0) {
3763
3784
  child.stdin.once("error", fail);
@@ -3785,7 +3806,13 @@ var dependencies = {
3785
3806
  };
3786
3807
  }
3787
3808
  },
3788
- launch: (commandSpec) => runProcess(commandSpec.executable, commandSpec.argv, commandSpec.cwd, commandSpec.stdin, true)
3809
+ launch: (commandSpec, options2) => runProcess(
3810
+ commandSpec.executable,
3811
+ commandSpec.argv,
3812
+ commandSpec.cwd,
3813
+ commandSpec.stdin,
3814
+ options2?.captureStdout === true ? "capture" : "inherit"
3815
+ )
3789
3816
  };
3790
3817
  var errorMessage = (error) => error instanceof Error ? error.message : String(error);
3791
3818
  var prepareLaunch = async (harness, input, active, guard) => {
@@ -3817,11 +3844,12 @@ var prepareLaunch = async (harness, input, active, guard) => {
3817
3844
  }
3818
3845
  return { kind: "ready", command: commandSpec };
3819
3846
  };
3820
- var launchPrepared = async (prepared, active, label) => {
3847
+ var launchPrepared = async (prepared, active, label, captureStdout = false) => {
3821
3848
  if (prepared.kind === "fallback") return prepared;
3822
3849
  try {
3823
- const launched = await active.launch(prepared.command);
3824
- return launched.exitCode === 0 ? { kind: "launched-success", exitCode: 0 } : { kind: "launched-failure", exitCode: launched.exitCode };
3850
+ const launched = await active.launch(prepared.command, { captureStdout });
3851
+ const stdout = launched.stdout === void 0 ? {} : { stdout: launched.stdout };
3852
+ return launched.exitCode === 0 ? { kind: "launched-success", exitCode: 0, ...stdout } : { kind: "launched-failure", exitCode: launched.exitCode, ...stdout };
3825
3853
  } catch (error) {
3826
3854
  return {
3827
3855
  kind: "infrastructure-failure",
@@ -1 +0,0 @@
1
- import{U as a,C as n}from"./mermaid.core-C6KsMc78.js";const t=(r,o)=>a.lang.round(n.parse(r)[o]);export{t as c};
@@ -1 +0,0 @@
1
- import{s as a,a as s,c as e,C as t}from"./chunk-727SXJPM-Ec_YNRXy.js";import{b as i}from"./mermaid.core-C6KsMc78.js";import"./chunk-FMBD7UC4-D3hDHEbQ.js";import"./chunk-ND2GUHAM-D7qdmfIe.js";import"./chunk-55IACEB6-YxIJIoS8.js";import"./chunk-2J33WTMH-w1zteFnE.js";import"./index-YT2EMDff.js";var n={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{n as diagram};
@@ -1 +0,0 @@
1
- import{s as a,a as s,c as e,C as t}from"./chunk-727SXJPM-Ec_YNRXy.js";import{b as i}from"./mermaid.core-C6KsMc78.js";import"./chunk-FMBD7UC4-D3hDHEbQ.js";import"./chunk-ND2GUHAM-D7qdmfIe.js";import"./chunk-55IACEB6-YxIJIoS8.js";import"./chunk-2J33WTMH-w1zteFnE.js";import"./index-YT2EMDff.js";var n={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{n as diagram};
@@ -1 +0,0 @@
1
- import{b as e,a as r,s as a,S as s}from"./chunk-AQP2D5EJ-Bq3XSb33.js";import{b as i}from"./mermaid.core-C6KsMc78.js";import"./chunk-55IACEB6-YxIJIoS8.js";import"./chunk-2J33WTMH-w1zteFnE.js";import"./index-YT2EMDff.js";var u={parser:a,get db(){return new s(2)},renderer:r,styles:e,init:i(t=>{t.state||(t.state={}),t.state.arrowMarkerAbsolute=t.arrowMarkerAbsolute},"init")};export{u as diagram};