@lazyingart/agintiflow 0.20.258 → 0.20.259
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.259",
|
|
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",
|
|
@@ -2618,6 +2618,38 @@ try {
|
|
|
2618
2618
|
JSON.stringify(["npm test"]),
|
|
2619
2619
|
"console output lines were mistaken for required shell commands"
|
|
2620
2620
|
);
|
|
2621
|
+
const operatorGuideMarkdown = [
|
|
2622
|
+
"# Service",
|
|
2623
|
+
"",
|
|
2624
|
+
"The controller must provide start, status, restart, and stop.",
|
|
2625
|
+
"",
|
|
2626
|
+
"## Operator Guidance",
|
|
2627
|
+
"",
|
|
2628
|
+
"### Start the service",
|
|
2629
|
+
"",
|
|
2630
|
+
"```bash",
|
|
2631
|
+
"python3 service_ctl.py start --state-dir .runtime",
|
|
2632
|
+
"```",
|
|
2633
|
+
"",
|
|
2634
|
+
"### Check service status",
|
|
2635
|
+
"",
|
|
2636
|
+
"```bash",
|
|
2637
|
+
"python3 service_ctl.py status --state-dir .runtime",
|
|
2638
|
+
"```",
|
|
2639
|
+
"",
|
|
2640
|
+
"## Running Tests",
|
|
2641
|
+
"",
|
|
2642
|
+
"Run the visible regression suite with:",
|
|
2643
|
+
"",
|
|
2644
|
+
"```bash",
|
|
2645
|
+
"python3 -m unittest discover -s tests -v",
|
|
2646
|
+
"```",
|
|
2647
|
+
].join("\n");
|
|
2648
|
+
assert(
|
|
2649
|
+
JSON.stringify(projectAcceptanceFromMarkdown(operatorGuideMarkdown, "README.md").requiredCommands) ===
|
|
2650
|
+
JSON.stringify(["python3 -m unittest discover -s tests -v"]),
|
|
2651
|
+
"ordinary operator examples became mandatory acceptance commands"
|
|
2652
|
+
);
|
|
2621
2653
|
const operatorContinuedCommandMarkdown = [
|
|
2622
2654
|
"# Task",
|
|
2623
2655
|
"",
|
|
@@ -60,6 +60,14 @@ const coordinatedForbiddenOutputContract = deriveScsTaskContract({
|
|
|
60
60
|
taskProfile: "devops",
|
|
61
61
|
});
|
|
62
62
|
|
|
63
|
+
const recoveryInstructionContract = deriveScsTaskContract({
|
|
64
|
+
goal: [
|
|
65
|
+
"Use the retained source and these two failures: the tests invoke ../service_ctl.py, while `python3 service_ctl.py start --state-dir .runtime` fails. Preserve the lifecycle assertions rather than replacing them, repair service_ctl.py, and remove the accidental untracked resume-after-git-baseline-recovery-dev-prompt.txt.",
|
|
66
|
+
"Then run `python3 -m unittest discover -s tests -v`, followed by `PYTHONDONTWRITEBYTECODE=1 python3 /tmp/devops_sensor_gateway_contract.py`. Do not use LocalLLM or change provider.",
|
|
67
|
+
].join("\n"),
|
|
68
|
+
taskProfile: "devops",
|
|
69
|
+
});
|
|
70
|
+
|
|
63
71
|
const readOnlyReviewContract = deriveScsTaskContract({
|
|
64
72
|
goal: [
|
|
65
73
|
"Review focus: changed files only.",
|
|
@@ -136,6 +144,33 @@ assert.deepEqual(
|
|
|
136
144
|
["scratch.py", "temporary.py"],
|
|
137
145
|
"a coordinated list did not retain each path governed by one exclusion"
|
|
138
146
|
);
|
|
147
|
+
assert(
|
|
148
|
+
recoveryInstructionContract.excludedOutputPaths.includes("resume-after-git-baseline-recovery-dev-prompt.txt") &&
|
|
149
|
+
!recoveryInstructionContract.exactOutputPaths.includes("resume-after-git-baseline-recovery-dev-prompt.txt"),
|
|
150
|
+
"an explicit deletion target became a required output"
|
|
151
|
+
);
|
|
152
|
+
assert.deepEqual(
|
|
153
|
+
recoveryInstructionContract.requiredTextTerms,
|
|
154
|
+
[],
|
|
155
|
+
"verification commands became required document prose"
|
|
156
|
+
);
|
|
157
|
+
assert.deepEqual(
|
|
158
|
+
recoveryInstructionContract.requiredExecutableTerms,
|
|
159
|
+
[],
|
|
160
|
+
"an environment assignment inside a verification command became required production source"
|
|
161
|
+
);
|
|
162
|
+
assert(
|
|
163
|
+
!recoveryInstructionContract.exactInputPaths.some((item) => item.includes("PYTHONDONTWRITEBYTECODE")),
|
|
164
|
+
"a quoted verification command became an input path"
|
|
165
|
+
);
|
|
166
|
+
assert.deepEqual(
|
|
167
|
+
recoveryInstructionContract.requiredProjectCommands,
|
|
168
|
+
[
|
|
169
|
+
"python3 -m unittest discover -s tests -v",
|
|
170
|
+
"PYTHONDONTWRITEBYTECODE=1 python3 /tmp/devops_sensor_gateway_contract.py",
|
|
171
|
+
],
|
|
172
|
+
"a verification command introduced by 'followed by' was not retained"
|
|
173
|
+
);
|
|
139
174
|
assert.equal(
|
|
140
175
|
readOnlyReviewContract.requiresWorkspaceMutation,
|
|
141
176
|
false,
|
package/src/agent-runner.js
CHANGED
|
@@ -5281,20 +5281,59 @@ function canonicalRequiredFenceCommand(value = "") {
|
|
|
5281
5281
|
);
|
|
5282
5282
|
}
|
|
5283
5283
|
|
|
5284
|
+
function markdownFenceRequiresCommandExecution(content = "", fenceIndex = 0) {
|
|
5285
|
+
const lines = String(content || "")
|
|
5286
|
+
.slice(0, Math.max(0, Number(fenceIndex || 0)))
|
|
5287
|
+
.split(/\r?\n/);
|
|
5288
|
+
while (lines.length && !lines.at(-1).trim()) lines.pop();
|
|
5289
|
+
if (!lines.length) return false;
|
|
5290
|
+
|
|
5291
|
+
const nearest = String(lines.at(-1) || "").trim();
|
|
5292
|
+
const heading = nearest.match(/^#{1,6}\s+(.+?)\s*#*$/);
|
|
5293
|
+
if (heading) {
|
|
5294
|
+
return /\b(?:acceptance|tests?|validation|verification)\b|(?:验收|驗收|测试|測試|验证|驗證)|(?:受入|テスト|検証)/iu.test(
|
|
5295
|
+
heading[1]
|
|
5296
|
+
);
|
|
5297
|
+
}
|
|
5298
|
+
|
|
5299
|
+
const paragraph = [];
|
|
5300
|
+
while (lines.length && paragraph.length < 5) {
|
|
5301
|
+
const line = String(lines.pop() || "").trim();
|
|
5302
|
+
if (!line || /^#{1,6}\s+/.test(line) || /^```/.test(line)) break;
|
|
5303
|
+
paragraph.unshift(line);
|
|
5304
|
+
}
|
|
5305
|
+
const cue = paragraph.join(" ").trim();
|
|
5306
|
+
if (!cue) return false;
|
|
5307
|
+
|
|
5308
|
+
const execution = /\b(?:commands?|execute|invoke|launch|regenerate|run|tests?|validate|validation|verify|verification)\b/iu.test(
|
|
5309
|
+
cue
|
|
5310
|
+
);
|
|
5311
|
+
const obligation = /\b(?:before\s+completion|must|required|shall|should)\b/iu.test(cue);
|
|
5312
|
+
const directImperative = /^(?:please\s+)?(?:execute|invoke|launch|regenerate|run|validate|verify)\b/iu.test(cue);
|
|
5313
|
+
const validationLead = /^(?:to\s+(?:check|test|validate|verify)\b|(?:required|mandatory)\s+(?:checks?|commands?|tests?|validation|verification)\b)/iu.test(
|
|
5314
|
+
cue
|
|
5315
|
+
);
|
|
5316
|
+
const cjkExecution = /(?:运行|運行|执行|執行|验证|驗證|检查|檢查|测试|測試|验收|驗收|実行|検証|確認|テスト)/u.test(cue);
|
|
5317
|
+
const cjkObligation = /(?:必须|必須|需要|应当|應當|完成前|完了前)/u.test(cue);
|
|
5318
|
+
const cjkDirectImperative = /^(?:请|請)?(?:运行|運行|执行|執行|验证|驗證|检查|檢查|测试|測試|验收|驗收|実行|検証|確認|テスト)/u.test(
|
|
5319
|
+
cue
|
|
5320
|
+
);
|
|
5321
|
+
return (
|
|
5322
|
+
(execution && obligation) ||
|
|
5323
|
+
directImperative ||
|
|
5324
|
+
validationLead ||
|
|
5325
|
+
(cjkExecution && cjkObligation) ||
|
|
5326
|
+
cjkDirectImperative
|
|
5327
|
+
);
|
|
5328
|
+
}
|
|
5329
|
+
|
|
5284
5330
|
function markdownRequiredCommands(content = "") {
|
|
5285
5331
|
const text = String(content || "");
|
|
5286
5332
|
const commands = [];
|
|
5287
5333
|
for (const match of text.matchAll(/```([A-Za-z0-9_-]*)[ \t]*\n([\s\S]*?)```/gi)) {
|
|
5288
5334
|
const language = String(match[1] || "").toLowerCase();
|
|
5289
5335
|
if (language && !["bash", "sh", "shell", "console"].includes(language)) continue;
|
|
5290
|
-
|
|
5291
|
-
if (
|
|
5292
|
-
!/(?:run|running|execute|command|verify|validation|regenerate)[^\n.]{0,180}(?:must|required|should|use|run|regenerate)|(?:必须|需要|应当|运行|执行|验证)[^。\n]{0,180}(?:命令|生成|输出|交付)/i.test(
|
|
5293
|
-
before
|
|
5294
|
-
)
|
|
5295
|
-
) {
|
|
5296
|
-
continue;
|
|
5297
|
-
}
|
|
5336
|
+
if (!markdownFenceRequiresCommandExecution(text, match.index)) continue;
|
|
5298
5337
|
const body = String(match[2] || "");
|
|
5299
5338
|
const fenceCommandStart = commands.length;
|
|
5300
5339
|
const context = [];
|
package/src/scs-evidence.js
CHANGED
|
@@ -326,6 +326,56 @@ function quotedTerms(text = "") {
|
|
|
326
326
|
return terms;
|
|
327
327
|
}
|
|
328
328
|
|
|
329
|
+
function looksLikeShellCommandLiteral(value = "") {
|
|
330
|
+
const text = String(value || "").trim();
|
|
331
|
+
if (!text || /[\r\n]/.test(text)) return false;
|
|
332
|
+
const command = text.replace(/^(?:[A-Za-z_][A-Za-z0-9_]*=[^\s]+\s+)+/, "");
|
|
333
|
+
const tokens = tokenizeShellWords(command);
|
|
334
|
+
if (!tokens.length) return false;
|
|
335
|
+
const executable = path.basename(String(tokens[0] || "")).toLowerCase();
|
|
336
|
+
return new Set([
|
|
337
|
+
"aginti",
|
|
338
|
+
"bash",
|
|
339
|
+
"bun",
|
|
340
|
+
"cargo",
|
|
341
|
+
"cmake",
|
|
342
|
+
"curl",
|
|
343
|
+
"dotnet",
|
|
344
|
+
"ffmpeg",
|
|
345
|
+
"git",
|
|
346
|
+
"gh",
|
|
347
|
+
"go",
|
|
348
|
+
"java",
|
|
349
|
+
"javac",
|
|
350
|
+
"latexmk",
|
|
351
|
+
"make",
|
|
352
|
+
"node",
|
|
353
|
+
"npm",
|
|
354
|
+
"npx",
|
|
355
|
+
"perl",
|
|
356
|
+
"php",
|
|
357
|
+
"pnpm",
|
|
358
|
+
"pytest",
|
|
359
|
+
"python",
|
|
360
|
+
"python3",
|
|
361
|
+
"ruby",
|
|
362
|
+
"sh",
|
|
363
|
+
"wget",
|
|
364
|
+
"xelatex",
|
|
365
|
+
"yarn",
|
|
366
|
+
"zsh",
|
|
367
|
+
]).has(executable);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
function indexFallsInsideInlineCommand(source = "", index = 0) {
|
|
371
|
+
for (const match of String(source || "").matchAll(/`([^`\r\n]+)`/g)) {
|
|
372
|
+
const start = Number(match.index || 0);
|
|
373
|
+
const end = start + String(match[0] || "").length;
|
|
374
|
+
if (index >= start && index < end && looksLikeShellCommandLiteral(match[1])) return true;
|
|
375
|
+
}
|
|
376
|
+
return false;
|
|
377
|
+
}
|
|
378
|
+
|
|
329
379
|
function splitInlineTerms(text = "") {
|
|
330
380
|
return String(text || "")
|
|
331
381
|
.split(/[、,,;;]/)
|
|
@@ -515,6 +565,10 @@ export function inferExplicitlyExcludedOutputPaths(goal = "") {
|
|
|
515
565
|
/(?:不要|不得|禁止|无需|不需要)[^。!?;\n]{0,140}(?:运行|执行|重跑|创建|建立|写入|生成|保存|输出|修改|编辑|提交|暂存)/u;
|
|
516
566
|
const cjkNegativeActionAfter =
|
|
517
567
|
/^(?:(?:不得|禁止|不要)(?:被)?(?:运行|执行|重跑|创建|建立|写入|生成|保存|输出|修改|编辑|提交|暂存)|(?:を)?(?:作成|生成|実行|再実行|保存|編集|変更|コミット)[^。!?;\n]{0,40}(?:しない|しなくてよい|してはいけない))/u;
|
|
568
|
+
const directRemovalBefore =
|
|
569
|
+
/\b(?:remove|delete|unlink|discard)\s+(?:(?:the|an?|this|that)\s+)?(?:(?:accidental|stale|temporary|untracked|generated|obsolete|old|private|empty)\s+)*(?:file\s+)?$/i;
|
|
570
|
+
const cjkDirectRemovalBefore =
|
|
571
|
+
/(?:删除|刪除|移除|清除)(?:(?:这个|這個|该|該|意外的|暂存的|暫存的|临时的|臨時的|未跟踪的|未追蹤的|旧的|舊的|私有的)\s*)*(?:文件)?\s*$/u;
|
|
518
572
|
const excluded = [];
|
|
519
573
|
for (const clause of source.split(/[;;\n]|(?<=[.!?。!?])\s+/u)) {
|
|
520
574
|
pathPattern.lastIndex = 0;
|
|
@@ -545,7 +599,9 @@ export function inferExplicitlyExcludedOutputPaths(goal = "") {
|
|
|
545
599
|
negativeActionAfter.test(after) ||
|
|
546
600
|
keepAbsent.test(`${before}${after}`) ||
|
|
547
601
|
cjkNegativeActionBefore.test(before) ||
|
|
548
|
-
cjkNegativeActionAfter.test(after)
|
|
602
|
+
cjkNegativeActionAfter.test(after) ||
|
|
603
|
+
directRemovalBefore.test(before) ||
|
|
604
|
+
cjkDirectRemovalBefore.test(before)
|
|
549
605
|
);
|
|
550
606
|
previousExcluded = directExclusion || coordinatedWithExcludedPrevious;
|
|
551
607
|
if (previousExcluded) {
|
|
@@ -655,7 +711,13 @@ function inferRequiredTextTerms(goal = "") {
|
|
|
655
711
|
}
|
|
656
712
|
// A quoted filename in "save as `report.md`" is an output location, not
|
|
657
713
|
// required prose inside that report. Path existence is validated separately.
|
|
658
|
-
return uniqueLimited(
|
|
714
|
+
return uniqueLimited(
|
|
715
|
+
terms.filter((term) => {
|
|
716
|
+
const cleaned = String(term).trim();
|
|
717
|
+
return !outputPathTerms.has(cleaned) && !looksLikeShellCommandLiteral(cleaned);
|
|
718
|
+
}),
|
|
719
|
+
24
|
|
720
|
+
);
|
|
659
721
|
}
|
|
660
722
|
|
|
661
723
|
const EXECUTABLE_SOURCE_EXTENSIONS = new Set([
|
|
@@ -701,6 +763,7 @@ export function inferRequiredExecutableTerms(goal = "") {
|
|
|
701
763
|
for (const match of source.matchAll(assignmentPattern)) {
|
|
702
764
|
const index = Number(match.index || 0);
|
|
703
765
|
if (executableRequirementIsNegated(source, index)) continue;
|
|
766
|
+
if (indexFallsInsideInlineCommand(source, index)) continue;
|
|
704
767
|
const window = source.slice(Math.max(0, index - 180), Math.min(source.length, index + match[0].length + 220));
|
|
705
768
|
const implementationRequirement =
|
|
706
769
|
/\b(?:actual|canonical|executable|implementation|source|code|call|argument|keyword|parameter|repair|fix|correct|replace|add|set|pass|use|must|required)\b/iu.test(window) ||
|
|
@@ -1316,9 +1379,9 @@ function prefixRequestsInlineCommandExecution(prefix = "") {
|
|
|
1316
1379
|
while (preamble.test(clause)) clause = clause.replace(preamble, "").trim();
|
|
1317
1380
|
clause = clause.replace(/(?:[::]|--?)\s*$/, "").trim();
|
|
1318
1381
|
return (
|
|
1319
|
-
/^(?:run|rerun|re-run|execute|invoke|launch|verify|validate|check|confirm)(?:\s+(?:(?:the|this|that)\s+)?(?:following\s+)?command(?:\s+named)?)?\s*$/i.test(
|
|
1382
|
+
/^(?:followed\s+by|run|rerun|re-run|execute|invoke|launch|verify|validate|check|confirm)(?:\s+(?:(?:the|this|that)\s+)?(?:following\s+)?command(?:\s+named)?)?\s*$/i.test(
|
|
1320
1383
|
clause
|
|
1321
|
-
) || /^(
|
|
1384
|
+
) || /^(?:随后运行|隨後運行|接着运行|接著運行|运行|運行|执行|執行|调用|調用|验证|驗證|检查|檢查|确认|確認)\s*$/.test(clause)
|
|
1322
1385
|
);
|
|
1323
1386
|
}
|
|
1324
1387
|
|
|
@@ -1408,6 +1471,7 @@ function inferExplicitRequestedCommands(goal = "") {
|
|
|
1408
1471
|
|
|
1409
1472
|
export function deriveScsTaskContract({ goal = "", taskProfile = "", acceptanceCriteria = [] } = {}) {
|
|
1410
1473
|
const evidenceGoal = scopedChatopsEvidenceGoal(goal, taskProfile);
|
|
1474
|
+
const positiveEvidenceGoal = stripForbiddenLanguage(evidenceGoal);
|
|
1411
1475
|
const artifactRoot = scopedArtifactRoot(goal);
|
|
1412
1476
|
const requirementCategories = inferRequirementCategories(evidenceGoal, taskProfile, acceptanceCriteria);
|
|
1413
1477
|
const requiredToolCalls = inferRequiredToolCalls(evidenceGoal);
|
|
@@ -1431,7 +1495,7 @@ export function deriveScsTaskContract({ goal = "", taskProfile = "", acceptanceC
|
|
|
1431
1495
|
excludedOutputPaths
|
|
1432
1496
|
);
|
|
1433
1497
|
const exactInputPaths = filterExplicitlyExcludedOutputPaths(
|
|
1434
|
-
inferExactInputPaths(
|
|
1498
|
+
inferExactInputPaths(positiveEvidenceGoal),
|
|
1435
1499
|
excludedOutputPaths
|
|
1436
1500
|
).filter((item) => !inferredOutputPaths.includes(item) && !exactOutputPaths.includes(item));
|
|
1437
1501
|
const declaredSourceRoots = inferDeclaredSourceRoots(evidenceGoal);
|
|
@@ -1455,8 +1519,8 @@ export function deriveScsTaskContract({ goal = "", taskProfile = "", acceptanceC
|
|
|
1455
1519
|
requiresWorkspaceMutation: goalRequestsWorkspaceMutation(evidenceGoal, taskProfile),
|
|
1456
1520
|
requiresFileMutation: goalRequestsFileMutation(evidenceGoal, taskProfile),
|
|
1457
1521
|
requiresSourceGrounding: requiresSourceGrounding(evidenceGoal),
|
|
1458
|
-
requiredTextTerms: inferRequiredTextTerms(
|
|
1459
|
-
requiredExecutableTerms: inferRequiredExecutableTerms(
|
|
1522
|
+
requiredTextTerms: inferRequiredTextTerms(positiveEvidenceGoal),
|
|
1523
|
+
requiredExecutableTerms: inferRequiredExecutableTerms(positiveEvidenceGoal),
|
|
1460
1524
|
forbiddenTextTerms: inferForbiddenTextTerms(evidenceGoal),
|
|
1461
1525
|
successCriteria: unique(acceptanceCriteria).slice(0, 10),
|
|
1462
1526
|
};
|