@lazyingart/agintiflow 0.20.319 → 0.20.321

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.319",
3
+ "version": "0.20.321",
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",
@@ -4615,6 +4615,46 @@ try {
4615
4615
  mutatingPipedTestResult.nonAuthoritativeTestOutputPipeline !== true,
4616
4616
  "a source mutation appended to an unsafe test pipeline escaped revision tracking"
4617
4617
  );
4618
+ const workspaceCdWrappedTestCommand =
4619
+ `cd ${workspace} && PYTHONPATH=src python -m pytest tests/test_wechat_document_reader.py -v; echo "EXIT=$?"`;
4620
+ assert(
4621
+ isSubstantiveTestCommand(workspaceCdWrappedTestCommand, {
4622
+ commandCwd: workspace,
4623
+ }),
4624
+ "a safe explicit-status test wrapper lost test identity behind a workspace cd"
4625
+ );
4626
+ const workspaceCdWrappedTestState = {
4627
+ meta: { goalContract: { revision: 1 } },
4628
+ };
4629
+ const workspaceCdWrappedTestResult = {
4630
+ toolName: "run_command",
4631
+ ok: true,
4632
+ exitCode: 0,
4633
+ args: { command: workspaceCdWrappedTestCommand },
4634
+ stdout: "7 passed in 0.06s\nEXIT=0\n",
4635
+ stderr: "",
4636
+ projectMutationPaths: [],
4637
+ commandPolicy: classifyCommand(workspaceCdWrappedTestCommand),
4638
+ };
4639
+ recordProjectVerificationOutcome(
4640
+ workspaceCdWrappedTestState,
4641
+ workspaceCdWrappedTestResult,
4642
+ {
4643
+ commandCwd: workspace,
4644
+ taskProfile: "qa",
4645
+ allowShellTool: true,
4646
+ sandboxMode: "host",
4647
+ }
4648
+ );
4649
+ assert(
4650
+ workspaceCdWrappedTestResult.projectTest?.passed === true &&
4651
+ workspaceCdWrappedTestState.meta.projectVerification?.testRuns?.length === 1,
4652
+ `a successful workspace-cd status wrapper did not produce one passing test run: ${JSON.stringify({
4653
+ projectTest: workspaceCdWrappedTestResult.projectTest,
4654
+ testRuns:
4655
+ workspaceCdWrappedTestState.meta.projectVerification?.testRuns,
4656
+ })}`
4657
+ );
4618
4658
  const pipedUnittestCommand =
4619
4659
  "python3 -m unittest discover -s tests -p 'test_wechat_document_reader.py' -v 2>&1 | tail -14; echo \"EXIT=${PIPESTATUS[0]}\"";
