@lazyingart/agintiflow 0.20.337-integration.0 → 0.20.339-integration.0
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/aginti-work-examples/deepseek-cli-fallback-20261001.md +9 -0
- package/docs/DEEPSEEK_ARTIFACT_COMPLETION.md +62 -0
- package/package.json +1 -1
- package/scripts/smoke-scs-evidence-visibility.js +15 -0
- package/scripts/smoke-truthful-completion.js +71 -0
- package/src/agent-runner.js +49 -36
- package/src/scs-evidence.js +22 -4
|
@@ -66,6 +66,15 @@ wall time. No external Codex/Claude/Gemini agent wrapper was called. The existin
|
|
|
66
66
|
Docker image was reused; no GPU model, GUI desktop, or dependency rebuild was
|
|
67
67
|
needed. The test-created containers exited after each command.
|
|
68
68
|
|
|
69
|
+
The packaged CLI was then installed globally and tested again in a separate fresh
|
|
70
|
+
workspace, using the installed entry point rather than the source checkout. All
|
|
71
|
+
three cases passed again: summary in 6.8 seconds / 4 turns, code repair in 37.1
|
|
72
|
+
seconds / 5 turns, and Chinese follow-up in 16.7 seconds / 4 additional turns.
|
|
73
|
+
The same independent checks passed, including all 22 oracle assertions and
|
|
74
|
+
unchanged input/code/test bytes where required. The installed package also passed
|
|
75
|
+
the 13 focused lifecycle and CLI-policy regressions. These timings describe that
|
|
76
|
+
individual run and are not a throughput guarantee.
|
|
77
|
+
|
|
69
78
|
## Usage
|
|
70
79
|
|
|
71
80
|
See [DeepSeek CLI fallback](../docs/deepseek-cli-fallback.md) for start/resume,
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# DeepSeek Artifact Completion and Host Integration
|
|
2
|
+
|
|
3
|
+
Machine hosts should invoke both new and resumed AgInTi turns with
|
|
4
|
+
`--no-wrappers` when AgInTi is the fallback for an unavailable external agent.
|
|
5
|
+
Keep the provider explicit; credentials do not authorize a provider switch.
|
|
6
|
+
Use the host's existing routines rather than rewriting them in the agent loop.
|
|
7
|
+
|
|
8
|
+
## Source Changes Are Not Artifact Changes
|
|
9
|
+
|
|
10
|
+
A task that reads inputs and writes a separate summary must not be pushed into
|
|
11
|
+
editing those inputs. A task that creates or updates artifacts inside an exact
|
|
12
|
+
host-provided root must not be pushed into changing the generator's source.
|
|
13
|
+
Private task files deliberately do not increment the project-source revision.
|
|
14
|
+
|
|
15
|
+
Execution and completion now share bounded artifact-root resolution. A real
|
|
16
|
+
current-turn scoped write can satisfy artifact freshness without an unrelated
|
|
17
|
+
project edit. Its saved timestamp must follow the current execution contract;
|
|
18
|
+
old mutations, no-op patches, and workspace-wide roots do not qualify for this
|
|
19
|
+
exemption. Explicit input repairs still require their requested changes.
|
|
20
|
+
After a verified scoped write satisfies a prior missing-file/freshness repair,
|
|
21
|
+
the runtime also stops enforcing that retained repair's obsolete source-edit
|
|
22
|
+
phase. Actual source or artifact quality defects remain blocking. Keeping the
|
|
23
|
+
current contract correct without retiring the obsolete phase can still trap a
|
|
24
|
+
valid routine in repeated no-op patches.
|
|
25
|
+
File, command, requested-format, source-grounding, and quality evidence gates
|
|
26
|
+
remain active. In particular, a pre-existing PDF cannot satisfy a request to
|
|
27
|
+
materially revise and rebuild it.
|
|
28
|
+
|
|
29
|
+
Postfix input declarations such as `requirements.txt is a read-only input`
|
|
30
|
+
are recognized without accidentally excluding a neighboring output path.
|
|
31
|
+
Coordinated preservation instructions such as `leave a.txt and b.txt untouched`
|
|
32
|
+
exclude both inputs from deliverables, not just paths adjacent to the verb.
|
|
33
|
+
An output requested after that preservation clause remains required.
|
|
34
|
+
|
|
35
|
+
## Source-Free Answers
|
|
36
|
+
|
|
37
|
+
Refusing to invent a forecast is not a forecast. Chinese and English negated
|
|
38
|
+
forecast clauses are stripped before assessing whether an answer needs source
|
|
39
|
+
evidence. A real prediction later in the same sentence remains evidence-gated.
|
|
40
|
+
Likewise, saying an item is unverified, pending confirmation, or needs no repeat
|
|
41
|
+
confirmation is not a claim that it has been independently validated. Only the
|
|
42
|
+
negated phrase is removed; real validation claims in the remaining text still
|
|
43
|
+
require evidence.
|
|
44
|
+
|
|
45
|
+
## Validation
|
|
46
|
+
|
|
47
|
+
Run the evidence-visibility, truthful-completion, and scoped-artifact-research
|
|
48
|
+
smokes, then the full `npm test`. The LabCanvas host adds separate mocked
|
|
49
|
+
timeout/session/concurrency tests and opt-in live DeepSeek acceptance:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
python scripts/evaluate_aginti_fallback.py --live --command /path/to/bin/aginti-cli.js
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The host test uses synthetic inputs, isolated session registries, actual routine
|
|
56
|
+
commands, a compiled Chinese memo PDF, and resumed turns. It prohibits external
|
|
57
|
+
chat sends, public publication, and external agent wrappers. Saved inputs and
|
|
58
|
+
attempted tool writes are checked independently of the model's final answer.
|
|
59
|
+
|
|
60
|
+
This is acceptance for simple host tasks, not a claim that DeepSeek matches
|
|
61
|
+
Codex across all tasks. Keep model/provider limitations separate from agent-loop
|
|
62
|
+
or host-integration failures.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lazyingart/agintiflow",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.339-integration.0",
|
|
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",
|
|
@@ -98,6 +98,21 @@ assert.deepEqual(immutableInputsContract.exactInputPaths, ["notes.txt", "risks.t
|
|
|
98
98
|
assert.deepEqual(immutableInputsContract.exactOutputPaths, ["summary.md"]);
|
|
99
99
|
assert.deepEqual(immutableInputsContract.excludedOutputPaths, ["notes.txt", "risks.txt"]);
|
|
100
100
|
assert.equal(immutableInputsContract.requiresSourceGrounding, true);
|
|
101
|
+
const coordinatedUntouchedInputsContract = deriveScsTaskContract({
|
|
102
|
+
goal: "Read notes.txt and risks.txt. Create artifacts/summary.md. Leave notes.txt and risks.txt untouched, then write artifacts/result.json.",
|
|
103
|
+
});
|
|
104
|
+
assert.deepEqual(coordinatedUntouchedInputsContract.excludedOutputPaths, ["notes.txt", "risks.txt"]);
|
|
105
|
+
assert.deepEqual(coordinatedUntouchedInputsContract.exactOutputPaths, ["artifacts/summary.md", "artifacts/result.json"]);
|
|
106
|
+
assert.deepEqual(coordinatedUntouchedInputsContract.exactInputPaths, ["notes.txt", "risks.txt"]);
|
|
107
|
+
const postfixReadonlyInputContract = deriveScsTaskContract({
|
|
108
|
+
goal: "Create a scene in bench.scene.json. requirements.txt is a read-only input.",
|
|
109
|
+
});
|
|
110
|
+
assert.deepEqual(postfixReadonlyInputContract.exactOutputPaths, ["bench.scene.json"]);
|
|
111
|
+
assert.deepEqual(postfixReadonlyInputContract.exactInputPaths, ["requirements.txt"]);
|
|
112
|
+
assert.deepEqual(postfixReadonlyInputContract.excludedOutputPaths, ["requirements.txt"]);
|
|
113
|
+
assert.deepEqual(deriveScsTaskContract({
|
|
114
|
+
goal: "Create summary.md. `source.json` must remain immutable. Then update output.json.",
|
|
115
|
+
}).excludedOutputPaths, ["source.json"], "postfix write protection leaked onto a later output");
|
|
101
116
|
assert.deepEqual(evaluateScsSemanticContract(immutableInputsContract, {
|
|
102
117
|
commandCwd: scopedReadThenWriteRoot,
|
|
103
118
|
events: [{ type: "tool.completed", data: { ok: true, toolName: "read_file", path: "notes.txt", content: "first input" } }],
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
assessResponseOnlyEmptyEnvelope,
|
|
10
10
|
assessResponseOnlyPerfectAudit,
|
|
11
11
|
completionRequirementCoverageInstruction,
|
|
12
|
+
completionTaskContract,
|
|
12
13
|
continuationExecutionContractDirective,
|
|
13
14
|
evaluateAuthoritativeStructuredCompletionCoverage,
|
|
14
15
|
nextStepRuntimeConfig,
|
|
@@ -1214,6 +1215,16 @@ for (const candidateResult of [
|
|
|
1214
1215
|
"No forecast is requested; please clarify what this number means.",
|
|
1215
1216
|
"这不是预测;这串数字缺少上下文,无法判断它的含义。",
|
|
1216
1217
|
"これは予測ではありません。この数字だけでは文脈が不足しており、意味を判断できません。",
|
|
1218
|
+
"对两类客户群做事实性对比,只呈现现有资料中的差异,不编造营收预测。",
|
|
1219
|
+
"对两个客户群做事实对比,不编造收入预测。",
|
|
1220
|
+
"任务是对两个客户群体做事实性对比,不做虚构营收预测。",
|
|
1221
|
+
"只做两个客户群的事实对比,不做收入预测。",
|
|
1222
|
+
"对两个客户细分做事实对比,不做臆测性营收预测。",
|
|
1223
|
+
"对两类客户客群做事实性对比,不使用收入预测。",
|
|
1224
|
+
"结论以现有可得资料为限,未证实部分明确标注为待确认。",
|
|
1225
|
+
"已确定事项不再重复确认。",
|
|
1226
|
+
"Compare the customer groups; do not invent revenue forecasts.",
|
|
1227
|
+
"Never fabricate market predictions.",
|
|
1217
1228
|
]) {
|
|
1218
1229
|
const negatedForecastClarification = evaluateSourceFreeResponseClaims({
|
|
1219
1230
|
goal: sourceFreeResearchGoal,
|
|
@@ -1231,6 +1242,10 @@ for (const candidateResult of [
|
|
|
1231
1242
|
"No forecast was requested, but demand will grow next year.",
|
|
1232
1243
|
"这串数字缺少上下文,但报告预测市场需求明年会增长。",
|
|
1233
1244
|
"予測ではありませんが、市場需要は来年増加する見込みです。",
|
|
1245
|
+
"不编造营收预测,但报告预测市场需求明年会增长。",
|
|
1246
|
+
"Do not invent revenue forecasts, but demand will grow next year.",
|
|
1247
|
+
"不做臆测性营收预测,但报告预测市场需求明年会增长。",
|
|
1248
|
+
"资料未证实部分待确认,但实验已经验证成功。",
|
|
1234
1249
|
]) {
|
|
1235
1250
|
const disguisedForecast = evaluateSourceFreeResponseClaims({
|
|
1236
1251
|
goal: sourceFreeResearchGoal,
|
|
@@ -2488,6 +2503,17 @@ try {
|
|
|
2488
2503
|
assert.equal(editRuntime.completionFreshMutationRequired, true, `${verb}: actual input correction was exempted`);
|
|
2489
2504
|
assert(editRuntime.completionFreshMutationPaths.includes("notes.txt"));
|
|
2490
2505
|
}
|
|
2506
|
+
const artifactRuntime = nextStepRuntimeConfig({ goal, commandCwd: summaryWorkspace }, {
|
|
2507
|
+
goal,
|
|
2508
|
+
commandCwd: summaryWorkspace,
|
|
2509
|
+
meta: {
|
|
2510
|
+
goalContract: { revision: 1, currentRequest: goal, activeGoal: goal },
|
|
2511
|
+
activeExecutionContract: { revision: 1, requiresFileMutation: true, requiresSourceGrounding: true, startedMutationRevision: 0 },
|
|
2512
|
+
projectVerification: { mutationRevision: 0, mutationHistory: [] },
|
|
2513
|
+
},
|
|
2514
|
+
});
|
|
2515
|
+
assert.notEqual(artifactRuntime.completionFreshMutationRequired, true,
|
|
2516
|
+
`${id}: separate deliverable forced a correction of its input or an unrelated source`);
|
|
2491
2517
|
}
|
|
2492
2518
|
|
|
2493
2519
|
const summaryFollowup = await runCase({
|
|
@@ -2511,6 +2537,51 @@ try {
|
|
|
2511
2537
|
assert.equal(await fs.readFile(path.join(followupWorkspace, "checklist.md"), "utf8"), "- Assign an archive owner.\n- Test the backup.\n");
|
|
2512
2538
|
|
|
2513
2539
|
const crossTaskIsolationId = "scoped-artifact-cross-task-completion";
|
|
2540
|
+
for (const nestedRoot of [true, false]) {
|
|
2541
|
+
const workspace = path.join(tempRoot, "workspaces", "scoped-json-freshness");
|
|
2542
|
+
await fs.mkdir(path.join(workspace, "artifacts"), { recursive: true });
|
|
2543
|
+
await fs.writeFile(path.join(workspace, "requirements.txt"), "Keep the tool source read-only.\n");
|
|
2544
|
+
await fs.writeFile(path.join(workspace, "artifacts", "bench.scene.json"), "{}\n");
|
|
2545
|
+
const artifactRoot = nestedRoot ? path.join(workspace, "artifacts") : workspace;
|
|
2546
|
+
const goal = scopedTaskGoal(
|
|
2547
|
+
"Use the existing routine to create artifacts/bench.scene.json and validate it. requirements.txt is a read-only input.",
|
|
2548
|
+
artifactRoot
|
|
2549
|
+
);
|
|
2550
|
+
const state = {
|
|
2551
|
+
goal, commandCwd: workspace,
|
|
2552
|
+
meta: {
|
|
2553
|
+
goalContract: { revision: 1, currentRequest: goal, activeGoal: goal },
|
|
2554
|
+
activeExecutionContract: {
|
|
2555
|
+
revision: 1, requiresFileMutation: true, requiresSourceGrounding: true, startedMutationRevision: 0,
|
|
2556
|
+
refreshedAt: "2026-10-01T05:00:00Z",
|
|
2557
|
+
scopedArtifactMutationAt: "2026-10-01T05:00:01Z",
|
|
2558
|
+
},
|
|
2559
|
+
projectVerification: { mutationRevision: 0, mutationHistory: [] },
|
|
2560
|
+
},
|
|
2561
|
+
};
|
|
2562
|
+
const contract = completionTaskContract({ goal, commandCwd: workspace }, state);
|
|
2563
|
+
assert.equal(contract.requiredFreshMutationRevision, nestedRoot ? 0 : 1,
|
|
2564
|
+
"task artifact writes were confused with project source corrections, or a workspace-wide root bypassed freshness");
|
|
2565
|
+
assert(contract.requiredEvidence.some((item) => item.category === "file"),
|
|
2566
|
+
"artifact creation must still require real file evidence");
|
|
2567
|
+
assert(contract.requiredEvidence.every((item) => !nestedRoot || !item.minimumMutationRevision));
|
|
2568
|
+
state.meta.completionEvidenceRepair = {
|
|
2569
|
+
key: "previous-file-evidence-rejection", at: "2026-10-01T05:00:00.500Z",
|
|
2570
|
+
requiresFreshFileMutation: true, requiredFreshMutationRevision: 1,
|
|
2571
|
+
};
|
|
2572
|
+
const runtime = nextStepRuntimeConfig({ goal, commandCwd: workspace }, state);
|
|
2573
|
+
assert.equal(runtime.completionFreshMutationRequired === true, !nestedRoot,
|
|
2574
|
+
"a satisfied artifact mutation remained trapped in the retained fresh-source repair phase");
|
|
2575
|
+
if (nestedRoot) {
|
|
2576
|
+
state.meta.completionEvidenceRepair.artifactQualityRepairRequired = true;
|
|
2577
|
+
assert.equal(nextStepRuntimeConfig({ goal, commandCwd: workspace }, state).completionFreshMutationRequired, true,
|
|
2578
|
+
"a fresh artifact write cannot waive an outstanding quality defect");
|
|
2579
|
+
state.meta.completionEvidenceRepair.artifactQualityRepairRequired = false;
|
|
2580
|
+
}
|
|
2581
|
+
state.meta.activeExecutionContract.scopedArtifactMutationAt = "2026-10-01T04:59:00Z";
|
|
2582
|
+
assert.equal(completionTaskContract({ goal, commandCwd: workspace }, state).requiredFreshMutationRevision, 1,
|
|
2583
|
+
"a prior artifact mutation cannot satisfy the current revision");
|
|
2584
|
+
}
|
|
2514
2585
|
const crossTaskWorkspace = path.join(tempRoot, "workspaces", crossTaskIsolationId);
|
|
2515
2586
|
const currentTaskRoot = path.join(crossTaskWorkspace, "output", "tasks", "current-task");
|
|
2516
2587
|
const siblingTaskRoot = path.join(crossTaskWorkspace, "output", "tasks", "sibling-task");
|
package/src/agent-runner.js
CHANGED
|
@@ -18940,6 +18940,23 @@ function groundedProjectTaskInstructionText(state = {}, config = {}, directContr
|
|
|
18940
18940
|
}
|
|
18941
18941
|
}
|
|
18942
18942
|
|
|
18943
|
+
function scopedArtifactTaskRoot(contract = {}, goal = "", commandCwd = process.cwd()) {
|
|
18944
|
+
const root = scopedArtifactRoot(goal);
|
|
18945
|
+
if (!root) return "";
|
|
18946
|
+
const cwd = path.resolve(commandCwd);
|
|
18947
|
+
const resolvedRoot = path.resolve(root);
|
|
18948
|
+
const relativeRoot = path.relative(cwd, resolvedRoot);
|
|
18949
|
+
if (!relativeRoot || relativeRoot.startsWith("..") || path.isAbsolute(relativeRoot)) return "";
|
|
18950
|
+
const outputs = Array.isArray(contract.exactOutputPaths) ? contract.exactOutputPaths : [];
|
|
18951
|
+
const scopedOutputs = outputs.length > 0 && outputs.every((item) => {
|
|
18952
|
+
const relative = path.relative(resolvedRoot, path.resolve(cwd, item));
|
|
18953
|
+
return relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative));
|
|
18954
|
+
});
|
|
18955
|
+
return contract.scopedArtifactDeliverable || contract.scopedArtifactOperation || scopedOutputs
|
|
18956
|
+
? relativeRoot.replace(/\\/g, "/")
|
|
18957
|
+
: "";
|
|
18958
|
+
}
|
|
18959
|
+
|
|
18943
18960
|
export function completionTaskContract(config = {}, state = {}) {
|
|
18944
18961
|
const taskProfile = config.taskProfile || state.meta?.taskProfile || "auto";
|
|
18945
18962
|
const contractGoal = completionContractGoal(config, state);
|
|
@@ -19021,9 +19038,22 @@ export function completionTaskContract(config = {}, state = {}) {
|
|
|
19021
19038
|
const scopedArtifactDeliverable = currentContract
|
|
19022
19039
|
? currentContract.scopedArtifactDeliverable === true
|
|
19023
19040
|
: activeExecutionContract.scopedArtifactDeliverable === true;
|
|
19041
|
+
const scopedMutationAt = Date.parse(String(activeExecutionContract.scopedArtifactMutationAt || ""));
|
|
19042
|
+
const refreshedAt = Date.parse(String(activeExecutionContract.refreshedAt || ""));
|
|
19043
|
+
const freshScopedMutation = Boolean(
|
|
19044
|
+
scopedArtifactTaskRoot(
|
|
19045
|
+
currentContract || contract, currentRequest || contractGoal,
|
|
19046
|
+
config.commandCwd || state.commandCwd || process.cwd()
|
|
19047
|
+
) &&
|
|
19048
|
+
Number.isFinite(scopedMutationAt) && Number.isFinite(refreshedAt) &&
|
|
19049
|
+
scopedMutationAt >= refreshedAt &&
|
|
19050
|
+
(currentContract?.exactInputPaths || []).every(
|
|
19051
|
+
(input) => !documentSourceMutationExplicitlyRequested(state, config, input)
|
|
19052
|
+
)
|
|
19053
|
+
);
|
|
19024
19054
|
const requiresFreshMutation = Boolean(
|
|
19025
19055
|
(currentContract?.requiresFileMutation || activeExecutionContract.requiresFileMutation) &&
|
|
19026
|
-
!scopedArtifactDeliverable
|
|
19056
|
+
!scopedArtifactDeliverable && !freshScopedMutation
|
|
19027
19057
|
);
|
|
19028
19058
|
const minimumMutationRevision = requiresFreshMutation
|
|
19029
19059
|
? startedMutationRevision + 1
|
|
@@ -19386,42 +19416,13 @@ export function nextStepRuntimeConfig(config = {}, state = {}) {
|
|
|
19386
19416
|
const currentGroundingGoal = String(
|
|
19387
19417
|
state.meta?.goalContract?.currentRequest || config.goal || state.goal || ""
|
|
19388
19418
|
);
|
|
19389
|
-
const scopedRoot = scopedArtifactRoot(completionContractGoal(config, state));
|
|
19390
19419
|
const commandCwd = path.resolve(
|
|
19391
19420
|
config.commandCwd || state.commandCwd || process.cwd()
|
|
19392
19421
|
);
|
|
19393
|
-
const
|
|
19394
|
-
|
|
19395
|
-
? path.relative(commandCwd, resolvedScopedRoot)
|
|
19396
|
-
: "";
|
|
19397
|
-
const exactScopedOutputs = Array.isArray(groundingTaskContract.exactOutputPaths)
|
|
19398
|
-
? groundingTaskContract.exactOutputPaths
|
|
19399
|
-
.map((item) => String(item || "").trim())
|
|
19400
|
-
.filter(Boolean)
|
|
19401
|
-
: [];
|
|
19402
|
-
const exactOutputsStayInsideScopedRoot = Boolean(
|
|
19403
|
-
resolvedScopedRoot &&
|
|
19404
|
-
exactScopedOutputs.length > 0 &&
|
|
19405
|
-
exactScopedOutputs.every((item) => {
|
|
19406
|
-
const absoluteOutput = path.resolve(commandCwd, item);
|
|
19407
|
-
const relativeOutput = path.relative(resolvedScopedRoot, absoluteOutput);
|
|
19408
|
-
return (
|
|
19409
|
-
relativeOutput === "" ||
|
|
19410
|
-
(!relativeOutput.startsWith("..") && !path.isAbsolute(relativeOutput))
|
|
19411
|
-
);
|
|
19412
|
-
})
|
|
19413
|
-
);
|
|
19414
|
-
const scopedArtifactTask = Boolean(
|
|
19415
|
-
(
|
|
19416
|
-
groundingTaskContract.scopedArtifactDeliverable === true ||
|
|
19417
|
-
groundingTaskContract.scopedArtifactOperation === true ||
|
|
19418
|
-
exactOutputsStayInsideScopedRoot
|
|
19419
|
-
) &&
|
|
19420
|
-
resolvedScopedRoot &&
|
|
19421
|
-
scopedRootRelative &&
|
|
19422
|
-
!scopedRootRelative.startsWith("..") &&
|
|
19423
|
-
!path.isAbsolute(scopedRootRelative)
|
|
19422
|
+
const scopedRootRelative = scopedArtifactTaskRoot(
|
|
19423
|
+
groundingTaskContract, completionContractGoal(config, state), commandCwd
|
|
19424
19424
|
);
|
|
19425
|
+
const scopedArtifactTask = Boolean(scopedRootRelative);
|
|
19425
19426
|
if (scopedArtifactTask) {
|
|
19426
19427
|
runtimeConfig.scopedArtifactTask = true;
|
|
19427
19428
|
runtimeConfig.scopedArtifactRoot = scopedRootRelative.replace(/\\/g, "/");
|
|
@@ -19544,20 +19545,32 @@ export function nextStepRuntimeConfig(config = {}, state = {}) {
|
|
|
19544
19545
|
),
|
|
19545
19546
|
retainedSourceQualityRepairRequired ? mutationRevision + 1 : 0
|
|
19546
19547
|
);
|
|
19548
|
+
const artifactRepairBoundaryAt = Date.parse(String(completionRepair.at || ""));
|
|
19549
|
+
const scopedArtifactSatisfiedRepair = Boolean(
|
|
19550
|
+
groundingScopedArtifactMutationSatisfied &&
|
|
19551
|
+
Number.isFinite(artifactRepairBoundaryAt) && scopedArtifactMutationAt > artifactRepairBoundaryAt &&
|
|
19552
|
+
Number(groundingTaskContract.requiredFreshMutationRevision || 0) === 0 &&
|
|
19553
|
+
!retainedSourceQualityRepairRequired &&
|
|
19554
|
+
completionRepair.sourceQualityRepairRequired !== true &&
|
|
19555
|
+
completionRepair.artifactQualityRepairRequired !== true
|
|
19556
|
+
);
|
|
19547
19557
|
const completionRepairRequiresFreshMutation = Boolean(
|
|
19548
|
-
|
|
19549
|
-
|
|
19558
|
+
!scopedArtifactSatisfiedRepair && (
|
|
19559
|
+
retainedSourceQualityRepairRequired ||
|
|
19560
|
+
completionRepair.requiresFreshFileMutation === true ||
|
|
19550
19561
|
(
|
|
19551
19562
|
completionRepair.key &&
|
|
19552
19563
|
groundingTaskContract.requiresFileMutation === true &&
|
|
19553
19564
|
completionFreshMutationRevision > mutationRevision
|
|
19554
19565
|
)
|
|
19566
|
+
)
|
|
19555
19567
|
);
|
|
19556
19568
|
const currentTurnRequiresFreshMutation = Boolean(
|
|
19557
19569
|
groundingExecutionContract.requiresFileMutation === true &&
|
|
19558
19570
|
groundingExecutionContract.requiresSourceGrounding === true &&
|
|
19559
19571
|
!groundingFreshMutationSatisfied &&
|
|
19560
|
-
!groundingScopedArtifactMutationSatisfied
|
|
19572
|
+
!groundingScopedArtifactMutationSatisfied &&
|
|
19573
|
+
!separateSourceDeliverable
|
|
19561
19574
|
);
|
|
19562
19575
|
const explicitHeadRestore = currentTurnRequiresFreshMutation
|
|
19563
19576
|
? explicitlyRequestedDirtyHeadRestore(state, config)
|
package/src/scs-evidence.js
CHANGED
|
@@ -891,8 +891,10 @@ export function inferExplicitlyExcludedOutputPaths(goal = "") {
|
|
|
891
891
|
// later exclusion backwards across coordinated clauses.
|
|
892
892
|
const negativeActionAfter =
|
|
893
893
|
/^\s*(?:(?:does\s+not|doesn't|is\s+not|isn't)\s+exist\b\s*(?:and\s+)?)?(?:must\s+not|should\s+not|never)\s+(?:be\s+)?(?:run|rerun|re-run|execut(?:e|ed)|creat(?:e|ed)|recreat(?:e|ed)|writ(?:e|ten)|generat(?:e|ed)|sav(?:e|ed)|output|touch(?:ed)?|modif(?:y|ied)|edit(?:ed)?|stag(?:e|ed)|commit(?:ted)?)(?:\b|\s)/i;
|
|
894
|
+
const immutablePathAfter =
|
|
895
|
+
/^[`"'\s]*(?:is|remains?|must\s+remain|should\s+remain)\s+(?:(?:an?|the)\s+)?(?:read[ -]?only|immutable)\b/i;
|
|
894
896
|
const keepAbsent =
|
|
895
|
-
/\b(?:keep|leave)\b[
|
|
897
|
+
/\b(?:keep|leave)\b[^!?。!?;;\n]{0,300}?\b(?:absent|missing|nonexistent|uncreated|untouched)\b/gi;
|
|
896
898
|
const cjkNegativeActionBefore =
|
|
897
899
|
/(?:不要|不得|禁止|无需|不需要)[^。!?;\n]{0,140}(?:运行|执行|重跑|创建|建立|写入|生成|保存|输出|修改|编辑|提交|暂存)/u;
|
|
898
900
|
const cjkNegativeActionAfter =
|
|
@@ -905,6 +907,7 @@ export function inferExplicitlyExcludedOutputPaths(goal = "") {
|
|
|
905
907
|
for (const clause of source.split(/[;;\n]|(?<=[.!?。!?])\s+/u)) {
|
|
906
908
|
pathPattern.lastIndex = 0;
|
|
907
909
|
const matches = [...clause.matchAll(pathPattern)];
|
|
910
|
+
const preservedPathSpans = [...clause.matchAll(keepAbsent)];
|
|
908
911
|
const immutablePathClause = Boolean(
|
|
909
912
|
/\b(?:treat|consider|regard)\b[^!?。!?;;\n]{0,260}\b(?:as\s+)?(?:immutable|read[ -]?only)\b/i.test(
|
|
910
913
|
clause
|
|
@@ -935,7 +938,10 @@ export function inferExplicitlyExcludedOutputPaths(goal = "") {
|
|
|
935
938
|
immutablePathClause ||
|
|
936
939
|
negativeActionBefore.test(before) ||
|
|
937
940
|
negativeActionAfter.test(after) ||
|
|
938
|
-
|
|
941
|
+
immutablePathAfter.test(after) ||
|
|
942
|
+
preservedPathSpans.some((span) =>
|
|
943
|
+
index >= span.index && index + rawPath.length <= span.index + span[0].length
|
|
944
|
+
) ||
|
|
939
945
|
cjkNegativeActionBefore.test(before) ||
|
|
940
946
|
cjkNegativeActionAfter.test(after) ||
|
|
941
947
|
directRemovalBefore.test(before) ||
|
|
@@ -2203,7 +2209,15 @@ function sourceFreeClaimSegmentOnlyNegatesForecast(text = "") {
|
|
|
2203
2209
|
" "
|
|
2204
2210
|
)
|
|
2205
2211
|
.replace(
|
|
2206
|
-
/(
|
|
2212
|
+
/(?:不是|並非|并非|没有|沒有|无|無|不作|不做|不使用|无需|無需|不需要)[^\s,,。!?;;但而]{0,12}?(?:预测|預測|预计|預計|推测|推測|预言|預言)/gu,
|
|
2213
|
+
" "
|
|
2214
|
+
)
|
|
2215
|
+
.replace(
|
|
2216
|
+
/\b(?:do\s+not|don't|must\s+not|never)\s+(?:invent|fabricate|make\s+up)\s+(?:any\s+)?(?:(?:revenue|income|market|demand)\s+)?(?:forecasts?|predictions?|projections?)\b/giu,
|
|
2217
|
+
" "
|
|
2218
|
+
)
|
|
2219
|
+
.replace(
|
|
2220
|
+
/(?:不|不要|不得|禁止)(?:编造|編造|虚构|虛構|捏造|杜撰)(?:任何)?(?:营收|營收|收入|市场|市場|需求)?(?:预测|預測|预计|預計|推测|推測)/gu,
|
|
2207
2221
|
" "
|
|
2208
2222
|
)
|
|
2209
2223
|
.replace(
|
|
@@ -2237,7 +2251,11 @@ function sourceFreeExternalClaimCategoriesForSegment(
|
|
|
2237
2251
|
text = "",
|
|
2238
2252
|
{ requireNamedEvidenceGrounding = false } = {}
|
|
2239
2253
|
) {
|
|
2240
|
-
|
|
2254
|
+
// Remove only negated verification phrases; reassess the remaining clause
|
|
2255
|
+
// so a real evidence claim beside a disclaimer still requires a source.
|
|
2256
|
+
const value = String(text || "")
|
|
2257
|
+
.replace(/(?:尚未|未经|未經|未|待)(?:被|得到|经过|經過)?(?:验证|驗證|核实|核實|证实|證實|确认|確認|证明|證明)/gu, " ")
|
|
2258
|
+
.replace(/(?:不再|不必|无需|無需|无须|無須)[^\s,,。!?;;但而]{0,12}?(?:验证|驗證|核实|核實|证实|證實|确认|確認|证明|證明)/gu, " ");
|
|
2241
2259
|
if (!value.trim()) return [];
|
|
2242
2260
|
const categories = [];
|
|
2243
2261
|
const add = (category, pattern) => {
|