@lazyingart/agintiflow 0.20.273 → 0.20.275

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.273",
3
+ "version": "0.20.275",
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",
@@ -6483,6 +6483,12 @@ try {
6483
6483
  }),
6484
6484
  "a direct clean-worktree assertion was not classified when the traceback omitted the Git helper call"
6485
6485
  );
6486
+ assert(
6487
+ failedTestRequiresCleanRepositoryState({
6488
+ failureSummary: "acceptance failed: repository is not clean",
6489
+ }),
6490
+ "a concise authoritative acceptance failure did not activate repository-state repair"
6491
+ );
6486
6492
  assert(
6487
6493
  !failedTestRequiresCleanRepositoryState({
6488
6494
  failureSummary: "The generated prose says the repository worktree is not clean.",
@@ -9789,6 +9795,20 @@ try {
9789
9795
  !shouldReviewToolResult(malformedReadOnlyCheck, { meta: {} }),
9790
9796
  "SCS should let the normal agent loop repair simple shell quoting mistakes"
9791
9797
  );
9798
+ const prospectivePatchSyntaxCorrection = {
9799
+ toolName: "apply_patch",
9800
+ ok: false,
9801
+ blocked: false,
9802
+ recoverable: true,
9803
+ stopRun: false,
9804
+ category: "python-syntax-regression",
9805
+ error: "Exact Python patch failed prospective syntax validation.",
9806
+ diagnosticHint: "SyntaxError: unterminated string literal",
9807
+ };
9808
+ assert(
9809
+ !shouldReviewToolResult(prospectivePatchSyntaxCorrection, { meta: {} }),
9810
+ "SCS replanned instead of letting the agent correct a deterministic prospective patch rejection"
9811
+ );
9792
9812
  const boundedSearchRecovery = {
9793
9813
  toolName: "run_command",
9794
9814
  ok: false,
@@ -1826,6 +1826,28 @@ assertStrict.deepEqual(
1826
1826
  "the external validator read was not schema-constrained to its exact path"
1827
1827
  );
1828
1828
 
1829
+ const canonicalRepairPathAliasTools = selectProgressiveTools(allTools, {
1830
+ config: {
1831
+ provider: "deepseek",
1832
+ commandCwd: "/tmp/aginti-canonical-repair",
1833
+ testFailureRepairActive: true,
1834
+ testFailureRepairMutationRequired: true,
1835
+ testFailureRepairOptionalRereadPaths: ["build_deck.py"],
1836
+ },
1837
+ goal: "Correct the canonical producer after a prospective patch rejection.",
1838
+ profile: "slides",
1839
+ });
1840
+ sameNames(
1841
+ canonicalRepairPathAliasTools,
1842
+ ["read_file", "apply_patch", "finish"],
1843
+ "a canonical repair reread did not preserve its bounded tool surface"
1844
+ );
1845
+ assertStrict.deepEqual(
1846
+ canonicalRepairPathAliasTools[0].function.parameters.properties.path.enum,
1847
+ ["build_deck.py", "/tmp/aginti-canonical-repair/build_deck.py"],
1848
+ "the exact in-workspace absolute alias was not accepted for the canonical repair path"
1849
+ );
1850
+
1829
1851
  const failedTestPatchContextTools = selectProgressiveTools(allTools, {
1830
1852
  config: {
1831
1853
  provider: "localllm",
@@ -1986,6 +2008,54 @@ assert(
1986
2008
  ),
1987
2009
  "repository-state repair did not explain the bounded Git workflow"
1988
2010
  );
2011
+ const conciseRepositoryStateRepairRuntime = nextStepRuntimeConfig(
2012
+ { provider: "deepseek", taskProfile: "slides" },
2013
+ {
2014
+ meta: {
2015
+ projectVerification: {
2016
+ mutationRevision: 18,
2017
+ testRuns: [{
2018
+ command: "python acceptance.py --root .",
2019
+ mutationRevision: 18,
2020
+ passed: false,
2021
+ failureEvidenceVersion: 2,
2022
+ failureSignature: "concise-repository-state-gate",
2023
+ failureSummary: "acceptance failed: repository is not clean",
2024
+ }],
2025
+ },
2026
+ failedTestRecoveryPacket: {
2027
+ packetVersion: 15,
2028
+ mutationRevision: 18,
2029
+ failureSignature: "concise-repository-state-gate",
2030
+ content: "Retained canonical source evidence from the prior content failure.",
2031
+ },
2032
+ toolLoop: {
2033
+ stagnationEpoch: 4,
2034
+ recent: [],
2035
+ },
2036
+ },
2037
+ messages: [],
2038
+ }
2039
+ );
2040
+ assertStrict.equal(
2041
+ conciseRepositoryStateRepairRuntime.testFailureRepositoryStateRepair,
2042
+ true,
2043
+ "a concise acceptance failure remained in canonical-source repair mode"
2044
+ );
2045
+ assertStrict.equal(
2046
+ conciseRepositoryStateRepairRuntime.testFailureRepairMutationRequired,
2047
+ false,
2048
+ "stale retained source evidence overrode a clean-repository repair gate"
2049
+ );
2050
+ sameNames(
2051
+ selectProgressiveTools(allTools, {
2052
+ config: conciseRepositoryStateRepairRuntime,
2053
+ goal: "Commit the accepted presentation and leave the repository clean.",
2054
+ profile: "slides",
2055
+ }),
2056
+ ["run_command", "finish"],
2057
+ "a concise clean-repository acceptance failure exposed content mutation tools"
2058
+ );
1989
2059
  const taskOwnedRepositoryState = {
1990
2060
  meta: {
1991
2061
  goalContract: { revision: 6 },
@@ -6306,6 +6306,9 @@ export function failedTestRequiresCleanRepositoryState(testRun = {}) {
6306
6306
  const directCleanStateAssertion =
6307
6307
  /(?:assertionerror|assert(?:ion)?(?:\s+failed)?)[^.!;]{0,200}(?:(?:project|repository)\s+)?(?:work\s*tree|worktree|repository)[^.!;]{0,80}(?:is\s+not\s+clean|must\s+be\s+clean|expected\s+(?:to\s+be\s+)?clean)\b/i.test(summary);
6308
6308
  if (directCleanStateAssertion) return true;
6309
+ const authoritativeCleanStateFailure =
6310
+ /(?:^|\b)(?:acceptance|validation|verification|contract|test|check)\s+failed\s*:[^.!;]{0,200}(?:(?:project|repository)\s+)?(?:work\s*tree|worktree|repository)[^.!;]{0,80}(?:is\s+not\s+clean|must\s+be\s+clean|expected\s+(?:to\s+be\s+)?clean)\b/i.test(summary);
6311
+ if (authoritativeCleanStateFailure) return true;
6309
6312
  const invokesShortStatus =
6310
6313
  /git[a-z_]*\s*\([^)]*["']status["'][^)]*(?:["']--short["']|["']--porcelain(?:=[^"']+)?["'])[^)]*\)/i.test(summary) ||
6311
6314
  /\bgit\s+status\s+(?:--short|--porcelain(?:=\S+)?)\b/i.test(summary);
@@ -1,3 +1,4 @@
1
+ import path from "node:path";
1
2
  import {
2
3
  hasLocalResearchWorkspaceIntent,
3
4
  shouldStartWithDeepResearch,
@@ -772,6 +773,25 @@ function constrainReadFilePaths(tool, paths, phase) {
772
773
  };
773
774
  }
774
775
 
776
+ function exactWorkspacePathAliases(paths = [], commandCwd = "") {
777
+ const workspaceRoot = String(commandCwd || "").trim()
778
+ ? path.resolve(String(commandCwd))
779
+ : "";
780
+ const aliases = [];
781
+ for (const item of paths) {
782
+ const normalized = String(item || "").replace(/\\/g, "/").trim();
783
+ if (!normalized) continue;
784
+ aliases.push(normalized);
785
+ if (!workspaceRoot || path.isAbsolute(normalized)) continue;
786
+ const absolute = path.resolve(workspaceRoot, normalized);
787
+ const relative = path.relative(workspaceRoot, absolute);
788
+ if (relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative))) {
789
+ aliases.push(absolute.replace(/\\/g, "/"));
790
+ }
791
+ }
792
+ return aliases.filter((item, index, items) => items.indexOf(item) === index);
793
+ }
794
+
775
795
  function escapeRegex(value = "") {
776
796
  return String(value).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
777
797
  }
@@ -2028,11 +2048,13 @@ export function selectProgressiveTools(
2028
2048
  .filter((item, index, items) => items.indexOf(item) === index)
2029
2049
  .slice(0, 3)
2030
2050
  : [];
2031
- const boundedRepairReadPaths = [
2032
- ...diagnosticReadPaths,
2033
- ...(repairContextPaths.length ? repairContextPaths : optionalRepairRereadPaths),
2034
- ]
2035
- .filter((item, index, items) => items.indexOf(item) === index)
2051
+ const boundedRepairReadPaths = exactWorkspacePathAliases(
2052
+ [
2053
+ ...diagnosticReadPaths,
2054
+ ...(repairContextPaths.length ? repairContextPaths : optionalRepairRereadPaths),
2055
+ ],
2056
+ config.commandCwd
2057
+ )
2036
2058
  .slice(0, 8);
2037
2059
  const constrainedRepairRead = boundedRepairReadPaths.length
2038
2060
  ? constrainReadFilePaths(
@@ -1156,10 +1156,28 @@ export function shouldRequestScsReplan(decision = {}) {
1156
1156
  return ["rethink_plan", "reject_phase", "finish_rejected"].includes(String(decision?.decision || ""));
1157
1157
  }
1158
1158
 
1159
+ export function isRecoverablePatchCorrectionResult(toolResult = {}) {
1160
+ if (
1161
+ String(toolResult?.toolName || "") !== "apply_patch" ||
1162
+ toolResult?.ok !== false ||
1163
+ toolResult?.recoverable !== true ||
1164
+ toolResult?.blocked === true ||
1165
+ toolResult?.stopRun === true
1166
+ ) {
1167
+ return false;
1168
+ }
1169
+ return new Set([
1170
+ "ambiguous-declaration-token-patch",
1171
+ "ambiguous-python-main-guard-patch",
1172
+ "python-syntax-regression",
1173
+ ]).has(String(toolResult?.category || ""));
1174
+ }
1175
+
1159
1176
  export function shouldReviewToolResult(toolResult, state = {}) {
1160
1177
  if (!toolResult || toolResult.done) return false;
1161
1178
  if (toolResult.permissionAdvice?.autoRecover) return false;
1162
1179
  if (isRecoverableShellToolResult(toolResult)) return false;
1180
+ if (isRecoverablePatchCorrectionResult(toolResult)) return false;
1163
1181
  if (toolResult.ok === false || toolResult.blocked || toolResult.error || toolResult.reason) return true;
1164
1182
  if (isSuspiciousBroadBrowserToolResult(toolResult)) return true;
1165
1183
  // A later successful call is progress, even when another call using the same