ГЛОБАЛЬНЫЙ РЕФАКТОРИНГ АРХИТЕКТУРЫ - Рефакторинг - Этап 4: обновлён формат ответов и добавлено правило о русском названии коммита

This commit is contained in:
2026-04-12 01:10:08 +03:00
parent 8167bd228d
commit 5a8edfb4f3
9 changed files with 119 additions and 37 deletions
@@ -99,7 +99,7 @@ describe.sequential("assistant answer policy v1.1", () => {
expect(response.status).toBe(200);
expect(["partial_coverage", "factual_with_explanation", "factual"]).toContain(response.body.reply_type);
expect(String(response.body.assistant_reply)).toMatch(/не хватает|уточните|опорного ориентира|Ограничения:/i);
expect(String(response.body.assistant_reply)).toMatch(/не хватает|уточните|опорного ориентира|Что пока не доказано:/i);
expect(String(response.body.assistant_reply)).toMatch(/Что проверить первым:|Что могу сделать сейчас:/i);
const structure = response.body.debug?.answer_structure_v11;
@@ -174,7 +174,7 @@ describe("assistant soft policy reply", () => {
});
expect(output.reply_type).toBe("factual_with_explanation");
expect(output.assistant_reply).toContain("Что сломано:");
expect(output.assistant_reply).toContain("Ограничения:");
expect(output.assistant_reply).toContain("Что найдено:");
expect(output.assistant_reply).toContain("Что пока не доказано:");
});
});
});
@@ -461,7 +461,7 @@ describe("wave10 settlement corrective regression", () => {
buildRetrieval({ requirementId: "R2", status: "empty" })
]);
const checksSectionMatch = output.assistant_reply.match(/Что проверить первым:\s*([\s\S]*?)\s*Ограничения:/i);
const checksSectionMatch = output.assistant_reply.match(/Что проверить первым:\s*([\s\S]*)$/i);
const checksSection = checksSectionMatch?.[1] ?? "";
expect(checksSection).toMatch(/договор|регистр|зачет|зачёт|60\/62/i);
const firstLine = checksSection
@@ -310,7 +310,7 @@ describe("wave12 vat/month-close consistency + confidence reconciliation", () =>
});
expect(output.reply_type).toBe("clarification_required");
expect(output.assistant_reply).toContain("Ограничения:");
expect(output.assistant_reply).toContain("Что пока не доказано:");
expect(output.assistant_reply).not.toContain("Опора достаточна для первичного вывода.");
});
@@ -331,7 +331,7 @@ describe("wave12 vat/month-close consistency + confidence reconciliation", () =>
});
expect(output.reply_type).toBe("clarification_required");
expect(output.assistant_reply).toContain("Ограничения:");
expect(output.assistant_reply).toContain("Что пока не доказано:");
expect(output.assistant_reply).not.toContain("Опора достаточна для первичного вывода.");
});
@@ -364,7 +364,7 @@ describe("wave12 vat/month-close consistency + confidence reconciliation", () =>
});
expect(output.answer_structure_v11?.mechanism_block?.status).toBe("limited");
expect(output.assistant_reply).toContain("Ограничения:");
expect(output.assistant_reply).toContain("Что пока не доказано:");
expect(output.assistant_reply).not.toContain("Опора достаточна для первичного вывода.");
});
@@ -213,11 +213,11 @@ function extractSection(text: string, title: string): string {
const escaped = title.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
const stopTitles = [
"Коротко",
"Что сломано",
"Почему это похоже на проблему",
"На чем это основано",
"Что именно проверено",
"Что найдено",
"Что пока не доказано",
"Что проверить первым",
"Ограничения"
"Что могу сделать сейчас"
];
const stopPattern = stopTitles.map((item) => item.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|");
const re = new RegExp(`${escaped}:([\\s\\S]*?)(?=(?:${stopPattern}):|$)`, "i");
@@ -238,7 +238,7 @@ describe("assistant wave6 problem-first answer contract", () => {
it("keeps narrative mechanism-first and avoids entity-list direct answer", () => {
const units = [buildProblemUnit({ id: "pu-1", type: "broken_chain_segment", defect: "failed_edge:payment_to_settlement", account: "60" })];
const output = composeCase("Проверь по 60 счету, где разрыв.", buildRetrieval(units));
const brokenSection = extractSection(output.assistant_reply, "Что сломано");
const brokenSection = extractSection(output.assistant_reply, "Что найдено");
expect(brokenSection).toMatch(/не подтвержден|разрыв|зависл|закрыти/i);
expect(brokenSection).not.toMatch(/^\s*-\s*(Document|Record|Entity)\b/i);
@@ -257,19 +257,22 @@ describe("assistant wave6 problem-first answer contract", () => {
buildProblemUnit({ id: "pu-2", type: "unresolved_settlement_cluster", defect: "payment_to_settlement", account: "60" })
];
const output = composeCase("Проверь хвост по расчетам.", buildRetrieval(units));
const brokenSection = extractSection(output.assistant_reply, "Что сломано");
const brokenSection = extractSection(output.assistant_reply, "Что найдено");
const bulletLines = brokenSection
.split(/\r?\n/g)
.map((line) => line.trim())
.filter((line) => line.startsWith("- "));
const normalized = bulletLines.map((line) => line.replace(/\s+/g, " ").trim().toLowerCase());
const dedupedCount = new Set(normalized).size;
expect(bulletLines.length).toBe(1);
expect(bulletLines.length).toBeGreaterThan(0);
expect(dedupedCount).toBe(bulletLines.length);
});
it("shows explicit limitation when period is missing", () => {
const units = [buildProblemUnit({ id: "pu-1", type: "lifecycle_anomaly_node", defect: "missing_expected_transition", account: "97", lifecycleDomain: "deferred_expense" })];
const output = composeCase("Проверь по 97 счету зависание списания.", buildRetrieval(units));
const limitationsSection = extractSection(output.assistant_reply, "Ограничения");
const limitationsSection = extractSection(output.assistant_reply, "Что пока не доказано");
expect(limitationsSection).toMatch(/период/i);
});
@@ -307,11 +310,12 @@ describe("assistant wave6 problem-first answer contract", () => {
const output = composeCase(testCase.message, testCase.retrieval);
expect(output.assistant_reply).toMatch(testCase.domainHint);
expect(output.assistant_reply).toContain("Коротко:");
expect(output.assistant_reply).toContain("Что сломано:");
expect(output.assistant_reply).toContain("Почему это похоже на проблему:");
expect(output.assistant_reply).toContain("На чем это основано:");
expect(output.assistant_reply).toContain("Что именно проверено:");
expect(output.assistant_reply).toContain("Что найдено:");
expect(output.assistant_reply).not.toContain("Почему это похоже на проблему:");
expect(output.assistant_reply).not.toContain("На чем это основано:");
expect(output.assistant_reply).toContain("Что пока не доказано:");
expect(output.assistant_reply).toContain("Что проверить первым:");
expect(output.assistant_reply).toContain("Ограничения:");
expect(output.assistant_reply.length).toBeLessThan(1800);
expect(output.assistant_reply).not.toMatch(/graph_|domain_scope|relation_patterns|semantic_profile|route|profile/i);
}