@lazyingart/agintiflow 0.20.310 → 0.20.312

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.310",
3
+ "version": "0.20.312",
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",
@@ -1009,6 +1009,93 @@ assert.equal(
1009
1009
  "the first exact-search mismatch did not immediately open one bounded current-source refresh"
1010
1010
  );
1011
1011
  const tracebackFirstRefreshState = structuredClone(stalePatchRefreshState);
1012
+ const scopedArtifactPath =
1013
+ "output/webapp/agent/tasks/source-intake-audit/report.md";
1014
+ const scopedArtifactRoot = path.join(
1015
+ repoRoot,
1016
+ "output/webapp/agent/tasks/source-intake-audit"
1017
+ );
1018
+ const scopedArtifactGoal = [
1019
+ "Correct and verify the exact source-intake audit report.",
1020
+ `AGINTI_EVIDENCE_SCOPE_JSON: ${JSON.stringify({
1021
+ mode: "task",
1022
+ request: "Correct and verify the exact source-intake audit report.",
1023
+ artifact_root: scopedArtifactRoot,
1024
+ })}`,
1025
+ ].join("\n");
1026
+ const scopedArtifactRefreshState = {
1027
+ commandCwd: repoRoot,
1028
+ meta: {
1029
+ goalContract: {
1030
+ revision: 9,
1031
+ activeGoal: scopedArtifactGoal,
1032
+ taskGoal: scopedArtifactGoal,
1033
+ history: [],
1034
+ },
1035
+ projectVerification: {
1036
+ mutationRevision: 2,
1037
+ testRuns: [],
1038
+ },
1039
+ toolLoop: {
1040
+ stagnationEpoch: 4,
1041
+ recent: [],
1042
+ },
1043
+ },
1044
+ };
1045
+ const scopedArtifactRefresh = patchContextRefreshDecision(
1046
+ scopedArtifactRefreshState,
1047
+ {
1048
+ toolName: "apply_patch",
1049
+ args: {
1050
+ path: scopedArtifactPath,
1051
+ search: "Planned dynamic check: run the guarded document reader test.",
1052
+ replace: "Guarded document reader test: passed.",
1053
+ },
1054
+ ok: false,
1055
+ category: "workspace-patch",
1056
+ error: `Patch search text was not found in ${scopedArtifactPath}.`,
1057
+ }
1058
+ );
1059
+ assert.equal(
1060
+ scopedArtifactRefresh?.path,
1061
+ scopedArtifactPath,
1062
+ "a stale patch inside the exact scoped task artifact root was not recoverable"
1063
+ );
1064
+ scopedArtifactRefreshState.meta.toolLoop.patchContextRequired =
1065
+ scopedArtifactRefresh;
1066
+ assert.equal(
1067
+ activePatchContextRefresh(scopedArtifactRefreshState)?.path,
1068
+ scopedArtifactPath,
1069
+ "the scoped task-artifact refresh marker was rejected as a generic output path"
1070
+ );
1071
+ assert.equal(
1072
+ nextStepRuntimeConfig(baseConfig, scopedArtifactRefreshState)
1073
+ .patchContextRefreshPath,
1074
+ scopedArtifactPath,
1075
+ "the scoped task-artifact refresh path did not reach the next constrained turn"
1076
+ );
1077
+ const scopedArtifactSource = [
1078
+ "# Source Intake Audit",
1079
+ "",
1080
+ "Document reader verification is pending.",
1081
+ "",
1082
+ ].join("\n");
1083
+ assert.equal(
1084
+ consumePatchContextRefreshRead(scopedArtifactRefreshState, {
1085
+ toolName: "read_file",
1086
+ args: { path: scopedArtifactPath },
1087
+ result: { path: scopedArtifactPath },
1088
+ content: scopedArtifactSource,
1089
+ ok: true,
1090
+ })?.path,
1091
+ scopedArtifactPath,
1092
+ "an exact reread did not consume the scoped task-artifact refresh"
1093
+ );
1094
+ assert.equal(
1095
+ activePatchContextRepair(scopedArtifactRefreshState)?.path,
1096
+ scopedArtifactPath,
1097
+ "the scoped task-artifact reread did not leave a bounded repair anchor"
1098
+ );
1012
1099
  tracebackFirstRefreshState.meta.projectVerification.testRuns[0].failureSummary =
