@lazyingart/agintiflow 0.20.222 → 0.20.223
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 +1 -1
- package/scripts/smoke-coding-tools.js +18 -0
- package/src/command-policy.js +23 -11
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lazyingart/agintiflow",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.223",
|
|
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",
|
|
@@ -658,6 +658,21 @@ try {
|
|
|
658
658
|
exactCompoundReadOnlyAuditPolicy.writesWorkspace === false,
|
|
659
659
|
"a finite read-only prelude and conditional directory audit incorrectly required destructive host permission"
|
|
660
660
|
);
|
|
661
|
+
const exactReadOnlyExistenceLoopWithSuffix =
|
|
662
|
+
'for f in scripts/xyq_cdp_browser.py scripts/xyq_chrome/launch_chrome.sh scripts/xyq_chrome/watch_thread_dom_download.py scripts/musia_mv_finalize.sh; do test -e "/home/lachlan/ProjectsLFS/LALACHAN/$f" && echo "OK $f" || echo "MISS $f"; done; echo "---mv_packs---"; ls -1 /home/lachlan/ProjectsLFS/Musia/data/mv_packs 2>&1; echo "---creative_projects---"; ls -1 /home/lachlan/ProjectsLFS/Musia/data/creative_projects 2>&1 | head -20';
|
|
663
|
+
const exactReadOnlyExistenceLoopWithSuffixPolicy = evaluateCommandPolicy(
|
|
664
|
+
exactReadOnlyExistenceLoopWithSuffix,
|
|
665
|
+
hostReadRootPolicy
|
|
666
|
+
);
|
|
667
|
+
assert(
|
|
668
|
+
exactReadOnlyExistenceLoopWithSuffixPolicy.allowed &&
|
|
669
|
+
exactReadOnlyExistenceLoopWithSuffixPolicy.category === "read-only" &&
|
|
670
|
+
exactReadOnlyExistenceLoopWithSuffixPolicy.boundedForLoop === true &&
|
|
671
|
+
exactReadOnlyExistenceLoopWithSuffixPolicy.boundedCompoundSequence === true &&
|
|
672
|
+
exactReadOnlyExistenceLoopWithSuffixPolicy.needsNetwork === false &&
|
|
673
|
+
exactReadOnlyExistenceLoopWithSuffixPolicy.writesWorkspace === false,
|
|
674
|
+
"a finite read-only existence loop with bounded list suffix incorrectly required destructive host permission"
|
|
675
|
+
);
|
|
661
676
|
const exactReadOnlyGitIdentityProbe =
|
|
662
677
|
'git status --short && echo "TOPLEVEL=$(git rev-parse --show-toplevel 2>&1)" && echo "BRANCH=$(git rev-parse --abbrev-ref HEAD 2>&1)"';
|
|
663
678
|
const exactReadOnlyGitIdentityProbePolicy = evaluateCommandPolicy(
|
|
@@ -754,6 +769,9 @@ try {
|
|
|
754
769
|
'echo start; for d in /tmp; do if [ -d "$d" ]; then if [ -f "$d/x" ]; then cat "$d/x"; else echo missing; fi; else echo absent; fi; done',
|
|
755
770
|
'echo start; for d in $ROOTS; do if [ -d "$d" ]; then ls "$d"; else echo missing; fi; done',
|
|
756
771
|
'echo start; for d in /tmp; do if [ -d "$d" ]; then ls "$d"; else echo missing; fi; done; rm -rf report.md',
|
|
772
|
+
'for f in README.md; do test -e "$f" && echo ok || echo missing; done; cp README.md copied.md',
|
|
773
|
+
'for f in README.md; do test -e "$f" && echo ok || echo missing; done; curl https://example.com',
|
|
774
|
+
'for f in README.md; do test -e "$f" && echo ok || echo missing; done; echo done > report.md',
|
|
757
775
|
]) {
|
|
758
776
|
const unsafeCompoundAuditPolicy = evaluateCommandPolicy(unsafeCompoundAudit, hostReadRootPolicy);
|
|
759
777
|
assert(
|
package/src/command-policy.js
CHANGED
|
@@ -1357,7 +1357,11 @@ function classifySimpleCommand(normalized) {
|
|
|
1357
1357
|
};
|
|
1358
1358
|
}
|
|
1359
1359
|
|
|
1360
|
-
if (
|
|
1360
|
+
if (
|
|
1361
|
+
matchAny(READ_ONLY_PATTERNS, commandForPatternMatching) ||
|
|
1362
|
+
isReadOnlyFindCommand(normalized) ||
|
|
1363
|
+
(!hasActiveShellExpansion(benignRedirectCommand) && isReadOnlyShellCondition(benignRedirectCommand))
|
|
1364
|
+
) {
|
|
1361
1365
|
return {
|
|
1362
1366
|
category: "read-only",
|
|
1363
1367
|
needsNetwork: false,
|
|
@@ -1767,7 +1771,7 @@ function classifyReadOnlyForLoop(normalized) {
|
|
|
1767
1771
|
|
|
1768
1772
|
function classifyReadOnlyCompoundSequence(normalized) {
|
|
1769
1773
|
const text = String(normalized || "").trim();
|
|
1770
|
-
if (!text ||
|
|
1774
|
+
if (!text || hasActiveShellCommandSubstitution(text)) return null;
|
|
1771
1775
|
|
|
1772
1776
|
let forIndex = findUnquotedShellWord(text, "for");
|
|
1773
1777
|
const startsAtCommandBoundary = (index) => {
|
|
@@ -1778,16 +1782,24 @@ function classifyReadOnlyCompoundSequence(normalized) {
|
|
|
1778
1782
|
while (forIndex > 0 && !startsAtCommandBoundary(forIndex)) {
|
|
1779
1783
|
forIndex = findUnquotedShellWord(text, "for", forIndex + 3);
|
|
1780
1784
|
}
|
|
1781
|
-
if (forIndex
|
|
1785
|
+
if (forIndex < 0) return null;
|
|
1782
1786
|
|
|
1783
1787
|
const prefixSource = trimShellListBoundary(text.slice(0, forIndex));
|
|
1784
|
-
const
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1788
|
+
const doneIndex = findUnquotedShellWord(text, "done", forIndex + 3);
|
|
1789
|
+
if (doneIndex < 0) return null;
|
|
1790
|
+
const loopSource = text.slice(forIndex, doneIndex + 4).trim();
|
|
1791
|
+
const suffixSource = trimShellListBoundary(text.slice(doneIndex + 4));
|
|
1792
|
+
if (!prefixSource && !suffixSource) return null;
|
|
1793
|
+
|
|
1794
|
+
for (const [label, source] of [["prelude", prefixSource], ["suffix", suffixSource]]) {
|
|
1795
|
+
if (!source) continue;
|
|
1796
|
+
const classification = classifyReadOnlyCommandList(source);
|
|
1797
|
+
if (classification.category === "blocked" || classification.category === "destructive") {
|
|
1798
|
+
return { ...classification, gitOnly: false };
|
|
1799
|
+
}
|
|
1800
|
+
if (classification.category !== "read-only" || classification.writesWorkspace) {
|
|
1801
|
+
return broadForLoopClassification(text, `the command ${label} is not read-only`);
|
|
1802
|
+
}
|
|
1791
1803
|
}
|
|
1792
1804
|
const loopClassification = classifyReadOnlyForLoop(loopSource);
|
|
1793
1805
|
if (!loopClassification) return null;
|
|
@@ -1801,7 +1813,7 @@ function classifyReadOnlyCompoundSequence(normalized) {
|
|
|
1801
1813
|
gitOnly: false,
|
|
1802
1814
|
boundedForLoop: true,
|
|
1803
1815
|
boundedCompoundSequence: true,
|
|
1804
|
-
reason: "
|
|
1816
|
+
reason: "A bounded read-only shell loop has only finite read-only command context.",
|
|
1805
1817
|
};
|
|
1806
1818
|
}
|
|
1807
1819
|
|