Files
proffesor-for-testing__agen…/src/shared/c4-model/confidence.ts
T
Dragan Spiridonov 9fd18ed00a feat(code-intelligence): first-class C4 architecture diagrams (ADR-112)
Consolidate C4 diagram generation onto a single engine and expose it to
users via CLI and MCP, with a deterministic confidence gate and real
Knowledge-Graph-derived relationships.

- Consolidation (C1/C6): C4ModelService is the single render/analyze/store
  engine; the bridge delegates and FAILS LOUD on a render error instead of
  silently degrading. Duplicate inline generators removed.
- C2: real component relationships from the Knowledge Graph (AST import/call
  edges) replace the naming heuristic; project-scoped via a new KG basePath
  so repos outside cwd don't trip the path-traversal guard.
- C3: deterministic confidence gate (high/medium/low + reasons) on every
  diagram — surfaces the detector's known limits instead of hiding them.
- C4/C5: `aqe code c4` CLI + `qe/code/c4` MCP tool (generate/search),
  verified at MCP-CLI parity and through the protocol-server bridge.
- Search: generate persists embeddings (opt-in `enableC4Embeddings`, on for
  MCP) so `qe/code/c4 search` returns hits in the standard flow.
- Fixed pre-existing lint in touched files (require->import, unused catches).

Docs: ADR-112 + docs/guides/c4-architecture-diagrams.md. tsc + lint clean;
C4 surface fully green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 11:27:25 +00:00

104 lines
3.9 KiB
TypeScript

/**
* ADR-112 — Deterministic C4 confidence gate.
*
* Pure, code-only (NO LLM in the gate — same discipline as ADR-111's accept
* gate). Turns the code-intelligence detector's known limits (the
* qe-code-intelligence skill records ~18% success on complex queries and
* degradation above ~50K LOC) into an explicit, surfaced signal so a
* confident-but-wrong diagram is never presented as ground truth.
*/
export type C4Confidence = 'high' | 'medium' | 'low';
export interface C4ConfidenceInputs {
/** Number of components the detector found. */
componentsDetected: number;
/** Number of component relationships (edges) detected. */
relationshipsDetected: number;
/** Number of external systems detected. */
externalSystemsDetected: number;
/** Number of source files analyzed. */
filesAnalyzed: number;
/** Total lines of code, if known (e.g. from MetricCollector). Optional. */
totalLoc?: number;
}
export interface C4ConfidenceAssessment {
/** Bucketed level for quick display. */
level: C4Confidence;
/** Continuous score in [0,1] the level is derived from. */
score: number;
/** Human-readable reasons (always populated). */
reasons: string[];
}
/** Repo size (LOC) beyond which the skill records detection degradation. */
export const C4_LOC_DEGRADE_THRESHOLD = 50_000;
const clamp01 = (x: number) => Math.max(0, Math.min(1, x));
/**
* Assess how much to trust an auto-generated C4 diagram. Deterministic: the same
* inputs always yield the same level + reasons.
*/
export function assessC4Confidence(inputs: C4ConfidenceInputs): C4ConfidenceAssessment {
const { componentsDetected, relationshipsDetected, externalSystemsDetected, totalLoc } = inputs;
const reasons: string[] = [];
// Empty diagram — nothing to trust.
if (componentsDetected === 0) {
return {
level: 'low',
score: 0,
reasons: ['No components detected — the diagram is effectively empty; verify against the source.'],
};
}
let score = 0.5;
// Relationships are the weakest link in heuristic detection. Their presence is
// the strongest signal that the STRUCTURE (not just a node list) is real.
const relDensity = relationshipsDetected / Math.max(1, componentsDetected);
if (relationshipsDetected === 0 && componentsDetected > 1) {
score -= 0.25;
reasons.push('No relationships detected between components — edges are heuristic-only or missing; the structure is unverified.');
} else if (relDensity >= 0.5) {
score += 0.2;
reasons.push(`${relationshipsDetected} relationship(s) detected across ${componentsDetected} components.`);
} else {
score += 0.05;
reasons.push(`${relationshipsDetected} relationship(s) detected (sparse) across ${componentsDetected} components.`);
}
// External systems detected → the Platform/Interfaces picture is grounded.
if (externalSystemsDetected > 0) {
score += 0.1;
reasons.push(`${externalSystemsDetected} external system(s) detected from dependencies.`);
}
// Repo size vs the known degradation threshold.
if (totalLoc !== undefined && totalLoc > C4_LOC_DEGRADE_THRESHOLD) {
score -= 0.3;
reasons.push(
`Repository is large (${totalLoc.toLocaleString()} LOC > ~${C4_LOC_DEGRADE_THRESHOLD / 1000}K) — detection accuracy degrades; treat the diagram as a draft.`,
);
}
// A healthy component count adds confidence; a single component is thin.
if (componentsDetected >= 5) {
score += 0.1;
} else if (componentsDetected === 1) {
score -= 0.05;
reasons.push('Only one component detected — likely an under-segmented view.');
}
score = clamp01(score);
const level: C4Confidence = score >= 0.7 ? 'high' : score >= 0.4 ? 'medium' : 'low';
if (level !== 'high' && !reasons.some((r) => r.includes('draft') || r.includes('verify'))) {
reasons.push('Auto-generated draft — verify against the source before relying on it.');
}
return { level, score: Math.round(score * 1000) / 1000, reasons };
}