@lazyingart/agintiflow 0.20.297 → 0.20.299
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 +1 -1
- package/scripts/smoke-dynamic-step-budget.js +212 -0
- package/scripts/smoke-execution-policy.js +42 -0
- package/scripts/smoke-model-roles.js +21 -0
- package/scripts/smoke-truthful-completion.js +5 -0
- package/src/agent-runner.js +198 -34
- package/src/config.js +5 -4
- package/src/model-client.js +9 -5
- package/src/scs-controller.js +9 -0
- package/src/scs-evidence.js +21 -2
- package/src/skill-library.js +14 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lazyingart/agintiflow",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.299",
|
|
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",
|
|
@@ -5800,6 +5800,167 @@ try {
|
|
|
5800
5800
|
evaluateScsEvidence(privateEvidenceContract, privateEvidenceLedger).ok,
|
|
5801
5801
|
"ignored private verification evidence invalidated a successful canonical build"
|
|
5802
5802
|
);
|
|
5803
|
+
const scopedTaskRoot = path.join(workspace, "output", "agent-task-1");
|
|
5804
|
+
const scopedTaskGoal = [
|
|
5805
|
+
"Create and verify output/result.json.",
|
|
5806
|
+
`AGINTI_EVIDENCE_SCOPE_JSON: ${JSON.stringify({
|
|
5807
|
+
mode: "task",
|
|
5808
|
+
request: "Create and verify output/result.json.",
|
|
5809
|
+
artifact_root: scopedTaskRoot,
|
|
5810
|
+
})}`,
|
|
5811
|
+
].join("\n");
|
|
5812
|
+
const scopedTaskState = {
|
|
5813
|
+
goal: scopedTaskGoal,
|
|
5814
|
+
commandCwd: workspace,
|
|
5815
|
+
meta: {
|
|
5816
|
+
goalContract: {
|
|
5817
|
+
revision: 1,
|
|
5818
|
+
taskGoal: scopedTaskGoal,
|
|
5819
|
+
currentRequest: "Create and verify output/result.json.",
|
|
5820
|
+
},
|
|
5821
|
+
},
|
|
5822
|
+
};
|
|
5823
|
+
recordProjectVerificationOutcome(
|
|
5824
|
+
scopedTaskState,
|
|
5825
|
+
{
|
|
5826
|
+
toolName: "write_file",
|
|
5827
|
+
ok: true,
|
|
5828
|
+
path: "output/result.json",
|
|
5829
|
+
changes: [
|
|
5830
|
+
{
|
|
5831
|
+
path: "output/result.json",
|
|
5832
|
+
created: true,
|
|
5833
|
+
beforeHash: "",
|
|
5834
|
+
afterHash: "requested-output",
|
|
5835
|
+
},
|
|
5836
|
+
],
|
|
5837
|
+
},
|
|
5838
|
+
{ commandCwd: workspace, taskProfile: "auto" }
|
|
5839
|
+
);
|
|
5840
|
+
const requestedOutputRevision =
|
|
5841
|
+
scopedTaskState.meta.projectVerification?.mutationRevision;
|
|
5842
|
+
const readOnlyArtifactValidation = {
|
|
5843
|
+
toolName: "run_command",
|
|
5844
|
+
ok: true,
|
|
5845
|
+
exitCode: 0,
|
|
5846
|
+
args: {
|
|
5847
|
+
command:
|
|
5848
|
+
"python3 -c \"import json; d=json.load(open('output/result.json')); assert d; print('PASS valid JSON')\"",
|
|
5849
|
+
},
|
|
5850
|
+
projectMutationPaths: [],
|
|
5851
|
+
stdout: "PASS valid JSON\n",
|
|
5852
|
+
stderr: "",
|
|
5853
|
+
};
|
|
5854
|
+
recordProjectVerificationOutcome(
|
|
5855
|
+
scopedTaskState,
|
|
5856
|
+
readOnlyArtifactValidation,
|
|
5857
|
+
{
|
|
5858
|
+
commandCwd: workspace,
|
|
5859
|
+
taskProfile: "auto",
|
|
5860
|
+
allowShellTool: true,
|
|
5861
|
+
sandboxMode: "host",
|
|
5862
|
+
}
|
|
5863
|
+
);
|
|
5864
|
+
recordProjectVerificationOutcome(
|
|
5865
|
+
scopedTaskState,
|
|
5866
|
+
{
|
|
5867
|
+
toolName: "write_file",
|
|
5868
|
+
ok: true,
|
|
5869
|
+
path: path.join(scopedTaskRoot, "agent-result.json"),
|
|
5870
|
+
changes: [
|
|
5871
|
+
{
|
|
5872
|
+
path: path.join(scopedTaskRoot, "agent-result.json"),
|
|
5873
|
+
created: true,
|
|
5874
|
+
beforeHash: "",
|
|
5875
|
+
afterHash: "delivery-manifest",
|
|
5876
|
+
},
|
|
5877
|
+
],
|
|
5878
|
+
},
|
|
5879
|
+
{ commandCwd: workspace, taskProfile: "auto" }
|
|
5880
|
+
);
|
|
5881
|
+
const scopedManifestCommand = {
|
|
5882
|
+
toolName: "run_command",
|
|
5883
|
+
ok: true,
|
|
5884
|
+
exitCode: 0,
|
|
5885
|
+
args: {
|
|
5886
|
+
command: `printf '%s\\n' '{}' > ${JSON.stringify(
|
|
5887
|
+
path.join(scopedTaskRoot, "agent-result.json")
|
|
5888
|
+
)}`,
|
|
5889
|
+
},
|
|
5890
|
+
stdout: "",
|
|
5891
|
+
stderr: "",
|
|
5892
|
+
};
|
|
5893
|
+
recordProjectVerificationOutcome(
|
|
5894
|
+
scopedTaskState,
|
|
5895
|
+
scopedManifestCommand,
|
|
5896
|
+
{
|
|
5897
|
+
commandCwd: workspace,
|
|
5898
|
+
taskProfile: "auto",
|
|
5899
|
+
allowShellTool: true,
|
|
5900
|
+
sandboxMode: "host",
|
|
5901
|
+
}
|
|
5902
|
+
);
|
|
5903
|
+
const pythonScopedManifestCommand = {
|
|
5904
|
+
toolName: "run_command",
|
|
5905
|
+
ok: true,
|
|
5906
|
+
exitCode: 0,
|
|
5907
|
+
args: {
|
|
5908
|
+
command: [
|
|
5909
|
+
"python3 - <<'PY'",
|
|
5910
|
+
`out = ${JSON.stringify(path.join(scopedTaskRoot, "agent-result.json"))}`,
|
|
5911
|
+
"with open(out, 'w', encoding='utf-8') as handle:",
|
|
5912
|
+
" handle.write('{}')",
|
|
5913
|
+
"PY",
|
|
5914
|
+
].join("\n"),
|
|
5915
|
+
},
|
|
5916
|
+
projectMutationPaths: [],
|
|
5917
|
+
stdout: "",
|
|
5918
|
+
stderr: "",
|
|
5919
|
+
};
|
|
5920
|
+
recordProjectVerificationOutcome(
|
|
5921
|
+
scopedTaskState,
|
|
5922
|
+
pythonScopedManifestCommand,
|
|
5923
|
+
{
|
|
5924
|
+
commandCwd: workspace,
|
|
5925
|
+
taskProfile: "auto",
|
|
5926
|
+
allowShellTool: true,
|
|
5927
|
+
sandboxMode: "host",
|
|
5928
|
+
}
|
|
5929
|
+
);
|
|
5930
|
+
assert(
|
|
5931
|
+
requestedOutputRevision === 1 &&
|
|
5932
|
+
scopedTaskState.meta.projectVerification?.mutationRevision === 1 &&
|
|
5933
|
+
readOnlyArtifactValidation.readOnlyArtifactValidation === true &&
|
|
5934
|
+
scopedManifestCommand.scopedTaskArtifactWrite === true &&
|
|
5935
|
+
pythonScopedManifestCommand.scopedTaskArtifactWrite === true,
|
|
5936
|
+
"task-scoped delivery bookkeeping invalidated requested artifact evidence"
|
|
5937
|
+
);
|
|
5938
|
+
const mutatingInlinePython = {
|
|
5939
|
+
toolName: "run_command",
|
|
5940
|
+
ok: true,
|
|
5941
|
+
exitCode: 0,
|
|
5942
|
+
args: {
|
|
5943
|
+
command: "python3 -c \"open('output/side.txt','w').write('changed')\"",
|
|
5944
|
+
},
|
|
5945
|
+
projectMutationPaths: [],
|
|
5946
|
+
stdout: "",
|
|
5947
|
+
stderr: "",
|
|
5948
|
+
};
|
|
5949
|
+
recordProjectVerificationOutcome(
|
|
5950
|
+
scopedTaskState,
|
|
5951
|
+
mutatingInlinePython,
|
|
5952
|
+
{
|
|
5953
|
+
commandCwd: workspace,
|
|
5954
|
+
taskProfile: "auto",
|
|
5955
|
+
allowShellTool: true,
|
|
5956
|
+
sandboxMode: "host",
|
|
5957
|
+
}
|
|
5958
|
+
);
|
|
5959
|
+
assert(
|
|
5960
|
+
scopedTaskState.meta.projectVerification?.mutationRevision === 2 &&
|
|
5961
|
+
mutatingInlinePython.readOnlyArtifactValidation !== true,
|
|
5962
|
+
"write-capable inline Python was incorrectly classified as read-only validation"
|
|
5963
|
+
);
|
|
5803
5964
|
const privateVerifierCommand =
|
|
5804
5965
|
"python3 .aginti/verification/lifecycle/smoke_test.py";
|
|
5805
5966
|
const privateVerifierState = {
|
|
@@ -8080,6 +8241,34 @@ try {
|
|
|
8080
8241
|
sourceGroundingRefreshState.meta.activeExecutionContract.requiresSourceGrounding === true,
|
|
8081
8242
|
"a concrete file correction did not require current source grounding"
|
|
8082
8243
|
);
|
|
8244
|
+
const scopedStaticArtifactRequest =
|
|
8245
|
+
"Create and verify output/parity/result.json with one JSON object. Read it back and finish.";
|
|
8246
|
+
const scopedStaticArtifactGoal = [
|
|
8247
|
+
"You are the persistent LabCanvas agent.",
|
|
8248
|
+
`AGINTI_EVIDENCE_SCOPE_JSON: ${JSON.stringify({
|
|
8249
|
+
mode: "task",
|
|
8250
|
+
request: scopedStaticArtifactRequest,
|
|
8251
|
+
artifact_root: "/tmp/labcanvas-task-1",
|
|
8252
|
+
})}`,
|
|
8253
|
+
"Read AGENTS.md and inspect implementation before editing.",
|
|
8254
|
+
].join("\n\n");
|
|
8255
|
+
const scopedStaticArtifactState = {
|
|
8256
|
+
goal: scopedStaticArtifactGoal,
|
|
8257
|
+
meta: {
|
|
8258
|
+
taskProfile: "auto",
|
|
8259
|
+
goalContract: {
|
|
8260
|
+
revision: 10,
|
|
8261
|
+
currentRequest: scopedStaticArtifactGoal,
|
|
8262
|
+
},
|
|
8263
|
+
projectVerification: { mutationRevision: 0 },
|
|
8264
|
+
},
|
|
8265
|
+
};
|
|
8266
|
+
resetSameTaskExecutionContract(scopedStaticArtifactState, 10);
|
|
8267
|
+
assert(
|
|
8268
|
+
scopedStaticArtifactState.meta.activeExecutionContract.requiresFileMutation === true &&
|
|
8269
|
+
scopedStaticArtifactState.meta.activeExecutionContract.requiresSourceGrounding === false,
|
|
8270
|
+
"LabCanvas wrapper instructions leaked into the scoped static-artifact execution contract"
|
|
8271
|
+
);
|
|
8083
8272
|
const concreteBudgetConfig = { maxSteps: 81, resetStepBudget: false };
|
|
8084
8273
|
assert(
|
|
8085
8274
|
applyConcreteContinuationStepBudgetBoundary(
|
|
@@ -11426,6 +11615,29 @@ try {
|
|
|
11426
11615
|
);
|
|
11427
11616
|
assert(artifactProgress.justActivated, "exact output mutation did not activate artifact validation");
|
|
11428
11617
|
assert(artifactState.meta.artifactProgress.complete, "exact output progress was not persisted");
|
|
11618
|
+
const commandArtifactState = {
|
|
11619
|
+
meta: {
|
|
11620
|
+
scs: {
|
|
11621
|
+
taskContract: {
|
|
11622
|
+
exactOutputPaths: ["output/generated.json"],
|
|
11623
|
+
},
|
|
11624
|
+
},
|
|
11625
|
+
},
|
|
11626
|
+
};
|
|
11627
|
+
const commandArtifactProgress = recordExactOutputProgress(
|
|
11628
|
+
commandArtifactState,
|
|
11629
|
+
{
|
|
11630
|
+
ok: true,
|
|
11631
|
+
toolName: "run_command",
|
|
11632
|
+
verifiedGeneratedOutputPaths: ["output/generated.json"],
|
|
11633
|
+
},
|
|
11634
|
+
{ commandCwd: workspace }
|
|
11635
|
+
);
|
|
11636
|
+
assert(
|
|
11637
|
+
commandArtifactProgress.justActivated &&
|
|
11638
|
+
commandArtifactState.meta.artifactProgress.complete,
|
|
11639
|
+
"snapshot-verified shell output did not activate exact artifact progress"
|
|
11640
|
+
);
|
|
11429
11641
|
assert(
|
|
11430
11642
|
nextStepRuntimeConfig({ provider: "localllm" }, artifactState).artifactValidationPhase === true,
|
|
11431
11643
|
"next step did not enter artifact validation mode"
|
|
@@ -15,6 +15,8 @@ import {
|
|
|
15
15
|
} from "../src/context-budget-controller.js";
|
|
16
16
|
import { maxStepsForExecutionPolicy, selectExecutionPolicy } from "../src/execution-policy.js";
|
|
17
17
|
import { SessionStore } from "../src/session-store.js";
|
|
18
|
+
import { selectSkillsForGoal } from "../src/skill-library.js";
|
|
19
|
+
import { scopedChatopsEvidenceGoal } from "../src/scs-evidence.js";
|
|
18
20
|
|
|
19
21
|
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
20
22
|
const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), "agintiflow-execution-policy-"));
|
|
@@ -97,6 +99,46 @@ try {
|
|
|
97
99
|
assert(responseOnlyConfig.executionTier === "focused", "response-only runtime did not select focused execution");
|
|
98
100
|
assert(!responseOnlyConfig.executionPolicy.requiresPlan, "response-only runtime still requires a plan");
|
|
99
101
|
|
|
102
|
+
const scopedArtifactGoal = [
|
|
103
|
+
"LabCanvas host wrapper: use browser automation, deep research, source ingestion, and recovery skills when relevant.",
|
|
104
|
+
"General host guidance: inspect complex repositories carefully and create a plan for difficult work.",
|
|
105
|
+
`AGINTI_EVIDENCE_SCOPE_JSON: ${JSON.stringify({
|
|
106
|
+
mode: "task",
|
|
107
|
+
request: "Create and verify output/parity/scoped-artifact.json with one valid JSON object.",
|
|
108
|
+
})}`,
|
|
109
|
+
].join("\n");
|
|
110
|
+
const scopedArtifactConfig = resolveRuntimeConfig(
|
|
111
|
+
{
|
|
112
|
+
provider: "mock",
|
|
113
|
+
routingMode: "smart",
|
|
114
|
+
model: "mock-agent",
|
|
115
|
+
goal: scopedArtifactGoal,
|
|
116
|
+
taskProfile: "auto",
|
|
117
|
+
enableScs: "auto",
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
baseDir: runtimeDir,
|
|
121
|
+
packageDir: repoRoot,
|
|
122
|
+
provider: "mock",
|
|
123
|
+
routingMode: "smart",
|
|
124
|
+
model: "mock-agent",
|
|
125
|
+
}
|
|
126
|
+
);
|
|
127
|
+
assert(
|
|
128
|
+
scopedArtifactConfig.executionTier === "focused" && !scopedArtifactConfig.executionPolicy.requiresPlan,
|
|
129
|
+
"host wrapper keywords inflated a scoped static-artifact task into planned execution"
|
|
130
|
+
);
|
|
131
|
+
assert(!scopedArtifactConfig.scsActive, "host wrapper keywords incorrectly activated SCS for a scoped static artifact");
|
|
132
|
+
const scopedSkillIds = selectSkillsForGoal(
|
|
133
|
+
scopedChatopsEvidenceGoal(scopedArtifactGoal, "auto"),
|
|
134
|
+
{ taskProfile: "auto", limit: 6, projectRoot: workspace }
|
|
135
|
+
).map((skill) => skill.id);
|
|
136
|
+
assert(scopedSkillIds.includes("structured-json"), "scoped JSON task did not retain its relevant structured-data skill");
|
|
137
|
+
assert(
|
|
138
|
+
!scopedSkillIds.some((id) => ["source-ingestion", "autonomous-artifact-pipeline", "wechat-labcanvas-chatops"].includes(id)),
|
|
139
|
+
`literal paths or payload values selected unrelated skills: ${scopedSkillIds.join(", ")}`
|
|
140
|
+
);
|
|
141
|
+
|
|
100
142
|
const simpleConfig = resolveRuntimeConfig(
|
|
101
143
|
{
|
|
102
144
|
provider: "mock",
|
|
@@ -1151,6 +1151,13 @@ const canvasArtifactContract = deriveScsTaskContract({
|
|
|
1151
1151
|
const jsonObjectContract = deriveScsTaskContract({
|
|
1152
1152
|
goal: "Extract a valid JSON object with schema from this text.",
|
|
1153
1153
|
});
|
|
1154
|
+
const scopedStaticJsonContract = deriveScsTaskContract({
|
|
1155
|
+
goal: [
|
|
1156
|
+
"Host wrapper: validate code, run commands, inspect browsers, and perform deep research when the request needs them.",
|
|
1157
|
+
'AGINTI_EVIDENCE_SCOPE_JSON: {"mode":"task","request":"Create and verify output/parity/aginti_verified_artifact.json with one valid JSON object, then read it back."}',
|
|
1158
|
+
].join("\n"),
|
|
1159
|
+
taskProfile: "code",
|
|
1160
|
+
});
|
|
1154
1161
|
const virtualFileContract = deriveScsTaskContract({
|
|
1155
1162
|
goal: "Create file: /workspace/virtual-output.txt with virtual Docker path support.",
|
|
1156
1163
|
});
|
|
@@ -1230,6 +1237,20 @@ assert(
|
|
|
1230
1237
|
!jsonObjectContract.requiredEvidence.some((item) => item.category === "file"),
|
|
1231
1238
|
"JSON object extraction should not be treated as a workspace file requirement without an explicit file/path"
|
|
1232
1239
|
);
|
|
1240
|
+
assert(
|
|
1241
|
+
scopedStaticJsonContract.requiredEvidence.some((item) => item.category === "file") &&
|
|
1242
|
+
!scopedStaticJsonContract.requiredEvidence.some((item) => item.category === "command"),
|
|
1243
|
+
"a scoped standalone JSON artifact should require file evidence without an unrelated shell command"
|
|
1244
|
+
);
|
|
1245
|
+
assert(
|
|
1246
|
+
scopedStaticJsonContract.exactOutputPaths.includes("output/parity/aginti_verified_artifact.json") &&
|
|
1247
|
+
!scopedStaticJsonContract.exactInputPaths.includes("output/parity/aginti_verified_artifact.json"),
|
|
1248
|
+
"create-and-verify should retain the structured-data path as an output rather than an input"
|
|
1249
|
+
);
|
|
1250
|
+
assert(
|
|
1251
|
+
scopedStaticJsonContract.requiredExecutableTerms.length === 0,
|
|
1252
|
+
"a required JSON boolean value was misclassified as executable production-source syntax"
|
|
1253
|
+
);
|
|
1233
1254
|
assert(
|
|
1234
1255
|
virtualFileContract.requiredEvidence.some((item) => item.category === "file") &&
|
|
1235
1256
|
!virtualFileContract.requiredEvidence.some((item) => item.category === "artifact"),
|
|
@@ -309,6 +309,11 @@ try {
|
|
|
309
309
|
String(explanation.state.messages.find((message) => message.role === "system")?.content || "").length < 10_000,
|
|
310
310
|
"focused runtime prompt did not use progressive disclosure"
|
|
311
311
|
);
|
|
312
|
+
assert.match(
|
|
313
|
+
String(explanation.state.messages.find((message) => message.role === "system")?.content || ""),
|
|
314
|
+
/run that command unchanged before probing --help, alternate wrappers/i,
|
|
315
|
+
"focused runtime did not prioritize exact established routine commands"
|
|
316
|
+
);
|
|
312
317
|
assert(
|
|
313
318
|
Math.max(
|
|
314
319
|
...explanation.state.messages
|
package/src/agent-runner.js
CHANGED
|
@@ -364,11 +364,14 @@ function textToolRetryInstruction(response) {
|
|
|
364
364
|
|
|
365
365
|
function buildScsRuntimeContext(config = {}, state = {}, extra = {}) {
|
|
366
366
|
const projectRoot = config.commandCwd || config.baseDir || process.cwd();
|
|
367
|
-
const selectedSkills = isRetainedWorkspaceProfile(config) ? [] : selectSkillsForGoal(
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
367
|
+
const selectedSkills = isRetainedWorkspaceProfile(config) ? [] : selectSkillsForGoal(
|
|
368
|
+
scopedChatopsEvidenceGoal(state.goal || config.goal || "", config.taskProfile),
|
|
369
|
+
{
|
|
370
|
+
taskProfile: config.taskProfile,
|
|
371
|
+
limit: 6,
|
|
372
|
+
projectRoot,
|
|
373
|
+
}
|
|
374
|
+
);
|
|
372
375
|
const verification = state.meta?.projectVerification || {};
|
|
373
376
|
const mutationRevision = Number(verification.mutationRevision || 0);
|
|
374
377
|
const privateMutationRevision = Number(verification.privateMutationRevision || 0);
|
|
@@ -435,11 +438,14 @@ function buildScsRuntimeContext(config = {}, state = {}, extra = {}) {
|
|
|
435
438
|
|
|
436
439
|
function withSelectedSkillReadOnlyRoots(config = {}, state = {}) {
|
|
437
440
|
const projectRoot = config.commandCwd || config.baseDir || process.cwd();
|
|
438
|
-
const selectedSkills = isRetainedWorkspaceProfile(config) ? [] : selectSkillsForGoal(
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
441
|
+
const selectedSkills = isRetainedWorkspaceProfile(config) ? [] : selectSkillsForGoal(
|
|
442
|
+
scopedChatopsEvidenceGoal(state.goal || config.goal || "", config.taskProfile),
|
|
443
|
+
{
|
|
444
|
+
taskProfile: config.taskProfile,
|
|
445
|
+
limit: 6,
|
|
446
|
+
projectRoot,
|
|
447
|
+
}
|
|
448
|
+
);
|
|
443
449
|
const skillReadOnlyRoots = [
|
|
444
450
|
...(Array.isArray(config.skillReadOnlyRoots) ? config.skillReadOnlyRoots : []),
|
|
445
451
|
...selectedSkills.map((skill) => skill.path).filter(Boolean),
|
|
@@ -2795,6 +2801,7 @@ function focusedCapabilityContext(config = {}) {
|
|
|
2795
2801
|
? `Advisory wrapper: ${normalizeWrapperName(config.preferredWrapper)} (${wrapperStatusText()}).`
|
|
2796
2802
|
: "Advisory wrappers: disabled.",
|
|
2797
2803
|
config.allowAuxiliaryTools ? "Auxiliary generation tools: enabled when the requested artifact needs them." : "Auxiliary tools: disabled.",
|
|
2804
|
+
"When the current request, project instructions, or routine contract names an exact established command, run that command unchanged before probing --help, alternate wrappers, process lists, or implementation source. If its result answers the request, stop discovery and finish.",
|
|
2798
2805
|
"Discovery must be bounded: after a blocked path or search, change method once; never use recursive grep. Prefer exact manifests, workspace search, or targeted rg with an explicit path, globs, and result limit.",
|
|
2799
2806
|
isRetainedWorkspaceProfile(config)
|
|
2800
2807
|
? isRetainedVisionWorkspaceProfile(config)
|
|
@@ -2891,7 +2898,11 @@ async function createInitialState(config, sessionId) {
|
|
|
2891
2898
|
const projectRoot = config.commandCwd || config.baseDir || process.cwd();
|
|
2892
2899
|
const selectedSkills = isRetainedWorkspaceProfile(config)
|
|
2893
2900
|
? []
|
|
2894
|
-
: selectSkillsForGoal(config.goal,
|
|
2901
|
+
: selectSkillsForGoal(scopedChatopsEvidenceGoal(config.goal, config.taskProfile), {
|
|
2902
|
+
taskProfile: config.taskProfile,
|
|
2903
|
+
limit: 6,
|
|
2904
|
+
projectRoot,
|
|
2905
|
+
});
|
|
2895
2906
|
const skillContext = formatSkillsForPrompt(selectedSkills);
|
|
2896
2907
|
const projectInstructions = await readProjectInstructions(config.baseDir || config.commandCwd || process.cwd());
|
|
2897
2908
|
const projectInstructionContext = formatProjectInstructions(projectInstructions);
|
|
@@ -4050,9 +4061,12 @@ export function resetSameTaskExecutionContract(state = {}, revision = 0) {
|
|
|
4050
4061
|
refreshPersistedProjectAcceptance(state);
|
|
4051
4062
|
const activeRevision = Math.max(0, Number(revision || state.meta?.goalContract?.revision || 0));
|
|
4052
4063
|
const currentRequest = String(state.meta?.goalContract?.currentRequest || state.goal || "").trim();
|
|
4064
|
+
const taskProfile = state.meta?.taskProfile || "auto";
|
|
4065
|
+
const scopedCurrentRequest =
|
|
4066
|
+
scopedChatopsEvidenceGoal(currentRequest, taskProfile) || currentRequest;
|
|
4053
4067
|
const currentTurnContract = deriveScsTaskContract({
|
|
4054
|
-
goal:
|
|
4055
|
-
taskProfile
|
|
4068
|
+
goal: scopedCurrentRequest,
|
|
4069
|
+
taskProfile,
|
|
4056
4070
|
});
|
|
4057
4071
|
const currentTurnCommands = normalizedRequiredProjectCommands(
|
|
4058
4072
|
currentTurnContract.requiredProjectCommands
|
|
@@ -4094,7 +4108,7 @@ export function resetSameTaskExecutionContract(state = {}, revision = 0) {
|
|
|
4094
4108
|
currentTurnContract.requiresSourceGrounding === true ||
|
|
4095
4109
|
(
|
|
4096
4110
|
currentTurnContract.requiresFileMutation === true &&
|
|
4097
|
-
goalClearlyAllowsOverwrite(
|
|
4111
|
+
goalClearlyAllowsOverwrite(scopedCurrentRequest)
|
|
4098
4112
|
)
|
|
4099
4113
|
),
|
|
4100
4114
|
requiredProjectCommands: currentTurnCommands,
|
|
@@ -4208,7 +4222,11 @@ async function applyContinuationPrompt(state, config, observers) {
|
|
|
4208
4222
|
const projectRoot = config.commandCwd || config.baseDir || process.cwd();
|
|
4209
4223
|
const selectedSkills = isRetainedWorkspaceProfile(config)
|
|
4210
4224
|
? []
|
|
4211
|
-
: selectSkillsForGoal(config.goal,
|
|
4225
|
+
: selectSkillsForGoal(scopedChatopsEvidenceGoal(config.goal, config.taskProfile), {
|
|
4226
|
+
taskProfile: config.taskProfile,
|
|
4227
|
+
limit: 6,
|
|
4228
|
+
projectRoot,
|
|
4229
|
+
});
|
|
4212
4230
|
const skillContext = formatSkillsForPrompt(selectedSkills);
|
|
4213
4231
|
const projectInstructions = await readProjectInstructions(config.baseDir || config.commandCwd || process.cwd());
|
|
4214
4232
|
state.meta = state.meta || {};
|
|
@@ -6384,9 +6402,9 @@ export function recordProjectVerificationOutcome(state = {}, toolResult = {}, co
|
|
|
6384
6402
|
}
|
|
6385
6403
|
}
|
|
6386
6404
|
|
|
6387
|
-
const projectMutationPaths = successfulProjectMutationPaths(toolResult);
|
|
6405
|
+
const projectMutationPaths = successfulProjectMutationPaths(toolResult, state, config);
|
|
6388
6406
|
const privateMutationPaths = successfulPrivateVerificationMutationPaths(toolResult);
|
|
6389
|
-
const materialMutationPaths = materialProjectMutationPaths(toolResult);
|
|
6407
|
+
const materialMutationPaths = materialProjectMutationPaths(toolResult, state, config);
|
|
6390
6408
|
if (["write_file", "apply_patch"].includes(toolName) && privateMutationPaths.length) {
|
|
6391
6409
|
delete state.meta.verifiedCompletionCandidate;
|
|
6392
6410
|
verification.privateMutationRevision += 1;
|
|
@@ -6549,12 +6567,23 @@ export function recordProjectVerificationOutcome(state = {}, toolResult = {}, co
|
|
|
6549
6567
|
config,
|
|
6550
6568
|
{ verificationCommand }
|
|
6551
6569
|
);
|
|
6570
|
+
const scopedTaskArtifactWrite = commandWritesOnlyScopedTaskArtifacts(
|
|
6571
|
+
mutationCommand,
|
|
6572
|
+
state,
|
|
6573
|
+
config
|
|
6574
|
+
);
|
|
6575
|
+
const readOnlyArtifactValidation = Boolean(
|
|
6576
|
+
commandMutationPaths.length === 0 &&
|
|
6577
|
+
commandIsBoundedReadOnlyArtifactValidation(mutationCommand)
|
|
6578
|
+
);
|
|
6552
6579
|
const projectContentMutation = Boolean(
|
|
6553
6580
|
command &&
|
|
6554
6581
|
toolResult.blocked !== true &&
|
|
6555
6582
|
!retainedExactVerification &&
|
|
6556
6583
|
!disposableGeneratedCleanup &&
|
|
6557
6584
|
!disposableGeneratedVerificationSideEffects &&
|
|
6585
|
+
!scopedTaskArtifactWrite &&
|
|
6586
|
+
!readOnlyArtifactValidation &&
|
|
6558
6587
|
(commandSucceeded || commandMutationPaths.length > 0) &&
|
|
6559
6588
|
(
|
|
6560
6589
|
commandCanMutateProjectContent(mutationCommand, commandPolicy) ||
|
|
@@ -6569,6 +6598,12 @@ export function recordProjectVerificationOutcome(state = {}, toolResult = {}, co
|
|
|
6569
6598
|
toolResult.disposableGeneratedVerificationSideEffects = true;
|
|
6570
6599
|
toolResult.disposableGeneratedVerificationPaths = commandMutationPaths;
|
|
6571
6600
|
}
|
|
6601
|
+
if (scopedTaskArtifactWrite) {
|
|
6602
|
+
toolResult.scopedTaskArtifactWrite = true;
|
|
6603
|
+
}
|
|
6604
|
+
if (readOnlyArtifactValidation) {
|
|
6605
|
+
toolResult.readOnlyArtifactValidation = true;
|
|
6606
|
+
}
|
|
6572
6607
|
let requiredBatch = currentRequiredCommandBatch(verification, requiredCommands);
|
|
6573
6608
|
const activeExecutionContract = state.meta?.activeExecutionContract;
|
|
6574
6609
|
const activeTurnCommands =
|
|
@@ -12084,7 +12119,27 @@ function isPrivateVerificationEvidencePath(value = "") {
|
|
|
12084
12119
|
);
|
|
12085
12120
|
}
|
|
12086
12121
|
|
|
12087
|
-
function
|
|
12122
|
+
function isScopedTaskArtifactEvidencePath(value = "", state = {}, config = {}) {
|
|
12123
|
+
const artifactRoot = scopedArtifactRoot(completionContractGoal(config, state));
|
|
12124
|
+
if (!artifactRoot) return false;
|
|
12125
|
+
const raw = String(value || "")
|
|
12126
|
+
.trim()
|
|
12127
|
+
.replace(/^(["'])|(["'])$/g, "")
|
|
12128
|
+
.replace(/\\/g, "/");
|
|
12129
|
+
if (!raw || raw.includes("\0") || /^https?:\/\//i.test(raw)) return false;
|
|
12130
|
+
const commandCwd = path.resolve(
|
|
12131
|
+
config.commandCwd || state.commandCwd || process.cwd()
|
|
12132
|
+
);
|
|
12133
|
+
const absoluteRoot = path.resolve(commandCwd, artifactRoot);
|
|
12134
|
+
const absoluteCandidate = path.resolve(commandCwd, raw);
|
|
12135
|
+
const relative = path.relative(absoluteRoot, absoluteCandidate);
|
|
12136
|
+
return Boolean(
|
|
12137
|
+
relative === "" ||
|
|
12138
|
+
(!relative.startsWith("..") && !path.isAbsolute(relative))
|
|
12139
|
+
);
|
|
12140
|
+
}
|
|
12141
|
+
|
|
12142
|
+
function commandWritesOnlyEvidenceMatching(command = "", pathMatches = () => false) {
|
|
12088
12143
|
const normalized = String(command || "").trim();
|
|
12089
12144
|
if (!normalized) return false;
|
|
12090
12145
|
const tokens = tokenizeShellWords(normalized);
|
|
@@ -12093,27 +12148,97 @@ function commandWritesOnlyPrivateVerificationEvidence(command = "") {
|
|
|
12093
12148
|
if (["-a", "--append"].includes(tokens[index])) index += 1;
|
|
12094
12149
|
if (tokens[index] === "--") index += 1;
|
|
12095
12150
|
const targets = tokens.slice(index);
|
|
12096
|
-
return targets.length > 0 && targets.every(
|
|
12151
|
+
return targets.length > 0 && targets.every(pathMatches);
|
|
12097
12152
|
}
|
|
12098
12153
|
if (tokens[0] === "mkdir") {
|
|
12099
12154
|
const targets = tokens.slice(1).filter((token) => token !== "-p" && token !== "--");
|
|
12100
|
-
return targets.length > 0 && targets.every(
|
|
12155
|
+
return targets.length > 0 && targets.every(pathMatches);
|
|
12101
12156
|
}
|
|
12102
12157
|
|
|
12103
|
-
let
|
|
12104
|
-
const
|
|
12158
|
+
let strippedEvidenceRedirect = false;
|
|
12159
|
+
const withoutEvidenceRedirects = normalized.replace(
|
|
12105
12160
|
/(^|\s)(?:\d*>>?|&>>?)\s*("[^"]+"|'[^']+'|[^\s;&|]+)/g,
|
|
12106
12161
|
(match, prefix, target) => {
|
|
12107
|
-
if (!
|
|
12108
|
-
|
|
12162
|
+
if (!pathMatches(target)) return match;
|
|
12163
|
+
strippedEvidenceRedirect = true;
|
|
12109
12164
|
return prefix;
|
|
12110
12165
|
}
|
|
12111
12166
|
).trim();
|
|
12112
|
-
if (!
|
|
12113
|
-
const underlyingPolicy = classifyCommand(
|
|
12167
|
+
if (!strippedEvidenceRedirect || !withoutEvidenceRedirects) return false;
|
|
12168
|
+
const underlyingPolicy = classifyCommand(withoutEvidenceRedirects);
|
|
12114
12169
|
return underlyingPolicy.writesWorkspace !== true && underlyingPolicy.mayMutateProject !== true;
|
|
12115
12170
|
}
|
|
12116
12171
|
|
|
12172
|
+
function commandWritesOnlyPrivateVerificationEvidence(command = "") {
|
|
12173
|
+
return commandWritesOnlyEvidenceMatching(
|
|
12174
|
+
command,
|
|
12175
|
+
isPrivateVerificationEvidencePath
|
|
12176
|
+
);
|
|
12177
|
+
}
|
|
12178
|
+
|
|
12179
|
+
function commandWritesOnlyScopedTaskArtifacts(command = "", state = {}, config = {}) {
|
|
12180
|
+
if (commandWritesOnlyEvidenceMatching(
|
|
12181
|
+
command,
|
|
12182
|
+
(candidate) => isScopedTaskArtifactEvidencePath(candidate, state, config)
|
|
12183
|
+
)) {
|
|
12184
|
+
return true;
|
|
12185
|
+
}
|
|
12186
|
+
const normalized = String(command || "").trim();
|
|
12187
|
+
const artifactRoot = scopedArtifactRoot(completionContractGoal(config, state));
|
|
12188
|
+
if (!normalized || !artifactRoot) return false;
|
|
12189
|
+
const assignments = new Map();
|
|
12190
|
+
for (const match of normalized.matchAll(
|
|
12191
|
+
/\b([A-Za-z_]\w*)\s*=\s*("[^"\n]+"|'[^'\n]+')/g
|
|
12192
|
+
)) {
|
|
12193
|
+
assignments.set(match[1], match[2]);
|
|
12194
|
+
}
|
|
12195
|
+
const writeTargets = [];
|
|
12196
|
+
for (const match of normalized.matchAll(
|
|
12197
|
+
/\bopen\s*\(\s*([^,\n]+)\s*,\s*(["'][^"']*[wax+][^"']*["'])/gi
|
|
12198
|
+
)) {
|
|
12199
|
+
const operand = String(match[1] || "").trim();
|
|
12200
|
+
const target = assignments.get(operand) || operand;
|
|
12201
|
+
if (!/^(?:"[^"\n]+"|'[^'\n]+')$/.test(target)) return false;
|
|
12202
|
+
writeTargets.push(target);
|
|
12203
|
+
}
|
|
12204
|
+
return Boolean(
|
|
12205
|
+
writeTargets.length > 0 &&
|
|
12206
|
+
writeTargets.every((candidate) =>
|
|
12207
|
+
isScopedTaskArtifactEvidencePath(candidate, state, config)
|
|
12208
|
+
)
|
|
12209
|
+
);
|
|
12210
|
+
}
|
|
12211
|
+
|
|
12212
|
+
function commandIsBoundedReadOnlyArtifactValidation(command = "") {
|
|
12213
|
+
const normalized = String(command || "").trim();
|
|
12214
|
+
if (!normalized) return false;
|
|
12215
|
+
if (
|
|
12216
|
+
!/\bassert\b|\bjson\.(?:load|loads)\s*\(|\bJSON\.parse\s*\(|\bjq\b|\bsha256sum\b|\bmd5sum\b|\b(?:valid|pass|verified?)\b/i.test(
|
|
12217
|
+
normalized
|
|
12218
|
+
)
|
|
12219
|
+
) {
|
|
12220
|
+
return false;
|
|
12221
|
+
}
|
|
12222
|
+
// Heredoc input (`<<`) is compatible with read-only validation. Any output
|
|
12223
|
+
// redirection or known mutator keeps conservative project revision tracking.
|
|
12224
|
+
if (/(^|[^<])>{1,2}(?!=)/m.test(normalized)) return false;
|
|
12225
|
+
if (
|
|
12226
|
+
/\b(?:cp|install|mkdir|mv|rm|rmdir|tee|touch|truncate)\b|\bsed\s+-i\b|\bperl\s+-pi\b/i.test(
|
|
12227
|
+
normalized
|
|
12228
|
+
)
|
|
12229
|
+
) {
|
|
12230
|
+
return false;
|
|
12231
|
+
}
|
|
12232
|
+
if (
|
|
12233
|
+
/\bopen\s*\([^\n)]*,\s*["'][^"']*[wax+][^"']*["']|\.(?:append|mkdir|rename|replace|rmdir|touch|unlink|write|write_bytes|write_text)\s*\(|\b(?:os\.(?:makedirs|mkdir|remove|rename|replace|rmdir|system|unlink)|shutil\.|subprocess\.)/i.test(
|
|
12234
|
+
normalized
|
|
12235
|
+
)
|
|
12236
|
+
) {
|
|
12237
|
+
return false;
|
|
12238
|
+
}
|
|
12239
|
+
return true;
|
|
12240
|
+
}
|
|
12241
|
+
|
|
12117
12242
|
const DISPOSABLE_GENERATED_PATH_SEGMENTS = new Set([
|
|
12118
12243
|
".build",
|
|
12119
12244
|
".gradle",
|
|
@@ -12974,6 +13099,17 @@ export function canonicalizeVerifiedArtifactCompletion(state = {}, result = "")
|
|
|
12974
13099
|
function successfulMutationPaths(toolResult = {}) {
|
|
12975
13100
|
if (!toolResult || toolResult.ok === false || toolResult.blocked || toolResult.skipped) return [];
|
|
12976
13101
|
if (toolResult.toolName === "deep_research" && toolResult.reportPath) return [toolResult.reportPath];
|
|
13102
|
+
if (toolResult.toolName === "run_command") {
|
|
13103
|
+
return [
|
|
13104
|
+
...new Set(
|
|
13105
|
+
(Array.isArray(toolResult.verifiedGeneratedOutputPaths)
|
|
13106
|
+
? toolResult.verifiedGeneratedOutputPaths
|
|
13107
|
+
: [])
|
|
13108
|
+
.map((item) => String(item || "").trim())
|
|
13109
|
+
.filter(Boolean)
|
|
13110
|
+
),
|
|
13111
|
+
];
|
|
13112
|
+
}
|
|
12977
13113
|
if (!["write_file", "apply_patch"].includes(String(toolResult.toolName || ""))) return [];
|
|
12978
13114
|
const changes = [
|
|
12979
13115
|
...(Array.isArray(toolResult.changes) ? toolResult.changes : []),
|
|
@@ -13026,9 +13162,11 @@ function successfulWorkspaceMutationPaths(toolResult = {}) {
|
|
|
13026
13162
|
];
|
|
13027
13163
|
}
|
|
13028
13164
|
|
|
13029
|
-
function successfulProjectMutationPaths(toolResult = {}) {
|
|
13165
|
+
function successfulProjectMutationPaths(toolResult = {}, state = {}, config = {}) {
|
|
13030
13166
|
return successfulWorkspaceMutationPaths(toolResult).filter(
|
|
13031
|
-
(candidate) =>
|
|
13167
|
+
(candidate) =>
|
|
13168
|
+
!isPrivateVerificationEvidencePath(candidate) &&
|
|
13169
|
+
!isScopedTaskArtifactEvidencePath(candidate, state, config)
|
|
13032
13170
|
);
|
|
13033
13171
|
}
|
|
13034
13172
|
|
|
@@ -13052,7 +13190,7 @@ function diffHasMaterialContentChange(diff = "") {
|
|
|
13052
13190
|
return JSON.stringify(compactRemoved) !== JSON.stringify(compactAdded);
|
|
13053
13191
|
}
|
|
13054
13192
|
|
|
13055
|
-
function materialProjectMutationPaths(toolResult = {}) {
|
|
13193
|
+
function materialProjectMutationPaths(toolResult = {}, state = {}, config = {}) {
|
|
13056
13194
|
if (!toolResult || toolResult.blocked || toolResult.skipped) {
|
|
13057
13195
|
return [];
|
|
13058
13196
|
}
|
|
@@ -13065,7 +13203,13 @@ function materialProjectMutationPaths(toolResult = {}) {
|
|
|
13065
13203
|
];
|
|
13066
13204
|
const paths = [];
|
|
13067
13205
|
for (const change of changes) {
|
|
13068
|
-
if (
|
|
13206
|
+
if (
|
|
13207
|
+
!change ||
|
|
13208
|
+
isPrivateVerificationEvidencePath(change.path) ||
|
|
13209
|
+
isScopedTaskArtifactEvidencePath(change.path, state, config)
|
|
13210
|
+
) {
|
|
13211
|
+
continue;
|
|
13212
|
+
}
|
|
13069
13213
|
if (
|
|
13070
13214
|
change.created === true ||
|
|
13071
13215
|
change.deleted === true ||
|
|
@@ -18472,7 +18616,7 @@ async function executeTool(browserState, toolCall, snapshot, config, store, obse
|
|
|
18472
18616
|
const isRequiredCommand = requiredCommands.some((candidate) =>
|
|
18473
18617
|
projectCommandsEquivalent(candidate, observedInnerCommand, config)
|
|
18474
18618
|
);
|
|
18475
|
-
const exactOutputSnapshotsBefore =
|
|
18619
|
+
const exactOutputSnapshotsBefore = policy.writesWorkspace && exactOutputPathsForState(state).length
|
|
18476
18620
|
? await captureExactOutputSnapshots(state, config)
|
|
18477
18621
|
: [];
|
|
18478
18622
|
const gitWorktreeBefore = captureMutationScope
|
|
@@ -18562,6 +18706,16 @@ async function executeTool(browserState, toolCall, snapshot, config, store, obse
|
|
|
18562
18706
|
const eventResult = sanitizeToolResult(result);
|
|
18563
18707
|
await store.appendEvent("tool.completed", eventResult);
|
|
18564
18708
|
observers.event("tool.completed", eventResult);
|
|
18709
|
+
for (const generatedPath of generatedOutputPaths) {
|
|
18710
|
+
const change = {
|
|
18711
|
+
path: generatedPath,
|
|
18712
|
+
toolName: "run_command",
|
|
18713
|
+
commandCwd: config.commandCwd,
|
|
18714
|
+
generatedByCommand: true,
|
|
18715
|
+
};
|
|
18716
|
+
await store.appendEvent("file.changed", change);
|
|
18717
|
+
observers.event("file.changed", change);
|
|
18718
|
+
}
|
|
18565
18719
|
return result;
|
|
18566
18720
|
}
|
|
18567
18721
|
case "tmux_list_sessions": {
|
|
@@ -19848,6 +20002,11 @@ async function completionEvidenceDecision({ config, state, store, observers, ste
|
|
|
19848
20002
|
const blocker = deterministicFinishBlocker(assessment.contract, assessment.ledger, assessment.evaluation);
|
|
19849
20003
|
const verificationDeficits = projectVerificationDeficits(state, config);
|
|
19850
20004
|
const requiredEvidence = (assessment.contract.requiredEvidence || []).map((item) => item.category);
|
|
20005
|
+
const requiresProjectTestEvidence = Boolean(
|
|
20006
|
+
requiredEvidence.includes("test") ||
|
|
20007
|
+
projectTestBlock ||
|
|
20008
|
+
verificationDeficits.failedTestRun
|
|
20009
|
+
);
|
|
19851
20010
|
const presentEvidence = assessment.ledger.categories || [];
|
|
19852
20011
|
const progressCount = Number(assessment.progressCount || 0);
|
|
19853
20012
|
const semanticFailureReason = assessment.semantic.checked && !assessment.semantic.ok
|
|
@@ -19881,8 +20040,13 @@ async function completionEvidenceDecision({ config, state, store, observers, ste
|
|
|
19881
20040
|
freshMutationRequirement.artifactQualityRepairRequired,
|
|
19882
20041
|
missingToolCalls: assessment.evaluation.missingToolCalls || [],
|
|
19883
20042
|
pendingProjectCommands: verificationDeficits.pendingCommands,
|
|
19884
|
-
pendingProjectTests:
|
|
19885
|
-
|
|
20043
|
+
pendingProjectTests:
|
|
20044
|
+
requiresProjectTestEvidence && !verificationDeficits.testsCurrent
|
|
20045
|
+
? verificationDeficits.discoveredTests
|
|
20046
|
+
: [],
|
|
20047
|
+
suggestedTestCommands: requiresProjectTestEvidence
|
|
20048
|
+
? verificationDeficits.suggestedTestCommands
|
|
20049
|
+
: [],
|
|
19886
20050
|
projectMutationRevision: verificationDeficits.revision,
|
|
19887
20051
|
failedProjectTestCommand: verificationDeficits.failedTestRun?.command || "",
|
|
19888
20052
|
failedProjectTestSignature: verificationDeficits.failedTestRun?.failureSignature || "",
|
|
@@ -23182,7 +23346,7 @@ async function runAgentOnceUnlocked(config) {
|
|
|
23182
23346
|
|
|
23183
23347
|
try {
|
|
23184
23348
|
throwIfAborted(config);
|
|
23185
|
-
const goalIntent = classifyGoalIntent(config.goal);
|
|
23349
|
+
const goalIntent = classifyGoalIntent(scopedChatopsEvidenceGoal(config.goal, config.taskProfile));
|
|
23186
23350
|
const canFinishDirectly =
|
|
23187
23351
|
!config.resume && !state.plan && Number(state.stepsCompleted || 0) === 0 && isDirectAnswerIntent(goalIntent);
|
|
23188
23352
|
if (canFinishDirectly) {
|
package/src/config.js
CHANGED
|
@@ -25,7 +25,7 @@ import { normalizeDynamicStepsMode } from "./step-budget-controller.js";
|
|
|
25
25
|
import { maxStepsForExecutionPolicy, selectExecutionPolicy } from "./execution-policy.js";
|
|
26
26
|
import { normalizeContextBudgetMode } from "./context-budget-controller.js";
|
|
27
27
|
import { BASELINE_PROVIDER, normalizeProviderBaseURL, normalizeProviderId } from "./provider-contract.js";
|
|
28
|
-
import { isResponseOnlyEvidenceScope } from "./scs-evidence.js";
|
|
28
|
+
import { isResponseOnlyEvidenceScope, scopedChatopsEvidenceGoal } from "./scs-evidence.js";
|
|
29
29
|
|
|
30
30
|
function parseBoolean(value, fallback) {
|
|
31
31
|
if (value === undefined) return fallback;
|
|
@@ -101,6 +101,7 @@ export function resolveRuntimeConfig(args, overrides = {}) {
|
|
|
101
101
|
const requestedProvider = resolveRequestedProvider(overrides, args);
|
|
102
102
|
const routingMode = normalizeRoutingMode(overrides.routingMode || args.routingMode || process.env.AGENT_ROUTING_MODE || "smart");
|
|
103
103
|
const taskProfile = normalizeTaskProfile(overrides.taskProfile || args.taskProfile || process.env.AGINTI_TASK_PROFILE || "auto");
|
|
104
|
+
const taskSelectionGoal = scopedChatopsEvidenceGoal(args.goal || "", taskProfile);
|
|
104
105
|
const language = resolveLanguage(overrides.language || args.language || process.env.AGINTI_LANGUAGE || "");
|
|
105
106
|
// Capability/resource snapshots are trusted runtime inputs. They are deliberately
|
|
106
107
|
// not inferred from ambient cloud credentials or optimistic environment flags.
|
|
@@ -141,7 +142,7 @@ export function resolveRuntimeConfig(args, overrides = {}) {
|
|
|
141
142
|
routingMode: sessionModelLocked ? "manual" : routingMode,
|
|
142
143
|
provider: requestedProvider,
|
|
143
144
|
model: requestedModel,
|
|
144
|
-
goal:
|
|
145
|
+
goal: taskSelectionGoal,
|
|
145
146
|
taskProfile,
|
|
146
147
|
routeProvider,
|
|
147
148
|
routeModel: overrides.routeModel || args.routeModel || process.env.AGINTI_ROUTE_MODEL || "",
|
|
@@ -190,7 +191,7 @@ export function resolveRuntimeConfig(args, overrides = {}) {
|
|
|
190
191
|
overrides.scsValidationMode ?? args.scsValidationMode ?? process.env.AGINTI_SCS_VALIDATION_MODE ?? "auto"
|
|
191
192
|
);
|
|
192
193
|
const scsActive = shouldActivateScs(scsMode, {
|
|
193
|
-
goal:
|
|
194
|
+
goal: taskSelectionGoal,
|
|
194
195
|
taskProfile,
|
|
195
196
|
complexityScore: route.complexityScore,
|
|
196
197
|
});
|
|
@@ -226,7 +227,7 @@ export function resolveRuntimeConfig(args, overrides = {}) {
|
|
|
226
227
|
? normalizeProviderBaseURL(activeProvider, overrides.baseURL || defaults.baseURL)
|
|
227
228
|
: overrides.baseURL || defaults.baseURL;
|
|
228
229
|
const defaultMaxSteps = recommendedMaxStepsForTask({
|
|
229
|
-
goal:
|
|
230
|
+
goal: taskSelectionGoal,
|
|
230
231
|
taskProfile,
|
|
231
232
|
complexityScore: route.complexityScore,
|
|
232
233
|
});
|
package/src/model-client.js
CHANGED
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
estimateToolSchemaTokens,
|
|
32
32
|
} from "./context-budget-controller.js";
|
|
33
33
|
import { attachToolContract } from "./tool-contract.js";
|
|
34
|
+
import { scopedChatopsEvidenceGoal } from "./scs-evidence.js";
|
|
34
35
|
|
|
35
36
|
function isRetainedWorkspaceProfile(config = {}) {
|
|
36
37
|
return config.integrationSessionProfile === INTEGRATION_TEXT_WORKSPACE_PROFILE_ID ||
|
|
@@ -1241,11 +1242,14 @@ export async function createPlan(client, config, state) {
|
|
|
1241
1242
|
const engineeringGuidance = isRetainedWorkspaceProfile(config)
|
|
1242
1243
|
? ""
|
|
1243
1244
|
: engineeringGuidanceForTask(state.goal, config.taskProfile);
|
|
1244
|
-
const selectedSkills = isRetainedWorkspaceProfile(config) ? [] : selectSkillsForGoal(
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1245
|
+
const selectedSkills = isRetainedWorkspaceProfile(config) ? [] : selectSkillsForGoal(
|
|
1246
|
+
scopedChatopsEvidenceGoal(state.goal, config.taskProfile),
|
|
1247
|
+
{
|
|
1248
|
+
taskProfile: config.taskProfile,
|
|
1249
|
+
limit: 5,
|
|
1250
|
+
projectRoot: config.commandCwd || config.baseDir || process.cwd(),
|
|
1251
|
+
}
|
|
1252
|
+
);
|
|
1249
1253
|
const skillContext = formatSkillsForPrompt(selectedSkills);
|
|
1250
1254
|
const projectInstructions = state.meta?.projectInstructions;
|
|
1251
1255
|
const platform = platformInfo();
|
package/src/scs-controller.js
CHANGED
|
@@ -277,6 +277,15 @@ export function shouldActivateScs(mode = "off", context = {}) {
|
|
|
277
277
|
const profile = String(context.taskProfile || "").toLowerCase();
|
|
278
278
|
const goal = String(context.goal || "");
|
|
279
279
|
if (SCS_AUTO_PROFILES.has(profile)) return true;
|
|
280
|
+
const staticDataPaths = goal.match(/(?:^|[\s`'"(])[^\s`'"()]+\.(?:csv|json|toml|ya?ml)\b/gi) || [];
|
|
281
|
+
const simpleStaticDataWrite =
|
|
282
|
+
staticDataPaths.length === 1 &&
|
|
283
|
+
/\b(?:create|emit|generate|save|write)\b/i.test(goal) &&
|
|
284
|
+
!/\b(?:app|application|build|cli|code|codebase|compile|database|dataset|deploy|implement|library|migrate|package|publish|refactor|release|repository|script|server|source|test|upload)\b/i.test(
|
|
285
|
+
goal
|
|
286
|
+
) &&
|
|
287
|
+
Number(context.complexityScore || 0) < 3;
|
|
288
|
+
if (simpleStaticDataWrite) return false;
|
|
280
289
|
if (SCS_AUTO_HINTS.some((hint) => hint.test(goal))) return true;
|
|
281
290
|
return Number(context.complexityScore || 0) >= 5;
|
|
282
291
|
}
|
package/src/scs-evidence.js
CHANGED
|
@@ -538,7 +538,10 @@ function inferExactOutputPaths(goal = "") {
|
|
|
538
538
|
if (!isOutputListItem && !hasDirectOutputAction) continue;
|
|
539
539
|
const sourceLine = !isOutputListItem && hasDirectOutputAction ? line.slice(directOutputIndex) : line;
|
|
540
540
|
if (!isOutputListItem && negatedOutputLine.test(sourceLine)) continue;
|
|
541
|
-
|
|
541
|
+
const verifierIndex = line.search(/\b(?:validate|verify|check|compile|run|execute)\b/i);
|
|
542
|
+
if (!isOutputListItem && nonOutputToolLine.test(line) && verifierIndex >= 0 && verifierIndex < directOutputIndex) {
|
|
543
|
+
continue;
|
|
544
|
+
}
|
|
542
545
|
if (!isOutputListItem && /\boutput\s+(?:subfolders?|directories|folders?|paths?)\b/i.test(sourceLine)) continue;
|
|
543
546
|
const outputDirMatch = sourceLine.match(/(?:to|at|in|under|到|至|在)\s*([^\s,,、;;。]+\/)/i);
|
|
544
547
|
activeOutputDir = outputDirMatch?.[1] || "";
|
|
@@ -962,6 +965,12 @@ export function inferRequiredExecutableTerms(goal = "") {
|
|
|
962
965
|
if (executableRequirementIsNegated(source, index)) continue;
|
|
963
966
|
if (indexFallsInsideInlineCommand(source, index)) continue;
|
|
964
967
|
const window = source.slice(Math.max(0, index - 180), Math.min(source.length, index + match[0].length + 220));
|
|
968
|
+
const structuredDataLiteral =
|
|
969
|
+
/\b(?:csv|json|toml|ya?ml)\b/i.test(window) &&
|
|
970
|
+
!/\b(?:actual|canonical|executable|implementation|source\s+code|function|call|argument|parameter|repair|fix|replace)\b/i.test(
|
|
971
|
+
window
|
|
972
|
+
);
|
|
973
|
+
if (structuredDataLiteral) continue;
|
|
965
974
|
const implementationRequirement =
|
|
966
975
|
/\b(?:actual|canonical|executable|implementation|source|code|call|argument|keyword|parameter|repair|fix|correct|replace|add|set|pass|use|must|required)\b/iu.test(window) ||
|
|
967
976
|
/实际|實際|实现|實現|源码|源碼|代码|代碼|调用|調用|参数|參數|修复|修復|改正|替换|替換|添加|设置|設定|使用|必须|必須|実装|ソース|コード|呼び出し|引数|修正|置換|追加|設定|使用/.test(window);
|
|
@@ -1229,12 +1238,22 @@ function codeProfileRequiresCommand(goal = "") {
|
|
|
1229
1238
|
/\b(?:note|notes?|markdown|readme|documentation|text file)\b/.test(text) ||
|
|
1230
1239
|
/\bnotes?\/[^\s]+\.(?:md|txt)\b/.test(text) ||
|
|
1231
1240
|
/\.(?:md|txt)\b/.test(text);
|
|
1241
|
+
const structuredDataProse = text.replace(
|
|
1242
|
+
/(?:^|[\s`'"(])[^\s`'"()]+\.(?:csv|json|toml|ya?ml)\b/g,
|
|
1243
|
+
" "
|
|
1244
|
+
);
|
|
1245
|
+
const simpleStructuredDataWrite =
|
|
1246
|
+
/\.(?:csv|json|toml|ya?ml)\b/.test(text) &&
|
|
1247
|
+
/\b(?:create|emit|generate|save|write)\b/.test(text) &&
|
|
1248
|
+
!/\b(?:app|application|build|cli|code|codebase|compile|execute|function|implement|library|lint|package|refactor|run|script|server|source|test|typecheck)\b/.test(
|
|
1249
|
+
structuredDataProse
|
|
1250
|
+
);
|
|
1232
1251
|
const substantiveCodeWork =
|
|
1233
1252
|
/\b(?:fix|repair|bug|implement|feature|refactor|test|run|build|compile|lint|typecheck|verify|validate|package|library|cli|api server|app|application|script|codebase|src\/|source code)\b/.test(
|
|
1234
1253
|
text
|
|
1235
1254
|
) ||
|
|
1236
1255
|
/\.(?:js|jsx|ts|tsx|mjs|cjs|py|rs|go|java|kt|swift|rb|php|cs|cpp|c|h|hpp|sh)\b/.test(text);
|
|
1237
|
-
return substantiveCodeWork && !simpleDocumentWrite;
|
|
1256
|
+
return substantiveCodeWork && !simpleDocumentWrite && !simpleStructuredDataWrite;
|
|
1238
1257
|
}
|
|
1239
1258
|
|
|
1240
1259
|
function goalRequestsExplicitTestMutation(text = "") {
|
package/src/skill-library.js
CHANGED
|
@@ -482,6 +482,7 @@ const GENERIC_ROUTING_TERMS = new Set([
|
|
|
482
482
|
"analysis",
|
|
483
483
|
"app",
|
|
484
484
|
"application",
|
|
485
|
+
"artifact",
|
|
485
486
|
"code",
|
|
486
487
|
"commit",
|
|
487
488
|
"data",
|
|
@@ -498,6 +499,18 @@ const GENERIC_ROUTING_TERMS = new Set([
|
|
|
498
499
|
"work",
|
|
499
500
|
]);
|
|
500
501
|
|
|
502
|
+
function normalizedSkillRoutingText(goal = "") {
|
|
503
|
+
return String(goal || "")
|
|
504
|
+
.toLowerCase()
|
|
505
|
+
.replace(
|
|
506
|
+
/(?:^|[\s`'"(])(?:~|\.{1,2}|\/|[a-z0-9_-])[a-z0-9_./~-]*\.([a-z0-9]{1,12})\b/gi,
|
|
507
|
+
(_match, extension) => ` file.${String(extension || "").toLowerCase()} `
|
|
508
|
+
)
|
|
509
|
+
.replace(/\b[a-z_][a-z0-9_.-]*\s*=\s*[a-z0-9_.-]+\b/gi, " ")
|
|
510
|
+
.replace(/\s+/g, " ")
|
|
511
|
+
.trim();
|
|
512
|
+
}
|
|
513
|
+
|
|
501
514
|
function descriptionTerms(value = "") {
|
|
502
515
|
return [
|
|
503
516
|
...new Set(
|
|
@@ -564,7 +577,7 @@ function textHasTrigger(text, needle) {
|
|
|
564
577
|
}
|
|
565
578
|
|
|
566
579
|
export function selectSkillsForGoal(goal = "", { taskProfile = "auto", limit = 6, includeBody = true, projectRoot = process.cwd() } = {}) {
|
|
567
|
-
const goalText =
|
|
580
|
+
const goalText = normalizedSkillRoutingText(goal);
|
|
568
581
|
const text = goalText;
|
|
569
582
|
const skills = listSkills({ includeBody, projectRoot });
|
|
570
583
|
const ranked = skills
|