diff --git a/crates/codeoid-protocol/src/session.rs b/crates/codeoid-protocol/src/session.rs index 1384456..6a46180 100644 --- a/crates/codeoid-protocol/src/session.rs +++ b/crates/codeoid-protocol/src/session.rs @@ -162,6 +162,21 @@ pub struct CollaborationRole { /// to. Write authority is opt-in per role. #[serde(default, skip_serializing_if = "Option::is_none")] pub write: Option, + /// Goal-blackboard artifact kinds this role may READ — `spec`, `research`, + /// `adr`, `task-list`, `diff`, `findings`, or `extra/`. + /// + /// `None` = the daemon's default profile for this role name; a role with no + /// profile and no declaration reads nothing. This is what makes reviewer + /// independence structural: `review` reads `diff`+`spec` and NOT + /// `research` or its peers' `findings`. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub reads: Option>, + /// Artifact kinds this role may WRITE. `None` = the default profile for + /// this role name. A role writing a multi-writer kind (`findings`) writes + /// into its own slot, chosen daemon-side, so one reviewer can never + /// overwrite another's. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub writes: Option>, } /// Set on a role-CHILD of a collaborative session: which collaboration it diff --git a/crates/codeoid-protocol/tests/wire_format.rs b/crates/codeoid-protocol/tests/wire_format.rs index e698fd6..699a40d 100644 --- a/crates/codeoid-protocol/tests/wire_format.rs +++ b/crates/codeoid-protocol/tests/wire_format.rs @@ -128,6 +128,8 @@ fn sample_session_info() -> SessionInfo { count: None, purpose: None, write: None, + reads: None, + writes: None, }, codeoid_protocol::CollaborationRole { name: "review".into(), @@ -136,6 +138,8 @@ fn sample_session_info() -> SessionInfo { count: Some(3), purpose: Some("independent critique".into()), write: Some(false), + reads: Some(vec!["spec".into(), "diff".into()]), + writes: Some(vec!["findings".into()]), }, ], }),