1013
1100
  'File "./service_ctl.py", line 139 -> return start_service(args.state_dir, args.host, args.port) parser = argparse.ArgumentParser()';
1014
1101
  const tracebackFirstRefresh = patchContextRefreshDecision(tracebackFirstRefreshState, {
@@ -734,6 +734,41 @@ assertStrict.deepEqual(
734
734
  { path: mandatoryRefreshPath },
735
735
  "mandatory patch-context recovery did not preserve the exact constrained path"
736
736
  );
737
+ const scopedMandatoryRefreshPath =
738
+ "output/webapp/agent/tasks/source-intake-audit/report.md";
739
+ const scopedMandatoryRefreshRoot =
740
+ "output/webapp/agent/tasks/source-intake-audit";
741
+ const scopedMandatoryRefreshReadDescriptor = {
742
+ ...canonicalReadDescriptor,
743
+ function: {
744
+ ...canonicalReadDescriptor.function,
745
+ parameters: {
746
+ ...canonicalReadDescriptor.function.parameters,
747
+ properties: {
748
+ path: { type: "string", enum: [scopedMandatoryRefreshPath] },
749
+ },
750
+ },
751
+ },
752
+ };
753
+ const recoveredScopedMandatoryRefresh =
754
+ recoverRequiredPatchContextReadWithoutToolCall(
755
+ {
756
+ commandCwd: process.cwd(),
757
+ scopedArtifactRoot: scopedMandatoryRefreshRoot,
758
+ patchContextRefreshRequired: true,
759
+ patchContextRefreshPath: scopedMandatoryRefreshPath,
760
+ },
761
+ [],
762
+ createToolContract([scopedMandatoryRefreshReadDescriptor, tool("finish")]),
763
+ { ok: true, calls: [], acceptedToolCalls: [], deferredToolCalls: [] }
764
+ );
765
+ assertStrict.deepEqual(
766
+ JSON.parse(
767
+ recoveredScopedMandatoryRefresh.acceptedToolCalls[0].function.arguments
768
+ ),
769
+ { path: scopedMandatoryRefreshPath },
770
+ "mandatory patch-context recovery rejected the exact scoped task artifact"
771
+ );
737
772
  const recoveredPrematureRefreshFinish = recoverRequiredPatchContextReadWithoutToolCall(
738
773
  {
739
774
  patchContextRefreshRequired: true,
@@ -8,6 +8,7 @@ import {
8
8
  completionRequirementCoverageInstruction,
9
9
  continuationExecutionContractDirective,
10
10
  removeSupersededCompletionRepairInstructions,
11
+ repositorySourcePrecedenceInstruction,
11
12
  runAgent,
12
13
  } from "../src/agent-runner.js";
13
14
  import { resolveRuntimeConfig } from "../src/config.js";
@@ -25,6 +26,36 @@ assert.match(completionCoverageInstruction, /authoritative structured routine/i)
25
26
  assert.match(completionCoverageInstruction, /every relevant section/i);
26
27
  assert.match(completionCoverageInstruction, /instead of summarizing only failures or only successes/i);
27
28
 
29
+ const sourcePrecedenceInstruction = repositorySourcePrecedenceInstruction();
30
+ assert.match(sourcePrecedenceInstruction, /current direct user request/i);
31
+ assert.match(sourcePrecedenceInstruction, /closest project instructions/i);
32
+ assert.match(sourcePrecedenceInstruction, /most specific current implementation and tests/i);
33
+ assert.match(sourcePrecedenceInstruction, /stale guides/i);
34
+ assert.match(sourcePrecedenceInstruction, /AGENTS\.md/i);
35
+
36
+ const readOnlyContractAuditGoal = `
37
+ Audit the current source-intake contract and cover an ordinary video, a hypothetical
38
+ same-chat publish request, a Finder card, and a document attachment. Do not send any
39
+ message, publish anything, alter a queue, open a browser, or modify configuration.
40
+ `;
41
+ const readOnlyContractAudit = deriveScsTaskContract({
42
+ goal: readOnlyContractAuditGoal,
43
+ taskProfile: "auto",
44
+ });
45
+ assert.equal(readOnlyContractAudit.readOnlyReadiness, true);
46
+ assert(
47
+ !readOnlyContractAudit.requiredEvidence.some((item) => item.category === "publish"),
48
+ "a hypothetical publish case inside a forbidden read-only contract audit required live publish evidence"
49
+ );
50
+ assert(
51
+ !readOnlyContractAudit.requiredEvidence.some((item) => item.category === "browser"),
52
+ "a forbidden browser action inside a read-only contract audit required browser evidence"
53
+ );
54
+ assert(
55
+ readOnlyContractAudit.forbiddenActions.some((item) => /publish anything/i.test(item)),
56
+ "the read-only audit lost its explicit publish prohibition"
57
+ );
58
+
28
59
  assert.equal(
29
60
  finishResultClaimsIncompleteWork(
30
61
  "The report is complete and the verification that was previously paused now passes. No work remains."
@@ -2973,6 +2973,10 @@ export function completionRequirementCoverageInstruction() {
2973
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
2974
  }
2975
2975
 
2976
+ export function repositorySourcePrecedenceInstruction() {
2977
+ return "Treat the current direct user request and the closest project instructions as authoritative. When describing an existing contract, inspect the most specific current implementation and tests, reconcile conflicting documentation, and never let examples, stale guides, or historical notes override AGENTS.md or current code. State any unresolved conflict instead of choosing silently.";
2978
+ }
2979
+
2976
2980
  function focusedCapabilityContext(config = {}) {
2977
2981
  return [
2978
2982
  config.allowFileTools
@@ -3017,6 +3021,7 @@ function buildFocusedRuntimeMessages({
3017
3021
  "Answer ordinary conversation directly. For executable work, act through the smallest relevant routine or tool, verify in proportion to risk, then stop.",
3018
3022
  "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
3023
  completionRequirementCoverageInstruction(),
3024
+ repositorySourcePrecedenceInstruction(),
3020
3025
  "Established project routines are capabilities to invoke, not workflows to reimplement. Discover more context only when the current task needs it.",
3021
3026
  formatBehaviorContractForPrompt({ mode: "focused" }),
3022
3027
  languageInstruction(config.language || "en"),
@@ -3236,6 +3241,7 @@ async function createInitialState(config, sessionId) {
3236
3241
  "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.",
3237
3242
  "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
3243
  completionRequirementCoverageInstruction(),
3244
+ repositorySourcePrecedenceInstruction(),
3239
3245
  browserStateReconciliationGuidance(),
3240
3246
  isRetainedWorkspaceProfile(config)
3241
3247
  ? "Choose descriptive non-conflicting workspace paths for durable outputs."
@@ -10165,7 +10171,8 @@ export function repeatedStaticToolBlock(state, toolName, args = {}, config = {})
10165
10171
  (
10166
10172
  (
10167
10173
  requiredPatchRefresh &&
10168
- safeRecoveryEvidencePath(args?.path) === requiredPatchRefresh.path
10174
+ safePatchContextEvidencePath(args?.path, state, config) ===
10175
+ requiredPatchRefresh.path
10169
10176
  ) ||
10170
10177
  boundedFailedTestReadPaths.includes(safeRecoveryEvidencePath(args?.path))
10171
10178
  )
@@ -12675,7 +12682,9 @@ function isPrivateVerificationEvidencePath(value = "") {
12675
12682
  }
12676
12683
 
12677
12684
  function isScopedTaskArtifactEvidencePath(value = "", state = {}, config = {}) {
12678
- const artifactRoot = scopedArtifactRoot(completionContractGoal(config, state));
12685
+ const artifactRoot =
12686
+ scopedArtifactRoot(completionContractGoal(config, state)) ||
12687
+ String(config.scopedArtifactRoot || "").trim();
12679
12688
  if (!artifactRoot) return false;
12680
12689
  const raw = String(value || "")
12681
12690
  .trim()
@@ -12694,6 +12703,41 @@ function isScopedTaskArtifactEvidencePath(value = "", state = {}, config = {}) {
12694
12703
  );
12695
12704
  }
12696
12705
 
12706
+ function safePatchContextEvidencePath(value = "", state = {}, config = {}) {
12707
+ const sourcePath = safeRecoveryEvidencePath(value);
12708
+ if (sourcePath) return sourcePath;
12709
+
12710
+ const raw = String(value || "")
12711
+ .trim()
12712
+ .replace(/^["']|["']$/g, "")
12713
+ .replace(/\\/g, "/");
12714
+ if (
12715
+ !raw ||
12716
+ raw.includes("\0") ||
12717
+ /^https?:\/\//i.test(raw) ||
12718
+ /(?:secret|credential|password|private[-_]?key|access[-_]?token)/i.test(raw)
12719
+ ) {
12720
+ return "";
12721
+ }
12722
+ const commandCwd = path.resolve(
12723
+ config.commandCwd || state.commandCwd || process.cwd()
12724
+ );
12725
+ const absolutePath = path.isAbsolute(raw)
12726
+ ? path.resolve(raw)
12727
+ : path.resolve(commandCwd, raw);
12728
+ const relativePath = path.relative(commandCwd, absolutePath).replace(/\\/g, "/");
12729
+ if (
12730
+ !relativePath ||
12731
+ relativePath.startsWith("..") ||
12732
+ path.isAbsolute(relativePath) ||
12733
+ !PLAIN_TEXT_FILE_EXTENSIONS.has(path.extname(relativePath).toLowerCase()) ||
12734
+ !isScopedTaskArtifactEvidencePath(raw, state, config)
12735
+ ) {
12736
+ return "";
12737
+ }
12738
+ return relativePath;
12739
+ }
12740
+
12697
12741
  function commandWritesOnlyEvidenceMatching(command = "", pathMatches = () => false) {
12698
12742
  const normalized = String(command || "").trim();
12699
12743
  if (!normalized) return false;
@@ -17604,10 +17648,11 @@ function validatedPatchContextCompleteSource(marker = {}) {
17604
17648
 
17605
17649
  export function activePatchContextRefresh(state = {}) {
17606
17650
  const marker = state.meta?.toolLoop?.patchContextRequired;
17651
+ const markerPath = safePatchContextEvidencePath(marker?.path, state);
17607
17652
  if (
17608
17653
  !marker ||
17609
17654
  Number(marker.version || 0) !== PATCH_CONTEXT_REFRESH_VERSION ||
17610
- !safeRecoveryEvidencePath(marker.path)
17655
+ !markerPath
17611
17656
  ) {
17612
17657
  return null;
17613
17658
  }
@@ -17638,16 +17683,17 @@ export function activePatchContextRefresh(state = {}) {
17638
17683
  }
17639
17684
  return {
17640
17685
  ...marker,
17641
- path: safeRecoveryEvidencePath(marker.path),
17686
+ path: markerPath,
17642
17687
  };
17643
17688
  }
17644
17689
 
17645
17690
  export function activePatchContextRepair(state = {}) {
17646
17691
  const marker = state.meta?.toolLoop?.patchContextRepair;
17692
+ const markerPath = safePatchContextEvidencePath(marker?.path, state);
17647
17693
  if (
17648
17694
  !marker ||
17649
17695
  Number(marker.version || 0) !== PATCH_CONTEXT_REPAIR_VERSION ||
17650
- !safeRecoveryEvidencePath(marker.path) ||
17696
+ !markerPath ||
17651
17697
  !String(marker.search || "") ||
17652
17698
  !String(marker.searchHash || "")
17653
17699
  ) {
@@ -17688,8 +17734,7 @@ export function activePatchContextRepair(state = {}) {
17688
17734
  const samePathFocuses = diagnosticMatchesRevision
17689
17735
  ? (Array.isArray(diagnostic.focuses) ? diagnostic.focuses : []).filter(
17690
17736
  (focus) =>
17691
- safeRecoveryEvidencePath(focus?.path) ===
17692
- safeRecoveryEvidencePath(marker.path) &&
17737
+ safePatchContextEvidencePath(focus?.path, state) === markerPath &&
17693
17738
  String(focus?.directSearch || "")
17694
17739
  )
17695
17740
  : [];
@@ -17706,7 +17751,7 @@ export function activePatchContextRepair(state = {}) {
17706
17751
  const completeSource = validatedPatchContextCompleteSource(marker);
17707
17752
  return {
17708
17753
  ...marker,
17709
- path: safeRecoveryEvidencePath(marker.path),
17754
+ path: markerPath,
17710
17755
  completeSource,
17711
17756
  completeSourceHash: completeSource ? String(marker.completeSourceHash || "") : "",
17712
17757
  completeSourceBytes: completeSource
@@ -18066,7 +18111,7 @@ function failedTestTracebackLineAnchor(state = {}, targetPath = "") {
18066
18111
  export function bindPatchContextRepairArguments(state = {}, requestedArgs = {}) {
18067
18112
  const marker = activePatchContextRepair(state);
18068
18113
  if (!marker || typeof requestedArgs?.replace !== "string") return null;
18069
- const requestedPath = safeRecoveryEvidencePath(requestedArgs.path);
18114
+ const requestedPath = safePatchContextEvidencePath(requestedArgs.path, state);
18070
18115
  if (requestedPath && requestedPath !== marker.path) return null;
18071
18116
  const requestedSearch = String(requestedArgs.search || "");
18072
18117
  const boundedSubrange = revisionBoundRequestedPatchSubrange(
@@ -18158,7 +18203,7 @@ export function bindPatchContextRepairArguments(state = {}, requestedArgs = {})
18158
18203
  }
18159
18204
 
18160
18205
  export function patchContextScopeMismatchAttemptCount(state = {}, targetPath = "") {
18161
- const normalizedPath = safeRecoveryEvidencePath(targetPath);
18206
+ const normalizedPath = safePatchContextEvidencePath(targetPath, state);
18162
18207
  if (!normalizedPath) return 0;
18163
18208
  const toolLoop = state.meta?.toolLoop || {};
18164
18209
  const stagnationEpoch = Math.max(0, Number(toolLoop.stagnationEpoch || 0));
@@ -18172,7 +18217,7 @@ export function patchContextScopeMismatchAttemptCount(state = {}, targetPath = "
18172
18217
  entry?.toolName !== "apply_patch" ||
18173
18218
  entry?.ok !== false ||
18174
18219
  entry?.category !== "patch-context-scope-mismatch" ||
18175
- safeRecoveryEvidencePath(entry?.path) !== normalizedPath ||
18220
+ safePatchContextEvidencePath(entry?.path, state) !== normalizedPath ||
18176
18221
  Number(entry?.stagnationEpoch || 0) !== stagnationEpoch
18177
18222
  ) {
18178
18223
  return false;
@@ -18253,7 +18298,7 @@ export function patchContextRefreshDecision(state = {}, toolResult = {}) {
18253
18298
  const recent = Array.isArray(toolLoop.recent) ? toolLoop.recent : [];
18254
18299
  const samePathRecent = recent.filter(
18255
18300
  (entry) =>
18256
- safeRecoveryEvidencePath(entry?.path) === targetPath &&
18301
+ safePatchContextEvidencePath(entry?.path, state) === targetPath &&
18257
18302
  Number(entry?.stagnationEpoch || 0) === stagnationEpoch
18258
18303
  );
18259
18304
  const priorMissingSearches = samePathRecent.filter(
@@ -18564,7 +18609,8 @@ export function consumePatchContextRepairMutation(state = {}, toolResult = {}) {
18564
18609
  String(toolResult.toolName || "") !== "apply_patch" ||
18565
18610
  toolResult.ok === false ||
18566
18611
  toolResult.blocked === true ||
18567
- toolResultWorkspacePath(toolResult) !== safeRecoveryEvidencePath(marker.path) ||
18612
+ toolResultWorkspacePath(toolResult) !==
18613
+ safePatchContextEvidencePath(marker.path, state) ||
18568
18614
  ![
18569
18615
  String(marker.searchHash || ""),
18570
18616
  String(marker.lastBoundSearchHash || ""),
@@ -24205,11 +24251,13 @@ export function recoverRequiredPatchContextReadWithoutToolCall(
24205
24251
  const selectedFailedTestReadMode = Boolean(
24206
24252
  !refreshMode && !repairMode && !selectedFailedTestDiagnosticReadMode && failedTestReadMode
24207
24253
  );
24254
+ const patchContextPath = (value) =>
24255
+ safePatchContextEvidencePath(value, {}, config);
24208
24256
  const exactPath = selectedFailedTestDiagnosticReadMode
24209
24257
  ? safeGeneratedDiagnosticEvidencePath(
24210
24258
  config.testFailureWorkspaceDiagnosticReadPaths?.[0]
24211
24259
  )
24212
- : safeRecoveryEvidencePath(
24260
+ : (refreshMode || repairMode ? patchContextPath : safeRecoveryEvidencePath)(
24213
24261
  refreshMode
24214
24262
  ? config.patchContextRefreshPath
24215
24263
  : repairMode
@@ -24220,7 +24268,9 @@ export function recoverRequiredPatchContextReadWithoutToolCall(
24220
24268
  const requestedCall = calls.length === 1 ? calls[0] : null;
24221
24269
  const requestedToolName = String(requestedCall?.function?.name || "");
24222
24270
  const requestedArgs = safeParseToolArgs(requestedCall);
24223
- const requestedPath = safeRecoveryEvidencePath(requestedArgs.path);
24271
+ const requestedPath = (refreshMode || repairMode
24272
+ ? patchContextPath
24273
+ : safeRecoveryEvidencePath)(requestedArgs.path);
24224
24274
  const missingRefreshCall = validation?.ok === true && calls.length === 0 && refreshMode;
24225
24275
  const unavailableContextCall =
24226
24276
  validation?.ok !== true &&
@@ -24289,7 +24339,9 @@ export function recoverRequiredPatchContextReadWithoutToolCall(
24289
24339
  readDescriptor.function?.parameters?.properties?.path?.enum;
24290
24340
  const normalizeAllowedPath = selectedFailedTestDiagnosticReadMode
24291
24341
  ? safeGeneratedDiagnosticEvidencePath
24292
- : safeRecoveryEvidencePath;
24342
+ : refreshMode || repairMode
24343
+ ? patchContextPath
24344
+ : safeRecoveryEvidencePath;
24293
24345
  if (
24294
24346
  !Array.isArray(allowedPaths) ||
24295
24347
  (!selectedFailedTestReadMode && !selectedFailedTestDiagnosticReadMode && allowedPaths.length !== 1) ||
@@ -454,6 +454,13 @@ function normalizeWrappedNegativePrefixes(goal = "") {
454
454
  );
455
455
  }
456
456
 
457
+ function normalizeSoftLineWraps(goal = "") {
458
+ return normalizeWrappedNegativePrefixes(goal).replace(
459
+ /([A-Za-z0-9,])[ \t]*\r?\n[ \t]*(?=[a-z])/g,
460
+ "$1 "
461
+ );
462
+ }
463
+
457
464
  function inferExactOutputPaths(goal = "") {
458
465
  const paths = [];
459
466
  const lines = String(goal || "").split(/\n/);
@@ -1406,10 +1413,17 @@ function isReadOnlyReadinessTask(goal = "") {
1406
1413
  /\b(?:readiness|capability)\s+(?:audit|check|report|assessment)\b/i.test(text) ||
1407
1414
  /\bwhether\s+(?:i|we|the\s+(?:agent|system))\s+can\b/i.test(text) ||
1408
1415
  /只读检查|只讀檢查|就绪检查|就緒檢查|能力检查|能力檢查|检查是否|檢查是否/.test(text);
1416
+ const contractAuditSignal =
1417
+ /\b(?:audit|inspect|review|assess|document|report\s+on)\s+(?:the\s+)?(?:current\s+)?[^.\n;]{0,140}\b(?:contract|policy|behavio(?:u)?r|workflow|implementation|routine|routing|readiness|capabilit(?:y|ies))\b/i.test(
1418
+ text
1419
+ ) ||
1420
+ /(?:审计|審計|检查|檢查|审查|審查|评估|評估|记录|記錄)[^。;\n]{0,120}(?:契约|契約|策略|行为|行為|流程|实现|實現|例程|路由|就绪|就緒|能力)/.test(
1421
+ text
1422
+ );
1409
1423
  const noActionSignal =
1410
- /\b(?:do not|don't|dont|never|without)\b[^.\n;]{0,260}\b(?:generate|submit|upload|publish|deploy|log in|login|restart|edit|modify|delete|purchase|pay)\b/i.test(text) ||
1424
+ /\b(?:do not|don't|dont|never|without)\b[^.\n;]{0,260}\b(?:send|generate|submit|upload|publish|deploy|open|browse|focus|restart|alter|change|edit|modify|write|mutate|delete|purchase|pay|log in|login)\b/i.test(text) ||
1411
1425
  /(?:不要|禁止)[^。\n;]{0,260}(?:生成|提交|上传|上傳|发布|發布|部署|登录|登入|重启|重啟|编辑|編輯|修改|删除|刪除|购买|購買|支付)/.test(text);
1412
- return readinessSignal && noActionSignal;
1426
+ return (readinessSignal || contractAuditSignal) && noActionSignal;
1413
1427
  }
1414
1428
 
1415
1429
  function requiresSourceGrounding(goal = "") {
@@ -1550,7 +1564,7 @@ function inferRequirementCategories(goal = "", taskProfile = "", acceptanceCrite
1550
1564
  }
1551
1565
 
1552
1566
  function inferForbiddenActions(goal = "") {
1553
- const text = String(goal || "");
1567
+ const text = normalizeSoftLineWraps(goal);
1554
1568
  const forbidden = [];
1555
1569
  const isAction = (value = "") =>
1556
1570
  /\b(use|open|click|browse|browser|upload|attach|submit|publish|deploy|run|execute|install|delete|remove|commit|push|call|api|alter|chang(?:e|ing)|edit(?:ing)?|fix(?:ing)?|modif(?:y|ying)|patch(?:ing)?|repair(?:ing)?|rewrit(?:e|ing)|send(?:ing)?|touch(?:ing)?|writ(?:e|ing))\b/i.test(
@@ -1601,7 +1615,7 @@ function inferRequiredToolCalls(goal = "") {
1601
1615
  }
1602
1616
 
1603
1617
  function stripForbiddenLanguage(goal = "") {
1604
- return normalizeWrappedNegativePrefixes(goal)
1618
+ return normalizeSoftLineWraps(goal)
1605
1619
  .replace(/\b(do not|don't|dont|must not|should not|never|no need to)\s+([^.\n;]+)/gi, "")
1606
1620
  .replace(/\bwithout\s+([^.,:\uFF1A\n;]+)/gi, "")
1607
1621
  .replace(/不要([^。\n;]+)/g, "")