a surface can ask Nexus for the id behind a name (V-511)

blocked_on stores a canonical entity id, so the form that fills it needs a way
to turn "Kate" into one. ipc.ResolveEntity is that seam: the store adapter
refuses it, because identity is not the store's to answer, and the daemon
overrides it with the Nexus client the voice path already holds.

Three outcomes are kept apart, because a caller deciding whether to store an
id has to tell them apart. No nexus block is ErrNotImplemented. A miss is
ErrNoEntity. Several matches come back Ambiguous with the names, and the
caller asks — picking one is how a task ends up blocked on the wrong person
with nobody able to see it happened.

An outage stays the transport error. "There is no such person" and "Nexus is
down" must not read the same.
This commit is contained in:
2026-08-05 20:42:28 +04:00
parent 43b0c32154
commit cb350efb19
9 changed files with 111 additions and 0 deletions
+7
View File
@@ -142,6 +142,13 @@ type TaskAPI interface {
// SetTaskStatus moves a task forward once: candidate→open|dropped,
// open→done|dropped. Any other move is refused.
SetTaskStatus(ctx context.Context, id int64, status string, ts time.Time, by string) error
// ResolveEntity asks Nexus for the canonical id behind a name. It is how a
// surface turns "Kate" into an entity id before storing one, because
// identity lives in Nexus and a local name is a second answer to a
// question Nexus already owns. ErrNotImplemented when no Nexus is
// configured, ErrNoEntity when the name matched nothing, and an Ambiguous
// ref when it matched several — the caller asks, it does not pick.
ResolveEntity(ctx context.Context, query string, types []string) (EntityRef, error)
// EditTask rewrites the three fields capture set: text, due date and
// weight. Status is not among them — that ladder is one-way and belongs to
// SetTaskStatus. A resolved task is refused, and a text edit that would