feat(ui): show merged-into-parent badge on adopted observations

ObservationCard renders a secondary "merged → <parent>" chip when
merged_into_project is set, next to the existing project label.
Both are meaningful: project is origin provenance, merged_into_project
is the current home.

Extends PaginationHelper's observations and summaries queries with
OR merged_into_project = ? so the single-project viewer fetch pulls
in adopted rows — the plan's Phase 3 covered multi-project context
injection; this is the single-project UI read path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Alex Newman
2026-04-16 19:33:47 -07:00
parent 5664fabce4
commit bce4ce32ec
5 changed files with 29 additions and 4 deletions
+1
View File
@@ -124,6 +124,7 @@ export interface Observation {
id: number; id: number;
memory_session_id: string; // Renamed from sdk_session_id memory_session_id: string; // Renamed from sdk_session_id
project: string; project: string;
merged_into_project: string | null;
platform_source: string; platform_source: string;
type: string; type: string;
title: string; title: string;
+9 -4
View File
@@ -80,6 +80,7 @@ export class PaginationHelper {
o.id, o.id,
o.memory_session_id, o.memory_session_id,
o.project, o.project,
o.merged_into_project,
COALESCE(s.platform_source, 'claude') as platform_source, COALESCE(s.platform_source, 'claude') as platform_source,
o.type, o.type,
o.title, o.title,
@@ -100,8 +101,10 @@ export class PaginationHelper {
const conditions: string[] = []; const conditions: string[] = [];
if (project) { if (project) {
conditions.push('o.project = ?'); // Include adopted merged-worktree rows so the parent project's view
params.push(project); // surfaces observations that originated under its merged children.
conditions.push('(o.project = ? OR o.merged_into_project = ?)');
params.push(project, project);
} }
if (platformSource) { if (platformSource) {
conditions.push(`COALESCE(s.platform_source, 'claude') = ?`); conditions.push(`COALESCE(s.platform_source, 'claude') = ?`);
@@ -156,8 +159,10 @@ export class PaginationHelper {
const conditions: string[] = []; const conditions: string[] = [];
if (project) { if (project) {
conditions.push('ss.project = ?'); // Include adopted merged-worktree summaries so the parent project's view
params.push(project); // surfaces rows that originated under its merged children.
conditions.push('(ss.project = ? OR ss.merged_into_project = ?)');
params.push(project, project);
} }
if (platformSource) { if (platformSource) {
+13
View File
@@ -1130,6 +1130,19 @@
color: var(--color-text-muted); color: var(--color-text-muted);
} }
/* Merged-into-parent provenance badge */
.card-merged-badge {
padding: 1px 6px;
border-radius: 3px;
font-size: 9px;
font-weight: 500;
letter-spacing: 0.02em;
color: var(--color-text-muted);
background: var(--color-type-badge-bg);
border: 1px solid var(--color-border);
opacity: 0.85;
}
.summary-card { .summary-card {
border-color: var(--color-border-summary); border-color: var(--color-border-summary);
background: var(--color-bg-summary); background: var(--color-bg-summary);
@@ -56,6 +56,11 @@ export function ObservationCard({ observation }: ObservationCardProps) {
{observation.platform_source || 'claude'} {observation.platform_source || 'claude'}
</span> </span>
<span className="card-project">{observation.project}</span> <span className="card-project">{observation.project}</span>
{observation.merged_into_project && (
<span className="card-merged-badge" title={`Merged into ${observation.merged_into_project}`}>
merged {observation.merged_into_project}
</span>
)}
</div> </div>
<div className="view-mode-toggles"> <div className="view-mode-toggles">
{hasFactsContent && ( {hasFactsContent && (
+1
View File
@@ -2,6 +2,7 @@ export interface Observation {
id: number; id: number;
memory_session_id: string; memory_session_id: string;
project: string; project: string;
merged_into_project?: string | null;
platform_source: string; platform_source: string;
type: string; type: string;
title: string | null; title: string | null;