mirror of
https://github.com/himanshudongre/smriti.git
synced 2026-08-28 05:14:59 +00:00
Harden lineage note indicator semantics
This commit is contained in:
parent
f8e5012f64
commit
91d93becfa
2 changed files with 74 additions and 11 deletions
|
|
@ -65,6 +65,16 @@ def _fork(client, space_id, checkpoint_id, branch_name="", provider="", model=""
|
|||
return r
|
||||
|
||||
|
||||
def _add_note(client, checkpoint_id, text, author="founder", kind="note"):
|
||||
r = client.post(f"/api/v5/checkpoint/{checkpoint_id}/notes", json={
|
||||
"text": text,
|
||||
"author": author,
|
||||
"kind": kind,
|
||||
})
|
||||
assert r.status_code == 201, r.text
|
||||
return r.json()
|
||||
|
||||
|
||||
# ── Fork tests ────────────────────────────────────────────────────────────────
|
||||
|
||||
def test_fork_creates_new_session(client):
|
||||
|
|
@ -357,6 +367,29 @@ def test_lineage_checkpoint_includes_author_agent(client):
|
|||
)
|
||||
|
||||
|
||||
def test_lineage_checkpoint_includes_note_summary(client):
|
||||
"""note_count and note_kinds round-trip through the lineage endpoint."""
|
||||
repo_id = _create_repo(client, "Lineage Note Summary")
|
||||
session_id = _create_session(client, repo_id)
|
||||
|
||||
mixed = _commit(client, repo_id, session_id, message="Checkpoint with mixed notes")
|
||||
plain = _commit(client, repo_id, session_id, message="Checkpoint without notes")
|
||||
|
||||
_add_note(client, mixed["id"], "Milestone note", kind="milestone")
|
||||
_add_note(client, mixed["id"], "Noise note", kind="noise")
|
||||
_add_note(client, mixed["id"], "Plain note", kind="note")
|
||||
|
||||
r = client.get(f"/api/v5/lineage/spaces/{repo_id}")
|
||||
assert r.status_code == 200, r.text
|
||||
checkpoints = r.json()["checkpoints"]
|
||||
by_id = {c["id"]: c for c in checkpoints}
|
||||
|
||||
assert by_id[mixed["id"]]["note_count"] == 3
|
||||
assert by_id[mixed["id"]]["note_kinds"] == ["milestone", "noise", "note"]
|
||||
assert by_id[plain["id"]]["note_count"] == 0
|
||||
assert by_id[plain["id"]]["note_kinds"] == []
|
||||
|
||||
|
||||
# ── Compare tests ─────────────────────────────────────────────────────────────
|
||||
|
||||
def test_compare_same_checkpoint(client):
|
||||
|
|
|
|||
|
|
@ -38,6 +38,42 @@ function fmt(d: string) {
|
|||
});
|
||||
}
|
||||
|
||||
function getCheckpointNoteBadge(checkpoint: CheckpointNode) {
|
||||
const kinds = checkpoint.note_kinds ?? [];
|
||||
const plural = checkpoint.note_count !== 1 ? 's' : '';
|
||||
const kindSummary = kinds.length > 0 ? kinds.join(' + ') : 'note';
|
||||
|
||||
if (kinds.length > 1) {
|
||||
return {
|
||||
label: 'mix',
|
||||
title: `${checkpoint.note_count} note${plural} · ${kindSummary}`,
|
||||
className: 'text-sky-300 bg-sky-950/30 border border-sky-500/30',
|
||||
};
|
||||
}
|
||||
|
||||
if (kinds.includes('milestone')) {
|
||||
return {
|
||||
label: '★',
|
||||
title: `${checkpoint.note_count} note${plural} · milestone`,
|
||||
className: 'text-amber-400 bg-amber-900/20 border border-amber-500/30',
|
||||
};
|
||||
}
|
||||
|
||||
if (kinds.includes('noise')) {
|
||||
return {
|
||||
label: '◌',
|
||||
title: `${checkpoint.note_count} note${plural} · noise`,
|
||||
className: 'text-gray-500 bg-gray-800/30 border border-gray-700',
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
label: '●',
|
||||
title: `${checkpoint.note_count} note${plural} · note`,
|
||||
className: 'text-gray-400 bg-gray-800/30 border border-gray-700',
|
||||
};
|
||||
}
|
||||
|
||||
// ── Compare Panel ─────────────────────────────────────────────────────────────
|
||||
|
||||
function ComparePanel({
|
||||
|
|
@ -296,6 +332,7 @@ function CheckpointCard({
|
|||
onFork: (c: CheckpointNode) => void;
|
||||
}) {
|
||||
const [expanded, setExpanded] = useState(false);
|
||||
const noteBadge = checkpoint.note_count > 0 ? getCheckpointNoteBadge(checkpoint) : null;
|
||||
|
||||
return (
|
||||
<div
|
||||
|
|
@ -320,19 +357,12 @@ function CheckpointCard({
|
|||
</span>
|
||||
)}
|
||||
<span className="text-[10px] text-gray-600">{fmt(checkpoint.created_at)}</span>
|
||||
{checkpoint.note_count > 0 && (
|
||||
{noteBadge && (
|
||||
<span
|
||||
className={`text-[9px] font-medium px-1 py-px rounded ${
|
||||
checkpoint.note_kinds.includes('milestone')
|
||||
? 'text-amber-400 bg-amber-900/20 border border-amber-500/30'
|
||||
: checkpoint.note_kinds.includes('noise')
|
||||
? 'text-gray-500 bg-gray-800/30 border border-gray-700'
|
||||
: 'text-gray-400 bg-gray-800/30 border border-gray-700'
|
||||
}`}
|
||||
title={`${checkpoint.note_count} note${checkpoint.note_count !== 1 ? 's' : ''}`}
|
||||
className={`text-[9px] font-medium px-1 py-px rounded ${noteBadge.className}`}
|
||||
title={noteBadge.title}
|
||||
>
|
||||
{checkpoint.note_kinds.includes('milestone') ? '★' :
|
||||
checkpoint.note_kinds.includes('noise') ? '◌' : '●'}
|
||||
{noteBadge.label}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue