@lazyingart/agintiflow 0.20.321 → 0.20.322

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.321",
3
+ "version": "0.20.322",
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",
@@ -7,6 +7,7 @@ import { fileURLToPath } from "node:url";
7
7
  import {
8
8
  completionRequirementCoverageInstruction,
9
9
  continuationExecutionContractDirective,
10
+ evaluateAuthoritativeStructuredCompletionCoverage,
10
11
  removeSupersededCompletionRepairInstructions,
11
12
  repositorySourcePrecedenceInstruction,
12
13
  runAgent,
@@ -26,6 +27,51 @@ assert.match(completionCoverageInstruction, /authoritative structured routine/i)
26
27
  assert.match(completionCoverageInstruction, /every relevant section/i);
27
28
  assert.match(completionCoverageInstruction, /instead of summarizing only failures or only successes/i);
28
29
 
30
+ const structuredHealthOutput = JSON.stringify({
31
+ ok: true,
32
+ degraded: true,
33
+ issues: ["wechat_login_required", "android_poll_stalled"],
34
+ queues: {
35
+ wechat: { pending: 0, active: 0, stale_count: 0, recent_failure_count: 0 },
36
+ wecom: { pending: 0, active: 0, stale_count: 0, recent_failure_count: 0 },
37
+ },
38
+ schedules: {
39
+ career_daily: { status: "waiting", running: true },
40
+ memo_daily: { status: "waiting", running: true },
41
+ echomind_daily_pdf: { status: "current", running: true },
42
+ },
43
+ });
44
+ const structuredHealthRecord = [{ output: structuredHealthOutput, authoritative: true }];
45
+ const badStructuredCoverage = evaluateAuthoritativeStructuredCompletionCoverage({
46
+ goal: "Report queue health, schedule state, and authentication blockers concisely.",
47
+ candidateResult: "The system is degraded because WeChat login is required. Schedule state is not visible in the retained output.",
48
+ commandOutputs: structuredHealthRecord,
49
+ });
50
+ assert.equal(badStructuredCoverage.checked, true);
51
+ assert.equal(badStructuredCoverage.ok, false);
52
+ assert(badStructuredCoverage.missingSections.includes("queues"));
53
+ assert(badStructuredCoverage.missingSections.includes("schedules"));
54
+ assert(badStructuredCoverage.contradictedSections.includes("schedules"));
55
+ assert.match(badStructuredCoverage.expectedSummary, /Queues: .*wechat pending 0 active 0.*wecom pending 0 active 0/i);
56
+ assert.match(badStructuredCoverage.expectedSummary, /Other schedules: .*career_daily.*memo_daily.*echomind_daily_pdf/i);
57
+
58
+ const goodStructuredCoverage = evaluateAuthoritativeStructuredCompletionCoverage({
59
+ goal: "Report queue health, schedule state, and authentication blockers concisely.",
60
+ candidateResult: "Both queues are clear: WeChat and WeCom have pending 0, active 0, stale 0, and failures 0. Schedules are running: career_daily and memo_daily are waiting, while echomind_daily_pdf is current. Authentication blockers are wechat_login_required and android_poll_stalled.",
61
+ commandOutputs: structuredHealthRecord,
62
+ });
63
+ assert.equal(goodStructuredCoverage.checked, true);
64
+ assert.equal(goodStructuredCoverage.ok, true);
65
+ assert.deepEqual(goodStructuredCoverage.missingSections, []);
66
+
67
+ const unstructuredCoverage = evaluateAuthoritativeStructuredCompletionCoverage({
68
+ goal: "Explain the architecture.",
69
+ candidateResult: "The architecture is complete.",
70
+ commandOutputs: [{ output: "ordinary prose", authoritative: true }],
71
+ });
72
+ assert.equal(unstructuredCoverage.checked, false);
73
+ assert.equal(unstructuredCoverage.ok, true);
74
+
29
75
  const sourcePrecedenceInstruction = repositorySourcePrecedenceInstruction();
30
76
  assert.match(sourcePrecedenceInstruction, /current direct user request/i);
31
77
  assert.match(sourcePrecedenceInstruction, /closest project instructions/i);
@@ -968,6 +1014,63 @@ try {
968
1014
  "finish-only reasoning repair still spent a separate empty-response repair turn"
969
1015
  );
970
1016
 
1017
+ const structuredCoverageFallback = await runCase({
1018
+ id: "authoritative-structured-completion-coverage",
1019
+ goal: [
1020
+ "User request:",
1021
+ "Report queue health, schedule state, and authentication blockers concisely. Read-only inspection; send nothing.",
1022
+ "",
1023
+ "Matched established routines",
1024
+ `- \`wechat-chatops\` ready=true; commands=[${JSON.stringify(compactHealthCommand)}, "python agentic_tools/wechat_gui_agent/scripts/wechat_android_ingress.py --status"]; outputs=["messages", "files", "task records"]; guidance=For a read-only phone, message-intake, queue, or schedule question, run the canonical compact health command first; it already includes both Android lanes. Treat that current snapshot as authoritative and stop once it answers the request. Do not inspect raw chat text or private message ledgers or artifact directories, and do not send or mutate anything, unless the current request explicitly needs it.`,
1025
+ ].join("\n"),
1026
+ taskProfile: "chatops",
1027
+ allowShellTool: true,
1028
+ allowDestructive: true,
1029
+ setup: async (workspace) => {
1030
+ await fs.mkdir(path.join(workspace, "src", "agenticapp"), { recursive: true });
1031
+ await fs.writeFile(path.join(workspace, "src", "agenticapp", "__init__.py"), "", "utf8");
1032
+ await fs.writeFile(
1033
+ path.join(workspace, "src", "agenticapp", "__main__.py"),
1034
+ `print(${JSON.stringify(structuredHealthOutput)})\n`,
1035
+ "utf8"
1036
+ );
1037
+ },
1038
+ responses: [
1039
+ assistant("", [toolCall("structured-health-command", "run_command", { command: compactHealthCommand })]),
1040
+ assistant("", [toolCall("structured-health-bad-finish-1", "finish", {
1041
+ result: "The system is degraded because WeChat login is required. Schedule state is not visible in the retained output.",
1042
+ })]),
1043
+ assistant("", [toolCall("structured-health-bad-finish-2", "finish", {
1044
+ result: "WeChat authentication remains blocked. The schedule section was not returned.",
1045
+ })]),
1046
+ ],
1047
+ });
1048
+ assert.equal(structuredCoverageFallback.calls.length, 3);
1049
+ assert.match(structuredCoverageFallback.result.result, /Queues: .*wechat pending 0 active 0.*wecom pending 0 active 0/i);
1050
+ assert.match(structuredCoverageFallback.result.result, /Other schedules: .*career_daily.*memo_daily.*echomind_daily_pdf/i);
1051
+ assert.match(structuredCoverageFallback.result.result, /issues=wechat_login_required,android_poll_stalled/i);
1052
+ assert.equal(
1053
+ structuredCoverageFallback.events.filter(
1054
+ (event) => event.type === "tool.started" && event.data?.toolName === "run_command"
1055
+ ).length,
1056
+ 1,
1057
+ "structured summary repair reran the authoritative command"
1058
+ );
1059
+ assert.equal(
1060
+ structuredCoverageFallback.events.filter(
1061
+ (event) => event.type === "completion.structured_output_repair_requested"
1062
+ ).length,
1063
+ 1,
1064
+ "structured summary defect did not request exactly one finish-only repair"
1065
+ );
1066
+ assert.equal(
1067
+ structuredCoverageFallback.events.filter(
1068
+ (event) => event.type === "completion.structured_output_fallback"
1069
+ ).length,
1070
+ 1,
1071
+ "repeated bad structured summary did not use the deterministic verified fallback"
1072
+ );
1073
+
971
1074
  const wordCompletionWithoutArtifact = await runCase({
972
1075
  id: "word-completion-without-artifact",
973
1076
  goal: "Create an editable, phone-friendly project handoff from this folder.",
@@ -4157,6 +4157,7 @@ export function resetGoalScopedRuntimeState(state = {}) {
4157
4157
  const keys = [
4158
4158
  "artifactProgress",
4159
4159
  "completionEvidenceRepair",
4160
+ "structuredCompletionRepair",
4160
4161
  "dataProjectWorkflow",
4161
4162
  "durableEvidenceCategories",
4162
4163
  "durableGitActions",
@@ -4243,6 +4244,7 @@ export function resetSameTaskExecutionContract(state = {}, revision = 0) {
4243
4244
  const keys = [
4244
4245
  "artifactProgress",
4245
4246
  "completionEvidenceRepair",
4247
+ "structuredCompletionRepair",
4246
4248
  "failedTestRecoveryPacket",
4247
4249
  "scs",
4248
4250
  "stepBudget",
@@ -22538,6 +22540,93 @@ async function completionEvidenceDecision({ config, state, store, observers, ste
22538
22540
  },
22539
22541
  };
22540
22542
  }
22543
+ const structuredCoverage = String(candidateResult || "").trim()
22544
+ ? evaluateAuthoritativeStructuredCompletionCoverage({
22545
+ goal: completionContractGoal(config, state),
22546
+ candidateResult,
22547
+ commandOutputs: assessment.commandOutputs,
22548
+ })
22549
+ : {
22550
+ checked: false,
22551
+ ok: true,
22552
+ requestedSections: [],
22553
+ missingSections: [],
22554
+ contradictedSections: [],
22555
+ expectedSummary: "",
22556
+ key: "",
22557
+ };
22558
+ if (structuredCoverage.checked) {
22559
+ const coverageDetail = {
22560
+ step,
22561
+ mode,
22562
+ ok: structuredCoverage.ok,
22563
+ requestedSections: structuredCoverage.requestedSections,
22564
+ missingSections: structuredCoverage.missingSections,
22565
+ contradictedSections: structuredCoverage.contradictedSections,
22566
+ };
22567
+ await store.appendEvent("completion.structured_output_assessed", coverageDetail);
22568
+ observers.event("completion.structured_output_assessed", coverageDetail);
22569
+ }
22570
+ if (assessment.ok && !claimsIncompleteWork && structuredCoverage.checked && !structuredCoverage.ok) {
22571
+ state.meta = state.meta || {};
22572
+ const prior = state.meta.structuredCompletionRepair || {};
22573
+ const attempts = prior.key === structuredCoverage.key
22574
+ ? Math.max(0, Number(prior.attempts || 0))
22575
+ : 0;
22576
+ const detail = {
22577
+ step,
22578
+ mode,
22579
+ key: structuredCoverage.key,
22580
+ repairAttempt: attempts + 1,
22581
+ requestedSections: structuredCoverage.requestedSections,
22582
+ missingSections: structuredCoverage.missingSections,
22583
+ contradictedSections: structuredCoverage.contradictedSections,
22584
+ expectedSummary: structuredCoverage.expectedSummary,
22585
+ };
22586
+ await store.appendEvent("completion.structured_output_rejected", detail);
22587
+ observers.event("completion.structured_output_rejected", detail);
22588
+ if (attempts < 1) {
22589
+ state.meta.structuredCompletionRepair = {
22590
+ key: structuredCoverage.key,
22591
+ attempts: attempts + 1,
22592
+ step,
22593
+ goalRevision: Math.max(0, Number(state.meta?.goalContract?.revision || 0)),
22594
+ at: new Date().toISOString(),
22595
+ };
22596
+ const affectedSections = [
22597
+ ...structuredCoverage.missingSections,
22598
+ ...structuredCoverage.contradictedSections,
22599
+ ];
22600
+ const instruction = [
22601
+ "Your proposed final answer omitted or contradicted requested sections that are present in the retained authoritative structured result.",
22602
+ affectedSections.length
22603
+ ? `Correct these sections: ${[...new Set(affectedSections)].join(", ")}.`
22604
+ : "Correct the structured status summary.",
22605
+ "Do not rerun the command, call another tool, or claim that a visible section is unavailable.",
22606
+ structuredCoverage.expectedSummary
22607
+ ? `Authoritative evidence summary: ${structuredCoverage.expectedSummary}`
22608
+ : "Use the retained authoritative output already in this session.",
22609
+ "Return one concise natural answer that covers every requested section, then finish.",
22610
+ ].filter(Boolean).join(" ");
22611
+ state.messages.push({ role: "user", content: instruction });
22612
+ await store.appendEvent("completion.structured_output_repair_requested", {
22613
+ ...detail,
22614
+ instruction,
22615
+ });
22616
+ observers.event("completion.structured_output_repair_requested", detail);
22617
+ return { action: "retry", assessment, detail };
22618
+ }
22619
+ const result = verifiedCompletionFallback(assessment, state);
22620
+ await store.appendEvent("completion.structured_output_fallback", {
22621
+ ...detail,
22622
+ result,
22623
+ });
22624
+ observers.event("completion.structured_output_fallback", detail);
22625
+ return { action: "accept", assessment, detail, resultOverride: result };
22626
+ }
22627
+ if (structuredCoverage.ok && state.meta?.structuredCompletionRepair) {
22628
+ delete state.meta.structuredCompletionRepair;
22629
+ }
22541
22630
  const hasRealBlocker = completionExternalBlockerCanClose({
22542
22631
  candidateResult,
22543
22632
  evidenceLedger: assessment.ledger,
@@ -22882,6 +22971,180 @@ function summarizeJsonCommandOutput(output = "") {
22882
22971
  return pairs.length ? `Observed JSON status: ${pairs.join(", ")}.` : "";
22883
22972
  }
22884
22973
 
22974
+ const AUTHORITATIVE_STRUCTURED_SECTION_ALIASES = Object.freeze({
22975
+ queues: ["queue", "queues", "backlog", "队列", "佇列"],
22976
+ schedules: ["schedule", "schedules", "scheduler", "schedulers", "日程", "定时", "定時", "排程"],
22977
+ issues: ["issue", "issues", "problem", "problems", "error", "errors", "blocker", "blockers", "auth", "authentication", "login", "问题", "問題", "错误", "錯誤", "阻塞", "登录", "登入", "授权", "授權"],
22978
+ ingress: ["ingress", "receiver", "receivers", "inbound", "intake", "message intake", "入口", "接收", "收件"],
22979
+ });
22980
+
22981
+ function structuredSectionAliases(key = "") {
22982
+ const normalized = String(key || "").trim().toLowerCase();
22983
+ const aliases = new Set(AUTHORITATIVE_STRUCTURED_SECTION_ALIASES[normalized] || []);
22984
+ if (normalized) {
22985
+ aliases.add(normalized);
22986
+ aliases.add(normalized.replace(/_/g, " "));
22987
+ if (normalized.endsWith("s") && normalized.length > 3) aliases.add(normalized.slice(0, -1));
22988
+ }
22989
+ return [...aliases].filter(Boolean);
22990
+ }
22991
+
22992
+ function completionTextHasAny(value = "", terms = []) {
22993
+ const normalized = String(value || "").toLowerCase();
22994
+ return terms.some((rawTerm) => {
22995
+ const term = String(rawTerm || "").trim().toLowerCase();
22996
+ if (!term) return false;
22997
+ if (!/^[a-z0-9_\- ]+$/u.test(term)) return normalized.includes(term);
22998
+ const escaped = term
22999
+ .replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
23000
+ .replace(/[ _-]+/g, "[ _-]+");
23001
+ return new RegExp(`(?:^|[^a-z0-9])${escaped}(?:$|[^a-z0-9])`, "iu").test(normalized);
23002
+ });
23003
+ }
23004
+
23005
+ function structuredSectionHasFalseAbsence(candidateResult = "", aliases = []) {
23006
+ const sentences = String(candidateResult || "")
23007
+ .split(/(?<=[.!?。!?;;\n])/u)
23008
+ .map((item) => item.trim())
23009
+ .filter(Boolean);
23010
+ const absence = /(?:\b(?:not|isn['’]?t|wasn['’]?t|no)\b.{0,70}\b(?:visible|available|present|returned|shown|included|provided|reported|exposed|found)\b|\b(?:missing|unavailable|unknown|absent)\b|未(?:显示|返回|提供|包含|找到|看到)|不可见|不存在|没有(?:显示|返回|提供|包含))/iu;
23011
+ return sentences.some((sentence) => completionTextHasAny(sentence, aliases) && absence.test(sentence));
23012
+ }
23013
+
23014
+ function structuredChildTerms(value) {
23015
+ if (!value || typeof value !== "object" || Array.isArray(value)) return [];
23016
+ return Object.keys(value)
23017
+ .flatMap((key) => [key, ...String(key).split(/[_\-\s]+/u)])
23018
+ .map((item) => String(item || "").trim().toLowerCase())
23019
+ .filter((item) => item.length >= 3 && !["daily", "status", "state", "count"].includes(item));
23020
+ }
23021
+
23022
+ function issueValueTerms(value) {
23023
+ if (!Array.isArray(value)) return [];
23024
+ return value
23025
+ .flatMap((item) => [String(item || ""), ...String(item || "").split(/[_\-\s]+/u)])
23026
+ .map((item) => item.trim().toLowerCase())
23027
+ .filter((item) => item.length >= 4 && !["required", "issue", "error"].includes(item));
23028
+ }
23029
+
23030
+ function authoritativeStructuredRequestText(goal = "") {
23031
+ const text = String(goal || "");
23032
+ const evidenceLine = text.match(/^AGINTI_EVIDENCE_SCOPE_JSON:\s*(\{[^\n]+\})/mu);
23033
+ if (evidenceLine) {
23034
+ try {
23035
+ const parsed = JSON.parse(evidenceLine[1]);
23036
+ if (String(parsed?.request || "").trim()) return String(parsed.request).trim();
23037
+ } catch {
23038
+ // Fall through to the visible user-request packet or the direct goal.
23039
+ }
23040
+ }
23041
+ const marker = text.match(/(?:^|\n)User request:\s*\n/iu);
23042
+ if (!marker || marker.index === undefined) return text;
23043
+ const start = marker.index + marker[0].length;
23044
+ const tail = text.slice(start);
23045
+ const boundary = tail.search(/\n(?:Matched established routines|Operating contract|Execution contract|Agent context|Task packet)\b/iu);
23046
+ return (boundary >= 0 ? tail.slice(0, boundary) : tail).trim();
23047
+ }
23048
+
23049
+ function requestedAuthoritativeStructuredSections(goal = "", data = {}) {
23050
+ const request = authoritativeStructuredRequestText(goal);
23051
+ const requested = [];
23052
+ for (const key of Object.keys(data || {})) {
23053
+ const normalized = String(key || "").trim().toLowerCase();
23054
+ const aliasKey = /ingress/i.test(normalized) ? "ingress" : normalized;
23055
+ const aliases = structuredSectionAliases(aliasKey);
23056
+ if (completionTextHasAny(request, aliases)) requested.push(normalized);
23057
+ }
23058
+ if (
23059
+ Object.prototype.hasOwnProperty.call(data || {}, "issues") &&
23060
+ completionTextHasAny(request, AUTHORITATIVE_STRUCTURED_SECTION_ALIASES.issues)
23061
+ ) {
23062
+ requested.push("issues");
23063
+ }
23064
+ return [...new Set(requested)];
23065
+ }
23066
+
23067
+ function authoritativeStructuredSectionCovered(key = "", value, candidateResult = "") {
23068
+ const normalized = String(key || "").toLowerCase();
23069
+ const aliasKey = /ingress/i.test(normalized) ? "ingress" : normalized;
23070
+ const aliases = structuredSectionAliases(aliasKey);
23071
+ if (structuredSectionHasFalseAbsence(candidateResult, aliases)) {
23072
+ return { covered: false, contradicted: true };
23073
+ }
23074
+ const sectionMentioned = completionTextHasAny(candidateResult, aliases);
23075
+ const childMentioned = completionTextHasAny(candidateResult, structuredChildTerms(value));
23076
+ if (normalized === "queues") {
23077
+ const queueState = /\b(?:pending|active|stale|failures?|failed|running|clear|healthy|idle|empty|backlog)\b|待处理|活动|运行|陈旧|失效|失败|健康|空闲|清空/iu.test(candidateResult);
23078
+ return { covered: (sectionMentioned || childMentioned) && queueState, contradicted: false };
23079
+ }
23080
+ if (normalized === "schedules") {
23081
+ const scheduleState = /\b(?:waiting|pending|running|delivered|current|due|retrying|retry|healthy|idle|enabled|disabled|paused|complete|completed)\b|等待|待处理|运行|已送达|已发送|重试|健康|启用|停用|暂停|完成/iu.test(candidateResult);
23082
+ return { covered: (sectionMentioned || childMentioned) && scheduleState && childMentioned, contradicted: false };
23083
+ }
23084
+ if (normalized === "issues") {
23085
+ const issueTerms = issueValueTerms(value);
23086
+ const noIssues = Array.isArray(value) && value.length === 0 && /\b(?:no|zero)\s+(?:issues?|errors?|blockers?)\b|没有(?:问题|错误|阻塞)/iu.test(candidateResult);
23087
+ return {
23088
+ covered: noIssues || ((sectionMentioned || completionTextHasAny(candidateResult, issueTerms)) && completionTextHasAny(candidateResult, issueTerms)),
23089
+ contradicted: false,
23090
+ };
23091
+ }
23092
+ if (/ingress/i.test(normalized)) {
23093
+ const ingressState = /\b(?:reach|reaches|reachable|received|receives|working|healthy|blocked|stale|unknown|ok)\b|可达|收到|接收|正常|健康|阻塞|未知/iu.test(candidateResult);
23094
+ return { covered: (sectionMentioned || childMentioned) && ingressState, contradicted: false };
23095
+ }
23096
+ if (value && typeof value === "object") {
23097
+ return { covered: sectionMentioned && childMentioned, contradicted: false };
23098
+ }
23099
+ const scalar = String(value ?? "").trim().toLowerCase();
23100
+ const scalarTerms = scalar
23101
+ .split(/[_\-\s]+/u)
23102
+ .map((item) => item.trim())
23103
+ .filter((item) => item.length >= 2);
23104
+ const scalarCovered = !scalar ||
23105
+ completionTextHasAny(candidateResult, [scalar]) ||
23106
+ (scalarTerms.length > 1 && scalarTerms.every((term) => completionTextHasAny(candidateResult, [term])));
23107
+ return {
23108
+ covered: sectionMentioned && scalarCovered,
23109
+ contradicted: false,
23110
+ };
23111
+ }
23112
+
23113
+ export function evaluateAuthoritativeStructuredCompletionCoverage({
23114
+ goal = "",
23115
+ candidateResult = "",
23116
+ commandOutputs = [],
23117
+ } = {}) {
23118
+ const authoritative = [...(Array.isArray(commandOutputs) ? commandOutputs : [])]
23119
+ .reverse()
23120
+ .find((item) => item?.authoritative === true && parseCommandJsonOutput(item.output));
23121
+ if (!authoritative) {
23122
+ return { checked: false, ok: true, requestedSections: [], missingSections: [], contradictedSections: [], expectedSummary: "", key: "" };
23123
+ }
23124
+ const data = parseCommandJsonOutput(authoritative.output);
23125
+ const requestedSections = requestedAuthoritativeStructuredSections(goal, data);
23126
+ if (!requestedSections.length) {
23127
+ return { checked: false, ok: true, requestedSections: [], missingSections: [], contradictedSections: [], expectedSummary: summarizeJsonCommandOutput(authoritative.output), key: "" };
23128
+ }
23129
+ const missingSections = [];
23130
+ const contradictedSections = [];
23131
+ for (const key of requestedSections) {
23132
+ const coverage = authoritativeStructuredSectionCovered(key, data[key], candidateResult);
23133
+ if (!coverage.covered) missingSections.push(key);
23134
+ if (coverage.contradicted) contradictedSections.push(key);
23135
+ }
23136
+ const expectedSummary = summarizeJsonCommandOutput(authoritative.output);
23137
+ return {
23138
+ checked: true,
23139
+ ok: missingSections.length === 0 && contradictedSections.length === 0,
23140
+ requestedSections,
23141
+ missingSections,
23142
+ contradictedSections,
23143
+ expectedSummary,
23144
+ key: hashForLog(`${String(goal || "")}\0${String(authoritative.output || "")}\0${requestedSections.join(",")}`),
23145
+ };
23146
+ }
23147
+
22885
23148
  function completionCommandOutputRecords(scoped = {}) {
22886
23149
  const events = Array.isArray(scoped.events) ? scoped.events : [];
22887
23150
  const state = scoped.state && typeof scoped.state === "object" ? scoped.state : {};
@@ -27689,7 +27952,9 @@ async function runAgentOnceUnlocked(config) {
27689
27952
  toolResult: completionDecision.artifactBlock,
27690
27953
  });
27691
27954
  }
27692
- let fallback = redactSensitiveText(assistantMessage.content?.trim() || "");
27955
+ let fallback = redactSensitiveText(
27956
+ completionDecision.resultOverride || assistantMessage.content?.trim() || ""
27957
+ );
27693
27958
  if (!fallback) {
27694
27959
  const emptyDecision = await repairEmptyCompletion({
27695
27960
  config,
@@ -27936,7 +28201,10 @@ async function runAgentOnceUnlocked(config) {
27936
28201
  toolResult: completionDecision.artifactBlock,
27937
28202
  });
27938
28203
  }
27939
- const completionResult = canonicalizeVerifiedArtifactCompletion(state, toolResult.result || "");
28204
+ const completionResult = canonicalizeVerifiedArtifactCompletion(
28205
+ state,
28206
+ completionDecision.resultOverride || toolResult.result || ""
28207
+ );
27940
28208
  if (config.scsActive) {
27941
28209
  const decision = await reviewScsFinish(client, config, state, completionResult, {
27942
28210
  events: await store.loadEvents(),