ЮИ - Упростить карточки автопрогонов до названия даты id режима и типа
This commit is contained in:
+4
-2
@@ -3,11 +3,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.TRACES_DIR = exports.DATA_DIR = exports.VAT_PAYABLE_19_PREFIXES = exports.VAT_PAYABLE_68_PREFIXES = exports.ASSISTANT_MCP_LIVE_LIMIT = exports.ASSISTANT_MCP_TIMEOUT_MS = exports.ASSISTANT_MCP_CHANNEL = exports.ASSISTANT_MCP_PROXY_URL = exports.FEATURE_ASSISTANT_LIVING_CHAT_ROUTER_V1 = exports.FEATURE_ASSISTANT_ROUTE_EXPECTATION_HARD_GUARD_V1 = exports.FEATURE_ASSISTANT_ROUTE_EXPECTATION_AUDIT_V1 = exports.FEATURE_ASSISTANT_ROUTE_SHADOW_PAYABLES_EXACT_V1 = exports.FEATURE_ASSISTANT_ROUTE_RECEIVABLES_HEURISTIC_V1 = exports.FEATURE_ASSISTANT_ROUTE_PAYABLES_HEURISTIC_V1 = exports.FEATURE_ASSISTANT_ROUTE_RECEIVABLES_CONFIRMED_V1 = exports.FEATURE_ASSISTANT_ROUTE_PAYABLES_CONFIRMED_V1 = exports.FEATURE_ASSISTANT_ROUTE_BALANCE_EXACT_V1 = exports.FEATURE_ASSISTANT_ROUTE_DRILLDOWN_V1 = exports.FEATURE_ASSISTANT_ROUTE_ADDRESS_GENERIC_V1 = exports.FEATURE_ASSISTANT_CAPABILITY_ROUTE_GUARD_V1 = exports.FEATURE_ASSISTANT_ADDRESS_NAVIGATION_STATE_V1 = exports.FEATURE_ASSISTANT_ADDRESS_QUERY_LIVE_V1 = exports.FEATURE_ASSISTANT_ADDRESS_QUERY_LLM_PREDECOMPOSE_V1 = exports.FEATURE_ASSISTANT_ADDRESS_QUERY_V1 = exports.FEATURE_ASSISTANT_MCP_RUNTIME_V1 = exports.FEATURE_ASSISTANT_GRAPH_RUNTIME_V1 = exports.FEATURE_ASSISTANT_LIFECYCLE_ANSWER_V1 = exports.FEATURE_ASSISTANT_LIFECYCLE_RUNTIME_V1 = exports.FEATURE_ASSISTANT_STAGE2_EVAL_V1 = exports.FEATURE_ASSISTANT_PROBLEM_UNIT_CONTINUITY_V1 = exports.FEATURE_ASSISTANT_PROBLEM_CENTRIC_ANSWER_V1 = exports.FEATURE_ASSISTANT_PROBLEM_UNITS_V1 = exports.FEATURE_ASSISTANT_ACCOUNTANT_EVAL_V1 = exports.FEATURE_ASSISTANT_ANSWER_POLICY_V11 = exports.FEATURE_ASSISTANT_ANTI_GENERIC_RANKING_GUARD_V1 = exports.FEATURE_ASSISTANT_MIN_EVIDENCE_GATE_V1 = exports.FEATURE_ASSISTANT_BROAD_GUARD_V1 = exports.FEATURE_ASSISTANT_EVIDENCE_ENRICHMENT_V1 = exports.FEATURE_ASSISTANT_STATE_FOLLOWUP_BINDING_V1 = exports.FEATURE_ASSISTANT_CONTRACTS_V11 = exports.FEATURE_ASSISTANT_INVESTIGATION_STATE_V1 = exports.DEFAULT_PROMPT_VERSION = exports.DEFAULT_MAX_OUTPUT_TOKENS = exports.DEFAULT_TEMPERATURE = exports.DEFAULT_MODEL = exports.DEFAULT_OPENAI_BASE_URL = exports.TIMEZONE = exports.PORT = exports.MODULE_ROOT = exports.BACKEND_ROOT = void 0;
|
||||
exports.MANUAL_CASE_DECISION_SCHEMA_FILE = exports.ASSISTANT_CAPABILITIES_REGISTRY_FILE = exports.ASSISTANT_CANON_FILE = exports.ARCH_EXPORT_2020_DIR = exports.SCHEMAS_DIR = exports.EVAL_DATASETS_DIR = exports.REPORTS_DIR = exports.PROMPTS_DIR = exports.SHARED_LLM_CONNECTION_FILE = exports.AUTORUN_GENERATOR_HISTORY_FILE = exports.AUTORUN_GENERATOR_DIR = exports.AUTORUN_ANNOTATIONS_FILE = exports.AUTORUN_ANNOTATIONS_DIR = exports.ASSISTANT_ANNOTATIONS_FILE = exports.ASSISTANT_ANNOTATIONS_DIR = exports.ASSISTANT_SESSIONS_DIR = exports.EVAL_CASES_DIR = exports.PRESETS_DIR = void 0;
|
||||
exports.DATA_DIR = exports.VAT_PAYABLE_19_PREFIXES = exports.VAT_PAYABLE_68_PREFIXES = exports.ASSISTANT_MCP_LIVE_LIMIT = exports.ASSISTANT_MCP_TIMEOUT_MS = exports.ASSISTANT_MCP_CHANNEL = exports.ASSISTANT_MCP_PROXY_URL = exports.FEATURE_ASSISTANT_LIVING_CHAT_ROUTER_V1 = exports.FEATURE_ASSISTANT_ROUTE_EXPECTATION_HARD_GUARD_V1 = exports.FEATURE_ASSISTANT_ROUTE_EXPECTATION_AUDIT_V1 = exports.FEATURE_ASSISTANT_ROUTE_SHADOW_PAYABLES_EXACT_V1 = exports.FEATURE_ASSISTANT_ROUTE_RECEIVABLES_HEURISTIC_V1 = exports.FEATURE_ASSISTANT_ROUTE_PAYABLES_HEURISTIC_V1 = exports.FEATURE_ASSISTANT_ROUTE_RECEIVABLES_CONFIRMED_V1 = exports.FEATURE_ASSISTANT_ROUTE_PAYABLES_CONFIRMED_V1 = exports.FEATURE_ASSISTANT_ROUTE_BALANCE_EXACT_V1 = exports.FEATURE_ASSISTANT_ROUTE_DRILLDOWN_V1 = exports.FEATURE_ASSISTANT_ROUTE_ADDRESS_GENERIC_V1 = exports.FEATURE_ASSISTANT_CAPABILITY_ROUTE_GUARD_V1 = exports.FEATURE_ASSISTANT_ADDRESS_NAVIGATION_STATE_V1 = exports.FEATURE_ASSISTANT_ADDRESS_QUERY_LIVE_V1 = exports.FEATURE_ASSISTANT_ADDRESS_QUERY_LLM_PREDECOMPOSE_V1 = exports.FEATURE_ASSISTANT_ADDRESS_QUERY_V1 = exports.FEATURE_ASSISTANT_MCP_RUNTIME_V1 = exports.FEATURE_ASSISTANT_GRAPH_RUNTIME_V1 = exports.FEATURE_ASSISTANT_LIFECYCLE_ANSWER_V1 = exports.FEATURE_ASSISTANT_LIFECYCLE_RUNTIME_V1 = exports.FEATURE_ASSISTANT_STAGE2_EVAL_V1 = exports.FEATURE_ASSISTANT_PROBLEM_UNIT_CONTINUITY_V1 = exports.FEATURE_ASSISTANT_PROBLEM_CENTRIC_ANSWER_V1 = exports.FEATURE_ASSISTANT_PROBLEM_UNITS_V1 = exports.FEATURE_ASSISTANT_ACCOUNTANT_EVAL_V1 = exports.FEATURE_ASSISTANT_ANSWER_POLICY_V11 = exports.FEATURE_ASSISTANT_ANTI_GENERIC_RANKING_GUARD_V1 = exports.FEATURE_ASSISTANT_MIN_EVIDENCE_GATE_V1 = exports.FEATURE_ASSISTANT_BROAD_GUARD_V1 = exports.FEATURE_ASSISTANT_EVIDENCE_ENRICHMENT_V1 = exports.FEATURE_ASSISTANT_STATE_FOLLOWUP_BINDING_V1 = exports.FEATURE_ASSISTANT_CONTRACTS_V11 = exports.FEATURE_ASSISTANT_INVESTIGATION_STATE_V1 = exports.DEFAULT_PROMPT_VERSION = exports.DEFAULT_MAX_OUTPUT_TOKENS = exports.DEFAULT_TEMPERATURE = exports.DEFAULT_MODEL = exports.DEFAULT_OPENAI_BASE_URL = exports.TIMEZONE = exports.PORT = exports.PROJECT_ROOT = exports.MODULE_ROOT = exports.BACKEND_ROOT = void 0;
|
||||
exports.MANUAL_CASE_DECISION_SCHEMA_FILE = exports.ASSISTANT_CAPABILITIES_REGISTRY_FILE = exports.ASSISTANT_CANON_FILE = exports.ARCH_EXPORT_2020_DIR = exports.SCHEMAS_DIR = exports.EVAL_DATASETS_DIR = exports.ARTIFACTS_DIR = exports.REPORTS_DIR = exports.PROMPTS_DIR = exports.SHARED_LLM_CONNECTION_FILE = exports.AUTORUN_GENERATOR_HISTORY_FILE = exports.AUTORUN_GENERATOR_DIR = exports.AUTORUN_ANNOTATIONS_FILE = exports.AUTORUN_ANNOTATIONS_DIR = exports.ASSISTANT_ANNOTATIONS_FILE = exports.ASSISTANT_ANNOTATIONS_DIR = exports.ASSISTANT_SESSIONS_DIR = exports.EVAL_CASES_DIR = exports.PRESETS_DIR = exports.TRACES_DIR = void 0;
|
||||
const path_1 = __importDefault(require("path"));
|
||||
exports.BACKEND_ROOT = path_1.default.resolve(__dirname, "..");
|
||||
exports.MODULE_ROOT = path_1.default.resolve(exports.BACKEND_ROOT, "..");
|
||||
exports.PROJECT_ROOT = path_1.default.resolve(exports.MODULE_ROOT, "..");
|
||||
function toBooleanFlag(value, defaultValue) {
|
||||
if (!value || value.trim() === "") {
|
||||
return defaultValue;
|
||||
@@ -93,6 +94,7 @@ exports.AUTORUN_GENERATOR_HISTORY_FILE = path_1.default.resolve(exports.AUTORUN_
|
||||
exports.SHARED_LLM_CONNECTION_FILE = path_1.default.resolve(exports.DATA_DIR, "shared_llm_connection.json");
|
||||
exports.PROMPTS_DIR = path_1.default.resolve(exports.MODULE_ROOT, "prompts");
|
||||
exports.REPORTS_DIR = path_1.default.resolve(exports.MODULE_ROOT, "reports");
|
||||
exports.ARTIFACTS_DIR = path_1.default.resolve(exports.PROJECT_ROOT, "artifacts");
|
||||
exports.EVAL_DATASETS_DIR = path_1.default.resolve(exports.MODULE_ROOT, "eval_cases");
|
||||
exports.SCHEMAS_DIR = path_1.default.resolve(exports.BACKEND_ROOT, "src", "schemas");
|
||||
exports.ARCH_EXPORT_2020_DIR = path_1.default.resolve(exports.MODULE_ROOT, "..", "docs", "ARCH", "2020экспорт");
|
||||
|
||||
+80
-3
@@ -10,6 +10,7 @@ const path_1 = __importDefault(require("path"));
|
||||
const express_1 = require("express");
|
||||
const iconv_lite_1 = __importDefault(require("iconv-lite"));
|
||||
const config_1 = require("../config");
|
||||
const agentSemanticRunRegistry_1 = require("../services/agentSemanticRunRegistry");
|
||||
const http_1 = require("../utils/http");
|
||||
const capabilitiesRegistry_1 = require("../services/capabilitiesRegistry");
|
||||
const openaiResponsesClient_1 = require("../services/openaiResponsesClient");
|
||||
@@ -189,7 +190,14 @@ function readAutoGenHistory() {
|
||||
? repairAutogenMojibake(String(toRecord(item.context)?.agent_focus))
|
||||
: null,
|
||||
architecture_phase: toStringSafe(toRecord(item.context)?.architecture_phase),
|
||||
source_spec_file: toStringSafe(toRecord(item.context)?.source_spec_file)
|
||||
source_spec_file: toStringSafe(toRecord(item.context)?.source_spec_file),
|
||||
scenario_id: toStringSafe(toRecord(item.context)?.scenario_id),
|
||||
semantic_tags: Array.isArray(toRecord(item.context)?.semantic_tags)
|
||||
? Array.from(new Set((toRecord(item.context)?.semantic_tags)
|
||||
.map((tag) => toStringSafe(tag))
|
||||
.filter((tag) => Boolean(tag))))
|
||||
: null,
|
||||
latest_acceptance: null
|
||||
}
|
||||
: null
|
||||
}))
|
||||
@@ -207,6 +215,75 @@ function writeAutoGenHistory(records) {
|
||||
}
|
||||
fs_1.default.writeFileSync(config_1.AUTORUN_GENERATOR_HISTORY_FILE, JSON.stringify(records, null, 2), "utf-8");
|
||||
}
|
||||
function isAgentSemanticHistoryRecord(record) {
|
||||
if (record.context?.agent_run === true) {
|
||||
return true;
|
||||
}
|
||||
if (record.context?.saved_case_set_kind === "agent_semantic_scenario") {
|
||||
return true;
|
||||
}
|
||||
return typeof record.title === "string" && record.title.trim().toUpperCase().startsWith("AGENT");
|
||||
}
|
||||
function hydrateAutoGenHistoryForApi(records) {
|
||||
const specSummaryCache = new Map();
|
||||
const acceptanceCache = new Map();
|
||||
const readSpecSummary = (sourceSpecFile) => {
|
||||
const normalizedPath = toStringSafe(sourceSpecFile);
|
||||
if (!normalizedPath) {
|
||||
return null;
|
||||
}
|
||||
if (specSummaryCache.has(normalizedPath)) {
|
||||
return specSummaryCache.get(normalizedPath) ?? null;
|
||||
}
|
||||
const summary = (0, agentSemanticRunRegistry_1.readAgentSemanticSpecSummaryFromFile)(normalizedPath);
|
||||
specSummaryCache.set(normalizedPath, summary);
|
||||
return summary;
|
||||
};
|
||||
const readAcceptanceSummary = (scenarioId) => {
|
||||
const normalizedScenarioId = toStringSafe(scenarioId);
|
||||
if (!normalizedScenarioId) {
|
||||
return null;
|
||||
}
|
||||
if (acceptanceCache.has(normalizedScenarioId)) {
|
||||
return acceptanceCache.get(normalizedScenarioId) ?? null;
|
||||
}
|
||||
const summary = (0, agentSemanticRunRegistry_1.findLatestAgentSemanticAcceptanceSummary)({
|
||||
artifactsRootDir: path_1.default.resolve(config_1.ARTIFACTS_DIR, "domain_runs"),
|
||||
repoRootDir: config_1.PROJECT_ROOT,
|
||||
scenarioId: normalizedScenarioId
|
||||
});
|
||||
acceptanceCache.set(normalizedScenarioId, summary);
|
||||
return summary;
|
||||
};
|
||||
return records.map((record) => {
|
||||
if (!isAgentSemanticHistoryRecord(record)) {
|
||||
return record;
|
||||
}
|
||||
const specSummary = readSpecSummary(record.context?.source_spec_file);
|
||||
const scenarioId = toStringSafe(record.context?.scenario_id) ?? specSummary?.scenario_id ?? null;
|
||||
const semanticTags = Array.isArray(record.context?.semantic_tags) && record.context?.semantic_tags.length > 0
|
||||
? Array.from(new Set(record.context?.semantic_tags.map((item) => String(item).trim()).filter((item) => item.length > 0)))
|
||||
: specSummary?.semantic_tags ?? [];
|
||||
const latestAcceptance = readAcceptanceSummary(scenarioId);
|
||||
return {
|
||||
...record,
|
||||
context: {
|
||||
...(record.context ?? {
|
||||
llm_provider: null,
|
||||
model: null,
|
||||
assistant_prompt_version: null,
|
||||
decomposition_prompt_version: null,
|
||||
prompt_fingerprint: null,
|
||||
autogen_personality_id: null,
|
||||
autogen_personality_prompt: null
|
||||
}),
|
||||
scenario_id: scenarioId,
|
||||
semantic_tags: semanticTags,
|
||||
latest_acceptance: latestAcceptance
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
function readEvalDatasetCases(filePath) {
|
||||
try {
|
||||
const parsed = JSON.parse(fs_1.default.readFileSync(filePath, "utf-8"));
|
||||
@@ -2015,9 +2092,9 @@ function buildAutoRunsRouter(services, openaiClient = new openaiResponsesClient_
|
||||
const rawMode = toStringSafe(req.query.mode);
|
||||
const includeAllModes = !rawMode || !isAutoGenMode(rawMode);
|
||||
const modeFilter = rawMode ?? "codex_creative";
|
||||
const items = readAutoGenHistory()
|
||||
const items = hydrateAutoGenHistoryForApi(readAutoGenHistory()
|
||||
.filter((item) => (includeAllModes ? true : item.mode === modeFilter))
|
||||
.slice(0, limit);
|
||||
.slice(0, limit));
|
||||
(0, http_1.ok)(res, {
|
||||
ok: true,
|
||||
generated_at: new Date().toISOString(),
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.readAgentSemanticSpecSummaryFromFile = readAgentSemanticSpecSummaryFromFile;
|
||||
exports.findLatestAgentSemanticAcceptanceSummary = findLatestAgentSemanticAcceptanceSummary;
|
||||
const fs_1 = __importDefault(require("fs"));
|
||||
const path_1 = __importDefault(require("path"));
|
||||
function toRecord(value) {
|
||||
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
||||
return null;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
function toStringSafe(value) {
|
||||
if (typeof value !== "string") {
|
||||
return null;
|
||||
}
|
||||
const trimmed = value.trim();
|
||||
return trimmed.length > 0 ? trimmed : null;
|
||||
}
|
||||
function toBooleanSafe(value) {
|
||||
if (typeof value === "boolean") {
|
||||
return value;
|
||||
}
|
||||
if (typeof value === "string") {
|
||||
const lowered = value.trim().toLowerCase();
|
||||
if (["1", "true", "yes", "on"].includes(lowered))
|
||||
return true;
|
||||
if (["0", "false", "no", "off"].includes(lowered))
|
||||
return false;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
function toNumberSafe(value) {
|
||||
if (typeof value === "number" && Number.isFinite(value)) {
|
||||
return value;
|
||||
}
|
||||
if (typeof value === "string" && value.trim().length > 0) {
|
||||
const parsed = Number(value);
|
||||
return Number.isFinite(parsed) ? parsed : null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
function readJsonFile(filePath) {
|
||||
return JSON.parse(fs_1.default.readFileSync(filePath, "utf-8"));
|
||||
}
|
||||
function normalizeSemanticTags(rawSteps) {
|
||||
if (!Array.isArray(rawSteps)) {
|
||||
return [];
|
||||
}
|
||||
const tags = new Set();
|
||||
for (const rawStep of rawSteps) {
|
||||
const step = toRecord(rawStep);
|
||||
if (!step || !Array.isArray(step.semantic_tags)) {
|
||||
continue;
|
||||
}
|
||||
for (const rawTag of step.semantic_tags) {
|
||||
const tag = toStringSafe(rawTag);
|
||||
if (tag) {
|
||||
tags.add(tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
return Array.from(tags).sort((left, right) => left.localeCompare(right));
|
||||
}
|
||||
function readAgentSemanticSpecSummaryFromFile(sourceSpecFile) {
|
||||
const normalizedPath = toStringSafe(sourceSpecFile);
|
||||
if (!normalizedPath || !fs_1.default.existsSync(normalizedPath)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
const parsed = readJsonFile(normalizedPath);
|
||||
const record = toRecord(parsed);
|
||||
if (!record) {
|
||||
return null;
|
||||
}
|
||||
const scenarioId = toStringSafe(record.scenario_id);
|
||||
if (!scenarioId) {
|
||||
return null;
|
||||
}
|
||||
const semanticTags = normalizeSemanticTags(record.steps);
|
||||
return {
|
||||
scenario_id: scenarioId,
|
||||
domain: toStringSafe(record.domain),
|
||||
title: toStringSafe(record.title),
|
||||
semantic_tags: semanticTags,
|
||||
steps_total: Array.isArray(record.steps) ? record.steps.length : 0
|
||||
};
|
||||
}
|
||||
catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
function buildInvariantSummary(rawValue) {
|
||||
const record = toRecord(rawValue);
|
||||
return {
|
||||
direct_answer_ok: toBooleanSafe(record?.direct_answer_ok),
|
||||
temporal_honesty_ok: toBooleanSafe(record?.temporal_honesty_ok),
|
||||
selected_object_continuity_ok: toBooleanSafe(record?.selected_object_continuity_ok),
|
||||
truth_gate_ok: toBooleanSafe(record?.truth_gate_ok),
|
||||
human_answer_quality_ok: toBooleanSafe(record?.human_answer_quality_ok),
|
||||
meta_context_integrity_ok: toBooleanSafe(record?.meta_context_integrity_ok)
|
||||
};
|
||||
}
|
||||
function findLatestAgentSemanticAcceptanceSummary(input) {
|
||||
const scenarioId = toStringSafe(input.scenarioId);
|
||||
if (!scenarioId) {
|
||||
return null;
|
||||
}
|
||||
if (!fs_1.default.existsSync(input.artifactsRootDir)) {
|
||||
return null;
|
||||
}
|
||||
const candidates = fs_1.default
|
||||
.readdirSync(input.artifactsRootDir, { withFileTypes: true })
|
||||
.filter((entry) => entry.isDirectory() && entry.name.startsWith(`${scenarioId}_`))
|
||||
.map((entry) => {
|
||||
const outputDir = path_1.default.resolve(input.artifactsRootDir, entry.name);
|
||||
const packStatePath = path_1.default.resolve(outputDir, "pack_state.json");
|
||||
if (!fs_1.default.existsSync(packStatePath)) {
|
||||
return null;
|
||||
}
|
||||
const stats = fs_1.default.statSync(packStatePath);
|
||||
return {
|
||||
outputDir,
|
||||
packStatePath,
|
||||
mtimeMs: stats.mtimeMs
|
||||
};
|
||||
})
|
||||
.filter((item) => item !== null)
|
||||
.sort((left, right) => right.mtimeMs - left.mtimeMs);
|
||||
const latest = candidates[0];
|
||||
if (!latest) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
const parsed = readJsonFile(latest.packStatePath);
|
||||
const packState = toRecord(parsed);
|
||||
if (!packState) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
scenario_id: scenarioId,
|
||||
output_dir: latest.outputDir,
|
||||
relative_output_dir: path_1.default.relative(input.repoRootDir, latest.outputDir).replace(/\\/g, "/"),
|
||||
final_status: toStringSafe(packState.final_status),
|
||||
final_status_reason: toStringSafe(packState.final_status_reason),
|
||||
review_overall_status: toStringSafe(packState.review_overall_status),
|
||||
acceptance_gate_passed: toBooleanSafe(packState.acceptance_gate_passed),
|
||||
critical_path_green: toBooleanSafe(packState.critical_path_green),
|
||||
unresolved_p0_count: toNumberSafe(packState.unresolved_p0_count),
|
||||
unresolved_p1_count: toNumberSafe(packState.unresolved_p1_count),
|
||||
unresolved_p2_count: toNumberSafe(packState.unresolved_p2_count),
|
||||
steps_total: toNumberSafe(packState.steps_total),
|
||||
steps_passed: toNumberSafe(packState.steps_passed),
|
||||
steps_with_warning: toNumberSafe(packState.steps_with_warning),
|
||||
steps_failed: toNumberSafe(packState.steps_failed),
|
||||
updated_at: toStringSafe(packState.updated_at),
|
||||
invariants: buildInvariantSummary(packState.invariants)
|
||||
};
|
||||
}
|
||||
catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import path from "path";
|
||||
|
||||
export const BACKEND_ROOT = path.resolve(__dirname, "..");
|
||||
export const MODULE_ROOT = path.resolve(BACKEND_ROOT, "..");
|
||||
export const PROJECT_ROOT = path.resolve(MODULE_ROOT, "..");
|
||||
|
||||
function toBooleanFlag(value: string | undefined, defaultValue: boolean): boolean {
|
||||
if (!value || value.trim() === "") {
|
||||
@@ -192,6 +193,7 @@ export const SHARED_LLM_CONNECTION_FILE = path.resolve(DATA_DIR, "shared_llm_con
|
||||
|
||||
export const PROMPTS_DIR = path.resolve(MODULE_ROOT, "prompts");
|
||||
export const REPORTS_DIR = path.resolve(MODULE_ROOT, "reports");
|
||||
export const ARTIFACTS_DIR = path.resolve(PROJECT_ROOT, "artifacts");
|
||||
export const EVAL_DATASETS_DIR = path.resolve(MODULE_ROOT, "eval_cases");
|
||||
export const SCHEMAS_DIR = path.resolve(BACKEND_ROOT, "src", "schemas");
|
||||
export const ARCH_EXPORT_2020_DIR = path.resolve(MODULE_ROOT, "..", "docs", "ARCH", "2020экспорт");
|
||||
|
||||
@@ -3,15 +3,21 @@ import path from "path";
|
||||
import { Router } from "express";
|
||||
import iconv from "iconv-lite";
|
||||
import {
|
||||
ARTIFACTS_DIR,
|
||||
ASSISTANT_SESSIONS_DIR,
|
||||
AUTORUN_ANNOTATIONS_FILE,
|
||||
AUTORUN_GENERATOR_HISTORY_FILE,
|
||||
EVAL_CASES_DIR,
|
||||
EVAL_DATASETS_DIR,
|
||||
MANUAL_CASE_DECISION_SCHEMA_FILE,
|
||||
PROJECT_ROOT,
|
||||
REPORTS_DIR
|
||||
} from "../config";
|
||||
import type { AppServices } from "../serverContext";
|
||||
import {
|
||||
findLatestAgentSemanticAcceptanceSummary,
|
||||
readAgentSemanticSpecSummaryFromFile
|
||||
} from "../services/agentSemanticRunRegistry";
|
||||
import { ApiError, ok } from "../utils/http";
|
||||
import { loadCapabilitiesRegistry, resolveNearestCapabilityGroup, type CapabilityGroup } from "../services/capabilitiesRegistry";
|
||||
import { OpenAIResponsesClient } from "../services/openaiResponsesClient";
|
||||
@@ -197,6 +203,34 @@ interface AutoGenHistoryRecord {
|
||||
agent_focus?: string | null;
|
||||
architecture_phase?: string | null;
|
||||
source_spec_file?: string | null;
|
||||
scenario_id?: string | null;
|
||||
semantic_tags?: string[] | null;
|
||||
latest_acceptance?: {
|
||||
scenario_id: string;
|
||||
output_dir: string;
|
||||
relative_output_dir: string;
|
||||
final_status: string | null;
|
||||
final_status_reason: string | null;
|
||||
review_overall_status: string | null;
|
||||
acceptance_gate_passed: boolean | null;
|
||||
critical_path_green: boolean | null;
|
||||
unresolved_p0_count: number | null;
|
||||
unresolved_p1_count: number | null;
|
||||
unresolved_p2_count: number | null;
|
||||
steps_total: number | null;
|
||||
steps_passed: number | null;
|
||||
steps_with_warning: number | null;
|
||||
steps_failed: number | null;
|
||||
updated_at: string | null;
|
||||
invariants: {
|
||||
direct_answer_ok: boolean | null;
|
||||
temporal_honesty_ok: boolean | null;
|
||||
selected_object_continuity_ok: boolean | null;
|
||||
truth_gate_ok: boolean | null;
|
||||
human_answer_quality_ok: boolean | null;
|
||||
meta_context_integrity_ok: boolean | null;
|
||||
};
|
||||
} | null;
|
||||
} | null;
|
||||
}
|
||||
|
||||
@@ -375,7 +409,18 @@ function readAutoGenHistory(): AutoGenHistoryRecord[] {
|
||||
? repairAutogenMojibake(String(toRecord(item.context)?.agent_focus))
|
||||
: null,
|
||||
architecture_phase: toStringSafe(toRecord(item.context)?.architecture_phase),
|
||||
source_spec_file: toStringSafe(toRecord(item.context)?.source_spec_file)
|
||||
source_spec_file: toStringSafe(toRecord(item.context)?.source_spec_file),
|
||||
scenario_id: toStringSafe(toRecord(item.context)?.scenario_id),
|
||||
semantic_tags: Array.isArray(toRecord(item.context)?.semantic_tags)
|
||||
? Array.from(
|
||||
new Set(
|
||||
(toRecord(item.context)?.semantic_tags as unknown[])
|
||||
.map((tag) => toStringSafe(tag))
|
||||
.filter((tag): tag is string => Boolean(tag))
|
||||
)
|
||||
)
|
||||
: null,
|
||||
latest_acceptance: null
|
||||
}
|
||||
: null
|
||||
}))
|
||||
@@ -394,6 +439,81 @@ function writeAutoGenHistory(records: AutoGenHistoryRecord[]): void {
|
||||
fs.writeFileSync(AUTORUN_GENERATOR_HISTORY_FILE, JSON.stringify(records, null, 2), "utf-8");
|
||||
}
|
||||
|
||||
function isAgentSemanticHistoryRecord(record: AutoGenHistoryRecord): boolean {
|
||||
if (record.context?.agent_run === true) {
|
||||
return true;
|
||||
}
|
||||
if (record.context?.saved_case_set_kind === "agent_semantic_scenario") {
|
||||
return true;
|
||||
}
|
||||
return typeof record.title === "string" && record.title.trim().toUpperCase().startsWith("AGENT");
|
||||
}
|
||||
|
||||
function hydrateAutoGenHistoryForApi(records: AutoGenHistoryRecord[]): AutoGenHistoryRecord[] {
|
||||
const specSummaryCache = new Map<string, ReturnType<typeof readAgentSemanticSpecSummaryFromFile>>();
|
||||
const acceptanceCache = new Map<string, ReturnType<typeof findLatestAgentSemanticAcceptanceSummary>>();
|
||||
|
||||
const readSpecSummary = (sourceSpecFile: string | null | undefined) => {
|
||||
const normalizedPath = toStringSafe(sourceSpecFile);
|
||||
if (!normalizedPath) {
|
||||
return null;
|
||||
}
|
||||
if (specSummaryCache.has(normalizedPath)) {
|
||||
return specSummaryCache.get(normalizedPath) ?? null;
|
||||
}
|
||||
const summary = readAgentSemanticSpecSummaryFromFile(normalizedPath);
|
||||
specSummaryCache.set(normalizedPath, summary);
|
||||
return summary;
|
||||
};
|
||||
|
||||
const readAcceptanceSummary = (scenarioId: string | null | undefined) => {
|
||||
const normalizedScenarioId = toStringSafe(scenarioId);
|
||||
if (!normalizedScenarioId) {
|
||||
return null;
|
||||
}
|
||||
if (acceptanceCache.has(normalizedScenarioId)) {
|
||||
return acceptanceCache.get(normalizedScenarioId) ?? null;
|
||||
}
|
||||
const summary = findLatestAgentSemanticAcceptanceSummary({
|
||||
artifactsRootDir: path.resolve(ARTIFACTS_DIR, "domain_runs"),
|
||||
repoRootDir: PROJECT_ROOT,
|
||||
scenarioId: normalizedScenarioId
|
||||
});
|
||||
acceptanceCache.set(normalizedScenarioId, summary);
|
||||
return summary;
|
||||
};
|
||||
|
||||
return records.map((record) => {
|
||||
if (!isAgentSemanticHistoryRecord(record)) {
|
||||
return record;
|
||||
}
|
||||
const specSummary = readSpecSummary(record.context?.source_spec_file);
|
||||
const scenarioId = toStringSafe(record.context?.scenario_id) ?? specSummary?.scenario_id ?? null;
|
||||
const semanticTags =
|
||||
Array.isArray(record.context?.semantic_tags) && record.context?.semantic_tags.length > 0
|
||||
? Array.from(new Set(record.context?.semantic_tags.map((item) => String(item).trim()).filter((item) => item.length > 0)))
|
||||
: specSummary?.semantic_tags ?? [];
|
||||
const latestAcceptance = readAcceptanceSummary(scenarioId);
|
||||
return {
|
||||
...record,
|
||||
context: {
|
||||
...(record.context ?? {
|
||||
llm_provider: null,
|
||||
model: null,
|
||||
assistant_prompt_version: null,
|
||||
decomposition_prompt_version: null,
|
||||
prompt_fingerprint: null,
|
||||
autogen_personality_id: null,
|
||||
autogen_personality_prompt: null
|
||||
}),
|
||||
scenario_id: scenarioId,
|
||||
semantic_tags: semanticTags,
|
||||
latest_acceptance: latestAcceptance
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function readEvalDatasetCases(filePath: string): Array<Record<string, unknown>> {
|
||||
try {
|
||||
const parsed = JSON.parse(fs.readFileSync(filePath, "utf-8")) as unknown;
|
||||
@@ -2416,9 +2536,11 @@ export function buildAutoRunsRouter(services: AppServices, openaiClient = new Op
|
||||
const rawMode = toStringSafe((req.query as Record<string, unknown>).mode);
|
||||
const includeAllModes = !rawMode || !isAutoGenMode(rawMode);
|
||||
const modeFilter = (rawMode as AutoGenMode | null) ?? "codex_creative";
|
||||
const items = readAutoGenHistory()
|
||||
const items = hydrateAutoGenHistoryForApi(
|
||||
readAutoGenHistory()
|
||||
.filter((item) => (includeAllModes ? true : item.mode === modeFilter))
|
||||
.slice(0, limit);
|
||||
.slice(0, limit)
|
||||
);
|
||||
|
||||
ok(res, {
|
||||
ok: true,
|
||||
|
||||
@@ -0,0 +1,208 @@
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
|
||||
interface AgentSemanticSpecSummary {
|
||||
scenario_id: string;
|
||||
domain: string | null;
|
||||
title: string | null;
|
||||
semantic_tags: string[];
|
||||
steps_total: number;
|
||||
}
|
||||
|
||||
interface AgentSemanticInvariantSummary {
|
||||
direct_answer_ok: boolean | null;
|
||||
temporal_honesty_ok: boolean | null;
|
||||
selected_object_continuity_ok: boolean | null;
|
||||
truth_gate_ok: boolean | null;
|
||||
human_answer_quality_ok: boolean | null;
|
||||
meta_context_integrity_ok: boolean | null;
|
||||
}
|
||||
|
||||
export interface AgentSemanticAcceptanceSummary {
|
||||
scenario_id: string;
|
||||
output_dir: string;
|
||||
relative_output_dir: string;
|
||||
final_status: string | null;
|
||||
final_status_reason: string | null;
|
||||
review_overall_status: string | null;
|
||||
acceptance_gate_passed: boolean | null;
|
||||
critical_path_green: boolean | null;
|
||||
unresolved_p0_count: number | null;
|
||||
unresolved_p1_count: number | null;
|
||||
unresolved_p2_count: number | null;
|
||||
steps_total: number | null;
|
||||
steps_passed: number | null;
|
||||
steps_with_warning: number | null;
|
||||
steps_failed: number | null;
|
||||
updated_at: string | null;
|
||||
invariants: AgentSemanticInvariantSummary;
|
||||
}
|
||||
|
||||
function toRecord(value: unknown): Record<string, unknown> | null {
|
||||
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
||||
return null;
|
||||
}
|
||||
return value as Record<string, unknown>;
|
||||
}
|
||||
|
||||
function toStringSafe(value: unknown): string | null {
|
||||
if (typeof value !== "string") {
|
||||
return null;
|
||||
}
|
||||
const trimmed = value.trim();
|
||||
return trimmed.length > 0 ? trimmed : null;
|
||||
}
|
||||
|
||||
function toBooleanSafe(value: unknown): boolean | null {
|
||||
if (typeof value === "boolean") {
|
||||
return value;
|
||||
}
|
||||
if (typeof value === "string") {
|
||||
const lowered = value.trim().toLowerCase();
|
||||
if (["1", "true", "yes", "on"].includes(lowered)) return true;
|
||||
if (["0", "false", "no", "off"].includes(lowered)) return false;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function toNumberSafe(value: unknown): number | null {
|
||||
if (typeof value === "number" && Number.isFinite(value)) {
|
||||
return value;
|
||||
}
|
||||
if (typeof value === "string" && value.trim().length > 0) {
|
||||
const parsed = Number(value);
|
||||
return Number.isFinite(parsed) ? parsed : null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function readJsonFile(filePath: string): unknown {
|
||||
return JSON.parse(fs.readFileSync(filePath, "utf-8"));
|
||||
}
|
||||
|
||||
function normalizeSemanticTags(rawSteps: unknown): string[] {
|
||||
if (!Array.isArray(rawSteps)) {
|
||||
return [];
|
||||
}
|
||||
const tags = new Set<string>();
|
||||
for (const rawStep of rawSteps) {
|
||||
const step = toRecord(rawStep);
|
||||
if (!step || !Array.isArray(step.semantic_tags)) {
|
||||
continue;
|
||||
}
|
||||
for (const rawTag of step.semantic_tags) {
|
||||
const tag = toStringSafe(rawTag);
|
||||
if (tag) {
|
||||
tags.add(tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
return Array.from(tags).sort((left, right) => left.localeCompare(right));
|
||||
}
|
||||
|
||||
export function readAgentSemanticSpecSummaryFromFile(sourceSpecFile: string | null | undefined): AgentSemanticSpecSummary | null {
|
||||
const normalizedPath = toStringSafe(sourceSpecFile);
|
||||
if (!normalizedPath || !fs.existsSync(normalizedPath)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
const parsed = readJsonFile(normalizedPath);
|
||||
const record = toRecord(parsed);
|
||||
if (!record) {
|
||||
return null;
|
||||
}
|
||||
const scenarioId = toStringSafe(record.scenario_id);
|
||||
if (!scenarioId) {
|
||||
return null;
|
||||
}
|
||||
const semanticTags = normalizeSemanticTags(record.steps);
|
||||
return {
|
||||
scenario_id: scenarioId,
|
||||
domain: toStringSafe(record.domain),
|
||||
title: toStringSafe(record.title),
|
||||
semantic_tags: semanticTags,
|
||||
steps_total: Array.isArray(record.steps) ? record.steps.length : 0
|
||||
};
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function buildInvariantSummary(rawValue: unknown): AgentSemanticInvariantSummary {
|
||||
const record = toRecord(rawValue);
|
||||
return {
|
||||
direct_answer_ok: toBooleanSafe(record?.direct_answer_ok),
|
||||
temporal_honesty_ok: toBooleanSafe(record?.temporal_honesty_ok),
|
||||
selected_object_continuity_ok: toBooleanSafe(record?.selected_object_continuity_ok),
|
||||
truth_gate_ok: toBooleanSafe(record?.truth_gate_ok),
|
||||
human_answer_quality_ok: toBooleanSafe(record?.human_answer_quality_ok),
|
||||
meta_context_integrity_ok: toBooleanSafe(record?.meta_context_integrity_ok)
|
||||
};
|
||||
}
|
||||
|
||||
export function findLatestAgentSemanticAcceptanceSummary(input: {
|
||||
artifactsRootDir: string;
|
||||
repoRootDir: string;
|
||||
scenarioId: string | null | undefined;
|
||||
}): AgentSemanticAcceptanceSummary | null {
|
||||
const scenarioId = toStringSafe(input.scenarioId);
|
||||
if (!scenarioId) {
|
||||
return null;
|
||||
}
|
||||
if (!fs.existsSync(input.artifactsRootDir)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const candidates = fs
|
||||
.readdirSync(input.artifactsRootDir, { withFileTypes: true })
|
||||
.filter((entry) => entry.isDirectory() && entry.name.startsWith(`${scenarioId}_`))
|
||||
.map((entry) => {
|
||||
const outputDir = path.resolve(input.artifactsRootDir, entry.name);
|
||||
const packStatePath = path.resolve(outputDir, "pack_state.json");
|
||||
if (!fs.existsSync(packStatePath)) {
|
||||
return null;
|
||||
}
|
||||
const stats = fs.statSync(packStatePath);
|
||||
return {
|
||||
outputDir,
|
||||
packStatePath,
|
||||
mtimeMs: stats.mtimeMs
|
||||
};
|
||||
})
|
||||
.filter((item): item is { outputDir: string; packStatePath: string; mtimeMs: number } => item !== null)
|
||||
.sort((left, right) => right.mtimeMs - left.mtimeMs);
|
||||
|
||||
const latest = candidates[0];
|
||||
if (!latest) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
const parsed = readJsonFile(latest.packStatePath);
|
||||
const packState = toRecord(parsed);
|
||||
if (!packState) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
scenario_id: scenarioId,
|
||||
output_dir: latest.outputDir,
|
||||
relative_output_dir: path.relative(input.repoRootDir, latest.outputDir).replace(/\\/g, "/"),
|
||||
final_status: toStringSafe(packState.final_status),
|
||||
final_status_reason: toStringSafe(packState.final_status_reason),
|
||||
review_overall_status: toStringSafe(packState.review_overall_status),
|
||||
acceptance_gate_passed: toBooleanSafe(packState.acceptance_gate_passed),
|
||||
critical_path_green: toBooleanSafe(packState.critical_path_green),
|
||||
unresolved_p0_count: toNumberSafe(packState.unresolved_p0_count),
|
||||
unresolved_p1_count: toNumberSafe(packState.unresolved_p1_count),
|
||||
unresolved_p2_count: toNumberSafe(packState.unresolved_p2_count),
|
||||
steps_total: toNumberSafe(packState.steps_total),
|
||||
steps_passed: toNumberSafe(packState.steps_passed),
|
||||
steps_with_warning: toNumberSafe(packState.steps_with_warning),
|
||||
steps_failed: toNumberSafe(packState.steps_failed),
|
||||
updated_at: toStringSafe(packState.updated_at),
|
||||
invariants: buildInvariantSummary(packState.invariants)
|
||||
};
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
import fs from "fs";
|
||||
import os from "os";
|
||||
import path from "path";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import {
|
||||
findLatestAgentSemanticAcceptanceSummary,
|
||||
readAgentSemanticSpecSummaryFromFile
|
||||
} from "../src/services/agentSemanticRunRegistry";
|
||||
|
||||
const tempRoots: string[] = [];
|
||||
|
||||
function makeTempRoot(): string {
|
||||
const root = fs.mkdtempSync(path.join(os.tmpdir(), "agent-semantic-registry-"));
|
||||
tempRoots.push(root);
|
||||
return root;
|
||||
}
|
||||
|
||||
function writeJson(filePath: string, payload: unknown): void {
|
||||
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
||||
fs.writeFileSync(filePath, JSON.stringify(payload, null, 2), "utf-8");
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
while (tempRoots.length > 0) {
|
||||
const root = tempRoots.pop();
|
||||
if (root && fs.existsSync(root)) {
|
||||
fs.rmSync(root, { recursive: true, force: true });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
describe("agentSemanticRunRegistry", () => {
|
||||
it("reads scenario id and deduplicated semantic tags from the source spec", () => {
|
||||
const root = makeTempRoot();
|
||||
const specPath = path.resolve(root, "docs", "orchestration", "sample_agent_spec.json");
|
||||
writeJson(specPath, {
|
||||
scenario_id: "address_truth_harness_demo",
|
||||
domain: "address_demo",
|
||||
title: "Demo AGENT spec",
|
||||
steps: [
|
||||
{ step_id: "step_01", question: "привет", semantic_tags: ["meta_smalltalk", "meta_scope"] },
|
||||
{ step_id: "step_02", question: "остатки", semantic_tags: ["inventory_root", "meta_scope"] }
|
||||
]
|
||||
});
|
||||
|
||||
const summary = readAgentSemanticSpecSummaryFromFile(specPath);
|
||||
|
||||
expect(summary).toEqual({
|
||||
scenario_id: "address_truth_harness_demo",
|
||||
domain: "address_demo",
|
||||
title: "Demo AGENT spec",
|
||||
semantic_tags: ["inventory_root", "meta_scope", "meta_smalltalk"],
|
||||
steps_total: 2
|
||||
});
|
||||
});
|
||||
|
||||
it("picks the newest pack_state for the scenario and exposes acceptance summary", () => {
|
||||
const root = makeTempRoot();
|
||||
const artifactsRoot = path.resolve(root, "artifacts", "domain_runs");
|
||||
|
||||
const olderDir = path.resolve(artifactsRoot, "address_truth_harness_demo_live_20260417");
|
||||
const olderPackStatePath = path.resolve(olderDir, "pack_state.json");
|
||||
writeJson(olderPackStatePath, {
|
||||
final_status: "partial",
|
||||
final_status_reason: "review_failures_remaining",
|
||||
review_overall_status: "fail",
|
||||
acceptance_gate_passed: false,
|
||||
critical_path_green: false,
|
||||
unresolved_p0_count: 1,
|
||||
unresolved_p1_count: 0,
|
||||
unresolved_p2_count: 0,
|
||||
steps_total: 4,
|
||||
steps_passed: 2,
|
||||
steps_with_warning: 1,
|
||||
steps_failed: 1,
|
||||
updated_at: "2026-04-17T09:00:00+00:00",
|
||||
invariants: {
|
||||
direct_answer_ok: false,
|
||||
temporal_honesty_ok: true,
|
||||
selected_object_continuity_ok: false,
|
||||
truth_gate_ok: true,
|
||||
human_answer_quality_ok: true,
|
||||
meta_context_integrity_ok: true
|
||||
}
|
||||
});
|
||||
fs.utimesSync(olderPackStatePath, new Date("2026-04-17T09:00:00.000Z"), new Date("2026-04-17T09:00:00.000Z"));
|
||||
|
||||
const newerDir = path.resolve(artifactsRoot, "address_truth_harness_demo_live_20260417_rerun2");
|
||||
const newerPackStatePath = path.resolve(newerDir, "pack_state.json");
|
||||
writeJson(newerPackStatePath, {
|
||||
final_status: "accepted",
|
||||
final_status_reason: "scenario_acceptance_gate_passed",
|
||||
review_overall_status: "pass",
|
||||
acceptance_gate_passed: true,
|
||||
critical_path_green: true,
|
||||
unresolved_p0_count: 0,
|
||||
unresolved_p1_count: 0,
|
||||
unresolved_p2_count: 0,
|
||||
steps_total: 4,
|
||||
steps_passed: 4,
|
||||
steps_with_warning: 0,
|
||||
steps_failed: 0,
|
||||
updated_at: "2026-04-17T09:10:00+00:00",
|
||||
invariants: {
|
||||
direct_answer_ok: true,
|
||||
temporal_honesty_ok: true,
|
||||
selected_object_continuity_ok: true,
|
||||
truth_gate_ok: true,
|
||||
human_answer_quality_ok: true,
|
||||
meta_context_integrity_ok: true
|
||||
}
|
||||
});
|
||||
fs.utimesSync(newerPackStatePath, new Date("2026-04-17T09:10:00.000Z"), new Date("2026-04-17T09:10:00.000Z"));
|
||||
|
||||
const summary = findLatestAgentSemanticAcceptanceSummary({
|
||||
artifactsRootDir: artifactsRoot,
|
||||
repoRootDir: root,
|
||||
scenarioId: "address_truth_harness_demo"
|
||||
});
|
||||
|
||||
expect(summary).not.toBeNull();
|
||||
expect(summary?.final_status).toBe("accepted");
|
||||
expect(summary?.relative_output_dir).toBe("artifacts/domain_runs/address_truth_harness_demo_live_20260417_rerun2");
|
||||
expect(summary?.steps_passed).toBe(4);
|
||||
expect(summary?.unresolved_p0_count).toBe(0);
|
||||
expect(summary?.invariants.meta_context_integrity_ok).toBe(true);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user