refactor(forge): classify account notifications beside the vocabulary
The triage mapped the forges' notification reasons onto the claw's verdicts, but it co-evolves with the vocabulary, not with the claw: a reason that enters it (Gitea's collapsed shape) needs a verdict in the same change, and its tests pin the mapping against the vocabulary's own types. It now lives in the integration crate as the default classification; a consumer may reclassify on top. The claw imports it like the rest of the forge seam.
This commit is contained in:
1 parent
5fdd17b901
commit
fc0cbbcb6b
5 files changed
+22
-17
No files matched your search
@@ -6,7 +6,7 @@
|
||||
//! list_account_watches`] — and loops the kind's repos through a
|
||||
//! [`Watcher`] (poll, ingest, advance the per-repo cursor), then the
|
||||
//! kind's account watches through the identity store's credentials:
|
||||
//! poll the account's notifications, [`crate::triage::classify`] each
|
||||
//! poll the account's notifications, [`triage::classify`] each
|
||||
//! one, and either ingest it as a role-tagged thread event, surface it
|
||||
//! to the account's human, or drop it. Neither pass touches the model
|
||||
//! (spec §1). Reading the tables every pass is what makes a watch added
|
||||
@@ -23,6 +23,7 @@ use std::sync::{Arc, Mutex, PoisonError};
|
||||
|
||||
use rhema_autonomous_agent::{Source, SourceError, async_trait};
|
||||
use rhema_forge_integration::forge_key_fn;
|
||||
use rhema_forge_integration::triage::{self, Triage};
|
||||
use rhema_forge_integration::{
|
||||
Forge, GitHubForge, GitLabForge, GiteaForge, Notification, Watcher, register_forge,
|
||||
};
|
||||
@@ -30,7 +31,6 @@ use rhema_identity::{IdentityStore, SecretKind};
|
||||
use rhema_rsd::{Clock, Dispatcher, Event, KeyFn, SystemClock};
|
||||
|
||||
use crate::config::{ForgeKind, resolve_token};
|
||||
use crate::triage::{self, Triage};
|
||||
use crate::watch_store::{AccountWatchRecord, ClawStore, WatchRecord};
|
||||
|
||||
/// The cache key of a forge client: everything that changes the client
|
||||
|
||||
@@ -25,12 +25,12 @@ use std::sync::{Arc, Mutex, PoisonError};
|
||||
|
||||
use crate::config::ForgeKind;
|
||||
use crate::forge::{record_client, resolve_watch_token};
|
||||
use crate::triage::Role;
|
||||
use crate::watch_store::ClawStore;
|
||||
use rhema_agent_tools::AllowAll;
|
||||
use rhema_autonomous_agent::{Handler, SessionContext, async_trait};
|
||||
use rhema_coding_agent::{CodingAgent, CodingAgentConfig};
|
||||
use rhema_core::{Content, Event as ModelEvent, EventSink, Message, Session};
|
||||
use rhema_forge_integration::triage::Role;
|
||||
use rhema_forge_integration::{
|
||||
EventKind, Forge, ForgeError, ForgeEvent, Notification, RepoRef, Snapshot, ThreadState, decode,
|
||||
parse_key,
|
||||
|
||||
@@ -94,7 +94,6 @@ pub mod settings;
|
||||
pub mod task_source;
|
||||
pub mod task_store;
|
||||
pub mod task_tools;
|
||||
pub mod triage;
|
||||
pub mod turn_store;
|
||||
pub mod watch_store;
|
||||
pub mod watch_tools;
|
||||
|
||||
@@ -41,6 +41,9 @@
|
||||
//! - [`watcher`] — the dispatcher seam: polls a forge into an RSD
|
||||
//! `Dispatcher` (keys, dedup, cursors) and decodes delivered inbox
|
||||
//! items back into forge events
|
||||
//! - [`triage`] — what an account notification earns: the default
|
||||
//! classification of the notification vocabulary into agent
|
||||
//! dispatches, surfaces, and drops
|
||||
|
||||
#![forbid(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
@@ -51,6 +54,7 @@ pub mod forge;
|
||||
pub mod gitea;
|
||||
pub mod github;
|
||||
pub mod gitlab;
|
||||
pub mod triage;
|
||||
pub mod watcher;
|
||||
|
||||
// Re-exported so implementors of the async seam can apply #[async_trait]
|
||||
@@ -65,6 +69,7 @@ pub use forge::{Forge, ForgePage};
|
||||
pub use gitea::GiteaForge;
|
||||
pub use github::GitHubForge;
|
||||
pub use gitlab::GitLabForge;
|
||||
pub use triage::{Role, Triage};
|
||||
pub use watcher::{
|
||||
WatchError, Watcher, decode, forge_key_fn, parse_key, register_forge, resource_key,
|
||||
};
|
||||
+14
-13
@@ -1,23 +1,24 @@
|
||||
//! The triage: what a notification earns, decided deterministically
|
||||
//! before any model call (spec §1 — the model is never the detector).
|
||||
//! The notification triage: what a notification earns, decided
|
||||
//! deterministically before any model call.
|
||||
//!
|
||||
//! A [`Notification`] carries the forge's own reason for bothering the
|
||||
//! account; [`classify`] reduces it to one of three verdicts. An
|
||||
//! account; [`classify`] reduces it to one of three verdicts. A
|
||||
//! [`Triage::Agent`] dispatch becomes an RSD event whose payload names
|
||||
//! the [`Role`] — the persona the handler's prompt opens with, so one
|
||||
//! thread can move from review-requested to implement-feedback across
|
||||
//! dispatches with the session carrying the continuity. A
|
||||
//! [`Triage::Surface`] never dispatches an agent: a mention is not a
|
||||
//! assignment, and the account's human hears about it through the
|
||||
//! device-notification queue instead. [`Triage::Ignore`] drops the noise
|
||||
//! (CI churn) on the floor.
|
||||
//! [`Triage::Surface`] never dispatches an agent: a mention is not an
|
||||
//! assignment, and the account's human hears about it some other way.
|
||||
//! [`Triage::Ignore`] drops the noise (CI churn) on the floor.
|
||||
//!
|
||||
//! The mapping is a pure function and this module's tests pin it: the
|
||||
//! forges' vocabularies are external data, and the policy must not drift
|
||||
//! with them.
|
||||
//! The mapping lives beside the vocabulary on purpose: a reason that
|
||||
//! enters it (Gitea's collapsed shape, a new adapter's spelling) needs
|
||||
//! a verdict in the same change, and this module's tests pin the
|
||||
//! mapping so the co-edit cannot drift. A consumer may reclassify on
|
||||
//! top — [`classify`] is the default, not a mandate.
|
||||
|
||||
use rhema_forge_integration::gitea::COLLAPSED_REASON;
|
||||
use rhema_forge_integration::{Notification, NotificationReason};
|
||||
use crate::gitea::COLLAPSED_REASON;
|
||||
use crate::{Notification, NotificationReason};
|
||||
|
||||
/// The agent persona a dispatched notification runs as. The key stays
|
||||
/// the thread — one session, one voice per thread, ever — and the role
|
||||
@@ -83,7 +84,7 @@ pub fn classify(notification: &Notification) -> Triage {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use rhema_forge_integration::{RepoRef, Timestamp};
|
||||
use crate::{RepoRef, Timestamp};
|
||||
|
||||
fn notification(reason: NotificationReason) -> Notification {
|
||||
Notification {
|
||||
Reference in new issue
Block a user