refactor(runtime): add approval tokens and session compaction pipeline#3231
Open
Gaurav-x111 wants to merge 1 commit into
Open
refactor(runtime): add approval tokens and session compaction pipeline#3231Gaurav-x111 wants to merge 1 commit into
Gaurav-x111 wants to merge 1 commit into
Conversation
- Implement an approval token system to handle controlled execution permissions via the policy engine, including support for delegated approvals. - Add a session compaction pipeline (compact_pipeline) to cut down on runtime memory usage and message overhead. - Connect both the approval and compaction systems into the core runtime execution path (specifically updating the Trident engine). - Update the CLI and test contracts to match these changes. Note: This is a major structural change affecting the policy, execution, and session lifecycle layers.
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
This PR modernizes Rust code patterns (Option handling, derives, small refactors), introduces a new “compact_pipeline” module in runtime, and significantly rewrites the approval-token system.
Changes:
- Replace
map_orpatterns withis_some_and, simplify control flow, and apply clippy/allow attributes in a few places. - Add
runtime::compact_pipelineand re-export its types/functions fromruntime::lib. - Rewrite
runtime::approval_tokenswith a new ledger/audit model and token lifecycle APIs.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| rust/crates/rusty-claude-cli/tests/output_format_contract.rs | Refactors Option assertions; adjusts path comparison in agent listing test. |
| rust/crates/rusty-claude-cli/src/main.rs | Minor refactors (string creation, loops, help metadata alias) and clippy allows. |
| rust/crates/runtime/src/trident.rs | Small refactors/optimizations and derive-based Default for stats. |
| rust/crates/runtime/src/policy_engine.rs | Adjust clippy allow list in a long test. |
| rust/crates/runtime/src/lib.rs | Exposes new compact_pipeline module and re-exports its public API. |
| rust/crates/runtime/src/config.rs | Adds #[allow(dead_code)] to settings helpers. |
| rust/crates/runtime/src/compact_pipeline.rs | New compaction pipeline module + unit tests. |
| rust/crates/runtime/src/approval_tokens.rs | Major redesign of approval tokens, ledger, and auditing. |
| rust/crates/api/src/lib.rs | Adds crate-level clippy allow for large error results. |
| rust/.gitignore | Ignores entire .claw/ directory. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+258
to
+276
| pub fn verify(&self, token: &str) -> Result<&ApprovalTokenGrant, ApprovalTokenError> { | ||
| let grant = self | ||
| .grants | ||
| .get_mut(token) | ||
| .ok_or(ApprovalTokenError::NoApproval)?; | ||
| Self::validate_grant(grant, scope, executing_actor, now_epoch_seconds)?; | ||
| grant.uses += 1; | ||
| if grant.uses >= grant.max_uses { | ||
| grant.status = ApprovalTokenStatus::Consumed; | ||
| .tokens | ||
| .get(token) | ||
| .ok_or(ApprovalTokenError::TokenNotFound)?; | ||
| if grant.status == ApprovalTokenStatus::Expired { | ||
| return Err(ApprovalTokenError::TokenExpired); | ||
| } | ||
| Ok(Self::audit_for(grant, executing_actor)) | ||
| } | ||
|
|
||
| fn validate_grant( | ||
| grant: &ApprovalTokenGrant, | ||
| scope: &ApprovalScope, | ||
| executing_actor: &str, | ||
| now_epoch_seconds: u64, | ||
| ) -> Result<(), ApprovalTokenError> { | ||
| match grant.status { | ||
| ApprovalTokenStatus::Pending => return Err(ApprovalTokenError::ApprovalPending), | ||
| ApprovalTokenStatus::Consumed => { | ||
| return Err(ApprovalTokenError::ApprovalAlreadyConsumed) | ||
| } | ||
| ApprovalTokenStatus::Expired => return Err(ApprovalTokenError::ApprovalExpired), | ||
| ApprovalTokenStatus::Revoked => return Err(ApprovalTokenError::ApprovalRevoked), | ||
| ApprovalTokenStatus::Granted => {} | ||
| if grant.status == ApprovalTokenStatus::Exhausted { | ||
| return Err(ApprovalTokenError::TokenExhausted); | ||
| } | ||
|
|
||
| if grant | ||
| .expires_at_epoch_seconds | ||
| .is_some_and(|expires_at| now_epoch_seconds > expires_at) | ||
| { | ||
| return Err(ApprovalTokenError::ApprovalExpired); | ||
| if grant.status == ApprovalTokenStatus::Revoked { | ||
| return Err(ApprovalTokenError::TokenRevoked); | ||
| } | ||
|
|
||
| if grant.uses >= grant.max_uses { | ||
| return Err(ApprovalTokenError::ApprovalAlreadyConsumed); | ||
| } | ||
|
|
||
| if grant.scope != *scope { | ||
| return Err(ApprovalTokenError::ScopeMismatch { | ||
| expected: Box::new(grant.scope.clone()), | ||
| actual: Box::new(scope.clone()), | ||
| }); | ||
| if grant.status != ApprovalTokenStatus::Granted { | ||
| return Err(ApprovalTokenError::InvalidToken); | ||
| } | ||
| Ok(grant) | ||
| } |
Comment on lines
+278
to
294
| pub fn consume(&mut self, token: &str) -> Result<(), ApprovalTokenError> { | ||
| let grant = self | ||
| .tokens | ||
| .get_mut(token) | ||
| .ok_or(ApprovalTokenError::TokenNotFound)?; | ||
| if let Err(_e) = grant.consume_use() { | ||
| return Err(ApprovalTokenError::InvalidToken); | ||
| } | ||
|
|
||
| self.audit_log.push(ApprovalTokenAudit { | ||
| token: token.to_string(), | ||
| action: TokenAuditAction::Consumed, | ||
| actor: "system".to_string(), | ||
| timestamp: current_timestamp(), | ||
| details: HashMap::new(), | ||
| }); | ||
| Ok(()) | ||
| } |
Comment on lines
+321
to
+327
| fn generate_token() -> String { | ||
| let ts = SystemTime::now() | ||
| .duration_since(UNIX_EPOCH) | ||
| .unwrap() | ||
| .as_nanos(); | ||
| format!("approval_{:x}", ts) | ||
| } |
Comment on lines
+235
to
239
| pub fn revoke( | ||
| &mut self, | ||
| token: &str, | ||
| scope: &ApprovalScope, | ||
| executing_actor: &str, | ||
| now_epoch_seconds: u64, | ||
| actor: &str, | ||
| ) -> Result<ApprovalTokenAudit, ApprovalTokenError> { |
Comment on lines
+166
to
+187
| while j < messages.len() && chain.len() < threshold { | ||
| let next = &messages[j]; | ||
| if next.summary.len() < 20 && next.tool_calls.is_empty() { | ||
| chain.push(next.clone()); | ||
| j += 1; | ||
| } else { | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| if chain.len() >= 2 { | ||
| collapsed += chain.len(); | ||
| result.push(CompactMessage { | ||
| id: chain.first().unwrap().id, | ||
| role: "assistant".to_string(), | ||
| summary: format!("[{} chatty messages collapsed]", chain.len()), | ||
| tool_calls: vec![], | ||
| file_ops: vec![], | ||
| }); | ||
| i = j; | ||
| continue; | ||
| } |
Comment on lines
+231
to
+238
| for &idx in &indices[1..] { | ||
| result[idx].summary = "[MERGED]".to_string(); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // Remove merged messages | ||
| result.retain(|msg| msg.summary != "[MERGED]"); |
| @@ -1,3 +1,5 @@ | |||
| #![allow(unused_variables)] | |||
Comment on lines
+5371
to
+5374
| && fs::canonicalize(&agent_path) | ||
| .map(|p| p.to_string_lossy().to_string()) | ||
| .expect("canonical listed agent path") | ||
| == agent["path"].as_str().expect("listed agent path") |
| @@ -1,3 +1,5 @@ | |||
| #![allow(clippy::result_large_err)] | |||
| .claw/settings.local.json | ||
| .claw/sessions/ | ||
| .clawhip/ | ||
| .claw/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Note: This is a major structural change affecting the policy, execution, and session lifecycle layers.
Summary
Anti-slop triage
Verification
git diff --checkpasses.Resolution gate