@lazyingart/agintiflow 0.20.239 → 0.20.240

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.239",
3
+ "version": "0.20.240",
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",
@@ -2302,6 +2302,112 @@ try {
2302
2302
  shellMutationState.meta.projectVerification?.mutationRevision === 1,
2303
2303
  "metadata-only Git chain with observational output invalidated current verification"
2304
2304
  );
2305
+ assert(
2306
+ classifyCommand("md5sum output/report.pdf").writesWorkspace === false &&
2307
+ classifyCommand("md5sum -c .aginti/verification/source-hashes.txt").writesWorkspace === false &&
2308
+ classifyCommand("diff .aginti/verification/run-1.txt .aginti/verification/run-2.txt").writesWorkspace === false,
2309
+ "checksum or diff evidence probes were not classified as read-only"
2310
+ );
2311
+ const privateEvidenceState = {
2312
+ meta: {
2313
+ goalContract: { revision: 1 },
2314
+ projectVerification: { requiredCommands: ["bash build.sh"] },
2315
+ },
2316
+ };
2317
+ const privateEvidenceBuild = {
2318
+ toolName: "run_command",
2319
+ ok: true,
2320
+ exitCode: 0,
2321
+ args: { command: "bash build.sh" },
2322
+ stdout: "build complete\n",
2323
+ stderr: "",
2324
+ };
2325
+ recordProjectVerificationOutcome(privateEvidenceState, privateEvidenceBuild, {
2326
+ commandCwd: workspace,
2327
+ taskProfile: "writing",
2328
+ allowShellTool: true,
2329
+ sandboxMode: "host",
2330
+ });
2331
+ const privateEvidenceRevision =
2332
+ privateEvidenceState.meta.projectVerification?.mutationRevision;
2333
+ const privateEvidenceCommand = {
2334
+ toolName: "run_command",
2335
+ ok: true,
2336
+ exitCode: 0,
2337
+ args: {
2338
+ command:
2339
+ "md5sum output/report.pdf > .aginti/verification/hashes-final.txt && cat .aginti/verification/hashes-final.txt && diff .aginti/verification/hashes-run1.txt .aginti/verification/hashes-final.txt && md5sum -c .aginti/verification/source-hashes.txt && git status --porcelain",
2340
+ },
2341
+ stdout: "MATCH\n",
2342
+ stderr: "",
2343
+ };
2344
+ recordProjectVerificationOutcome(privateEvidenceState, privateEvidenceCommand, {
2345
+ commandCwd: workspace,
2346
+ taskProfile: "writing",
2347
+ allowShellTool: true,
2348
+ sandboxMode: "host",
2349
+ });
2350
+ const privateEvidenceWrite = {
2351
+ toolName: "write_file",
2352
+ ok: true,
2353
+ path: ".aginti/verification/visual-check.txt",
2354
+ changes: [
2355
+ {
2356
+ path: ".aginti/verification/visual-check.txt",
2357
+ created: true,
2358
+ beforeHash: "",
2359
+ afterHash: "private-evidence",
2360
+ },
2361
+ ],
2362
+ };
2363
+ recordProjectVerificationOutcome(privateEvidenceState, privateEvidenceWrite, {
2364
+ commandCwd: workspace,
2365
+ taskProfile: "writing",
2366
+ });
2367
+ const privateEvidenceContract = augmentScsTaskContractWithProjectVerification(
2368
+ {
2369
+ requiresExternalEvidence: false,
2370
+ requiredEvidence: [],
2371
+ requiredToolCalls: [],
2372
+ requiredGitActions: [],
2373
+ taskProfile: "writing",
2374
+ },
2375
+ privateEvidenceState,
2376
+ { taskProfile: "writing" }
2377
+ );
2378
+ const privateEvidenceLedger = buildScsEvidenceLedger({
2379
+ state: {
2380
+ messages: [privateEvidenceBuild, privateEvidenceCommand, privateEvidenceWrite].map((result) =>
2381
+ toolMessage(result)
2382
+ ),
2383
+ },
2384
+ });
2385
+ assert(
2386
+ privateEvidenceRevision === 1 &&
2387
+ privateEvidenceState.meta.projectVerification?.mutationRevision === 1 &&
2388
+ privateEvidenceState.meta.projectVerification?.requiredCommandBatch?.complete === true &&
2389
+ evaluateScsEvidence(privateEvidenceContract, privateEvidenceLedger).ok,
2390
+ "ignored private verification evidence invalidated a successful canonical build"
2391
+ );
2392
+ const publicEvidenceMutation = {
2393
+ toolName: "run_command",
2394
+ ok: true,
2395
+ exitCode: 0,
2396
+ args: { command: "md5sum output/report.pdf > output/hashes-final.txt" },
2397
+ stdout: "",
2398
+ stderr: "",
2399
+ };
2400
+ recordProjectVerificationOutcome(privateEvidenceState, publicEvidenceMutation, {
2401
+ commandCwd: workspace,
2402
+ taskProfile: "writing",
2403
+ allowShellTool: true,
2404
+ sandboxMode: "host",
2405
+ });
2406
+ assert(
2407
+ privateEvidenceState.meta.projectVerification?.mutationRevision === 2 &&
2408
+ !privateEvidenceState.meta.projectVerification?.requiredCommandBatch,
2409
+ "a non-private output write was incorrectly exempted from project mutation tracking"
2410
+ );
2305
2411
  const gitCheckoutResult = {
2306
2412
  toolName: "run_command",
2307
2413
  ok: true,
@@ -5991,6 +5991,49 @@ const WORKTREE_CHANGING_GIT_ACTIONS = new Set([
5991
5991
  "switch",
5992
5992
  ]);
5993
5993
 
5994
+ function isPrivateVerificationEvidencePath(value = "") {
5995
+ const normalized = String(value || "")
5996
+ .trim()
5997
+ .replace(/^["']|["']$/g, "")
5998
+ .replace(/\\/g, "/")
5999
+ .replace(/^\.\//, "");
6000
+ return Boolean(
6001
+ normalized === ".aginti/verification" ||
6002
+ normalized.startsWith(".aginti/verification/") ||
6003
+ normalized.includes("/.aginti/verification/")
6004
+ );
6005
+ }
6006
+
6007
+ function commandWritesOnlyPrivateVerificationEvidence(command = "") {
6008
+ const normalized = String(command || "").trim();
6009
+ if (!normalized) return false;
6010
+ const tokens = tokenizeShellWords(normalized);
6011
+ if (tokens[0] === "tee") {
6012
+ let index = 1;
6013
+ if (["-a", "--append"].includes(tokens[index])) index += 1;
6014
+ if (tokens[index] === "--") index += 1;
6015
+ const targets = tokens.slice(index);
6016
+ return targets.length > 0 && targets.every(isPrivateVerificationEvidencePath);
6017
+ }
6018
+ if (tokens[0] === "mkdir") {
6019
+ const targets = tokens.slice(1).filter((token) => token !== "-p" && token !== "--");
6020
+ return targets.length > 0 && targets.every(isPrivateVerificationEvidencePath);
6021
+ }
6022
+
6023
+ let strippedPrivateRedirect = false;
6024
+ const withoutPrivateRedirects = normalized.replace(
6025
+ /(^|\s)(?:\d*>>?|&>>?)\s*("[^"]+"|'[^']+'|[^\s;&|]+)/g,
6026
+ (match, prefix, target) => {
6027
+ if (!isPrivateVerificationEvidencePath(target)) return match;
6028
+ strippedPrivateRedirect = true;
6029
+ return prefix;
6030
+ }
6031
+ ).trim();
6032
+ if (!strippedPrivateRedirect || !withoutPrivateRedirects) return false;
6033
+ const underlyingPolicy = classifyCommand(withoutPrivateRedirects);
6034
+ return underlyingPolicy.writesWorkspace !== true && underlyingPolicy.mayMutateProject !== true;
6035
+ }
6036
+
5994
6037
  function commandCanMutateProjectContent(command = "", commandPolicy = {}) {
5995
6038
  if (commandPolicy.writesWorkspace !== true && commandPolicy.mayMutateProject !== true) return false;
5996
6039
  const sequence = parseTopLevelShellSequence(String(command || ""));
@@ -6004,6 +6047,7 @@ function commandCanMutateProjectContent(command = "", commandPolicy = {}) {
6004
6047
  commandCanMutateProjectContent(segment, classifyCommand(segment))
6005
6048
  );
6006
6049
  }
6050
+ if (commandWritesOnlyPrivateVerificationEvidence(command)) return false;
6007
6051
  const category = String(commandPolicy.category || "");
6008
6052
  if (!["git-workflow", "git-remote"].includes(category)) return true;
6009
6053
  if (/\bgit\s+clone\b/i.test(String(command || ""))) return true;
@@ -6490,7 +6534,7 @@ function successfulProjectMutationPaths(toolResult = {}) {
6490
6534
  [
6491
6535
  toolResult.path,
6492
6536
  ...actualChanges.flatMap((change) => [change.path, change.fromPath]),
6493
- ].filter(Boolean)
6537
+ ].filter((candidate) => candidate && !isPrivateVerificationEvidencePath(candidate))
6494
6538
  ),
6495
6539
  ];
6496
6540
  }
@@ -108,17 +108,31 @@ function isReadOnlyUniqFilter(command = "") {
108
108
  );
109
109
  }
