@lazyingart/agintiflow 0.20.259 → 0.20.260

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.259",
3
+ "version": "0.20.260",
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",
@@ -2650,6 +2650,82 @@ try {
2650
2650
  JSON.stringify(["python3 -m unittest discover -s tests -v"]),
2651
2651
  "ordinary operator examples became mandatory acceptance commands"
2652
2652
  );
2653
+ const refreshedAcceptanceState = {
2654
+ commandCwd: workspace,
2655
+ meta: {
2656
+ projectVerification: {
2657
+ requiredOutputs: ["stale-output.txt"],
2658
+ requiredCommands: [
2659
+ "python3 service_ctl.py start --state-dir .runtime",
2660
+ "python3 service_ctl.py status --state-dir .runtime",
2661
+ ],
2662
+ acceptanceSource: "README.md",
2663
+ },
2664
+ },
2665
+ };
2666
+ recordProjectVerificationOutcome(
2667
+ refreshedAcceptanceState,
2668
+ {
2669
+ ok: true,
2670
+ toolName: "read_file",
2671
+ path: "README.md",
2672
+ content: operatorGuideMarkdown,
2673
+ },
2674
+ { commandCwd: workspace, taskProfile: "devops" }
2675
+ );
2676
+ assert(
2677
+ JSON.stringify(refreshedAcceptanceState.meta.projectVerification.requiredCommands) ===
2678
+ JSON.stringify(["python3 -m unittest discover -s tests -v"]) &&
2679
+ refreshedAcceptanceState.meta.projectVerification.requiredOutputs.length === 0,
2680
+ "rereading one authoritative source retained its stale acceptance requirements"
2681
+ );
2682
+ const resumedAcceptanceWorkspace = path.join(workspace, "resumed-acceptance");
2683
+ await fs.mkdir(resumedAcceptanceWorkspace, { recursive: true });
2684
+ await fs.writeFile(
2685
+ path.join(resumedAcceptanceWorkspace, "README.md"),
2686
+ operatorGuideMarkdown,
2687
+ "utf8"
2688
+ );
2689
+ const resumedAcceptanceState = {
2690
+ commandCwd: resumedAcceptanceWorkspace,
2691
+ goal: "Repair the service and run its tests.",
2692
+ meta: {
2693
+ goalContract: { revision: 4, currentRequest: "Repair the service and run its tests." },
2694
+ projectVerification: {
2695
+ requiredCommands: [
2696
+ "python3 service_ctl.py start --state-dir .runtime",
2697
+ "python3 service_ctl.py status --state-dir .runtime",
2698
+ ],
2699
+ acceptanceSource: "README.md",
2700
+ },
2701
+ },
2702
+ };
2703
+ resetSameTaskExecutionContract(resumedAcceptanceState, 4);
2704
+ assert(
2705
+ JSON.stringify(resumedAcceptanceState.meta.projectVerification.requiredCommands) ===
2706
+ JSON.stringify(["python3 -m unittest discover -s tests -v"]),
2707
+ "same-task resume retained stale requirements from an older README parser"
2708
+ );
2709
+ recordProjectVerificationOutcome(
2710
+ refreshedAcceptanceState,
2711
+ {
2712
+ ok: true,
2713
+ toolName: "read_file",
2714
+ path: "TASK.md",
2715
+ content: requiredCommandMarkdown,
2716
+ },
2717
+ { commandCwd: workspace, taskProfile: "devops" }
2718
+ );
2719
+ assert(
2720
+ JSON.stringify(refreshedAcceptanceState.meta.projectVerification.requiredCommands) ===
2721
+ JSON.stringify([
2722
+ "python3 -m unittest discover -s tests -v",
2723
+ "npm run check",
2724
+ "npm test",
2725
+ "python scripts/verify.py --strict",
2726
+ ]),
2727
+ "source-scoped acceptance refresh discarded a distinct authoritative source"
2728
+ );
2653
2729
  const operatorContinuedCommandMarkdown = [
2654
2730
  "# Task",
2655
2731
  "",
@@ -3769,6 +3769,67 @@ export function resetGoalScopedRuntimeState(state = {}) {
3769
3769
  return removed;
3770
3770
  }
3771
3771
 
3772
+ function refreshPersistedProjectAcceptance(state = {}) {
3773
+ const verification = state.meta?.projectVerification;
3774
+ if (!verification || typeof verification !== "object") return false;
3775
+ const priorBySource =
3776
+ verification.acceptanceBySource &&
3777
+ typeof verification.acceptanceBySource === "object" &&
3778
+ !Array.isArray(verification.acceptanceBySource)
3779
+ ? verification.acceptanceBySource
3780
+ : {};
3781
+ const sources = [
3782
+ ...Object.keys(priorBySource),
3783
+ String(verification.acceptanceSource || "").trim(),
3784
+ ].filter(Boolean);
3785
+ if (!sources.length) return false;
3786
+
3787
+ const commandCwd = path.resolve(state.commandCwd || process.cwd());
3788
+ const refreshed = {};
3789
+ let inspected = 0;
3790
+ for (const source of [...new Set(sources)].slice(-16)) {
3791
+ const sourceKey = normalizedProjectAcceptancePath(source, commandCwd);
3792
+ if (!sourceKey || !projectAcceptanceSourceIsAuthoritative(sourceKey, {
3793
+ commandCwd,
3794
+ authoritativePaths: [sourceKey],
3795
+ })) {
3796
+ continue;
3797
+ }
3798
+ const absolutePath = path.resolve(commandCwd, sourceKey);
3799
+ if (absolutePath !== commandCwd && !absolutePath.startsWith(`${commandCwd}${path.sep}`)) continue;
3800
+ inspected += 1;
3801
+ if (!fsSync.existsSync(absolutePath)) continue;
3802
+ try {
3803
+ const acceptance = projectAcceptanceFromMarkdown(
3804
+ fsSync.readFileSync(absolutePath, "utf8"),
3805
+ sourceKey,
3806
+ { commandCwd, authoritativePaths: [sourceKey] }
3807
+ );
3808
+ refreshed[sourceKey] = {
3809
+ requiredOutputs: acceptance.requiredOutputs,
3810
+ requiredCommands: acceptance.requiredCommands,
3811
+ readAt: new Date().toISOString(),
3812
+ };
3813
+ } catch {
3814
+ inspected -= 1;
3815
+ }
3816
+ }
3817
+ if (!inspected) return false;
3818
+ verification.acceptanceBySource = refreshed;
3819
+ verification.requiredOutputs = [
3820
+ ...new Set(
3821
+ Object.values(refreshed).flatMap((item) => item.requiredOutputs || [])
3822
+ ),
3823
+ ].slice(0, 64);
3824
+ verification.requiredCommands = [
3825
+ ...new Set(
3826
+ Object.values(refreshed).flatMap((item) => item.requiredCommands || [])
3827
+ ),
3828
+ ].slice(0, 24);
3829
+ verification.acceptanceRefreshedAt = new Date().toISOString();
3830
+ return true;
3831
+ }
3832
+
3772
3833
  export function resetSameTaskExecutionContract(state = {}, revision = 0) {
3773
3834
  state.meta = state.meta || {};
3774
3835
  const keys = [
@@ -3786,6 +3847,7 @@ export function resetSameTaskExecutionContract(state = {}, revision = 0) {
3786
3847
  removed.push(key);
3787
3848
  }
3788
3849
  state.plan = "";
3850
+ refreshPersistedProjectAcceptance(state);
3789
3851
  const activeRevision = Math.max(0, Number(revision || state.meta?.goalContract?.revision || 0));
3790
3852
  const currentRequest = String(state.meta?.goalContract?.currentRequest || state.goal || "").trim();
3791
3853
  const currentTurnContract = deriveScsTaskContract({
@@ -5381,11 +5443,9 @@ function normalizedProjectAcceptancePath(sourcePath = "", commandCwd = "") {
5381
5443
  return raw.replace(/\\/g, "/").replace(/^\.\//, "");
5382
5444
  }
5383
5445
 
5384
- export function projectAcceptanceFromMarkdown(content = "", sourcePath = "", options = {}) {
5446
+ function projectAcceptanceSourceIsAuthoritative(sourcePath = "", options = {}) {
5385
5447
  const basename = path.basename(String(sourcePath || "")).toLowerCase();
5386
- if (!/^(?:readme|task|agents?|aginti)(?:\.[^.]+)?$/.test(basename)) {
5387
- return { requiredOutputs: [], requiredCommands: [] };
5388
- }
5448
+ if (!/^(?:readme|task|agents?|aginti)(?:\.[^.]+)?$/.test(basename)) return false;
5389
5449
  const normalizedSource = normalizedProjectAcceptancePath(
5390
5450
  sourcePath,
5391
5451
  options.commandCwd
@@ -5395,10 +5455,11 @@ export function projectAcceptanceFromMarkdown(content = "", sourcePath = "", opt
5395
5455
  .map((item) => normalizedProjectAcceptancePath(item, options.commandCwd))
5396
5456
  .filter(Boolean)
5397
5457
  );
5398
- if (
5399
- normalizedSource.includes("/") &&
5400
- !authoritativePaths.has(normalizedSource)
5401
- ) {
5458
+ return !normalizedSource.includes("/") || authoritativePaths.has(normalizedSource);
5459
+ }
5460
+
5461
+ export function projectAcceptanceFromMarkdown(content = "", sourcePath = "", options = {}) {
5462
+ if (!projectAcceptanceSourceIsAuthoritative(sourcePath, options)) {
5402
5463
  return { requiredOutputs: [], requiredCommands: [] };
5403
5464
  }
5404
5465
  return {
@@ -5778,29 +5839,72 @@ export function recordProjectVerificationOutcome(state = {}, toolResult = {}, co
5778
5839
  goal: completionContractGoal(config, state),
5779
5840
  taskProfile: config.taskProfile || state.meta?.taskProfile || "auto",
5780
5841
  });
5842
+ const sourcePath = String(toolResult.path || toolResult.args?.path || "");
5843
+ const acceptanceOptions = {
5844
+ commandCwd: config.commandCwd || state.commandCwd || process.cwd(),
5845
+ authoritativePaths: [
5846
+ ...(Array.isArray(currentTaskContract.exactInputPaths)
5847
+ ? currentTaskContract.exactInputPaths
5848
+ : []),
5849
+ ...(Array.isArray(currentTaskContract.exactOutputPaths)
5850
+ ? currentTaskContract.exactOutputPaths
5851
+ : []),
5852
+ ],
5853
+ };
5781
5854
  const acceptance = projectAcceptanceFromMarkdown(
5782
5855
  toolResult.content,
5783
- toolResult.path || toolResult.args?.path || "",
5784
- {
5785
- commandCwd: config.commandCwd || state.commandCwd || process.cwd(),
5786
- authoritativePaths: [
5787
- ...(Array.isArray(currentTaskContract.exactInputPaths)
5788
- ? currentTaskContract.exactInputPaths
5789
- : []),
5790
- ...(Array.isArray(currentTaskContract.exactOutputPaths)
5791
- ? currentTaskContract.exactOutputPaths
5792
- : []),
5793
- ],
5794
- }
5856
+ sourcePath,
5857
+ acceptanceOptions
5795
5858
  );
5796
- verification.requiredOutputs = [
5797
- ...new Set([...verification.requiredOutputs, ...acceptance.requiredOutputs]),
5798
- ].slice(0, 64);
5799
- verification.requiredCommands = [
5800
- ...new Set([...verification.requiredCommands, ...acceptance.requiredCommands]),
5801
- ].slice(0, 24);
5802
- if (acceptance.requiredOutputs.length || acceptance.requiredCommands.length) {
5803
- verification.acceptanceSource = String(toolResult.path || toolResult.args?.path || "");
5859
+ if (projectAcceptanceSourceIsAuthoritative(sourcePath, acceptanceOptions)) {
5860
+ const sourceKey = normalizedProjectAcceptancePath(
5861
+ sourcePath,
5862
+ acceptanceOptions.commandCwd
5863
+ );
5864
+ const acceptanceBySource =
5865
+ verification.acceptanceBySource &&
5866
+ typeof verification.acceptanceBySource === "object" &&
5867
+ !Array.isArray(verification.acceptanceBySource)
5868
+ ? { ...verification.acceptanceBySource }
5869
+ : {};
5870
+ const legacySourceKey = normalizedProjectAcceptancePath(
5871
+ verification.acceptanceSource || "",
5872
+ acceptanceOptions.commandCwd
5873
+ );
5874
+ if (
5875
+ !Object.keys(acceptanceBySource).length &&
5876
+ legacySourceKey &&
5877
+ legacySourceKey !== sourceKey
5878
+ ) {
5879
+ acceptanceBySource[legacySourceKey] = {
5880
+ requiredOutputs: [...verification.requiredOutputs],
5881
+ requiredCommands: [...verification.requiredCommands],
5882
+ readAt: verification.acceptanceReadAt || "",
5883
+ };
5884
+ }
5885
+ acceptanceBySource[sourceKey] = {
5886
+ requiredOutputs: acceptance.requiredOutputs,
5887
+ requiredCommands: acceptance.requiredCommands,
5888
+ readAt: now,
5889
+ };
5890
+ verification.acceptanceBySource = Object.fromEntries(
5891
+ Object.entries(acceptanceBySource).slice(-16)
5892
+ );
5893
+ verification.requiredOutputs = [
5894
+ ...new Set(
5895
+ Object.values(verification.acceptanceBySource).flatMap((item) =>
5896
+ Array.isArray(item?.requiredOutputs) ? item.requiredOutputs : []
5897
+ )
5898
+ ),
5899
+ ].slice(0, 64);
5900
+ verification.requiredCommands = [
5901
+ ...new Set(
5902
+ Object.values(verification.acceptanceBySource).flatMap((item) =>
5903
+ Array.isArray(item?.requiredCommands) ? item.requiredCommands : []
5904
+ )
5905
+ ),
5906
+ ].slice(0, 24);
5907
+ verification.acceptanceSource = sourcePath;
5804
5908
  verification.acceptanceReadAt = now;
5805
5909
  }
5806
5910
  }