@lazyingart/agintiflow 0.20.316 → 0.20.318

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lazyingart/agintiflow",
3
- "version": "0.20.316",
3
+ "version": "0.20.318",
4
4
  "type": "module",
5
5
  "description": "AgInTiFlow is a project-aware agent workspace for hybrid wet-dry R&D, hardware-aware intelligence, software automation, and industrial workflows.",
6
6
  "license": "Apache-2.0",
@@ -6132,6 +6132,242 @@ try {
6132
6132
  sandboxMode: "host",
6133
6133
  }
6134
6134
  );
6135
+ const scopedRelativeTaskRoot = path.relative(workspace, scopedTaskRoot).replace(/\\/g, "/");
6136
+ const liveScopedGroupTestLogCommand = {
6137
+ toolName: "run_command",
6138
+ ok: true,
6139
+ exitCode: 0,
6140
+ args: {
6141
+ command:
6142
+ `cd ${JSON.stringify(workspace)} && ` +
6143
+ `TASK=${scopedRelativeTaskRoot} && LOG="$TASK/document-reader-test.log" && ` +
6144
+ `{ echo "=== focused test ==="; python3 -m unittest discover -s tests -p 'test_reader.py' -v; RC=$?; echo "EXIT=$RC"; } ` +
6145
+ `> "$LOG" 2>&1; tail -n 6 "$LOG"; echo "LOG_OK=$([ -s "$LOG" ] && echo yes || echo no)"`,
6146
+ },
6147
+ projectMutationPaths: [],
6148
+ stdout: "Ran 7 tests in 0.01s\nOK\nEXIT=0\nLOG_OK=yes\n",
6149
+ stderr: "",
6150
+ };
6151
+ recordProjectVerificationOutcome(
6152
+ scopedTaskState,
6153
+ liveScopedGroupTestLogCommand,
6154
+ {
6155
+ commandCwd: workspace,
6156
+ taskProfile: "qa",
6157
+ allowShellTool: true,
6158
+ sandboxMode: "host",
6159
+ }
6160
+ );
6161
+ const liveScopedTeeTestLogCommand = {
6162
+ toolName: "run_command",
6163
+ ok: true,
6164
+ exitCode: 0,
6165
+ args: {
6166
+ command:
6167
+ `cd ${JSON.stringify(workspace)} && ` +
6168
+ `TASK=${scopedRelativeTaskRoot} && LOG="$TASK/document-reader-test.log" && ` +
6169
+ `{ echo "=== focused test ==="; python3 -m unittest discover -s tests -p 'test_reader.py' -v 2>&1; RC=$?; echo "EXIT=$RC"; } ` +
6170
+ `| tee "$LOG"; grep -q '^OK$' "$LOG"; echo "DONE_EXIT=$?"`,
6171
+ },
6172
+ projectMutationPaths: [],
6173
+ stdout: "Ran 7 tests in 0.01s\nOK\nEXIT=0\nDONE_EXIT=0\n",
6174
+ stderr: "",
6175
+ };
6176
+ recordProjectVerificationOutcome(
6177
+ scopedTaskState,
6178
+ liveScopedTeeTestLogCommand,
6179
+ {
6180
+ commandCwd: workspace,
6181
+ taskProfile: "qa",
6182
+ allowShellTool: true,
6183
+ sandboxMode: "host",
6184
+ }
6185
+ );
6186
+ const liveScopedOutsideStatusTestLogCommand = {
6187
+ toolName: "run_command",
6188
+ ok: true,
6189
+ exitCode: 0,
6190
+ args: {
6191
+ command:
6192
+ `cd ${JSON.stringify(workspace)} && ` +
6193
+ `TASK=${scopedRelativeTaskRoot} && ` +
6194
+ `{ date -u +"RUN_AT=%FT%TZ"; PYTHONPATH=src python -m pytest tests/test_wechat_document_reader.py -q; } ` +
6195
+ `> "$TASK/document-reader-test.log" 2>&1; rc=$?; echo "PYTEST_EXIT=$rc"; ` +
6196
+ `cat "$TASK/document-reader-test.log"`,
6197
+ },
6198
+ projectMutationPaths: [],
6199
+ stdout: "PYTEST_EXIT=0\n....... [100%]\n7 passed in 0.04s\n",
6200
+ stderr: "",
6201
+ };
6202
+ recordProjectVerificationOutcome(
6203
+ scopedTaskState,
6204
+ liveScopedOutsideStatusTestLogCommand,
6205
+ {
6206
+ commandCwd: workspace,
6207
+ taskProfile: "qa",
6208
+ allowShellTool: true,
6209
+ sandboxMode: "host",
6210
+ }
6211
+ );
6212
+ const conditionalTestCommand =
6213
+ `cd ${JSON.stringify(workspace)} && ` +
6214
+ `if PYTHONPATH=src python -c "import pytest" 2>/dev/null; then ` +
6215
+ `PYTHONPATH=src python -m pytest tests/test_wechat_document_reader.py -q; else ` +
6216
+ `PYTHONPATH=src python -m unittest tests.test_wechat_document_reader -v; fi`;
6217
+ const conditionalTestState = { meta: { goalContract: { revision: 1 } } };
6218
+ const conditionalTestResult = {
6219
+ toolName: "run_command",
6220
+ ok: true,
6221
+ exitCode: 0,
6222
+ args: { command: conditionalTestCommand },
6223
+ projectMutationPaths: [],
6224
+ stdout: "....... [100%]\n7 passed in 0.04s\n",
6225
+ stderr: "",
6226
+ commandPolicy: classifyCommand(conditionalTestCommand),
6227
+ };
6228
+ recordProjectVerificationOutcome(
6229
+ conditionalTestState,
6230
+ conditionalTestResult,
6231
+ {
6232
+ commandCwd: workspace,
6233
+ taskProfile: "qa",
6234
+ allowShellTool: true,
6235
+ sandboxMode: "host",
6236
+ }
6237
+ );
6238
+ const mutatingConditionalTestCommand = conditionalTestCommand.replace(
6239
+ "tests.test_wechat_document_reader -v; fi",
6240
+ "tests.test_wechat_document_reader -v; touch src/agent-runner.js; fi"
6241
+ );
6242
+ const mutatingConditionalTestState = { meta: { goalContract: { revision: 1 } } };
6243
+ const mutatingConditionalTestResult = {
6244
+ toolName: "run_command",
6245
+ ok: true,
6246
+ exitCode: 0,
6247
+ args: { command: mutatingConditionalTestCommand },
6248
+ projectMutationPaths: [],
6249
+ stdout: "7 passed in 0.04s\n",
6250
+ stderr: "",
6251
+ commandPolicy: classifyCommand(mutatingConditionalTestCommand),
6252
+ };
6253
+ recordProjectVerificationOutcome(
6254
+ mutatingConditionalTestState,
6255
+ mutatingConditionalTestResult,
6256
+ {
6257
+ commandCwd: workspace,
6258
+ taskProfile: "qa",
6259
+ allowShellTool: true,
6260
+ allowDestructive: true,
6261
+ sandboxMode: "host",
6262
+ }
6263
+ );
6264
+ const unsafeScopedLogState = {
6265
+ goal: scopedTaskGoal,
6266
+ commandCwd: workspace,
6267
+ meta: {
6268
+ goalContract: {
6269
+ revision: 1,
6270
+ taskGoal: scopedTaskGoal,
6271
+ currentRequest: "Create and verify output/result.json.",
6272
+ },
6273
+ },
6274
+ };
6275
+ const outsideScopedGroupTestLogCommand = {
6276
+ toolName: "run_command",
6277
+ ok: true,
6278
+ exitCode: 0,
6279
+ args: {
6280
+ command:
6281
+ `cd ${JSON.stringify(workspace)} && LOG="source-tree-test.log" && ` +
6282
+ `{ python3 -m unittest discover -s tests -p 'test_reader.py' -v; RC=$?; echo "EXIT=$RC"; } ` +
6283
+ `> "$LOG" 2>&1; tail -n 6 "$LOG"`,
6284
+ },
6285
+ projectMutationPaths: [],
6286
+ stdout: "Ran 7 tests in 0.01s\nOK\nEXIT=0\n",
6287
+ stderr: "",
6288
+ };
6289
+ recordProjectVerificationOutcome(
6290
+ unsafeScopedLogState,
6291
+ outsideScopedGroupTestLogCommand,
6292
+ {
6293
+ commandCwd: workspace,
6294
+ taskProfile: "qa",
6295
+ allowShellTool: true,
6296
+ sandboxMode: "host",
6297
+ }
6298
+ );
6299
+ const sourceWriteAfterScopedLogState = {
6300
+ goal: scopedTaskGoal,
6301
+ commandCwd: workspace,
6302
+ meta: {
6303
+ goalContract: {
6304
+ revision: 1,
6305
+ taskGoal: scopedTaskGoal,
6306
+ currentRequest: "Create and verify output/result.json.",
6307
+ },
6308
+ },
6309
+ };
6310
+ const sourceWriteAfterScopedLogCommand = {
6311
+ toolName: "run_command",
6312
+ ok: true,
6313
+ exitCode: 0,
6314
+ args: {
6315
+ command:
6316
+ `cd ${JSON.stringify(workspace)} && ` +
6317
+ `TASK=${scopedRelativeTaskRoot} && LOG="$TASK/document-reader-test.log" && ` +
6318
+ `{ python3 -m unittest discover -s tests -p 'test_reader.py' -v; RC=$?; echo "EXIT=$RC"; } ` +
6319
+ `> "$LOG" 2>&1; touch src/agent-runner.js; tail -n 6 "$LOG"`,
6320
+ },
6321
+ projectMutationPaths: [],
6322
+ stdout: "Ran 7 tests in 0.01s\nOK\nEXIT=0\n",
6323
+ stderr: "",
6324
+ };
6325
+ recordProjectVerificationOutcome(
6326
+ sourceWriteAfterScopedLogState,
6327
+ sourceWriteAfterScopedLogCommand,
6328
+ {
6329
+ commandCwd: workspace,
6330
+ taskProfile: "qa",
6331
+ allowShellTool: true,
6332
+ sandboxMode: "host",
6333
+ }
6334
+ );
6335
+ const spoofedCapturedStatusState = {
6336
+ goal: scopedTaskGoal,
6337
+ commandCwd: workspace,
6338
+ meta: {
6339
+ goalContract: {
6340
+ revision: 1,
6341
+ taskGoal: scopedTaskGoal,
6342
+ currentRequest: "Create and verify output/result.json.",
6343
+ },
6344
+ },
6345
+ };
6346
+ const spoofedCapturedStatusCommand = {
6347
+ toolName: "run_command",
6348
+ ok: true,
6349
+ exitCode: 0,
6350
+ args: {
6351
+ command:
6352
+ `cd ${JSON.stringify(workspace)} && ` +
6353
+ `TASK=${scopedRelativeTaskRoot} && LOG="$TASK/document-reader-test.log" && ` +
6354
+ `{ python3 -m unittest discover -s tests -p 'test_reader.py' -v; RC=$?; echo "EXIT=$RC"; } ` +
6355
+ `> "$LOG" 2>&1; tail -n 6 "$LOG"; echo "EXIT=0"`,
6356
+ },
6357
+ projectMutationPaths: [],
6358
+ stdout: "FAILED (failures=1)\nEXIT=1\nEXIT=0\n",
6359
+ stderr: "",
6360
+ };
6361
+ recordProjectVerificationOutcome(
6362
+ spoofedCapturedStatusState,
6363
+ spoofedCapturedStatusCommand,
6364
+ {
6365
+ commandCwd: workspace,
6366
+ taskProfile: "qa",
6367
+ allowShellTool: true,
6368
+ sandboxMode: "host",
6369
+ }
6370
+ );
6135
6371
  const nullRedirectValidationCommand = {
6136
6372
  toolName: "run_command",
6137
6373
  ok: true,
@@ -6169,6 +6405,25 @@ try {
6169
6405
  scopedManifestCommand.scopedTaskArtifactWrite === true &&
6170
6406
  pythonScopedManifestCommand.scopedTaskArtifactWrite === true &&
6171
6407
  scopedCompoundTestLogCommand.scopedTaskArtifactWrite === true &&
6408
+ liveScopedGroupTestLogCommand.scopedTaskArtifactWrite === true &&
6409
+ liveScopedGroupTestLogCommand.projectTest?.passed === true &&
6410
+ liveScopedGroupTestLogCommand.projectTest?.explicitExitStatus === 0 &&
6411
+ liveScopedTeeTestLogCommand.scopedTaskArtifactWrite === true &&
6412
+ liveScopedTeeTestLogCommand.projectTest?.passed === true &&
6413
+ liveScopedTeeTestLogCommand.projectTest?.explicitExitStatus === 0 &&
6414
+ liveScopedOutsideStatusTestLogCommand.scopedTaskArtifactWrite === true &&
6415
+ liveScopedOutsideStatusTestLogCommand.projectTest?.passed === true &&
6416
+ liveScopedOutsideStatusTestLogCommand.projectTest?.explicitExitStatus === 0 &&
6417
+ conditionalTestState.meta.projectVerification?.mutationRevision === 0 &&
6418
+ conditionalTestResult.boundedReadOnlyTestWrapper === true &&
6419
+ conditionalTestResult.projectTest?.passed === true &&
6420
+ mutatingConditionalTestState.meta.projectVerification?.mutationRevision === 1 &&
6421
+ mutatingConditionalTestResult.projectTest === undefined &&
6422
+ unsafeScopedLogState.meta.projectVerification?.mutationRevision === 1 &&
6423
+ outsideScopedGroupTestLogCommand.scopedTaskArtifactWrite !== true &&
6424
+ sourceWriteAfterScopedLogState.meta.projectVerification?.mutationRevision === 1 &&
6425
+ sourceWriteAfterScopedLogCommand.scopedTaskArtifactWrite !== true &&
6426
+ spoofedCapturedStatusCommand.projectTest === undefined &&
6172
6427
  nullRedirectValidationCommand.readOnlyArtifactValidation === true,
6173
6428
  `task-scoped delivery bookkeeping invalidated requested artifact evidence: ${JSON.stringify({
6174
6429
  requestedOutputRevision,
@@ -6181,6 +6436,46 @@ try {
6181
6436
  pythonScopedManifestCommand.scopedTaskArtifactWrite,
6182
6437
  scopedCompoundTestLogCommand:
6183
6438
  scopedCompoundTestLogCommand.scopedTaskArtifactWrite,
6439
+ liveScopedGroupTestLogCommand: {
6440
+ scopedTaskArtifactWrite: liveScopedGroupTestLogCommand.scopedTaskArtifactWrite,
6441
+ projectTest: liveScopedGroupTestLogCommand.projectTest,
6442
+ },
6443
+ liveScopedTeeTestLogCommand: {
6444
+ scopedTaskArtifactWrite: liveScopedTeeTestLogCommand.scopedTaskArtifactWrite,
6445
+ projectTest: liveScopedTeeTestLogCommand.projectTest,
6446
+ },
6447
+ liveScopedOutsideStatusTestLogCommand: {
6448
+ scopedTaskArtifactWrite:
6449
+ liveScopedOutsideStatusTestLogCommand.scopedTaskArtifactWrite,
6450
+ projectTest: liveScopedOutsideStatusTestLogCommand.projectTest,
6451
+ },
6452
+ conditionalTestResult: {
6453
+ mutationRevision:
6454
+ conditionalTestState.meta.projectVerification?.mutationRevision,
6455
+ boundedReadOnlyTestWrapper:
6456
+ conditionalTestResult.boundedReadOnlyTestWrapper,
6457
+ projectTest: conditionalTestResult.projectTest,
6458
+ },
6459
+ mutatingConditionalTestResult: {
6460
+ mutationRevision:
6461
+ mutatingConditionalTestState.meta.projectVerification?.mutationRevision,
6462
+ projectTest: mutatingConditionalTestResult.projectTest,
6463
+ },
6464
+ outsideScopedGroupTestLogCommand: {
6465
+ mutationRevision:
6466
+ unsafeScopedLogState.meta.projectVerification?.mutationRevision,
6467
+ scopedTaskArtifactWrite:
6468
+ outsideScopedGroupTestLogCommand.scopedTaskArtifactWrite,
6469
+ },
6470
+ sourceWriteAfterScopedLogCommand: {
6471
+ mutationRevision:
6472
+ sourceWriteAfterScopedLogState.meta.projectVerification?.mutationRevision,
6473
+ scopedTaskArtifactWrite:
6474
+ sourceWriteAfterScopedLogCommand.scopedTaskArtifactWrite,
6475
+ },
6476
+ spoofedCapturedStatusCommand: {
6477
+ projectTest: spoofedCapturedStatusCommand.projectTest,
6478
+ },
6184
6479
  nullRedirectValidationCommand:
6185
6480
  nullRedirectValidationCommand.readOnlyArtifactValidation,
6186
6481
  })}`
@@ -4967,6 +4967,407 @@ function normalizeProjectCommand(command = "") {
4967
4967
  return canonicalizeShellCommand(command);
4968
4968
  }
4969
4969
 
4970
+ function shellBraceGroups(value = "") {
4971
+ const text = String(value || "");
4972
+ const groups = [];
4973
+ let quote = "";
4974
+ let escaped = false;
4975
+ let start = -1;
4976
+ let depth = 0;
4977
+
4978
+ const isGroupOpen = (index) => {
4979
+ if (text[index] !== "{" || text[index - 1] === "$") return false;
4980
+ const before = text[index - 1] || "";
4981
+ const after = text[index + 1] || "";
4982
+ return (!before || /[\s;&|()]/u.test(before)) && /\s/u.test(after);
4983
+ };
4984
+ const isGroupClose = (index) => {
4985
+ if (text[index] !== "}") return false;
4986
+ const before = text[index - 1] || "";
4987
+ const after = text[index + 1] || "";
4988
+ return /\s/u.test(before) && (!after || /[\s;&|<>)]/u.test(after));
4989
+ };
4990
+
4991
+ for (let index = 0; index < text.length; index += 1) {
4992
+ const char = text[index];
4993
+ if (quote === "'") {
4994
+ if (char === "'") quote = "";
4995
+ continue;
4996
+ }
4997
+ if (escaped) {
4998
+ escaped = false;
4999
+ continue;
5000
+ }
5001
+ if (char === "\\") {
5002
+ escaped = true;
5003
+ continue;
5004
+ }
5005
+ if (quote === '"') {
5006
+ if (char === '"') quote = "";
5007
+ continue;
5008
+ }
5009
+ if (char === "'" || char === '"') {
5010
+ quote = char;
5011
+ continue;
5012
+ }
5013
+ if (start < 0 && isGroupOpen(index)) {
5014
+ start = index;
5015
+ depth = 1;
5016
+ continue;
5017
+ }
5018
+ if (start >= 0 && isGroupOpen(index)) {
5019
+ depth += 1;
5020
+ continue;
5021
+ }
5022
+ if (start >= 0 && isGroupClose(index)) {
5023
+ depth -= 1;
5024
+ if (depth > 0) continue;
5025
+ groups.push({
5026
+ start,
5027
+ end: index,
5028
+ body: text.slice(start + 1, index).trim(),
5029
+ });
5030
+ start = -1;
5031
+ depth = 0;
5032
+ }
5033
+ }
5034
+ return groups;
5035
+ }
5036
+
5037
+ function unquotedShellControlDelimiter(value = "", keyword = "", startIndex = 0) {
5038
+ const text = String(value || "");
5039
+ const expected = String(keyword || "").toLowerCase();
5040
+ let quote = "";
5041
+ let escaped = false;
5042
+ for (let index = Math.max(0, Number(startIndex || 0)); index < text.length; index += 1) {
5043
+ const char = text[index];
5044
+ if (quote === "'") {
5045
+ if (char === "'") quote = "";
5046
+ continue;
5047
+ }
5048
+ if (escaped) {
5049
+ escaped = false;
5050
+ continue;
5051
+ }
5052
+ if (char === "\\") {
5053
+ escaped = true;
5054
+ continue;
5055
+ }
5056
+ if (quote === '"') {
5057
+ if (char === '"') quote = "";
5058
+ continue;
5059
+ }
5060
+ if (char === "'" || char === '"') {
5061
+ quote = char;
5062
+ continue;
5063
+ }
5064
+ if (char !== ";") continue;
5065
+ const suffix = text.slice(index + 1).match(/^\s*([A-Za-z]+)\b/u);
5066
+ if (String(suffix?.[1] || "").toLowerCase() === expected) return index;
5067
+ }
5068
+ return -1;
5069
+ }
5070
+
5071
+ function boundedTestAvailabilityProbe(value = "") {
5072
+ let command = normalizeProjectCommand(value);
5073
+ if (!command || /(?:`|\$\()/u.test(command)) return false;
5074
+ command = command
5075
+ .replace(/(?:^|\s)(?:\d*>>?|&>>?)\s*(?:"\/dev\/null"|'\/dev\/null'|\/dev\/null)/gu, " ")
5076
+ .trim()
5077
+ .replace(/^(?:[A-Za-z_]\w*=(?:"[^"\n]*"|'[^'\n]*'|[^\s;&|]+)\s*)+/u, "")
5078
+ .trim();
5079
+ const tokens = tokenizeShellWords(command);
5080
+ if (
5081
+ ["command", "which"].includes(String(tokens[0] || "")) &&
5082
+ (tokens[0] !== "command" || tokens[1] === "-v")
5083
+ ) {
5084
+ const target = tokens[0] === "command" ? tokens[2] : tokens[1];
5085
+ return Boolean(target && /^[A-Za-z0-9_.+-]+$/u.test(target) && tokens.length <= 3);
5086
+ }
5087
+ const executable = String(tokens[0] || "").split(/[\\/]/u).at(-1) || "";
5088
+ const codeIndex = tokens.indexOf("-c");
5089
+ if (!/^python(?:\d+(?:\.\d+)*)?$/iu.test(executable) || codeIndex < 1) return false;
5090
+ const code = String(tokens[codeIndex + 1] || "").trim();
5091
+ if (!code || codeIndex + 2 !== tokens.length) return false;
5092
+ return /^(?:import\s+[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*|from\s+[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*\s+import\s+[A-Za-z_]\w*)$/u.test(
5093
+ code
5094
+ );
5095
+ }
5096
+
5097
+ function boundedTestCommandClassification(value = "") {
5098
+ const command = normalizeProjectCommand(value);
5099
+ const executableCommand = command
5100
+ .replace(/^(?:[A-Za-z_]\w*=(?:"[^"\n]*"|'[^'\n]*'|[^\s;&|]+)\s*)+/u, "")
5101
+ .trim();
5102
+ return {
5103
+ command,
5104
+ executableCommand,
5105
+ policy: classifyCommand(executableCommand),
5106
+ };
5107
+ }
5108
+
5109
+ function parseBoundedConditionalTestWrapper(value = "") {
5110
+ let normalized = normalizeProjectCommand(value);
5111
+ if (!normalized) return null;
5112
+ normalized = normalized.replace(
5113
+ /^cd\s+(?:"[^"\n]+"|'[^'\n]+'|[^\s;&|]+)\s*&&\s*/u,
5114
+ ""
5115
+ );
5116
+ if (!/^if\s+/u.test(normalized)) return null;
5117
+ const thenAt = unquotedShellControlDelimiter(normalized, "then", 3);
5118
+ if (thenAt < 0) return null;
5119
+ const thenMatch = normalized.slice(thenAt + 1).match(/^\s*then\b/u);
5120
+ if (!thenMatch) return null;
5121
+ const thenBodyStart = thenAt + 1 + thenMatch[0].length;
5122
+ const elseAt = unquotedShellControlDelimiter(normalized, "else", thenBodyStart);
5123
+ if (elseAt < 0) return null;
5124
+ const elseMatch = normalized.slice(elseAt + 1).match(/^\s*else\b/u);
5125
+ if (!elseMatch) return null;
5126
+ const elseBodyStart = elseAt + 1 + elseMatch[0].length;
5127
+ const fiAt = unquotedShellControlDelimiter(normalized, "fi", elseBodyStart);
5128
+ if (fiAt < 0 || !/^\s*fi\s*$/u.test(normalized.slice(fiAt + 1))) return null;
5129
+
5130
+ const condition = normalized.slice(3, thenAt).trim();
5131
+ const thenCommand = normalizeProjectCommand(
5132
+ normalized.slice(thenBodyStart, elseAt).trim()
5133
+ );
5134
+ const elseCommand = normalizeProjectCommand(
5135
+ normalized.slice(elseBodyStart, fiAt).trim()
5136
+ );
5137
+ if (!boundedTestAvailabilityProbe(condition)) return null;
5138
+ const branches = [thenCommand, elseCommand];
5139
+ const classifications = branches.map((candidate) =>
5140
+ boundedTestCommandClassification(candidate)
5141
+ );
5142
+ const policies = classifications.map((candidate) => candidate.policy);
5143
+ if (
5144
+ branches.some((candidate) => {
5145
+ const sequence = parseTopLevelShellSequence(candidate);
5146
+ return (
5147
+ !candidate ||
5148
+ sequence.openQuote ||
5149
+ sequence.trailingEscape ||
5150
+ sequence.trailingSeparator ||
5151
+ sequence.commands.length !== 1
5152
+ );
5153
+ }) ||
5154
+ policies.some((policy) => policy.substantiveTest !== true)
5155
+ ) {
5156
+ return null;
5157
+ }
5158
+ return {
5159
+ command: thenCommand,
5160
+ alternateCommand: elseCommand,
5161
+ wrappedCommand: normalizeProjectCommand(value),
5162
+ statusSource: "process",
5163
+ semanticallyReadOnly: policies.every(
5164
+ (policy, index) =>
5165
+ !commandCanMutateProjectContent(
5166
+ classifications[index].executableCommand,
5167
+ policy
5168
+ )
5169
+ ),
5170
+ };
5171
+ }
5172
+
5173
+ function capturedStatusEcho(value = "", statusVariable = "") {
5174
+ const label =
5175
+ "(?:(?:[A-Z][A-Z0-9_]{0,31}_)?(?:EXIT|STATUS|RESULT)(?:_CODE)?)";
5176
+ const variable = String(statusVariable || "");
5177
+ const statusOperand = variable
5178
+ ? `\\$(?:\\{${variable.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&")}\\}|${variable.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&")})`
5179
+ : "\\$\\?";
5180
+ return String(value || "").trim().match(
5181
+ new RegExp(
5182
+ `^echo\\s+(?:-n\\s+)?["']?(?<label>${label})\\s*[:=]\\s*${statusOperand}["']?$`,
5183
+ "iu"
5184
+ )
5185
+ );
5186
+ }
5187
+
5188
+ function boundedReadOnlyTestPrefixCommand(value = "") {
5189
+ const command = normalizeProjectCommand(value);
5190
+ if (!command) return false;
5191
+ const tokens = tokenizeShellWords(command);
5192
+ if (
5193
+ ["date", "echo", "printf"].includes(String(tokens[0] || "")) &&
5194
+ !/(?:`|\$\()/u.test(command)
5195
+ ) {
5196
+ return true;
5197
+ }
5198
+ if (
5199
+ ["cat", "grep", "head", "stat", "tail", "wc"].includes(
5200
+ String(tokens[0] || "")
5201
+ ) &&
5202
+ !/(?:`|\$\(|[|<>])/u.test(command)
5203
+ ) {
5204
+ return true;
5205
+ }
5206
+ const policy = classifyCommand(command);
5207
+ return (
5208
+ policy.writesWorkspace !== true &&
5209
+ policy.mayMutateProject !== true &&
5210
+ policy.substantiveTest !== true
5211
+ );
5212
+ }
5213
+
5214
+ function parseCapturedTestExitStatusWrapper(value = "") {
5215
+ const normalized = normalizeProjectCommand(value);
5216
+ if (!normalized) return null;
5217
+ const label = "(?:EXIT|STATUS|RESULT)(?:_CODE)?";
5218
+ for (const group of shellBraceGroups(normalized)) {
5219
+ const sequence = parseTopLevelShellSequence(group.body);
5220
+ if (
5221
+ sequence.openQuote ||
5222
+ sequence.trailingEscape ||
5223
+ (sequence.trailingSeparator && sequence.trailingSeparator !== ";") ||
5224
+ sequence.commands.length < 1
5225
+ ) {
5226
+ continue;
5227
+ }
5228
+ for (let index = 1; index < sequence.commands.length - 1; index += 1) {
5229
+ const statusAssignment = String(sequence.commands[index] || "")
5230
+ .trim()
5231
+ .match(/^([A-Za-z_]\w*)\s*=\s*\$\?$/u);
5232
+ if (!statusAssignment) continue;
5233
+ const statusVariable = statusAssignment[1];
5234
+ const escapedVariable = statusVariable.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
5235
+ const statusEcho = String(sequence.commands[index + 1] || "").trim();
5236
+ const echoPattern = new RegExp(
5237
+ `^echo\\s+(?:-n\\s+)?["']?(?<label>${label})\\s*[:=]\\s*\\$(?:\\{${escapedVariable}\\}|${escapedVariable})["']?$`,
5238
+ "iu"
5239
+ );
5240
+ const echoMatch = statusEcho.match(echoPattern);
5241
+ if (!echoMatch) continue;
5242
+ const outsideGroup = `${normalized.slice(0, group.start)} ${normalized.slice(group.end + 1)}`;
5243
+ if (
5244
+ /\b(?:echo|printf)\b[^;&|\n]{0,240}\b(?:EXIT|STATUS|RESULT)(?:_CODE)?\s*[:=]/iu.test(
5245
+ outsideGroup
5246
+ )
5247
+ ) {
5248
+ continue;
5249
+ }
5250
+ const testCommand = normalizeProjectCommand(sequence.commands[index - 1]);
5251
+ if (boundedTestCommandClassification(testCommand).policy.substantiveTest !== true) continue;
5252
+ return {
5253
+ command: testCommand,
5254
+ wrappedCommand: normalized,
5255
+ label: String(echoMatch.groups?.label || "").toUpperCase(),
5256
+ statusSource: "captured-group",
5257
+ statusVariable,
5258
+ };
5259
+ }
5260
+
5261
+ for (let index = 0; index < sequence.commands.length - 1; index += 1) {
5262
+ const testCommand = normalizeProjectCommand(sequence.commands[index]);
5263
+ const directEcho = capturedStatusEcho(sequence.commands[index + 1]);
5264
+ if (
5265
+ !directEcho ||
5266
+ boundedTestCommandClassification(testCommand).policy.substantiveTest !== true
5267
+ ) {
5268
+ continue;
5269
+ }
5270
+ if (
5271
+ sequence.commands.slice(0, index).some(
5272
+ (candidate) => !boundedReadOnlyTestPrefixCommand(candidate)
5273
+ ) ||
5274
+ sequence.commands.length !== index + 2
5275
+ ) {
5276
+ continue;
5277
+ }
5278
+ const outsideGroup = `${normalized.slice(0, group.start)} ${normalized.slice(group.end + 1)}`;
5279
+ if (
5280
+ /\b(?:echo|printf)\b[^;&|\n]{0,240}\b(?:EXIT|STATUS|RESULT)(?:_CODE)?\s*[:=]/iu.test(
5281
+ outsideGroup
5282
+ )
5283
+ ) {
5284
+ continue;
5285
+ }
5286
+ return {
5287
+ command: testCommand,
5288
+ wrappedCommand: normalized,
5289
+ label: String(directEcho.groups?.label || "").toUpperCase(),
5290
+ statusSource: "captured-group",
5291
+ };
5292
+ }
5293
+
5294
+ const bodyCommands = sequence.commands.map((candidate) =>
5295
+ normalizeProjectCommand(candidate)
5296
+ );
5297
+ const testCommand = bodyCommands.at(-1) || "";
5298
+ if (
5299
+ boundedTestCommandClassification(testCommand).policy.substantiveTest !== true ||
5300
+ bodyCommands.slice(0, -1).some(
5301
+ (candidate) => !boundedReadOnlyTestPrefixCommand(candidate)
5302
+ )
5303
+ ) {
5304
+ continue;
5305
+ }
5306
+ const suffix = normalized
5307
+ .slice(group.end + 1)
5308
+ .replace(
5309
+ /^\s*(?:(?:\d*>>?|&>>?)\s*(?:"[^"\n]+"|'[^'\n]+'|&\d+|[^\s;&|]+)\s*)+/u,
5310
+ ""
5311
+ )
5312
+ .replace(/^\s*;\s*/u, "");
5313
+ const suffixSequence = parseTopLevelShellSequence(suffix);
5314
+ if (
5315
+ !suffix ||
5316
+ suffixSequence.openQuote ||
5317
+ suffixSequence.trailingEscape ||
5318
+ suffixSequence.trailingSeparator ||
5319
+ suffixSequence.commands.length < 2
5320
+ ) {
5321
+ continue;
5322
+ }
5323
+ const statusAssignment = String(suffixSequence.commands[0] || "")
5324
+ .trim()
5325
+ .match(/^([A-Za-z_]\w*)\s*=\s*\$\?$/u);
5326
+ if (!statusAssignment) continue;
5327
+ const statusEcho = capturedStatusEcho(
5328
+ suffixSequence.commands[1],
5329
+ statusAssignment[1]
5330
+ );
5331
+ if (!statusEcho) continue;
5332
+ if (
5333
+ suffixSequence.commands.slice(2).some((candidate) => {
5334
+ if (
5335
+ /\b(?:echo|printf)\b[^;&|\n]{0,240}\b(?:[A-Z][A-Z0-9_]{0,31}_)?(?:EXIT|STATUS|RESULT)(?:_CODE)?\s*[:=]/iu.test(
5336
+ candidate
5337
+ )
5338
+ ) {
5339
+ return true;
5340
+ }
5341
+ return !boundedReadOnlyTestPrefixCommand(candidate);
5342
+ })
5343
+ ) {
5344
+ continue;
5345
+ }
5346
+ return {
5347
+ command: testCommand,
5348
+ wrappedCommand: normalized,
5349
+ label: String(statusEcho.groups?.label || "").toUpperCase(),
5350
+ statusSource: "captured-group",
5351
+ statusVariable: statusAssignment[1],
5352
+ };
5353
+ }
5354
+ return null;
5355
+ }
5356
+
5357
+ function projectTestCommandWrapper(command = "") {
5358
+ return (
5359
+ parseCapturedTestExitStatusWrapper(command) ||
5360
+ parseBoundedConditionalTestWrapper(command)
5361
+ );
5362
+ }
5363
+
5364
+ function projectExitStatusWrapper(command = "") {
5365
+ return (
5366
+ parseNonMutatingExitStatusWrapper(command) ||
5367
+ parseCapturedTestExitStatusWrapper(command)
5368
+ );
5369
+ }
5370
+
4970
5371
  function normalizeLeadingWorkspaceCd(command = "", config = {}) {
4971
5372
  const normalized = normalizeProjectCommand(command);
4972
5373
  const sequence = parseTopLevelShellSequence(normalized);
@@ -5037,7 +5438,8 @@ function isRetainedExactVerificationCommand(command = "", config = {}) {
5037
5438
  export function isSubstantiveTestCommand(command = "", config = {}) {
5038
5439
  if (isRetainedExactVerificationCommand(command, config)) return true;
5039
5440
  const normalized = normalizeProjectCommand(normalizeCommandForPolicy(command, config));
5040
- const text = parseNonMutatingExitStatusWrapper(normalized)?.command || normalized;
5441
+ if (projectTestCommandWrapper(normalized)) return true;
5442
+ const text = projectExitStatusWrapper(normalized)?.command || normalized;
5041
5443
  if (!text) return false;
5042
5444
  const classification = classifyCommand(text);
5043
5445
  if (classification.substantiveTest !== true) return false;
@@ -5142,7 +5544,7 @@ function testRunRepresentsInvalidInvocation(testRun = {}) {
5142
5544
 
5143
5545
  function explicitExitProbeStatus(command = "", result = {}) {
5144
5546
  const normalizedCommand = normalizeProjectCommand(command);
5145
- const exitProbe = parseNonMutatingExitStatusWrapper(normalizedCommand);
5547
+ const exitProbe = projectExitStatusWrapper(normalizedCommand);
5146
5548
  if (!exitProbe) {
5147
5549
  return {
5148
5550
  present: false,
@@ -5152,9 +5554,26 @@ function explicitExitProbeStatus(command = "", result = {}) {
5152
5554
  };
5153
5555
  }
5154
5556
 
5557
+ let status = parseExplicitExitStatus(result.stdout || "");
5558
+ if (status === null && exitProbe.statusSource === "captured-group") {
5559
+ const escapedLabel = String(exitProbe.label || "")
5560
+ .replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
5561
+ const matches = [
5562
+ ...String(result.stdout || "").matchAll(
5563
+ escapedLabel
5564
+ ? new RegExp(
5565
+ `(?:^|\\n)\\s*${escapedLabel}\\s*[:=]\\s*(-?\\d+)\\s*(?=\\n|$)`,
5566
+ "giu"
5567
+ )
5568
+ : /(?:^|\n)\s*(?:EXIT|STATUS|RESULT)(?:_CODE)?\s*[:=]\s*(-?\d+)\s*(?=\n|$)/giu
5569
+ ),
5570
+ ];
5571
+ if (matches.length) status = Number(matches.at(-1)[1]);
5572
+ }
5573
+
5155
5574
  return {
5156
5575
  present: true,
5157
- status: parseExplicitExitStatus(result.stdout || ""),
5576
+ status,
5158
5577
  command: exitProbe.command,
5159
5578
  wrappedCommand: exitProbe.wrappedCommand || exitProbe.command,
5160
5579
  };
@@ -6719,6 +7138,7 @@ export function recordProjectVerificationOutcome(state = {}, toolResult = {}, co
6719
7138
 
6720
7139
  if (toolName === "run_command") {
6721
7140
  const command = normalizeProjectCommand(toolResult.args?.command || "");
7141
+ const testCommandWrapper = projectTestCommandWrapper(command);
6722
7142
  const retainedExactVerification = isRetainedExactVerificationCommand(
6723
7143
  command,
6724
7144
  config
@@ -6832,6 +7252,7 @@ export function recordProjectVerificationOutcome(state = {}, toolResult = {}, co
6832
7252
  command &&
6833
7253
  toolResult.blocked !== true &&
6834
7254
  !retainedExactVerification &&
7255
+ testCommandWrapper?.semanticallyReadOnly !== true &&
6835
7256
  !disposableGeneratedCleanup &&
6836
7257
  !disposableGeneratedVerificationSideEffects &&
6837
7258
  !scopedTaskArtifactWrite &&
@@ -6856,6 +7277,9 @@ export function recordProjectVerificationOutcome(state = {}, toolResult = {}, co
6856
7277
  if (readOnlyArtifactValidation) {
6857
7278
  toolResult.readOnlyArtifactValidation = true;
6858
7279
  }
7280
+ if (testCommandWrapper?.semanticallyReadOnly === true) {
7281
+ toolResult.boundedReadOnlyTestWrapper = true;
7282
+ }
6859
7283
  let requiredBatch = currentRequiredCommandBatch(verification, requiredCommands);
6860
7284
  const activeExecutionContract = state.meta?.activeExecutionContract;
6861
7285
  const activeTurnCommands =
@@ -7396,7 +7820,7 @@ export function recordAlreadyCommittedRepositoryRepair(state = {}, toolResult =
7396
7820
 
7397
7821
  function projectTestCommandKey(command = "") {
7398
7822
  const normalized = normalizeProjectCommand(command);
7399
- const exitProbe = parseNonMutatingExitStatusWrapper(normalized);
7823
+ const exitProbe = projectExitStatusWrapper(normalized);
7400
7824
  const invocation = normalizeProjectCommand(exitProbe?.command || normalized)
7401
7825
  // These wrappers alter bytecode/output handling, not the tests selected or
7402
7826
  // executed. Treating them as distinct suites can leave an old failure
@@ -12777,40 +13201,106 @@ function commandWritesOnlyEvidenceMatching(command = "", pathMatches = () => fal
12777
13201
  for (const match of normalized.matchAll(
12778
13202
  /(?:^|[\s;&|])([A-Za-z_]\w*)\s*=\s*("[^"\n]+"|'[^'\n]+'|[^\s;&|]+)/g
12779
13203
  )) {
12780
- assignments.set(
12781
- match[1],
12782
- String(match[2] || "").replace(/^["']|["']$/g, "")
12783
- );
13204
+ assignments.set(match[1], String(match[2] || "").replace(/^["']|["']$/g, ""));
12784
13205
  }
12785
- const resolveTarget = (value = "") => {
12786
- const target = String(value || "")
13206
+ const resolveTarget = (value = "", seen = new Set()) => {
13207
+ let target = String(value || "")
12787
13208
  .trim()
12788
13209
  .replace(/^["']|["']$/g, "");
12789
- const variable = target.match(/^\$(?:\{([A-Za-z_]\w*)\}|([A-Za-z_]\w*))$/);
12790
- return variable
12791
- ? String(assignments.get(variable[1] || variable[2]) || "")
12792
- : target;
13210
+ if (!target || /\$\(|`/u.test(target)) return "";
13211
+ for (let depth = 0; depth < 8; depth += 1) {
13212
+ let unresolved = false;
13213
+ let changed = false;
13214
+ const expanded = target.replace(
13215
+ /\$(?:\{([A-Za-z_]\w*)\}|([A-Za-z_]\w*))/gu,
13216
+ (match, bracedName, bareName) => {
13217
+ const name = bracedName || bareName;
13218
+ if (!assignments.has(name) || seen.has(name)) {
13219
+ unresolved = true;
13220
+ return match;
13221
+ }
13222
+ const nextSeen = new Set(seen);
13223
+ nextSeen.add(name);
13224
+ const resolved = resolveTarget(assignments.get(name), nextSeen);
13225
+ if (!resolved) {
13226
+ unresolved = true;
13227
+ return match;
13228
+ }
13229
+ changed = true;
13230
+ return resolved;
13231
+ }
13232
+ );
13233
+ target = expanded;
13234
+ if (unresolved) return "";
13235
+ if (!changed) return target;
13236
+ }
13237
+ return "";
12793
13238
  };
12794
- const tokens = tokenizeShellWords(normalized);
12795
- if (tokens[0] === "tee") {
13239
+ const evidenceTargetsFromTee = (tokens = []) => {
13240
+ if (tokens[0] !== "tee") return [];
12796
13241
  let index = 1;
12797
13242
  if (["-a", "--append"].includes(tokens[index])) index += 1;
12798
13243
  if (tokens[index] === "--") index += 1;
12799
- const targets = tokens.slice(index).map(resolveTarget);
13244
+ return tokens.slice(index).map((target) => resolveTarget(target));
13245
+ };
13246
+ const evidenceTargetsFromMkdir = (tokens = []) =>
13247
+ tokens[0] === "mkdir"
13248
+ ? tokens
13249
+ .slice(1)
13250
+ .filter((token) => token !== "-p" && token !== "--")
13251
+ .map((target) => resolveTarget(target))
13252
+ : [];
13253
+ const boundedEchoProbeIsReadOnly = (segment = "") => {
13254
+ const source = String(segment || "").trim();
13255
+ const sourceTokens = tokenizeShellWords(source);
13256
+ if (!["echo", "printf"].includes(String(sourceTokens[0] || ""))) return false;
13257
+ if (source.includes("`") || !source.includes("$(")) return !source.includes("`");
13258
+ const substitutions = [];
13259
+ const remainder = source.replace(/\$\(([^()]*)\)/gu, (match, body) => {
13260
+ substitutions.push(String(body || ""));
13261
+ return "";
13262
+ });
13263
+ if (!substitutions.length || remainder.includes("$(")) return false;
13264
+ return substitutions.every((body) => {
13265
+ const sequence = parseTopLevelShellSequence(body);
13266
+ if (
13267
+ sequence.openQuote ||
13268
+ sequence.trailingEscape ||
13269
+ sequence.trailingSeparator ||
13270
+ !sequence.commands.length
13271
+ ) {
13272
+ return false;
13273
+ }
13274
+ return sequence.commands.every((candidate) => {
13275
+ const candidateTokens = tokenizeShellWords(candidate);
13276
+ if (["echo", "printf"].includes(String(candidateTokens[0] || ""))) {
13277
+ return !String(candidate || "").includes("$(") && !String(candidate || "").includes("`");
13278
+ }
13279
+ if (["[", "test"].includes(String(candidateTokens[0] || ""))) {
13280
+ const operands = candidateTokens.filter(
13281
+ (token) => !["[", "]", "test", "!", "-e", "-f", "-r", "-s"].includes(token)
13282
+ );
13283
+ return operands.length > 0 && operands.every((operand) => Boolean(resolveTarget(operand)));
13284
+ }
13285
+ const policy = classifyCommand(candidate);
13286
+ return policy.writesWorkspace !== true && policy.mayMutateProject !== true;
13287
+ });
13288
+ });
13289
+ };
13290
+ const tokens = tokenizeShellWords(normalized);
13291
+ if (tokens[0] === "tee") {
13292
+ const targets = evidenceTargetsFromTee(tokens);
12800
13293
  return targets.length > 0 && targets.every(pathMatches);
12801
13294
  }
12802
13295
  if (tokens[0] === "mkdir") {
12803
- const targets = tokens
12804
- .slice(1)
12805
- .filter((token) => token !== "-p" && token !== "--")
12806
- .map(resolveTarget);
13296
+ const targets = evidenceTargetsFromMkdir(tokens);
12807
13297
  return targets.length > 0 && targets.every(pathMatches);
12808
13298
  }
12809
13299
 
12810
13300
  let strippedEvidenceRedirect = false;
12811
13301
  let rejectedRedirect = false;
12812
13302
  const withoutEvidenceRedirects = normalized.replace(
12813
- /(^|\s)(?:\d*>>?|&>>?)\s*("[^"]+"|'[^']+'|[^\s;&|]+)/g,
13303
+ /(^|\s)(?:\d*>>?|&>>?)\s*("[^"]+"|'[^']+'|&\d+|[^\s;&|]+)/g,
12814
13304
  (match, prefix, target) => {
12815
13305
  const resolvedTarget = resolveTarget(target);
12816
13306
  if (/^(?:&\d+|\/dev\/null)$/u.test(resolvedTarget)) return prefix;
@@ -12822,15 +13312,19 @@ function commandWritesOnlyEvidenceMatching(command = "", pathMatches = () => fal
12822
13312
  return prefix;
12823
13313
  }
12824
13314
  ).trim();
12825
- if (rejectedRedirect || !strippedEvidenceRedirect || !withoutEvidenceRedirects) {
13315
+ if (rejectedRedirect || !withoutEvidenceRedirects) {
12826
13316
  return false;
12827
13317
  }
12828
13318
  const sequence = parseTopLevelShellSequence(withoutEvidenceRedirects);
12829
13319
  if (sequence.openQuote || sequence.trailingEscape || sequence.trailingSeparator) {
12830
13320
  return false;
12831
13321
  }
12832
- return sequence.commands.every((segment) => {
13322
+ let sawEvidenceWrite = strippedEvidenceRedirect;
13323
+ const safeSequence = sequence.commands.every((segment) => {
12833
13324
  const withoutAssignments = String(segment || "")
13325
+ .trim()
13326
+ .replace(/^\{\s*/u, "")
13327
+ .replace(/\s*\}$/u, "")
12834
13328
  .trim()
12835
13329
  .replace(
12836
13330
  /^(?:[A-Za-z_]\w*=(?:"[^"\n]*"|'[^'\n]*'|[^\s;&|]+)\s*)+/u,
@@ -12839,6 +13333,20 @@ function commandWritesOnlyEvidenceMatching(command = "", pathMatches = () => fal
12839
13333
  .trim();
12840
13334
  if (!withoutAssignments) return true;
12841
13335
  const commandTokens = tokenizeShellWords(withoutAssignments);
13336
+ if (boundedReadOnlyTestPrefixCommand(withoutAssignments)) return true;
13337
+ const teeTargets = evidenceTargetsFromTee(commandTokens);
13338
+ if (teeTargets.length) {
13339
+ const safe = teeTargets.every(pathMatches);
13340
+ if (safe) sawEvidenceWrite = true;
13341
+ return safe;
13342
+ }
13343
+ const mkdirTargets = evidenceTargetsFromMkdir(commandTokens);
13344
+ if (mkdirTargets.length) {
13345
+ const safe = mkdirTargets.every(pathMatches);
13346
+ if (safe) sawEvidenceWrite = true;
13347
+ return safe;
13348
+ }
13349
+ if (boundedEchoProbeIsReadOnly(withoutAssignments)) return true;
12842
13350
  if (
12843
13351
  ["cat", "cd", "head", "ls", "stat", "tail", "wc"].includes(
12844
13352
  String(commandTokens[0] || "")
@@ -12852,6 +13360,7 @@ function commandWritesOnlyEvidenceMatching(command = "", pathMatches = () => fal
12852
13360
  underlyingPolicy.mayMutateProject !== true
12853
13361
  );
12854
13362
  });
13363
+ return safeSequence && sawEvidenceWrite;
12855
13364
  }
12856
13365
 
12857
13366
  function commandWritesOnlyPrivateVerificationEvidence(command = "") {