@lazyingart/agintiflow 0.20.227 → 0.20.229
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.229",
|
|
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",
|
|
@@ -32,7 +32,11 @@ import {
|
|
|
32
32
|
import { createPlan } from "../src/model-client.js";
|
|
33
33
|
import { selectModelRoute } from "../src/model-routing.js";
|
|
34
34
|
import { listParallelScouts, runParallelScouts, shouldRunParallelScouts } from "../src/parallel-scouts.js";
|
|
35
|
-
import {
|
|
35
|
+
import {
|
|
36
|
+
buildFailedCommandAdvice,
|
|
37
|
+
buildPermissionAdvice,
|
|
38
|
+
isOptionalGeneratedPreviewCleanup,
|
|
39
|
+
} from "../src/permission-advice.js";
|
|
36
40
|
import { runJsonSpecialist } from "../src/json-specialist.js";
|
|
37
41
|
import { SessionStore } from "../src/session-store.js";
|
|
38
42
|
import { getTaskProfile } from "../src/task-profiles.js";
|
|
@@ -1115,6 +1119,27 @@ try {
|
|
|
1115
1119
|
assert(cdWorkspacePolicy.allowed, "cd /workspace should be allowed in docker-workspace mode");
|
|
1116
1120
|
const gitCleanDryRunPolicy = evaluateCommandPolicy("git clean -nd reports", dockerWorkspacePolicy);
|
|
1117
1121
|
assert(gitCleanDryRunPolicy.allowed, "git clean dry-run should be allowed as read-only inspection evidence");
|
|
1122
|
+
const gitRmCachedPolicy = evaluateCommandPolicy(
|
|
1123
|
+
"git rm --cached -q build/__pycache__/content.cpython-312.pyc",
|
|
1124
|
+
dockerWorkspaceNoInstallsPolicy
|
|
1125
|
+
);
|
|
1126
|
+
assert(gitRmCachedPolicy.allowed, "bounded git rm --cached should preserve the working tree and remain allowed");
|
|
1127
|
+
assert(gitRmCachedPolicy.category === "git-workflow", "bounded git rm --cached should be a git workflow command");
|
|
1128
|
+
const gitRmCachedRecursivePolicy = evaluateCommandPolicy(
|
|
1129
|
+
"git rm --cached -r build",
|
|
1130
|
+
dockerWorkspaceNoInstallsPolicy
|
|
1131
|
+
);
|
|
1132
|
+
assert(!gitRmCachedRecursivePolicy.allowed, "recursive git rm --cached should remain guarded");
|
|
1133
|
+
const gitRmCachedGlobPolicy = evaluateCommandPolicy(
|
|
1134
|
+
"git rm --cached 'build/**/*.pyc'",
|
|
1135
|
+
dockerWorkspaceNoInstallsPolicy
|
|
1136
|
+
);
|
|
1137
|
+
assert(!gitRmCachedGlobPolicy.allowed, "globbed git rm --cached should remain guarded");
|
|
1138
|
+
const gitRmWorkingTreePolicy = evaluateCommandPolicy(
|
|
1139
|
+
"git rm build/content.py",
|
|
1140
|
+
dockerWorkspaceNoInstallsPolicy
|
|
1141
|
+
);
|
|
1142
|
+
assert(!gitRmWorkingTreePolicy.allowed, "git rm without --cached must remain guarded");
|
|
1118
1143
|
const localGitInitPolicy = evaluateCommandPolicy("git init", dockerWorkspaceNoInstallsPolicy);
|
|
1119
1144
|
assert(localGitInitPolicy.allowed, "local git init should be allowed without package installs");
|
|
1120
1145
|
assert(localGitInitPolicy.category === "git-workflow", "local git init should be classified as git-workflow");
|
|
@@ -1182,6 +1207,38 @@ try {
|
|
|
1182
1207
|
destructiveAdvice.destructiveApprovalCommand.includes("--allow-destructive"),
|
|
1183
1208
|
"destructive advice did not provide an explicit approval command"
|
|
1184
1209
|
);
|
|
1210
|
+
const optionalPreviewCleanupArgs = {
|
|
1211
|
+
command:
|
|
1212
|
+
"rm -f build/verification/page-1.png build/verification/page-2.png; git status --short",
|
|
1213
|
+
};
|
|
1214
|
+
assert(
|
|
1215
|
+
isOptionalGeneratedPreviewCleanup("run_command", optionalPreviewCleanupArgs),
|
|
1216
|
+
"bounded generated verification-preview cleanup was not recognized"
|
|
1217
|
+
);
|
|
1218
|
+
const optionalPreviewCleanupAdvice = buildPermissionAdvice({
|
|
1219
|
+
toolName: "run_command",
|
|
1220
|
+
args: optionalPreviewCleanupArgs,
|
|
1221
|
+
guard: {
|
|
1222
|
+
category: "destructive",
|
|
1223
|
+
reason: "Destructive shell commands require Allow destructive actions.",
|
|
1224
|
+
},
|
|
1225
|
+
config: dockerWorkspacePolicy,
|
|
1226
|
+
state: { sessionId: "coding-optional-preview-cleanup-smoke" },
|
|
1227
|
+
});
|
|
1228
|
+
assert(
|
|
1229
|
+
optionalPreviewCleanupAdvice.autoRecover === true,
|
|
1230
|
+
"optional generated-preview cleanup should retain evidence and recover without pausing"
|
|
1231
|
+
);
|
|
1232
|
+
assert(
|
|
1233
|
+
/leave the ignored preview files in place/i.test(optionalPreviewCleanupAdvice.instruction),
|
|
1234
|
+
"optional generated-preview cleanup advice did not tell the agent to retain evidence"
|
|
1235
|
+
);
|
|
1236
|
+
assert(
|
|
1237
|
+
!isOptionalGeneratedPreviewCleanup("run_command", {
|
|
1238
|
+
command: "rm -f output/final-report.pdf",
|
|
1239
|
+
}),
|
|
1240
|
+
"a requested final artifact was misclassified as optional preview cleanup"
|
|
1241
|
+
);
|
|
1185
1242
|
const failedNetworkAdvice = buildFailedCommandAdvice({
|
|
1186
1243
|
args: { command: "git clone https://github.com/lazyingart/AgInTiFlow.git" },
|
|
1187
1244
|
commandPolicy: clonePolicy,
|
|
@@ -264,6 +264,16 @@ assert(
|
|
|
264
264
|
"excluding output filenames also removed a real required text term"
|
|
265
265
|
);
|
|
266
266
|
|
|
267
|
+
const wordDocumentContract = deriveScsTaskContract({
|
|
268
|
+
goal: "Create an editable DOCX and a phone-friendly PDF, then verify both outputs.",
|
|
269
|
+
taskProfile: "word",
|
|
270
|
+
});
|
|
271
|
+
assert.deepEqual(
|
|
272
|
+
wordDocumentContract.requiredEvidence.map((item) => item.category).sort(),
|
|
273
|
+
["artifact", "command", "file", "visual"],
|
|
274
|
+
"Word document production must require written files, validation, durable artifacts, and visual evidence"
|
|
275
|
+
);
|
|
276
|
+
|
|
267
277
|
const groundingRoot = fs.mkdtempSync(path.join(os.tmpdir(), "aginti-source-grounding-"));
|
|
268
278
|
try {
|
|
269
279
|
const reportPath = path.join(groundingRoot, "READINESS.md");
|
package/src/command-policy.js
CHANGED
|
@@ -1226,6 +1226,48 @@ function classifyGitCleanDryRun(normalized) {
|
|
|
1226
1226
|
};
|
|
1227
1227
|
}
|
|
1228
1228
|
|
|
1229
|
+
function classifyGitRmCached(normalized) {
|
|
1230
|
+
if (!/^git\s+rm\b/.test(normalized) || hasActiveShellExpansion(normalized)) return null;
|
|
1231
|
+
const tokens = tokenizeShellWords(normalized);
|
|
1232
|
+
if (tokens[0] !== "git" || tokens[1] !== "rm") return null;
|
|
1233
|
+
|
|
1234
|
+
let cached = false;
|
|
1235
|
+
const paths = [];
|
|
1236
|
+
let afterOptions = false;
|
|
1237
|
+
for (const token of tokens.slice(2)) {
|
|
1238
|
+
if (!afterOptions && token === "--") {
|
|
1239
|
+
afterOptions = true;
|
|
1240
|
+
continue;
|
|
1241
|
+
}
|
|
1242
|
+
if (!afterOptions && ["--cached"].includes(token)) {
|
|
1243
|
+
cached = true;
|
|
1244
|
+
continue;
|
|
1245
|
+
}
|
|
1246
|
+
if (!afterOptions && ["-q", "--quiet"].includes(token)) continue;
|
|
1247
|
+
if (!afterOptions && token.startsWith("-")) return null;
|
|
1248
|
+
paths.push(token);
|
|
1249
|
+
}
|
|
1250
|
+
if (!cached || !paths.length || paths.length > 20) return null;
|
|
1251
|
+
if (
|
|
1252
|
+
paths.some(
|
|
1253
|
+
(target) =>
|
|
1254
|
+
target === "." ||
|
|
1255
|
+
/[*?\[\]{}]/.test(target) ||
|
|
1256
|
+
!isSafeRelativeDir(target)
|
|
1257
|
+
)
|
|
1258
|
+
) {
|
|
1259
|
+
return null;
|
|
1260
|
+
}
|
|
1261
|
+
return {
|
|
1262
|
+
category: "git-workflow",
|
|
1263
|
+
needsNetwork: false,
|
|
1264
|
+
writesWorkspace: true,
|
|
1265
|
+
gitOnly: true,
|
|
1266
|
+
reason:
|
|
1267
|
+
"Git rm --cached removes only bounded literal workspace paths from the index; working-tree files are preserved.",
|
|
1268
|
+
};
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1229
1271
|
function classifyGitClone(normalized) {
|
|
1230
1272
|
const match = normalized.match(
|
|
1231
1273
|
/^git\s+clone(?:\s+--depth\s+\d+)?(?:\s+--branch\s+[-\w./]+)?\s+(https:\/\/\S+)(?:\s+([-\w./]+))?$/
|
|
@@ -1305,6 +1347,8 @@ function classifySimpleCommand(normalized) {
|
|
|
1305
1347
|
}
|
|
1306
1348
|
const gitCleanDryRun = classifyGitCleanDryRun(normalized);
|
|
1307
1349
|
if (gitCleanDryRun) return gitCleanDryRun;
|
|
1350
|
+
const gitRmCached = classifyGitRmCached(normalized);
|
|
1351
|
+
if (gitRmCached) return gitRmCached;
|
|
1308
1352
|
const scopedReadOnlyGitProbe = classifyScopedReadOnlyGitProbe(normalized);
|
|
1309
1353
|
if (scopedReadOnlyGitProbe) return scopedReadOnlyGitProbe;
|
|
1310
1354
|
const gitWorkflowClassification = classifyGitWorkflow(normalized);
|
package/src/permission-advice.js
CHANGED
|
@@ -23,6 +23,50 @@ const DOCKER_WORKSPACE_PATH_FAILURE_PATTERNS = [
|
|
|
23
23
|
/cannot statx? ['"][^'"]+['"]:\s+No such file or directory/i,
|
|
24
24
|
];
|
|
25
25
|
|
|
26
|
+
function unquoteShellToken(value = "") {
|
|
27
|
+
const text = String(value || "").trim();
|
|
28
|
+
if (
|
|
29
|
+
text.length >= 2 &&
|
|
30
|
+
((text.startsWith("'") && text.endsWith("'")) ||
|
|
31
|
+
(text.startsWith('"') && text.endsWith('"')))
|
|
32
|
+
) {
|
|
33
|
+
return text.slice(1, -1);
|
|
34
|
+
}
|
|
35
|
+
return text;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function isGeneratedVerificationPreviewPath(value = "") {
|
|
39
|
+
const target = unquoteShellToken(value).replace(/\\/g, "/");
|
|
40
|
+
if (
|
|
41
|
+
!target ||
|
|
42
|
+
target.startsWith("/") ||
|
|
43
|
+
target.includes("..") ||
|
|
44
|
+
/[*?\[\]{}$`]/.test(target)
|
|
45
|
+
) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
return (
|
|
49
|
+
/^(?:build|artifacts)\/verification\/[A-Za-z0-9._/-]+\.(?:png|jpe?g|webp)$/i.test(target) ||
|
|
50
|
+
/^output\/preview[-_][A-Za-z0-9._-]+\.(?:png|jpe?g|webp)$/i.test(target)
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function isOptionalGeneratedPreviewCleanup(toolName = "", args = {}) {
|
|
55
|
+
if (toolName !== "run_command") return false;
|
|
56
|
+
const firstSegment = String(args.command || args.text || "")
|
|
57
|
+
.trim()
|
|
58
|
+
.split(/(?:&&|;|\n)/, 1)[0]
|
|
59
|
+
.trim();
|
|
60
|
+
const match = firstSegment.match(/^rm\s+-f\s+(.+)$/);
|
|
61
|
+
if (!match) return false;
|
|
62
|
+
const targets = match[1].trim().split(/\s+/).filter(Boolean);
|
|
63
|
+
return (
|
|
64
|
+
targets.length > 0 &&
|
|
65
|
+
targets.length <= 20 &&
|
|
66
|
+
targets.every((target) => isGeneratedVerificationPreviewPath(target))
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
26
70
|
function quoteShell(value = "") {
|
|
27
71
|
const text = String(value || "");
|
|
28
72
|
return `'${text.replace(/'/g, `'\\''`)}'`;
|
|
@@ -214,6 +258,21 @@ function adviceForCategory(category = "", { toolName = "", args = {}, config = {
|
|
|
214
258
|
}
|
|
215
259
|
|
|
216
260
|
if (category === "destructive") {
|
|
261
|
+
if (isOptionalGeneratedPreviewCleanup(toolName, args)) {
|
|
262
|
+
return {
|
|
263
|
+
...base,
|
|
264
|
+
autoRecover: true,
|
|
265
|
+
summary:
|
|
266
|
+
"Optional generated-preview cleanup was blocked safely; the verification evidence can remain ignored and the task should continue.",
|
|
267
|
+
instruction:
|
|
268
|
+
"Do not retry, rename, or seek approval for this cleanup. Leave the ignored preview files in place, run any remaining read-only checks in a separate call, and finish the requested task when its substantive evidence passes.",
|
|
269
|
+
options: [
|
|
270
|
+
"Retain the generated previews as private verification evidence.",
|
|
271
|
+
"Run source hashes, artifact checks, and git status separately without a delete command.",
|
|
272
|
+
"Continue to a real content or layout repair if validation still reports a defect.",
|
|
273
|
+
],
|
|
274
|
+
};
|
|
275
|
+
}
|
|
217
276
|
return {
|
|
218
277
|
...base,
|
|
219
278
|
summary:
|
package/src/scs-evidence.js
CHANGED
|
@@ -259,7 +259,7 @@ const PROFILE_REQUIREMENTS = {
|
|
|
259
259
|
design: ["artifact", "visual"],
|
|
260
260
|
image: ["artifact", "visual"],
|
|
261
261
|
slides: ["artifact"],
|
|
262
|
-
word: ["artifact"],
|
|
262
|
+
word: ["file", "command", "artifact", "visual"],
|
|
263
263
|
data: ["file", "command", "artifact"],
|
|
264
264
|
qa: ["command"],
|
|
265
265
|
review: ["command"],
|
package/src/task-profiles.js
CHANGED
|
@@ -276,7 +276,7 @@ export const TASK_PROFILES = {
|
|
|
276
276
|
id: "word",
|
|
277
277
|
label: "Word documents",
|
|
278
278
|
prompt:
|
|
279
|
-
"Bias toward Word/docx/document workflows while still using writing, conversion, LaTeX, or scripts when useful. Preserve
|
|
279
|
+
"Bias toward Word/docx/document workflows while still using writing, conversion, LaTeX, or scripts when useful. Preserve source material byte-for-byte and synthesize a reader-facing document from the authoritative current facts instead of concatenating notes, logs, schemas, task IDs, private paths, or delivery instructions. Reconcile conflicting or superseded source facts before drafting; publish only the current state unless history is explicitly requested or necessary to explain a live decision. Prefer mature editable-document tooling already available in the workspace, such as python-docx, pandoc, or LibreOffice, over hand-written OOXML; when direct OOXML is genuinely necessary, validate its package parts and openability. Keep one maintainable source of truth and a reproducible project-local build command. Verify the DOCX is structurally editable, compile the PDF, run pdftotext or an equivalent extraction check that rejects replacement characters and unexpected control glyphs, and render every PDF page to a separate image under an ignored build/verification directory. Inspect every rendered page individually and repair orphaned headings, near-empty spill pages, awkward table or paragraph breaks, overlaps, clipping, excessive whitespace, weak hierarchy, and inconsistent number formatting before finishing. Retain ignored verification renders as evidence; optional cleanup must never block completion. Use clear descriptive filenames, exclude caches and generated debris from commits, inspect git status/diff before committing, and report success only after the editable source, reader-facing current-state content, visual layout, searchable text, and requested artifacts all pass.",
|
|
280
280
|
tools: ["files", "shell", "canvas", "sandbox"],
|
|
281
281
|
},
|
|
282
282
|
latex: {
|