{t("Authorized scope")}
+{error}
} {!post && !error &&{t("Loading...")}
} {post && ( <> -{post.voc_type_label ?? post.voc_type_code} ·{" "} {post.visibility_label ?? post.visibility_code} ·{" "} @@ -1929,63 +2256,481 @@ function PostDetailPopup({ {liveBodyWarning}
) : null} -- {t("Source body was not imported; summary and semantic extraction are unavailable.")} -
- )} -+ {t("Last saved summary shown. Retry semantic refresh.")} {" "} + +
) : null} - {post.source_detail_state_code ? ( +{summary.korean_summary}
+ {(summary.key_event_details?.length ?? summary.key_events.length) > 0 && ( <> -{t("Raw source codes are shown; no state label was inferred.")}
+ {post.source_lineage_hints ? ( ++ {sourceLineageContextLabel(post.source_lineage_hints)}{" "} + {t("Combination code")}: {post.source_lineage_hints.combination_code}{" "} + {t("Inferred from field presence")} +
+{t("Field combination")}
++ {t("Lifecycle vector")}: {post.source_lineage_hints.lifecycle_vector} · {t("Raw codes only")} +
+- {t("Last saved summary shown. Retry semantic refresh.")} {" "} - -
- ) : null} -{summary.korean_summary}
- {(summary.key_event_details?.length ?? summary.key_events.length) > 0 && ( - <> -{summaryError}
+{t("No summary is available for this record yet.")}
++ {t("Source body was not imported; summary and semantic extraction are unavailable.")} +
)}- Connect a TEPP transport from this Failed row. Request a lineage - reconstruction does not invent a measurement. + {selected.run_kind_code === "analysis_run_topic_lineage" + ? "Connect a topic-lineage transport from this Failed row. Request a " + + "lineage reconstruction does not invent a topic model." + : "Connect a TEPP transport from this Failed row. Request a lineage " + + "reconstruction does not invent a measurement."}
)} {analysisRunReportPeriod(selected) && onSelectReportPeriod && ( @@ -3566,19 +4231,81 @@ function ReportsPanel({ ); } -const POST_PAGE_SIZE = 50; -type BoardSortOrder = PostSortOrder; +const POST_PAGE_SIZE = 50; +type BoardSortOrder = PostSortOrder; + +const VOC_TYPE_PRESENTATIONS: Record{t("Search includes post text and semantic evidence.")}
- - - - {hasBoardFilters && ( - - )} +@@ -3915,7 +4772,11 @@ function PostList({
) : ({t("Authorized customer scope")}
+{t("Customer scope")}
{t("Customer entities available to this account.")}
+{t("Customer entities available to this account.")}
{error ?{error}
: null} {master === null && !error ?{t("Loading customer master...")}
: null} {master?.corporate_entities.length === 0 ? ({t("No customer entities are connected to this account.")}
) : null} + + {searchedHintCode && master && master.source_customer_hints.length === 0 ? ( ++ {tf("No source customer evidence matches {code}.", { code: searchedHintCode })} +
+ ) : null} {master && master.corporate_entities.length > 0 ? ( + + ) : null} + {master && master.corporate_entities.length > 0 && filteredEntities.length === 0 ? ( ++ {t("No entities match the current scope filter.")} +
+ ) : null} + {filteredEntities.length > 0 ? (+
{t("A counterparty can hold more than one role over time -- a customer in one post can be a competitor, supplier, or partner in another. Every role observed for a name is listed, not just the most frequent.")}
+
{t("Source identifiers are hints only; ontology and semantic evidence must resolve them before binding a customer.")}
{master.source_customer_hints.length > HINT_RENDER_LIMIT && ( @@ -4466,7 +5464,30 @@ function CustomerMasterPanel({ ); } -function AskAgentPanel({ +type AskAgentExchange = { + id: string; + question: string; + status: "pending" | "complete" | "error"; + response?: AskAgentResponse; + error?: string; +}; + +const ASK_AGENT_STARTERS = [ + "What happened between these events?", + "Who is involved?", + "What is the next commitment?", +] as const; + +function toAskAgentExchanges(conversation: Awaited{t("Evidence-grounded questions")}
-{t("Questions use authorized posts and their evidence.")}
- {error ?{error}
: null} - - - {answer && ( -{answer.answer_text}
: null} - {answer.next_action ?{t(answer.next_action)}
: null} - {answer.cited_posts && answer.cited_posts.length > 0 && ( - <> -