@lazyingart/agintiflow 0.20.308 → 0.20.310

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.308",
3
+ "version": "0.20.310",
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",
@@ -7348,6 +7348,31 @@ try {
7348
7348
  "missing-artifact-commit"
7349
7349
  );
7350
7350
  await fs.mkdir(missingArtifactCommitWorkspace, { recursive: true });
7351
+ const documentEvidenceWorkspace = path.join(
7352
+ tempRoot,
7353
+ "document-evidence"
7354
+ );
7355
+ await fs.mkdir(documentEvidenceWorkspace, { recursive: true });
7356
+ await fs.writeFile(
7357
+ path.join(documentEvidenceWorkspace, "daily_memo.pdf"),
7358
+ "%PDF-1.4\n% current task generated PDF evidence\n",
7359
+ "utf8"
7360
+ );
7361
+ await fs.writeFile(
7362
+ path.join(documentEvidenceWorkspace, "retained_memo.pdf"),
7363
+ "%PDF-1.4\n% retained same-task PDF evidence\n",
7364
+ "utf8"
7365
+ );
7366
+ await fs.writeFile(
7367
+ path.join(documentEvidenceWorkspace, "stale-root.pdf"),
7368
+ "%PDF-1.4\n% wrong-task stale PDF evidence\n",
7369
+ "utf8"
7370
+ );
7371
+ await fs.writeFile(
7372
+ path.join(documentEvidenceWorkspace, "retained_memo.tex"),
7373
+ "\\documentclass{article}\n\\begin{document}\nRetained memo.\n\\end{document}\n",
7374
+ "utf8"
7375
+ );
7351
7376
  const missingArtifactCommitState = {
7352
7377
  goal:
7353
7378
  "Create editable memo.tex and compiled mobile-readable memo.pdf, verify both, and commit only the intentional work.",
@@ -7524,7 +7549,7 @@ try {
7524
7549
  "run_command",
7525
7550
  { command: "git add -- daily_memo.tex daily_memo.pdf && git commit -m memo" },
7526
7551
  {
7527
- commandCwd: missingArtifactCommitWorkspace,
7552
+ commandCwd: documentEvidenceWorkspace,
7528
7553
  taskProfile: "writing",
7529
7554
  documentArtifactValidator: async (input) => {
7530
7555
  currentGoalDocumentValidatorInput = input;
@@ -7556,6 +7581,351 @@ try {
7556
7581
  currentGoalDocumentValidatorInput
7557
7582
  )}`
7558
7583
  );
7584
+ const resumedTaskGoal =
7585
+ "Read TASK.md and complete it carefully. Use the complete chat history, verify the finished PDF, and leave the repository clean.";
7586
+ const resumedTaskHash = crypto
7587
+ .createHash("sha256")
7588
+ .update(resumedTaskGoal)
7589
+ .digest("hex");
7590
+ const sameTaskResumeDocumentState = {
7591
+ goal:
7592
+ "Continue the same task. Reuse the existing verified source and PDF unless the diagnostic finds a real defect, then commit cleanly.",
7593
+ messages: [],
7594
+ meta: {
7595
+ taskProfile: "writing",
7596
+ goalContract: {
7597
+ version: 3,
7598
+ revision: 2,
7599
+ activeGoalRevision: 2,
7600
+ taskGoal: resumedTaskGoal,
7601
+ activeGoal:
7602
+ "Continue the same task. Reuse the existing verified source and PDF unless the diagnostic finds a real defect, then commit cleanly.",
7603
+ currentRequest:
7604
+ "Continue the same task. Reuse the existing verified source and PDF unless the diagnostic finds a real defect, then commit cleanly.",
7605
+ taskRelation: "same-task",
7606
+ history: [
7607
+ {
7608
+ revision: 1,
7609
+ kind: "initial",
7610
+ hash: resumedTaskHash,
7611
+ preview: resumedTaskGoal,
7612
+ },
7613
+ {
7614
+ revision: 2,
7615
+ kind: "same-task-continuation",
7616
+ relation: "same-task",
7617
+ hash: crypto
7618
+ .createHash("sha256")
7619
+ .update(
7620
+ "Continue the same task. Reuse the existing verified source and PDF unless the diagnostic finds a real defect, then commit cleanly."
7621
+ )
7622
+ .digest("hex"),
7623
+ taskHash: resumedTaskHash,
7624
+ previousHash: resumedTaskHash,
7625
+ },
7626
+ ],
7627
+ },
7628
+ projectVerification: {
7629
+ mutationRevision: 6,
7630
+ privateMutationRevision: 0,
7631
+ mutationHistory: [
7632
+ {
7633
+ revision: 2,
7634
+ at: "2026-09-01T10:00:00.000Z",
7635
+ toolName: "run_command",
7636
+ paths: ["retained_memo.pdf"],
7637
+ commandCategory: "toolchain",
7638
+ goalRevision: 1,
7639
+ taskHash: resumedTaskHash,
7640
+ },
7641
+ {
7642
+ revision: 3,
7643
+ at: "2026-09-01T10:01:00.000Z",
7644
+ toolName: "run_command",
7645
+ paths: ["stale-root.pdf"],
7646
+ commandCategory: "toolchain",
7647
+ goalRevision: 1,
7648
+ taskHash: "different-task",
7649
+ },
7650
+ {
7651
+ revision: 4,
7652
+ at: "2026-09-01T10:02:00.000Z",
7653
+ toolName: "run_command",
7654
+ paths: ["missing-retained.pdf"],
7655
+ commandCategory: "toolchain",
7656
+ goalRevision: 1,
7657
+ taskHash: resumedTaskHash,
7658
+ },
7659
+ {
7660
+ revision: 5,
7661
+ at: "2026-09-01T10:03:00.000Z",
7662
+ toolName: "apply_patch",
7663
+ paths: ["TASK.md"],
7664
+ patch: {
7665
+ path: "TASK.md",
7666
+ searchHash: "before-task-touch",
7667
+ replaceHash: "temporary-task-touch",
7668
+ },
7669
+ goalRevision: 2,
7670
+ taskHash: resumedTaskHash,
7671
+ },
7672
+ {
7673
+ revision: 6,
7674
+ at: "2026-09-01T10:04:00.000Z",
7675
+ toolName: "apply_patch",
7676
+ paths: ["TASK.md"],
7677
+ patch: {
7678
+ path: "TASK.md",
7679
+ searchHash: "temporary-task-touch",
7680
+ replaceHash: "before-task-touch",
7681
+ },
7682
+ goalRevision: 2,
7683
+ taskHash: resumedTaskHash,
7684
+ },
7685
+ ],
7686
+ },
7687
+ },
7688
+ };
7689
+ let sameTaskResumeValidatorInput = null;
7690
+ const sameTaskResumeAssessment = await documentQualityCommitAssessment(
7691
+ sameTaskResumeDocumentState,
7692
+ "run_command",
7693
+ { command: "git add -- retained_memo.pdf && git commit -m memo" },
7694
+ {
7695
+ commandCwd: documentEvidenceWorkspace,
7696
+ taskProfile: "writing",
7697
+ documentArtifactValidator: async (input) => {
7698
+ sameTaskResumeValidatorInput = input;
7699
+ return {
7700
+ ok: true,
7701
+ checked: true,
7702
+ artifacts: [{ path: "retained_memo.pdf" }],
7703
+ defects: [],
7704
+ reason:
7705
+ "Independent document checks passed for retained_memo.pdf.",
7706
+ };
7707
+ },
7708
+ }
7709
+ );
7710
+ assert(
7711
+ sameTaskResumeAssessment?.ok === true &&
7712
+ sameTaskResumeValidatorInput?.exactOutputPaths?.includes(
7713
+ "retained_memo.pdf"
7714
+ ) &&
7715
+ !sameTaskResumeValidatorInput.exactOutputPaths.includes(
7716
+ "stale-root.pdf"
7717
+ ) &&
7718
+ !sameTaskResumeValidatorInput.exactOutputPaths.includes(
7719
+ "missing-retained.pdf"
7720
+ ) &&
7721
+ sameTaskResumeDocumentState.meta.completionEvidenceRepair === undefined,
7722
+ `same-task resume did not preserve the prior verified document artifact safely: ${JSON.stringify({
7723
+ assessment: sameTaskResumeAssessment,
7724
+ input: sameTaskResumeValidatorInput,
7725
+ repair: sameTaskResumeDocumentState.meta.completionEvidenceRepair,
7726
+ })}`
7727
+ );
7728
+ const missingMutationHashState = structuredClone(sameTaskResumeDocumentState);
7729
+ delete missingMutationHashState.meta.projectVerification.mutationHistory[0]
7730
+ .taskHash;
7731
+ let missingMutationHashValidatorInput = null;
7732
+ const missingMutationHashAssessment = await documentQualityCommitAssessment(
7733
+ missingMutationHashState,
7734
+ "run_command",
7735
+ { command: "git add -- retained_memo.pdf && git commit -m memo" },
7736
+ {
7737
+ commandCwd: documentEvidenceWorkspace,
7738
+ taskProfile: "writing",
7739
+ documentArtifactValidator: async (input) => {
7740
+ missingMutationHashValidatorInput = input;
7741
+ return {
7742
+ ok: false,
7743
+ checked: true,
7744
+ artifacts: [],
7745
+ defects: [{ code: "missing-document-artifact" }],
7746
+ reason:
7747
+ "No readable DOCX or PDF artifact was found for the completed document task.",
7748
+ };
7749
+ },
7750
+ }
7751
+ );
7752
+ assert(
7753
+ missingMutationHashAssessment?.ok === false &&
7754
+ missingMutationHashAssessment.category ===
7755
+ "document-quality-incomplete" &&
7756
+ !missingMutationHashValidatorInput?.exactOutputPaths?.includes(
7757
+ "retained_memo.pdf"
7758
+ ),
7759
+ `a cross-revision retained PDF with missing mutation task hash was accepted: ${JSON.stringify({
7760
+ assessment: missingMutationHashAssessment,
7761
+ input: missingMutationHashValidatorInput,
7762
+ })}`
7763
+ );
7764
+ const missingContinuationHashState = structuredClone(
7765
+ sameTaskResumeDocumentState
7766
+ );
7767
+ delete missingContinuationHashState.meta.goalContract.history[1].taskHash;
7768
+ let missingContinuationHashValidatorInput = null;
7769
+ const missingContinuationHashAssessment =
7770
+ await documentQualityCommitAssessment(
7771
+ missingContinuationHashState,
7772
+ "run_command",
7773
+ { command: "git add -- retained_memo.pdf && git commit -m memo" },
7774
+ {
7775
+ commandCwd: documentEvidenceWorkspace,
7776
+ taskProfile: "writing",
7777
+ documentArtifactValidator: async (input) => {
7778
+ missingContinuationHashValidatorInput = input;
7779
+ return {
7780
+ ok: false,
7781
+ checked: true,
7782
+ artifacts: [],
7783
+ defects: [{ code: "missing-document-artifact" }],
7784
+ reason:
7785
+ "No readable DOCX or PDF artifact was found for the completed document task.",
7786
+ };
7787
+ },
7788
+ }
7789
+ );
7790
+ assert(
7791
+ missingContinuationHashAssessment?.ok === false &&
7792
+ missingContinuationHashAssessment.category ===
7793
+ "document-quality-incomplete" &&
7794
+ !missingContinuationHashValidatorInput?.exactOutputPaths?.includes(
7795
+ "retained_memo.pdf"
7796
+ ),
7797
+ `a cross-revision retained PDF with missing same-task continuation hash was accepted: ${JSON.stringify({
7798
+ assessment: missingContinuationHashAssessment,
7799
+ input: missingContinuationHashValidatorInput,
7800
+ })}`
7801
+ );
7802
+ const staleSourceResumeState = structuredClone(sameTaskResumeDocumentState);
7803
+ staleSourceResumeState.meta.projectVerification = {
7804
+ mutationRevision: 3,
7805
+ privateMutationRevision: 0,
7806
+ mutationHistory: [
7807
+ {
7808
+ revision: 2,
7809
+ at: "2026-09-01T10:00:00.000Z",
7810
+ toolName: "run_command",
7811
+ paths: ["retained_memo.pdf"],
7812
+ commandCategory: "toolchain",
7813
+ goalRevision: 1,
7814
+ taskHash: resumedTaskHash,
7815
+ },
7816
+ {
7817
+ revision: 3,
7818
+ at: "2026-09-01T10:05:00.000Z",
7819
+ toolName: "apply_patch",
7820
+ paths: ["retained_memo.tex"],
7821
+ patch: {
7822
+ path: "retained_memo.tex",
7823
+ searchHash: "old-retained-source",
7824
+ replaceHash: "changed-retained-source",
7825
+ },
7826
+ goalRevision: 2,
7827
+ taskHash: resumedTaskHash,
7828
+ },
7829
+ ],
7830
+ };
7831
+ let staleSourceValidatorInput = null;
7832
+ const staleSourceAssessment = await documentQualityCommitAssessment(
7833
+ staleSourceResumeState,
7834
+ "run_command",
7835
+ { command: "git add -- retained_memo.tex retained_memo.pdf && git commit -m memo" },
7836
+ {
7837
+ commandCwd: documentEvidenceWorkspace,
7838
+ taskProfile: "writing",
7839
+ documentArtifactValidator: async (input) => {
7840
+ staleSourceValidatorInput = input;
7841
+ return {
7842
+ ok: false,
7843
+ checked: true,
7844
+ artifacts: [],
7845
+ defects: [{ code: "missing-document-artifact" }],
7846
+ reason:
7847
+ "No readable DOCX or PDF artifact was found for the completed document task.",
7848
+ };
7849
+ },
7850
+ }
7851
+ );
7852
+ assert(
7853
+ staleSourceAssessment?.ok === false &&
7854
+ staleSourceAssessment.category === "document-quality-incomplete" &&
7855
+ !staleSourceValidatorInput?.exactOutputPaths?.includes(
7856
+ "retained_memo.pdf"
7857
+ ) &&
7858
+ staleSourceResumeState.meta.completionEvidenceRepair
7859
+ ?.documentArtifactGenerationRequired === true &&
7860
+ staleSourceResumeState.meta.completionEvidenceRepair
7861
+ ?.documentArtifactProducerCommand.includes("retained_memo.tex"),
7862
+ `a retained prior PDF survived a later same-task source mutation or failed to keep producer repair active: ${JSON.stringify({
7863
+ assessment: staleSourceAssessment,
7864
+ input: staleSourceValidatorInput,
7865
+ repair: staleSourceResumeState.meta.completionEvidenceRepair,
7866
+ })}`
7867
+ );
7868
+ const differentGoalResumeState = structuredClone(sameTaskResumeDocumentState);
7869
+ differentGoalResumeState.goal =
7870
+ "Start a different memo task and create a new verified PDF.";
7871
+ differentGoalResumeState.meta.goalContract = {
7872
+ version: 3,
7873
+ revision: 2,
7874
+ activeGoalRevision: 2,
7875
+ taskGoal: "Start a different memo task and create a new verified PDF.",
7876
+ activeGoal: "Start a different memo task and create a new verified PDF.",
7877
+ currentRequest:
7878
+ "Start a different memo task and create a new verified PDF.",
7879
+ taskRelation: "different-task",
7880
+ history: [
7881
+ {
7882
+ revision: 1,
7883
+ kind: "initial",
7884
+ hash: resumedTaskHash,
7885
+ preview: resumedTaskGoal,
7886
+ },
7887
+ {
7888
+ revision: 2,
7889
+ kind: "new-task",
7890
+ relation: "different-task",
7891
+ hash: crypto
7892
+ .createHash("sha256")
7893
+ .update("Start a different memo task and create a new verified PDF.")
7894
+ .digest("hex"),
7895
+ },
7896
+ ],
7897
+ };
7898
+ let differentGoalValidatorInput = null;
7899
+ const differentGoalAssessment = await documentQualityCommitAssessment(
7900
+ differentGoalResumeState,
7901
+ "run_command",
7902
+ { command: "git add -- retained_memo.pdf && git commit -m memo" },
7903
+ {
7904
+ commandCwd: documentEvidenceWorkspace,
7905
+ taskProfile: "writing",
7906
+ documentArtifactValidator: async (input) => {
7907
+ differentGoalValidatorInput = input;
7908
+ return {
7909
+ ok: false,
7910
+ checked: true,
7911
+ artifacts: [],
7912
+ defects: [{ code: "missing-document-artifact" }],
7913
+ reason:
7914
+ "No readable DOCX or PDF artifact was found for the completed document task.",
7915
+ };
7916
+ },
7917
+ }
7918
+ );
7919
+ assert(
7920
+ differentGoalAssessment?.ok === false &&
7921
+ differentGoalAssessment.category === "document-quality-incomplete" &&
7922
+ !differentGoalValidatorInput?.exactOutputPaths?.includes(
7923
+ "retained_memo.pdf"
7924
+ ),
7925
+ `a different task reused a prior same-root document artifact: ${JSON.stringify(
7926
+ differentGoalValidatorInput
7927
+ )}`
7928
+ );
7559
7929
  const unrelatedRootWorkspace = path.join(
7560
7930
  tempRoot,
7561
7931
  "unrelated-root-document"
@@ -7642,7 +8012,7 @@ try {
7642
8012
  "run_command",
7643
8013
  { command: "git add -- daily_memo.tex daily_memo.pdf && git commit -m memo" },
7644
8014
  {
7645
- commandCwd: missingArtifactCommitWorkspace,
8015
+ commandCwd: documentEvidenceWorkspace,
7646
8016
  taskProfile: "writing",
7647
8017
  documentArtifactValidator: async (input) => {
7648
8018
  semanticGateValidatorInput = input;
@@ -5,6 +5,7 @@ import os from "node:os";
5
5
  import path from "node:path";
6
6
  import { fileURLToPath } from "node:url";
7
7
  import {
8
+ completionRequirementCoverageInstruction,
8
9
  continuationExecutionContractDirective,
9
10
  removeSupersededCompletionRepairInstructions,
10
11
  runAgent,
@@ -17,6 +18,13 @@ const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."
17
18
  const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), "agintiflow-truthful-completion-"));
18
19
  process.env.AGINTIFLOW_HOME = path.join(tempRoot, "home");
19
20
 
21
+ const completionCoverageInstruction = completionRequirementCoverageInstruction();
22
+ assert.match(completionCoverageInstruction, /requirement by requirement/i);
23
+ assert.match(completionCoverageInstruction, /Every distinct subject/i);
24
+ assert.match(completionCoverageInstruction, /authoritative structured routine/i);
25
+ assert.match(completionCoverageInstruction, /every relevant section/i);
26
+ assert.match(completionCoverageInstruction, /instead of summarizing only failures or only successes/i);
27
+
20
28
  assert.equal(
21
29
  finishResultClaimsIncompleteWork(
22
30
  "The report is complete and the verification that was previously paused now passes. No work remains."
@@ -2969,6 +2969,10 @@ function usesFocusedRuntimePrompt(config = {}) {
2969
2969
  return config.executionTier === "focused" && !config.scsActive;
2970
2970
  }
2971
2971
 
2972
+ export function completionRequirementCoverageInstruction() {
2973
+ return "Before finishing, check the current user request requirement by requirement. Every distinct subject, requested action, and deliverable must be completed, answered, deliberately grouped under one verified shared state, or named with a concrete blocker. When an authoritative structured routine returns named sections relevant to the request, report every relevant section instead of summarizing only failures or only successes.";
2974
+ }
2975
+
2972
2976
  function focusedCapabilityContext(config = {}) {
2973
2977
  return [
2974
2978
  config.allowFileTools
@@ -3012,6 +3016,7 @@ function buildFocusedRuntimeMessages({
3012
3016
  "You are AgInTiFlow, a persistent tool-capable agent.",
3013
3017
  "Answer ordinary conversation directly. For executable work, act through the smallest relevant routine or tool, verify in proportion to risk, then stop.",
3014
3018
  "Treat queued user input as a safe-boundary interruption: preserve every material requirement, merge related consecutive messages, revise the durable goal, and never repeat a completed external side effect.",
3019
+ completionRequirementCoverageInstruction(),
3015
3020
  "Established project routines are capabilities to invoke, not workflows to reimplement. Discover more context only when the current task needs it.",
3016
3021
  formatBehaviorContractForPrompt({ mode: "focused" }),
3017
3022
  languageInstruction(config.language || "en"),
@@ -3230,6 +3235,7 @@ async function createInitialState(config, sessionId) {
3230
3235
  : "For website/app/code/LaTeX/Python/C/shell tasks, create or edit real workspace files, run available build/compile/test commands, and surface artifacts through the canvas when useful.",
3231
3236
  "For LaTeX/PDF tasks, check existing latexmk/pdflatex first and compile with the available host or Docker TeX toolchain before installing packages or rebuilding the sandbox.",
3232
3237
  "For research or web-search tasks, use browser tools or safe shell network tools when the current policy allows; cite or save useful sources in workspace notes when the task needs traceability.",
3238
+ completionRequirementCoverageInstruction(),
3233
3239
  browserStateReconciliationGuidance(),
3234
3240
  isRetainedWorkspaceProfile(config)
3235
3241
  ? "Choose descriptive non-conflicting workspace paths for durable outputs."
@@ -10257,7 +10263,7 @@ export async function documentQualityCommitAssessment(
10257
10263
  ? contract.exactOutputPaths
10258
10264
  : []),
10259
10265
  ...exactOutputPathsForState(state),
10260
- ...currentGoalDocumentArtifactPathsForState(state),
10266
+ ...currentGoalDocumentArtifactPathsForState(state, config),
10261
10267
  ...(Array.isArray(config.taskOwnedCommitPaths)
10262
10268
  ? config.taskOwnedCommitPaths
10263
10269
  : []),
@@ -14186,7 +14192,163 @@ function exactOutputPathsForState(state = {}) {
14186
14192
  ], exclusions).slice(0, 32);
14187
14193
  }
14188
14194
 
14189
- function currentGoalDocumentArtifactPathsForState(state = {}) {
14195
+ function currentGoalRevisionBelongsToActiveTask(state = {}, mutation = {}) {
14196
+ const goalContract = state.meta?.goalContract || {};
14197
+ const currentGoalRevision = Math.max(0, Number(goalContract.revision || 0));
14198
+ const mutationGoalRevision = Math.max(0, Number(mutation?.goalRevision || 0));
14199
+ if (
14200
+ currentGoalRevision <= 0 ||
14201
+ mutationGoalRevision <= 0 ||
14202
+ mutationGoalRevision > currentGoalRevision
14203
+ ) {
14204
+ return false;
14205
+ }
14206
+ const taskGoal = String(goalContract.taskGoal || state.goal || "").trim();
14207
+ const currentTaskHash = taskGoal ? hashForLog(taskGoal) : "";
14208
+ const goalHistory = Array.isArray(goalContract.history)
14209
+ ? goalContract.history
14210
+ : [];
14211
+ const mutationGoalEntry = goalHistory.find(
14212
+ (entry) => Number(entry?.revision || 0) === mutationGoalRevision
14213
+ );
14214
+ const mutationTaskHash = String(
14215
+ mutation?.taskHash ||
14216
+ mutationGoalEntry?.taskHash ||
14217
+ (mutationGoalEntry?.kind === "initial" ? mutationGoalEntry?.hash : "") ||
14218
+ ""
14219
+ );
14220
+ if (
14221
+ currentTaskHash &&
14222
+ mutationTaskHash &&
14223
+ mutationTaskHash !== currentTaskHash
14224
+ ) {
14225
+ return false;
14226
+ }
14227
+ if (mutationGoalRevision === currentGoalRevision) return true;
14228
+ const explicitMutationTaskHash = String(mutation?.taskHash || "");
14229
+ if (
14230
+ !currentTaskHash ||
14231
+ !explicitMutationTaskHash ||
14232
+ explicitMutationTaskHash !== currentTaskHash
14233
+ ) {
14234
+ return false;
14235
+ }
14236
+ const interveningGoalEntries = goalHistory.filter((entry) => {
14237
+ const revision = Number(entry?.revision || 0);
14238
+ return revision > mutationGoalRevision && revision <= currentGoalRevision;
14239
+ });
14240
+ if (!interveningGoalEntries.length) return false;
14241
+ return interveningGoalEntries.every((entry) => {
14242
+ const relation = String(entry?.relation || "");
14243
+ const kind = String(entry?.kind || "");
14244
+ const entryTaskHash = String(entry?.taskHash || "");
14245
+ return (
14246
+ (relation === "same-task" || kind === "same-task-continuation") &&
14247
+ entryTaskHash === currentTaskHash
14248
+ );
14249
+ });
14250
+ }
14251
+
14252
+ function currentGoalDocumentArtifactStillExists(candidate = "", state = {}, config = {}) {
14253
+ const normalized = safeTaskOwnedCommitPath(candidate);
14254
+ if (!normalized || !/\.(?:docx|pdf)$/iu.test(normalized)) return false;
14255
+ if (
14256
+ isPrivateVerificationEvidencePath(normalized) ||
14257
+ isScopedTaskArtifactEvidencePath(normalized, state, config)
14258
+ ) {
14259
+ return false;
14260
+ }
14261
+ const commandCwd = path.resolve(
14262
+ config.commandCwd || state.commandCwd || process.cwd()
14263
+ );
14264
+ const absolutePath = path.resolve(commandCwd, normalized);
14265
+ const relativePath = path.relative(commandCwd, absolutePath);
14266
+ if (
14267
+ !relativePath ||
14268
+ relativePath.startsWith("..") ||
14269
+ path.isAbsolute(relativePath)
14270
+ ) {
14271
+ return false;
14272
+ }
14273
+ try {
14274
+ const stat = fsSync.lstatSync(absolutePath);
14275
+ return stat.isFile() && !stat.isSymbolicLink() && stat.size > 0;
14276
+ } catch {
14277
+ return false;
14278
+ }
14279
+ }
14280
+
14281
+ const LIKELY_DOCUMENT_SOURCE_EXTENSIONS = new Set([
14282
+ ".tex",
14283
+ ".md",
14284
+ ".markdown",
14285
+ ".rmd",
14286
+ ".qmd",
14287
+ ".typ",
14288
+ ]);
14289
+
14290
+ function documentArtifactFreshnessKey(value = "") {
14291
+ const candidate = safeTaskOwnedCommitPath(value);
14292
+ if (!candidate) return "";
14293
+ const extension = path.posix.extname(candidate).toLocaleLowerCase("en-US");
14294
+ const basename = path.posix.basename(candidate, extension);
14295
+ const dirname = path.posix.dirname(candidate);
14296
+ return `${dirname === "." ? "" : `${dirname}/`}${basename}`.toLocaleLowerCase("en-US");
14297
+ }
14298
+
14299
+ function mutationArtifactPaths(mutation = {}) {
14300
+ return [
14301
+ ...(Array.isArray(mutation?.paths) ? mutation.paths : []),
14302
+ ...(Array.isArray(mutation?.projectMutationPaths)
14303
+ ? mutation.projectMutationPaths
14304
+ : []),
14305
+ ...(Array.isArray(mutation?.verifiedGeneratedOutputPaths)
14306
+ ? mutation.verifiedGeneratedOutputPaths
14307
+ : []),
14308
+ ];
14309
+ }
14310
+
14311
+ function mutationInvalidatesDocumentArtifact(mutation = {}, artifactPath = "") {
14312
+ const artifact = safeTaskOwnedCommitPath(artifactPath);
14313
+ if (!artifact) return false;
14314
+ const artifactKey = documentArtifactFreshnessKey(artifact);
14315
+ if (!artifactKey) return false;
14316
+ for (const value of mutationArtifactPaths(mutation)) {
14317
+ const candidate = safeTaskOwnedCommitPath(value);
14318
+ if (!candidate) continue;
14319
+ if (candidate === artifact) return true;
14320
+ const extension = path.posix.extname(candidate).toLocaleLowerCase("en-US");
14321
+ if (
14322
+ LIKELY_DOCUMENT_SOURCE_EXTENSIONS.has(extension) &&
14323
+ documentArtifactFreshnessKey(candidate) === artifactKey
14324
+ ) {
14325
+ return true;
14326
+ }
14327
+ }
14328
+ return false;
14329
+ }
14330
+
14331
+ function retainedDocumentArtifactMutationIsFresh(
14332
+ state = {},
14333
+ history = [],
14334
+ mutation = {},
14335
+ artifactPath = ""
14336
+ ) {
14337
+ const artifactRevision = Math.max(0, Number(mutation?.revision || 0));
14338
+ if (artifactRevision <= 0) return false;
14339
+ for (const laterMutation of history) {
14340
+ if (Math.max(0, Number(laterMutation?.revision || 0)) <= artifactRevision) {
14341
+ continue;
14342
+ }
14343
+ if (!currentGoalRevisionBelongsToActiveTask(state, laterMutation)) continue;
14344
+ if (mutationInvalidatesDocumentArtifact(laterMutation, artifactPath)) {
14345
+ return false;
14346
+ }
14347
+ }
14348
+ return true;
14349
+ }
14350
+
14351
+ function currentGoalDocumentArtifactPathsForState(state = {}, config = {}) {
14190
14352
  const verification = state.meta?.projectVerification || {};
14191
14353
  const history = Array.isArray(verification.mutationHistory)
14192
14354
  ? verification.mutationHistory
@@ -14199,7 +14361,7 @@ function currentGoalDocumentArtifactPathsForState(state = {}) {
14199
14361
  const candidates = [];
14200
14362
  const seen = new Set();
14201
14363
  for (const mutation of history) {
14202
- if (Number(mutation?.goalRevision || 0) !== currentGoalRevision) continue;
14364
+ if (!currentGoalRevisionBelongsToActiveTask(state, mutation)) continue;
14203
14365
  const paths = [
14204
14366
  ...(Array.isArray(mutation?.paths) ? mutation.paths : []),
14205
14367
  ...(Array.isArray(mutation?.projectMutationPaths)
@@ -14214,6 +14376,13 @@ function currentGoalDocumentArtifactPathsForState(state = {}) {
14214
14376
  if (
14215
14377
  !candidate ||
14216
14378
  !/\.(?:docx|pdf)$/iu.test(candidate) ||
14379
+ !currentGoalDocumentArtifactStillExists(candidate, state, config) ||
14380
+ !retainedDocumentArtifactMutationIsFresh(
14381
+ state,
14382
+ history,
14383
+ mutation,
14384
+ candidate
14385
+ ) ||
14217
14386
  seen.has(candidate)
14218
14387
  ) {
14219
14388
  continue;
@@ -21430,7 +21599,7 @@ async function completionEvidenceDecision({ config, state, store, observers, ste
21430
21599
  const documentExactOutputPaths = [
21431
21600
  ...(assessment.contract?.exactOutputPaths || []),
21432
21601
  ...exactOutputPathsForState(state),
21433
- ...currentGoalDocumentArtifactPathsForState(state),
21602
+ ...currentGoalDocumentArtifactPathsForState(state, config),
21434
21603
  ];
21435
21604
  const documentContractText = `${completionContractGoal(config, state)}\n${candidateResult}`;
21436
21605
  const documentDeliverableRequested =