feat(#70): IMP-41 application_mode forwarding to FramePanel V4 badge tooltip (u1~u5)
Forward backend Step 9 `unit.application_candidates[]` (application_mode /
auto_applicable / delegated_to) onto FrameCandidate and surface the
application_mode as a Korean consequence phrase in the FramePanel V4-label
inline badge tooltip. Deterministic frontend-only refactor; no LLM call,
no V4-label color change, no outer composedTitle change.
u1: types/designAgent.ts — add optional applicationMode / autoApplicable /
delegatedTo on FrameCandidate (legacy fixtures keep undefined).
u2: services/applicationMode.ts (new) — pure helper exporting
ApplicationMode union, APPLICATION_MODE_TOOLTIP_KR (keyed by backend
mode VALUE, NOT V4 label), buildBadgeTitle, mergeApplicationCandidates.
u3: tests/imp41_application_mode.test.ts (new) — 13 Vitest cases pinning
composite output per mode, undefined/unknown→legacy fallback, merge by
template_id, skip missing/empty/non-string keys, first-wins on dupes,
empty/null/non-array input.
u4: services/designAgentApi.ts — bridge consumes mergeApplicationCandidates
and forwards three fields onto FrameCandidate while preserving
LABEL_PRIORITY sort and TOP_N_FRAMES slicing.
u5: components/FramePanel.tsx — V4-label badge `title` now calls
`buildBadgeTitle(candidate.label, candidate.applicationMode)`;
badge color className map preserved verbatim; outer composedTitle
untouched.
Scope-qualified verification (5 files, IMP-41 axis only):
- Vitest: client/tests/imp41_application_mode.test.ts — 13/13 PASS.
- Diff↔Plan parity: 5 files match Stage 2 plan, no scope creep.
- AI-isolation contract honored: tooltip values originate from backend
enum; no frontend re-derivation from V4 label.
- No spacing/font shrink; clipping resolution stays at layout/zone/frame
layer (feedback_phase_z_spacing_direction).
Pre-existing unrelated diagnostics (BottomActions.tsx,
imp47b_human_review_toast.test.tsx) remain open on their own axes and are
not gated by this commit.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -20,6 +20,8 @@ import {
|
||||
MOCK_FRAME_CANDIDATES_SECTION1,
|
||||
} from "../data/mockDesignAgentData";
|
||||
|
||||
import { mergeApplicationCandidates } from "./applicationMode";
|
||||
|
||||
/** 네트워크 지연 시뮬레이션 */
|
||||
const simulateDelay = (ms: number = 800) =>
|
||||
new Promise((resolve) => setTimeout(resolve, ms));
|
||||
@@ -527,9 +529,20 @@ export async function loadRun(runId: string): Promise<LoadRunResult> {
|
||||
if (lp !== 0) return lp;
|
||||
return (b.confidence ?? 0) - (a.confidence ?? 0);
|
||||
});
|
||||
// ─── IMP-41 u4 — application_candidates enrichment (issue #70) ───────────
|
||||
// Backend Step 9 emits `unit.application_candidates[]` (src/phase_z2_pipeline.py
|
||||
// _application_candidates_for_unit, :3071-3092) one entry per v4 candidate with
|
||||
// application_mode / auto_applicable / delegated_to derived from
|
||||
// APPLICATION_MODE_BY_V4_LABEL (:107-112). Indexing delegated to the pure
|
||||
// helper `mergeApplicationCandidates` (services/applicationMode.ts) keyed
|
||||
// by template_id. Enrichment ONLY — does NOT alter candidate source
|
||||
// priority, sorting, or TOP_N_FRAMES slicing.
|
||||
const applicationModeMap = mergeApplicationCandidates(unit.application_candidates);
|
||||
const frameCandidates: FrameCandidate[] = v4Source
|
||||
.slice(0, TOP_N_FRAMES)
|
||||
.map((c: any) => ({
|
||||
.map((c: any) => {
|
||||
const appMatch = applicationModeMap.get(c.template_id);
|
||||
return ({
|
||||
id: c.template_id,
|
||||
name: c.template_id,
|
||||
score: c.confidence ?? 0,
|
||||
@@ -559,7 +572,15 @@ export async function loadRun(runId: string): Promise<LoadRunResult> {
|
||||
decision: c.decision,
|
||||
reason: c.reason,
|
||||
capacityFit: c.capacity_fit,
|
||||
}));
|
||||
// ─── IMP-41 u2 — application_mode forwarding (issue #70) ───────────
|
||||
// Source = unit.application_candidates[] indexed by template_id above.
|
||||
// Optional fields — undefined when no matching application_candidate
|
||||
// (legacy fixtures pre-IMP-32 or candidates filtered out at Step 9).
|
||||
applicationMode: appMatch?.application_mode,
|
||||
autoApplicable: appMatch?.auto_applicable,
|
||||
delegatedTo: appMatch?.delegated_to ?? null,
|
||||
});
|
||||
});
|
||||
|
||||
const displayStrategy = (
|
||||
runMeta.display_strategy_candidates_by_zone[posEntry.name]?.[0] ??
|
||||
|
||||
Reference in New Issue
Block a user