Stage 3 Wave 1: lifecycle-слой встроен в pipeline

This commit is contained in:
2026-03-26 15:48:38 +03:00
parent 96353cfd48
commit d0b842adb0
59 changed files with 5132 additions and 154 deletions
@@ -13,6 +13,8 @@ import {
PROBLEM_UNIT_SCHEMA_VERSION,
PROBLEM_UNIT_SUMMARY_SCHEMA_VERSION
} from "../types/stage2ProblemUnits";
import { FEATURE_ASSISTANT_LIFECYCLE_RUNTIME_V1 } from "../config";
import { enrichProblemUnitLifecycle, rankLifecycleProblemUnits } from "./lifecycleRuntime";
type RetrievalResultType = "list" | "summary" | "object" | "chain" | "ranking";
@@ -486,6 +488,18 @@ function collapseSignature(unit: ProblemUnit): string {
return [unit.problem_unit_type, unit.business_defect_class, unit.failed_expected_edge ?? "none", backlink].join("|");
}
function preferredLifecycleSource(left: ProblemUnit, right: ProblemUnit): ProblemUnit {
const leftRank = left.lifecycle_ranking_score ?? 0;
const rightRank = right.lifecycle_ranking_score ?? 0;
if (rightRank > leftRank) {
return right;
}
if (leftRank > rightRank) {
return left;
}
return right.confidence.score > left.confidence.score ? right : left;
}
export function collapseDuplicates(units: ProblemUnit[]): {
problem_units: ProblemUnit[];
duplicate_collapses: number;
@@ -502,6 +516,7 @@ export function collapseDuplicates(units: ProblemUnit[]): {
}
duplicateCollapses += 1;
const preferredLifecycle = preferredLifecycleSource(existing, unit);
bySignature.set(signature, {
...existing,
evidence_pack: uniqueStrings([...existing.evidence_pack, ...unit.evidence_pack]),
@@ -521,7 +536,72 @@ export function collapseDuplicates(units: ProblemUnit[]): {
affected_contracts: uniqueStrings([...existing.affected_contracts, ...unit.affected_contracts]),
snapshot_limitations: uniqueStrings([...existing.snapshot_limitations, ...unit.snapshot_limitations]),
severity: unit.severity.score > existing.severity.score ? unit.severity : existing.severity,
confidence: unit.confidence.score > existing.confidence.score ? unit.confidence : existing.confidence
confidence: unit.confidence.score > existing.confidence.score ? unit.confidence : existing.confidence,
...(preferredLifecycle.lifecycle_domain
? {
lifecycle_domain: preferredLifecycle.lifecycle_domain
}
: {}),
...(preferredLifecycle.lifecycle_object_id
? {
lifecycle_object_id: preferredLifecycle.lifecycle_object_id
}
: {}),
...(preferredLifecycle.current_lifecycle_state
? {
current_lifecycle_state: preferredLifecycle.current_lifecycle_state
}
: {}),
...(preferredLifecycle.expected_lifecycle_state
? {
expected_lifecycle_state: preferredLifecycle.expected_lifecycle_state
}
: {}),
...(preferredLifecycle.missing_transition
? {
missing_transition: preferredLifecycle.missing_transition
}
: {}),
...(preferredLifecycle.invalid_transition
? {
invalid_transition: preferredLifecycle.invalid_transition
}
: {}),
...(preferredLifecycle.lifecycle_defect_type
? {
lifecycle_defect_type: preferredLifecycle.lifecycle_defect_type
}
: {}),
...(preferredLifecycle.stale_duration
? {
stale_duration: preferredLifecycle.stale_duration
}
: {}),
...(preferredLifecycle.lifecycle_confidence
? {
lifecycle_confidence: preferredLifecycle.lifecycle_confidence
}
: {}),
...(preferredLifecycle.business_lifecycle_interpretation
? {
business_lifecycle_interpretation: preferredLifecycle.business_lifecycle_interpretation
}
: {}),
...(preferredLifecycle.lifecycle_resolution
? {
lifecycle_resolution: preferredLifecycle.lifecycle_resolution
}
: {}),
...(preferredLifecycle.lifecycle_ranking_score !== undefined
? {
lifecycle_ranking_score: preferredLifecycle.lifecycle_ranking_score
}
: {}),
...(preferredLifecycle.lifecycle_ranking_basis
? {
lifecycle_ranking_basis: preferredLifecycle.lifecycle_ranking_basis
}
: {})
});
}
@@ -544,11 +624,21 @@ function buildSummary(units: ProblemUnit[], duplicateCollapses: number): Problem
medium: 0,
high: 0
};
const lifecycleDomainDistribution: NonNullable<ProblemUnitSummary["lifecycle_domain_distribution"]> = {};
const lifecycleDefectDistribution: NonNullable<ProblemUnitSummary["lifecycle_defect_distribution"]> = {};
let lifecycleEnrichedUnits = 0;
for (const unit of units) {
typeDistribution[unit.problem_unit_type] = (typeDistribution[unit.problem_unit_type] ?? 0) + 1;
severityDistribution[unit.severity.grade] += 1;
confidenceDistribution[unit.confidence.grade] += 1;
if (unit.lifecycle_domain) {
lifecycleEnrichedUnits += 1;
lifecycleDomainDistribution[unit.lifecycle_domain] = (lifecycleDomainDistribution[unit.lifecycle_domain] ?? 0) + 1;
}
if (unit.lifecycle_defect_type) {
lifecycleDefectDistribution[unit.lifecycle_defect_type] = (lifecycleDefectDistribution[unit.lifecycle_defect_type] ?? 0) + 1;
}
}
return {
@@ -559,7 +649,10 @@ function buildSummary(units: ProblemUnit[], duplicateCollapses: number): Problem
type_distribution: typeDistribution,
severity_distribution: severityDistribution,
confidence_distribution: confidenceDistribution,
primary_unit_type: units[0]?.problem_unit_type ?? null
primary_unit_type: units[0]?.problem_unit_type ?? null,
lifecycle_enriched_units: lifecycleEnrichedUnits,
lifecycle_domain_distribution: lifecycleDomainDistribution,
lifecycle_defect_distribution: lifecycleDefectDistribution
};
}
@@ -580,13 +673,24 @@ export function assembleProblemUnits(input: AssembleProblemUnitsInput): {
risk_factors: uniqueStrings(input.risk_factors ?? [])
});
const clusters = clusterCandidateEvidence(candidates);
const units = clusters.map((cluster, index) => buildProblemUnit(cluster, index));
const units = clusters.map((cluster, index) => {
const baseUnit = buildProblemUnit(cluster, index);
if (!FEATURE_ASSISTANT_LIFECYCLE_RUNTIME_V1) {
return baseUnit;
}
return enrichProblemUnitLifecycle({
unit: baseUnit,
candidates: cluster.candidates
});
});
const collapsed = collapseDuplicates(units);
const rankedUnits = FEATURE_ASSISTANT_LIFECYCLE_RUNTIME_V1
? rankLifecycleProblemUnits(collapsed.problem_units)
: collapsed.problem_units;
return {
candidate_evidence: candidates,
problem_units: collapsed.problem_units,
problem_unit_summary: buildSummary(collapsed.problem_units, collapsed.duplicate_collapses)
problem_units: rankedUnits,
problem_unit_summary: buildSummary(rankedUnits, collapsed.duplicate_collapses)
};
}