feat(#2635): wire harness-local questions mirror (inc2 pt2)

This commit is contained in:
damocles 2026-07-23 21:10:51 +02:00 committed by mara
commit e5ef5a72be
8 changed files with 465 additions and 191 deletions

View file

@ -1,33 +1,30 @@
//! Harness-local questions mirror — increment 2 part 2 of #2635 (see the
//! design comment on the issue). c0re stays the `Ask`/`Answer` routing +
//! delivery rendezvous (mara's "2a" call); this store only holds the
//! *durable "I still owe/am owed a reply" view* `get_loose_ends` renders,
//! so that view survives a hive migration the same way todos/reminders
//! already do.
//! Harness-local questions mirror — the second increment of the
//! loose-ends-v2 migration's questions phase (see the design comment on
//! the tracking issue). c0re stays the `Ask`/`Answer` routing + delivery
//! rendezvous (mara's "2a" call); this store only holds the *durable "I
//! still owe/am owed a reply" view* `get_loose_ends` renders, so that view
//! survives a hive migration the same way todos/reminders already do.
//!
//! One row per outstanding question **from this agent's point of view**,
//! keyed by the c0re-assigned question id (globally unique, so `id` alone
//! is the primary key — an agent is never both asker and target of the
//! same question, self-asks are rejected at the c0re layer):
//! keyed by the c0re-assigned question id (globally unique — an agent is
//! never both asker and target of the same question, self-asks are
//! rejected at the c0re layer):
//!
//! - `role = "asked"`: this agent called `ask()`; `peer` is the target
//! (`"operator"` when asked with `to: None`). Cleared when the
//! `question_answered` system event for `id` arrives in this agent's
//! inbox (see `main.rs`'s inbound-event hook).
//! `question_answered` system event for `id` arrives (see `main.rs`'s
//! inbound-event hook).
//! - `role = "answering"`: this agent received a `question_asked` system
//! event for `id`; `peer` is the asker. Cleared when this agent calls
//! `answer()` for `id` (see `hive-agent-mcp`'s tool impl).
//!
//! Known gap: if the asker cancels their own question
//! (`cancel_loose_end` kind `"question"`), the target is not notified
//! today (`hive-c0re::questions::handle_cancel_loose_end` only notifies
//! a *different* canceller than the asker, which never happens on the
//! agent-socket path since cancel is ownership-gated to the asker). A
//! target's `answering` row then lingers until they call `answer()`
//! (which now returns a "no such question" error from c0re rather than
//! silently succeeding) or the row goes stale. Flagged on #2635 rather
//! than fixed here — fixing it means teaching `handle_cancel_loose_end`
//! to also notify the target, a small but separate change.
//! Known gap: if the asker cancels their own question, the target is not
//! notified today (`hive-c0re::questions::handle_cancel_loose_end` only
//! notifies a *different* canceller than the asker, which never happens
//! via the ownership-gated agent-socket cancel path). A target's
//! `answering` row then lingers until they call `answer()` (now a "no
//! such question" error from c0re) or the row goes stale. Flagged on the
//! tracking issue rather than fixed here.
use std::path::Path;
use std::sync::Mutex;