110
110
 
111
- function isReadOnlySha256Command(command = "") {
111
+ function isReadOnlyDigestCommand(command = "") {
112
112
  const normalized = stripBenignRedirections(command);
113
113
  if (hasActiveShellExpansion(normalized)) return false;
114
114
  const tokens = tokenizeShellWords(normalized);
115
- if (tokens[0] !== "sha256sum" || tokens.length < 2) return false;
116
- const paths = tokens.slice(1).filter((token) => token !== "--");
115
+ if (!["md5sum", "sha256sum"].includes(tokens[0]) || tokens.length < 2) return false;
116
+ let index = 1;
117
+ if (["-c", "--check"].includes(tokens[index])) index += 1;
118
+ if (tokens[index] === "--") index += 1;
119
+ const paths = tokens.slice(index);
117
120
  return paths.length > 0 && paths.every((token) =>
118
121
  !token.startsWith("-") && READ_ONLY_FOR_LOOP_LITERAL_PATTERN.test(token)
119
122
  );
120
123
  }
121
124
 
125
+ function isReadOnlyDiffCommand(command = "") {
126
+ const normalized = stripBenignRedirections(command);
127
+ if (hasActiveShellExpansion(normalized)) return false;
128
+ const tokens = tokenizeShellWords(normalized);
129
+ if (tokens[0] !== "diff" || tokens.length < 3) return false;
130
+ const operands = tokens.slice(1).filter((token) => token !== "--" && !token.startsWith("-"));
131
+ return operands.length === 2 && operands.every((token) =>
132
+ READ_ONLY_FOR_LOOP_LITERAL_PATTERN.test(token)
133
+ );
134
+ }
135
+
122
136
  function isReadOnlyFindCommand(command = "") {
123
137
  const normalized = stripBenignRedirections(command);
124
138
  if (!/^find\s+/.test(normalized)) return false;
@@ -1511,7 +1525,8 @@ function classifySimpleCommand(normalized) {
1511
1525
  isReadOnlyPrintfCommand(commandForPatternMatching) ||
1512
1526
  isReadOnlyTrDeleteFilter(commandForPatternMatching) ||
1513
1527
  isReadOnlyUniqFilter(commandForPatternMatching) ||
1514
- isReadOnlySha256Command(commandForPatternMatching) ||
1528
+ isReadOnlyDigestCommand(commandForPatternMatching) ||
1529
+ isReadOnlyDiffCommand(commandForPatternMatching) ||
1515
1530
  isReadOnlyFindCommand(normalized) ||
1516
1531
  (!hasActiveShellExpansion(benignRedirectCommand) && isReadOnlyShellCondition(benignRedirectCommand))
1517
1532
  ) {