4620
4660
  assert(
@@ -167,6 +167,53 @@ assert.equal(
167
167
  );
168
168
  fs.rmSync(educationWorkspace, { recursive: true, force: true });
169
169
 
170
+ const crowdedWorkspace = fs.mkdtempSync(
171
+ path.join(os.tmpdir(), "aginti-crowded-scoped-artifact-")
172
+ );
173
+ const crowdedArtifactRoot = path.join(crowdedWorkspace, "output", "task-artifacts");
174
+ const crowdedReportDir = path.join(crowdedArtifactRoot, "reports", "final");
175
+ fs.mkdirSync(crowdedReportDir, { recursive: true });
176
+ for (let index = 0; index < 3005; index += 1) {
177
+ fs.writeFileSync(
178
+ path.join(crowdedWorkspace, `unrelated-${String(index).padStart(4, "0")}.txt`),
179
+ "noise\n",
180
+ "utf8"
181
+ );
182
+ }
183
+ fs.writeFileSync(
184
+ path.join(crowdedReportDir, "wecom-external-group-ai-bot-capabilities.md"),
185
+ "# Source-grounded report\n",
186
+ "utf8"
187
+ );
188
+ const crowdedScopedContract = deriveScsTaskContract({
189
+ goal: [
190
+ "Save one concise source-grounded Markdown report under the task artifact directory.",
191
+ `AGINTI_EVIDENCE_SCOPE_JSON: ${JSON.stringify({
192
+ mode: "task",
193
+ request:
194
+ "Save one concise source-grounded Markdown report under the task artifact directory.",
195
+ artifact_root: crowdedArtifactRoot,
196
+ })}`,
197
+ ].join("\n"),
198
+ taskProfile: "research",
199
+ });
200
+ const crowdedScopedArtifacts = evaluateRequestedArtifactRequirements(
201
+ crowdedScopedContract,
202
+ { commandCwd: crowdedWorkspace, state: {} }
203
+ );
204
+ assert.equal(
205
+ crowdedScopedArtifacts.ok,
206
+ true,
207
+ `a valid scoped Markdown report was hidden by unrelated workspace files: ${crowdedScopedArtifacts.reason}`
208
+ );
209
+ assert(
210
+ crowdedScopedArtifacts.candidates.some((item) =>
211
+ item.path.endsWith("wecom-external-group-ai-bot-capabilities.md")
212
+ ),
213
+ "the host-declared task artifact root was not inspected before the bounded workspace scan"
214
+ );
215
+ fs.rmSync(crowdedWorkspace, { recursive: true, force: true });
216
+
170
217
  function fakeStudentClient(json) {
171
218
  return {
172
219
  chat: {
@@ -5495,10 +5495,12 @@ export function isSubstantiveTestCommand(command = "", config = {}) {
5495
5495
  if (isRetainedExactVerificationCommand(command, config)) return true;
5496
5496
  const normalized = normalizeProjectCommand(normalizeCommandForPolicy(command, config));
5497
5497
  if (projectTestCommandWrapper(normalized)) return true;
5498
- const text = projectExitStatusWrapper(normalized)?.command || normalized;
5498
+ const wrappedTestCommand =
5499
+ projectExitStatusWrapper(normalized)?.command || normalized;
5500
+ const text = normalizeLeadingWorkspaceCd(wrappedTestCommand, config);
5499
5501
  if (!text) return false;
5500
- const classification = classifyCommand(text);
5501
- if (classification.substantiveTest !== true) return false;
5502
+ const classification = boundedTestCommandClassification(text);
5503
+ if (classification.policy.substantiveTest !== true) return false;
5502
5504
  const sequence = parseTopLevelShellSequence(text);
5503
5505
  if (sequence.commands.length <= 1) return true;
5504
5506
  if (!sequence.separators.every((separator) => separator === "&&")) return false;
@@ -5506,9 +5508,17 @@ export function isSubstantiveTestCommand(command = "", config = {}) {
5506
5508
  let lastTestIndex = -1;
5507
5509
  let lastMutationIndex = -1;
5508
5510
  sequence.commands.forEach((segment, index) => {
5509
- const segmentPolicy = classifyCommand(segment);
5511
+ const segmentClassification = boundedTestCommandClassification(segment);
5512
+ const segmentPolicy = segmentClassification.policy;
5510
5513
  if (segmentPolicy.substantiveTest === true) lastTestIndex = index;
5511
- if (commandCanMutateProjectContent(segment, segmentPolicy)) lastMutationIndex = index;
5514
+ if (
5515
+ commandCanMutateProjectContent(
5516
+ segmentClassification.executableCommand,
5517
+ segmentPolicy
5518
+ )
5519
+ ) {
5520
+ lastMutationIndex = index;
5521
+ }
5512
5522
  });
5513
5523
  return lastTestIndex >= 0 && lastTestIndex >= lastMutationIndex;
5514
5524
  }
@@ -2654,58 +2654,86 @@ function taskArtifactMutationPaths(state = {}) {
2654
2654
  return paths;
2655
2655
  }
2656
2656
 
2657
- function collectRequestedArtifactCandidates(commandCwd = process.cwd(), state = {}) {
2657
+ function collectRequestedArtifactCandidates(
2658
+ commandCwd = process.cwd(),
2659
+ state = {},
2660
+ artifactRoot = ""
2661
+ ) {
2658
2662
  const root = path.resolve(commandCwd || process.cwd());
2659
2663
  const freshnessBoundary = taskArtifactFreshnessBoundary(state);
2660
2664
  const mutationPaths = taskArtifactMutationPaths(state);
2661
2665
  const candidates = [];
2662
- const queue = [{ absolutePath: root, depth: 0 }];
2663
- let visited = 0;
2664
- while (queue.length && candidates.length < 3000 && visited < 6000) {
2665
- const current = queue.shift();
2666
- visited += 1;
2667
- let entries = [];
2666
+ const seenFiles = new Set();
2667
+ const scanRoots = [];
2668
+ const appendScanRoot = (rawPath = "") => {
2669
+ const absolutePath = rawPath
2670
+ ? resolveContractPath(root, rawPath)
2671
+ : root;
2672
+ if (!absolutePath || scanRoots.includes(absolutePath)) return;
2668
2673
  try {
2669
- entries = fs.readdirSync(current.absolutePath, { withFileTypes: true });
2674
+ if (!fs.statSync(absolutePath).isDirectory()) return;
2670
2675
  } catch {
2671
- continue;
2676
+ return;
2672
2677
  }
2673
- for (const entry of entries) {
2674
- if (entry.isSymbolicLink()) continue;
2675
- const absolutePath = path.join(current.absolutePath, entry.name);
2676
- if (entry.isDirectory()) {
2677
- if (
2678
- current.depth < 7 &&
2679
- !ARTIFACT_SCAN_IGNORED_DIRECTORIES.has(entry.name) &&
2680
- !entry.name.startsWith(".cache")
2681
- ) {
2682
- queue.push({ absolutePath, depth: current.depth + 1 });
2683
- }
2684
- continue;
2685
- }
2686
- if (!entry.isFile()) continue;
2687
- let stat;
2678
+ scanRoots.push(absolutePath);
2679
+ };
2680
+ // A host-declared task artifact root is authoritative and usually sits deep
2681
+ // inside a large application workspace. Inspect it before the bounded broad
2682
+ // workspace scan so unrelated files cannot exhaust the candidate limit and
2683
+ // hide a valid task deliverable.
2684
+ appendScanRoot(artifactRoot);
2685
+ appendScanRoot();
2686
+ let visited = 0;
2687
+ for (const scanRoot of scanRoots) {
2688
+ const queue = [{ absolutePath: scanRoot, depth: 0 }];
2689
+ while (queue.length && candidates.length < 3000 && visited < 6000) {
2690
+ const current = queue.shift();
2691
+ visited += 1;
2692
+ let entries = [];
2688
2693
  try {
2689
- stat = fs.statSync(absolutePath);
2694
+ entries = fs.readdirSync(current.absolutePath, { withFileTypes: true });
2690
2695
  } catch {
2691
2696
  continue;
2692
2697
  }
2693
- if (!stat.size) continue;
2694
- const relativePath = path.relative(root, absolutePath).replace(/\\/g, "/");
2695
- const normalized = normalizedContractPath(relativePath).toLocaleLowerCase("en-US");
2696
- const fresh = Boolean(
2697
- mutationPaths.has(normalized) ||
2698
- freshnessBoundary === 0 ||
2699
- Number(stat.mtimeMs || 0) >= freshnessBoundary
2700
- );
2701
- candidates.push({
2702
- path: relativePath,
2703
- extension: path.extname(entry.name).toLocaleLowerCase("en-US"),
2704
- basename: entry.name.toLocaleLowerCase("en-US"),
2705
- bytes: stat.size,
2706
- mtimeMs: Number(stat.mtimeMs || 0),
2707
- fresh,
2708
- });
2698
+ for (const entry of entries) {
2699
+ if (entry.isSymbolicLink()) continue;
2700
+ const absolutePath = path.join(current.absolutePath, entry.name);
2701
+ if (entry.isDirectory()) {
2702
+ if (
2703
+ current.depth < 7 &&
2704
+ !ARTIFACT_SCAN_IGNORED_DIRECTORIES.has(entry.name) &&
2705
+ !entry.name.startsWith(".cache")
2706
+ ) {
2707
+ queue.push({ absolutePath, depth: current.depth + 1 });
2708
+ }
2709
+ continue;
2710
+ }
2711
+ if (!entry.isFile()) continue;
2712
+ if (seenFiles.has(absolutePath)) continue;
2713
+ seenFiles.add(absolutePath);
2714
+ let stat;
2715
+ try {
2716
+ stat = fs.statSync(absolutePath);
2717
+ } catch {
2718
+ continue;
2719
+ }
2720
+ if (!stat.size) continue;
2721
+ const relativePath = path.relative(root, absolutePath).replace(/\\/g, "/");
2722
+ const normalized = normalizedContractPath(relativePath).toLocaleLowerCase("en-US");
2723
+ const fresh = Boolean(
2724
+ mutationPaths.has(normalized) ||
2725
+ freshnessBoundary === 0 ||
2726
+ Number(stat.mtimeMs || 0) >= freshnessBoundary
2727
+ );
2728
+ candidates.push({
2729
+ path: relativePath,
2730
+ extension: path.extname(entry.name).toLocaleLowerCase("en-US"),
2731
+ basename: entry.name.toLocaleLowerCase("en-US"),
2732
+ bytes: stat.size,
2733
+ mtimeMs: Number(stat.mtimeMs || 0),
2734
+ fresh,
2735
+ });
2736
+ }
2709
2737
  }
2710
2738
  }
2711
2739
  return candidates;
@@ -2763,7 +2791,11 @@ export function evaluateRequestedArtifactRequirements(
2763
2791
  reason: "No semantic artifact-set contract was inferred.",
2764
2792
  };
2765
2793
  }
2766
- const candidates = collectRequestedArtifactCandidates(commandCwd, state);
2794
+ const candidates = collectRequestedArtifactCandidates(
2795
+ commandCwd,
2796
+ state,
2797
+ String(contract.artifactRoot || "")
2798
+ );
2767
2799
  const requireFresh = contract.requiresFileMutation === true;
2768
2800
  const usableCandidates = requireFresh
2769
2801
  ? candidates.filter((candidate) => candidate.fresh)