@lazyingart/agintiflow 0.20.253 → 0.20.254
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.254",
|
|
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",
|
|
@@ -204,6 +204,7 @@ const digest = (value) => crypto.createHash("sha256").update(value).digest("hex"
|
|
|
204
204
|
const durableMutation = {
|
|
205
205
|
revision: 4,
|
|
206
206
|
goalRevision: 7,
|
|
207
|
+
taskHash: digest("Repair the sensor gateway lifecycle."),
|
|
207
208
|
toolName: "apply_patch",
|
|
208
209
|
paths: ["service_ctl.py"],
|
|
209
210
|
patch: {
|
|
@@ -214,7 +215,17 @@ const durableMutation = {
|
|
|
214
215
|
};
|
|
215
216
|
const durablePatchState = {
|
|
216
217
|
meta: {
|
|
217
|
-
goalContract: {
|
|
218
|
+
goalContract: {
|
|
219
|
+
revision: 7,
|
|
220
|
+
taskGoal: "Repair the sensor gateway lifecycle.",
|
|
221
|
+
history: [
|
|
222
|
+
{
|
|
223
|
+
revision: 7,
|
|
224
|
+
kind: "initial",
|
|
225
|
+
hash: digest("Repair the sensor gateway lifecycle."),
|
|
226
|
+
},
|
|
227
|
+
],
|
|
228
|
+
},
|
|
218
229
|
toolLoop: {
|
|
219
230
|
recent: Array.from({ length: 20 }, (_, index) =>
|
|
220
231
|
failed("apply_patch", `later-failure-${index}`)
|
|
@@ -240,7 +251,47 @@ assert.equal(
|
|
|
240
251
|
...durablePatchState,
|
|
241
252
|
meta: {
|
|
242
253
|
...durablePatchState.meta,
|
|
243
|
-
goalContract: {
|
|
254
|
+
goalContract: {
|
|
255
|
+
revision: 8,
|
|
256
|
+
taskGoal: "Repair the sensor gateway lifecycle.",
|
|
257
|
+
history: [
|
|
258
|
+
...durablePatchState.meta.goalContract.history,
|
|
259
|
+
{
|
|
260
|
+
revision: 8,
|
|
261
|
+
kind: "same-task-continuation",
|
|
262
|
+
relation: "same-task",
|
|
263
|
+
taskHash: digest("Repair the sensor gateway lifecycle."),
|
|
264
|
+
},
|
|
265
|
+
],
|
|
266
|
+
},
|
|
267
|
+
},
|
|
268
|
+
},
|
|
269
|
+
"apply_patch",
|
|
270
|
+
durablePatchArgs,
|
|
271
|
+
{ commandCwd: process.cwd() }
|
|
272
|
+
)?.category,
|
|
273
|
+
"repeated-successful-mutation",
|
|
274
|
+
"a same-task continuation must not forget an earlier successful mutation"
|
|
275
|
+
);
|
|
276
|
+
assert.equal(
|
|
277
|
+
repeatedSuccessfulMutationBlock(
|
|
278
|
+
{
|
|
279
|
+
...durablePatchState,
|
|
280
|
+
meta: {
|
|
281
|
+
...durablePatchState.meta,
|
|
282
|
+
goalContract: {
|
|
283
|
+
revision: 8,
|
|
284
|
+
taskGoal: "Implement a separate service migration.",
|
|
285
|
+
history: [
|
|
286
|
+
...durablePatchState.meta.goalContract.history,
|
|
287
|
+
{
|
|
288
|
+
revision: 8,
|
|
289
|
+
kind: "continuation",
|
|
290
|
+
relation: "new-request",
|
|
291
|
+
taskHash: digest("Implement a separate service migration."),
|
|
292
|
+
},
|
|
293
|
+
],
|
|
294
|
+
},
|
|
244
295
|
},
|
|
245
296
|
},
|
|
246
297
|
"apply_patch",
|
|
@@ -248,7 +299,24 @@ assert.equal(
|
|
|
248
299
|
{ commandCwd: process.cwd() }
|
|
249
300
|
),
|
|
250
301
|
null,
|
|
251
|
-
"a genuine
|
|
302
|
+
"a genuine new task boundary must not inherit an unrelated mutation block"
|
|
303
|
+
);
|
|
304
|
+
const sanitizedDurablePatchArgs = {
|
|
305
|
+
...durablePatchArgs,
|
|
306
|
+
search: durablePatchArgs.search.slice(0, 20),
|
|
307
|
+
replace: durablePatchArgs.replace.slice(0, 20),
|
|
308
|
+
searchHash: digest(durablePatchArgs.search),
|
|
309
|
+
replaceHash: digest(durablePatchArgs.replace),
|
|
310
|
+
};
|
|
311
|
+
assert.equal(
|
|
312
|
+
repeatedSuccessfulMutationBlock(
|
|
313
|
+
durablePatchState,
|
|
314
|
+
"apply_patch",
|
|
315
|
+
sanitizedDurablePatchArgs,
|
|
316
|
+
{ commandCwd: process.cwd() }
|
|
317
|
+
)?.category,
|
|
318
|
+
"repeated-successful-mutation",
|
|
319
|
+
"redacted patch previews must use their retained full-content hashes for idempotency"
|
|
252
320
|
);
|
|
253
321
|
assert.equal(
|
|
254
322
|
repeatedSuccessfulMutationBlock(
|
package/src/agent-runner.js
CHANGED
|
@@ -4397,9 +4397,13 @@ function clearRequiredCommandBatch(verification = {}) {
|
|
|
4397
4397
|
}
|
|
4398
4398
|
|
|
4399
4399
|
function appendProjectMutation(state = {}, verification = {}, mutation = {}, config = {}) {
|
|
4400
|
+
const taskGoal = String(
|
|
4401
|
+
state.meta?.goalContract?.taskGoal || state.goal || ""
|
|
4402
|
+
).trim();
|
|
4400
4403
|
const record = {
|
|
4401
4404
|
...mutation,
|
|
4402
4405
|
goalRevision: Math.max(0, Number(state.meta?.goalContract?.revision || 0)),
|
|
4406
|
+
taskHash: taskGoal ? hashForLog(taskGoal) : "",
|
|
4403
4407
|
revision: Math.max(0, Number(mutation.revision || verification.mutationRevision || 0)),
|
|
4404
4408
|
paths: Array.isArray(mutation.paths)
|
|
4405
4409
|
? [...new Set(mutation.paths.map((item) => String(item || "")).filter(Boolean))].slice(0, 24)
|
|
@@ -6244,16 +6248,50 @@ export function repeatedSuccessfulMutationBlock(state, toolName, args = {}, conf
|
|
|
6244
6248
|
? [verification.lastMutation]
|
|
6245
6249
|
: [];
|
|
6246
6250
|
const targetPath = typeof args.path === "string" ? safeRecoveryEvidencePath(args.path) : "";
|
|
6247
|
-
const searchHash =
|
|
6248
|
-
|
|
6249
|
-
|
|
6251
|
+
const searchHash = String(
|
|
6252
|
+
args.searchHash || (typeof args.search === "string" ? hashForLog(args.search) : "")
|
|
6253
|
+
);
|
|
6254
|
+
const replaceHash = String(
|
|
6255
|
+
args.replaceHash || (typeof args.replace === "string" ? hashForLog(args.replace) : "")
|
|
6256
|
+
);
|
|
6257
|
+
const goalContract = state.meta?.goalContract || {};
|
|
6258
|
+
const currentGoalRevision = Math.max(0, Number(goalContract.revision || 0));
|
|
6259
|
+
const currentTaskGoal = String(goalContract.taskGoal || state.goal || "").trim();
|
|
6260
|
+
const currentTaskHash = currentTaskGoal ? hashForLog(currentTaskGoal) : "";
|
|
6261
|
+
const goalHistory = Array.isArray(goalContract.history) ? goalContract.history : [];
|
|
6262
|
+
const mutationBelongsToCurrentTask = (mutation = {}) => {
|
|
6263
|
+
const mutationGoalRevision = Math.max(0, Number(mutation.goalRevision || 0));
|
|
6264
|
+
const goalEntry = goalHistory.find(
|
|
6265
|
+
(entry) => Number(entry?.revision || 0) === mutationGoalRevision
|
|
6266
|
+
);
|
|
6267
|
+
const mutationTaskHash = String(
|
|
6268
|
+
mutation.taskHash ||
|
|
6269
|
+
goalEntry?.taskHash ||
|
|
6270
|
+
(goalEntry?.kind === "initial" ? goalEntry?.hash : "") ||
|
|
6271
|
+
""
|
|
6272
|
+
);
|
|
6273
|
+
if (currentTaskHash && mutationTaskHash) return currentTaskHash === mutationTaskHash;
|
|
6274
|
+
if (mutationGoalRevision === currentGoalRevision) return true;
|
|
6275
|
+
const interveningGoalEntries = goalHistory.filter((entry) => {
|
|
6276
|
+
const revision = Number(entry?.revision || 0);
|
|
6277
|
+
return revision > mutationGoalRevision && revision <= currentGoalRevision;
|
|
6278
|
+
});
|
|
6279
|
+
return (
|
|
6280
|
+
interveningGoalEntries.length > 0 &&
|
|
6281
|
+
interveningGoalEntries.every(
|
|
6282
|
+
(entry) =>
|
|
6283
|
+
String(entry?.relation || "") === "same-task" ||
|
|
6284
|
+
String(entry?.kind || "") === "same-task-continuation"
|
|
6285
|
+
)
|
|
6286
|
+
);
|
|
6287
|
+
};
|
|
6250
6288
|
let matchingHistoryIndex = -1;
|
|
6251
6289
|
if (targetPath && searchHash && replaceHash) {
|
|
6252
6290
|
for (let index = history.length - 1; index >= 0; index -= 1) {
|
|
6253
6291
|
const mutation = history[index];
|
|
6254
6292
|
if (
|
|
6255
6293
|
mutation?.toolName === "apply_patch" &&
|
|
6256
|
-
|
|
6294
|
+
mutationBelongsToCurrentTask(mutation) &&
|
|
6257
6295
|
safeRecoveryEvidencePath(mutation?.patch?.path) === targetPath &&
|
|
6258
6296
|
String(mutation?.patch?.searchHash || "") === searchHash &&
|
|
6259
6297
|
String(mutation?.patch?.replaceHash || "") === replaceHash
|
|
@@ -6267,7 +6305,7 @@ export function repeatedSuccessfulMutationBlock(state, toolName, args = {}, conf
|
|
|
6267
6305
|
matchingHistoryIndex >= 0 &&
|
|
6268
6306
|
!history.slice(matchingHistoryIndex + 1).some(
|
|
6269
6307
|
(mutation) =>
|
|
6270
|
-
|
|
6308
|
+
mutationBelongsToCurrentTask(mutation) &&
|
|
6271
6309
|
Number(mutation?.revision || 0) >
|
|
6272
6310
|
Number(history[matchingHistoryIndex]?.revision || 0)
|
|
6273
6311
|
);
|
|
@@ -6275,7 +6313,7 @@ export function repeatedSuccessfulMutationBlock(state, toolName, args = {}, conf
|
|
|
6275
6313
|
if (!alreadyApplied) return null;
|
|
6276
6314
|
return {
|
|
6277
6315
|
reason:
|
|
6278
|
-
"This exact patch already succeeded without
|
|
6316
|
+
"This exact patch already succeeded in the current task lineage without a later successful mutation that changed source state.",
|
|
6279
6317
|
category: "repeated-successful-mutation",
|
|
6280
6318
|
permissionAdvice: {
|
|
6281
6319
|
category: "repeated-successful-mutation",
|