@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.
|
|
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: {
|
package/src/agent-runner.js
CHANGED
|
@@ -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
|
|
5498
|
+
const wrappedTestCommand =
|
|
5499
|
+
projectExitStatusWrapper(normalized)?.command || normalized;
|
|
5500
|
+
const text = normalizeLeadingWorkspaceCd(wrappedTestCommand, config);
|
|
5499
5501
|
if (!text) return false;
|
|
5500
|
-
const classification =
|
|
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
|
|
5511
|
+
const segmentClassification = boundedTestCommandClassification(segment);
|
|
5512
|
+
const segmentPolicy = segmentClassification.policy;
|
|
5510
5513
|
if (segmentPolicy.substantiveTest === true) lastTestIndex = index;
|
|
5511
|
-
if (
|
|
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
|
}
|
package/src/scs-evidence.js
CHANGED
|
@@ -2654,58 +2654,86 @@ function taskArtifactMutationPaths(state = {}) {
|
|
|
2654
2654
|
return paths;
|
|
2655
2655
|
}
|
|
2656
2656
|
|
|
2657
|
-
function collectRequestedArtifactCandidates(
|
|
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
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
const
|
|
2666
|
-
|
|
2667
|
-
|
|
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
|
-
|
|
2674
|
+
if (!fs.statSync(absolutePath).isDirectory()) return;
|
|
2670
2675
|
} catch {
|
|
2671
|
-
|
|
2676
|
+
return;
|
|
2672
2677
|
}
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
let
|
|
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
|
-
|
|
2694
|
+
entries = fs.readdirSync(current.absolutePath, { withFileTypes: true });
|
|
2690
2695
|
} catch {
|
|
2691
2696
|
continue;
|
|
2692
2697
|
}
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
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(
|
|
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)
|