@lazyingart/agintiflow 0.20.279 → 0.20.281

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.279",
3
+ "version": "0.20.281",
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",
@@ -191,15 +191,6 @@ try {
191
191
  const readOnlyVerificationState = {
192
192
  goal: readOnlyVerificationGoal,
193
193
  messages: [
194
- toolMessage({
195
- toolName: "run_command",
196
- ok: true,
197
- exitCode: 0,
198
- args: { command: "git commit -m 'Complete retained repair'" },
199
- stdout: "[main abcdef1] Complete retained repair\n 1 file changed, 1 insertion(+)",
200
- goalRevision: 13,
201
- projectMutationRevision: 19,
202
- }),
203
194
  toolMessage({
204
195
  toolName: "run_command",
205
196
  ok: true,
@@ -265,6 +256,12 @@ try {
265
256
  },
266
257
  buildScsEvidenceLedger({ state: readOnlyVerificationState })
267
258
  );
259
+ assert(
260
+ readOnlyVerificationState.messages.every(
261
+ (message) => !String(message.content || "").includes("git commit")
262
+ ),
263
+ "read-only compaction regression accidentally retained the historical commit message"
264
+ );
268
265
  assert(
269
266
  readOnlyGitEvaluation.missingGitActions.length === 0,
270
267
  "a prior verified same-task commit did not satisfy a read-only completion continuation"
@@ -2785,6 +2782,16 @@ try {
2785
2782
  acceptanceClassification.substantiveTest === true,
2786
2783
  "a structurally named Python acceptance validator was treated as an arbitrary mutating script"
2787
2784
  );
2785
+ const externalAcceptanceValidator =
2786
+ "/opt/conda/bin/python /tmp/supervision/acceptance/webapp_booking_contract.py";
2787
+ const externalAcceptanceClassification = classifyCommand(externalAcceptanceValidator);
2788
+ assert(
2789
+ externalAcceptanceClassification.category === "general-shell" &&
2790
+ externalAcceptanceClassification.writesWorkspace === true &&
2791
+ externalAcceptanceClassification.mayMutateProject === true &&
2792
+ externalAcceptanceClassification.semanticMayMutateProject === false,
2793
+ "trusted-shell authorization for an external Python validator was conflated with project mutation"
2794
+ );
2788
2795
  assert(
2789
2796
  classifyCommand(`${acceptanceValidator} --output report.json`).writesWorkspace === true,
2790
2797
  "a Python acceptance validator with an explicit output destination was treated as read-only"
@@ -3682,6 +3689,32 @@ try {
3682
3689
  readOnlyValidatorResult.projectMutationRevision === 0,
3683
3690
  "a semantically read-only validator fabricated project mutation progress"
3684
3691
  );
3692
+ const externalReadOnlyValidatorState = { meta: { goalContract: { revision: 1 } } };
3693
+ const externalReadOnlyValidatorCommand =
3694
+ "cd . && /opt/conda/bin/python /tmp/supervision/acceptance/webapp_booking_contract.py && git status --short";
3695
+ const externalReadOnlyValidatorResult = {
3696
+ toolName: "run_command",
3697
+ ok: true,
3698
+ exitCode: 0,
3699
+ args: { command: externalReadOnlyValidatorCommand },
3700
+ stdout: "webapp booking contract: PASS\n",
3701
+ stderr: "",
3702
+ commandPolicy: classifyCommand(externalReadOnlyValidatorCommand),
3703
+ };
3704
+ recordProjectVerificationOutcome(
3705
+ externalReadOnlyValidatorState,
3706
+ externalReadOnlyValidatorResult,
3707
+ {
3708
+ commandCwd: workspace,
3709
+ taskProfile: "app",
3710
+ sandboxMode: "host",
3711
+ }
3712
+ );
3713
+ assert(
3714
+ externalReadOnlyValidatorState.meta.projectVerification?.mutationRevision === 0 &&
3715
+ externalReadOnlyValidatorResult.projectMutationRevision === 0,
3716
+ "an absolute-interpreter acceptance validator forced a post-validation commit"
3717
+ );
3685
3718
  const shellMutationState = { meta: { goalContract: { revision: 1 } } };
3686
3719
  const shellMutationResult = {
3687
3720
  toolName: "run_command",
@@ -10110,6 +10110,12 @@ function commandCanMutateProjectContent(command = "", commandPolicy = {}) {
10110
10110
  const category = String(commandPolicy.category || "");
10111
10111
  const requiresGitMutationInspection =
10112
10112
  ["git-workflow", "git-remote"].includes(category);
10113
+ if (
10114
+ commandPolicy.semanticMayMutateProject === false &&
10115
+ !requiresGitMutationInspection
10116
+ ) {
10117
+ return false;
10118
+ }
10113
10119
  if (requiresGitMutationInspection && commandPolicy.gitOnly === true) {
10114
10120
  return inferGitActionsFromCommand(command, { requireFailurePropagation: false }).some((action) =>
10115
10121
  WORKTREE_CHANGING_GIT_ACTIONS.has(action)
@@ -293,8 +293,9 @@ function delegatedValidationPlanClassification(tokens = []) {
293
293
  const args = tokens.slice(1).map((token) => String(token || ""));
294
294
  const executablePath = validationExecutablePathMetadata(tokens[0]);
295
295
  const basenameCommand = [executable, ...args].join(" ");
296
+ const structuredValidation = structuredValidationCommand(basenameCommand);
296
297
  const validationLike = Boolean(
297
- structuredValidationCommand(basenameCommand) || matchAny(TEST_PATTERNS, basenameCommand)
298
+ structuredValidation || matchAny(TEST_PATTERNS, basenameCommand)
298
299
  );
299
300
  if (executablePath.outsideWorkspace && validationLike) {
300
301
  return {
@@ -302,6 +303,12 @@ function delegatedValidationPlanClassification(tokens = []) {
302
303
  needsNetwork: true,
303
304
  writesWorkspace: true,
304
305
  mayMutateProject: true,
306
+ // Requiring trusted-shell authorization for an external executable does
307
+ // not prove that its bounded validation invocation mutates the project.
308
+ // Preserve that semantic distinction for post-command evidence tracking.
309
+ semanticMayMutateProject:
310
+ structuredValidation?.mayMutateProject ??
311
+ validationCommandMayMutateProject(basenameCommand),
305
312
  substantiveTest: false,
306
313
  reason:
307
314
  "The validation executable is outside the current workspace and requires trusted shell policy.",
@@ -3359,7 +3359,20 @@ export function buildScsEvidenceLedger({ state = {}, context = {} } = {}) {
3359
3359
  .slice(-80)
3360
3360
  .map((item) => revalidateArtifactEvidence(item, state, context));
3361
3361
  const verifiedItems = items.filter((item) => item?.verified !== false);
3362
- const categories = unique(verifiedItems.map((item) => item.category));
3362
+ const durableGitEvidence = (
3363
+ Array.isArray(state.meta?.durableGitEvidence) ? state.meta.durableGitEvidence : []
3364
+ )
3365
+ .map((item) => ({
3366
+ action: String(item?.action || "").toLowerCase(),
3367
+ goalRevision: Math.max(0, Number(item?.goalRevision || 0)),
3368
+ mutationRevision: Math.max(0, Number(item?.mutationRevision || 0)),
3369
+ }))
3370
+ .filter((item) => item.action)
3371
+ .slice(-80);
3372
+ const categories = unique([
3373
+ ...verifiedItems.map((item) => item.category),
3374
+ ...(durableGitEvidence.length ? ["git"] : []),
3375
+ ]);
3363
3376
  const toolNames = unique(verifiedItems.map((item) => item.toolName).filter(Boolean));
3364
3377
  const blockerEvents = events
3365
3378
  .filter((event) => ["tool.blocked", "tool.failed"].includes(String(event?.type || "")))
@@ -3392,6 +3405,7 @@ export function buildScsEvidenceLedger({ state = {}, context = {} } = {}) {
3392
3405
  toolNames,
3393
3406
  blockerCount: blockers.length,
3394
3407
  blockers,
3408
+ durableGitEvidence,
3395
3409
  items: items.map((item, index) => ({
3396
3410
  id: `e${String(index + 1).padStart(3, "0")}`,
3397
3411
  ...item,
@@ -3410,8 +3424,26 @@ export function evaluateScsEvidence(contract = {}, ledger = {}) {
3410
3424
  0,
3411
3425
  Number(contract.requiredGitMutationRevision || 0)
3412
3426
  );
3427
+ const durableGitEvidence = (
3428
+ Array.isArray(ledger.durableGitEvidence) ? ledger.durableGitEvidence : []
3429
+ ).filter(
3430
+ (item) =>
3431
+ item?.action &&
3432
+ (requiredGitRevision === 0 || Number(item?.goalRevision || 0) >= requiredGitRevision) &&
3433
+ (requiredGitMutationRevision === 0 ||
3434
+ Number(item?.mutationRevision || 0) >= requiredGitMutationRevision)
3435
+ );
3436
+ const observedGitEvidence = durableGitEvidence.length
3437
+ ? durableGitEvidence.map((item) => ({
3438
+ category: "git",
3439
+ verified: true,
3440
+ gitAction: item.action,
3441
+ goalRevision: item.goalRevision,
3442
+ mutationRevision: item.mutationRevision,
3443
+ }))
3444
+ : ledgerItems;
3413
3445
  const observedGitActionSequence =
3414
- ledgerItems
3446
+ observedGitEvidence
3415
3447
  .filter(
3416
3448
  (item) =>
3417
3449
  item?.category === "git" &&