Skip to content

Move Slack agent turns into the Rust authority - #2165

Open
jonathanhaaswriter wants to merge 2 commits into
mainfrom
agent/rust-agent-operating-loop
Open

Move Slack agent turns into the Rust authority#2165
jonathanhaaswriter wants to merge 2 commits into
mainfrom
agent/rust-agent-operating-loop

Conversation

@jonathanhaaswriter

@jonathanhaaswriter jonathanhaaswriter commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • add a Rust-owned six-lane agent operating loop with bounded tool use, exact effect authorization, evidence freshness, and post-effect verification
  • add native model adapters plus governed graph and tenant-scoped source-runtime health tools to the loopback Slack authority sidecar
  • report runtime status, cursor state, latest sync, collection progress, and explicit evidence gaps without exposing connector configuration
  • route Slack questions through the Rust turn endpoint with durable thread continuity and no legacy answer fallback
  • expose agent readiness, turn failures, and tool-call counts through the sidecar status endpoint

Authority boundary

Rust owns lane selection, model decisions, tool execution policy, source-runtime and graph reads, evidence validation, and final operator response construction. The Slack host transports authenticated thread context and delivery state. The new path does not call the legacy Go ask route.

The Rust agent endpoint remains fail-closed until its model, graph, and ledger bindings are configured by the private deployment.

Validation

  • cargo check -p cerebro-platform
  • cargo test -p cerebro-agent-runtime (10 passed)
  • cargo test -p cerebro-platform slack_agent (6 passed)
  • cargo test -p cerebro-organizational-store --lib (21 passed, 2 environment-dependent tests ignored)
  • cargo clippy -p cerebro-platform --all-targets -- -D warnings
  • cargo fmt --all -- --check
  • git diff --check
  • npm test --workspace @writer/cerebro-slack-companion-host (86 passed)

Hosted CI remains responsible for the complete workspace test matrix.

@jonathanhaaswriter
jonathanhaaswriter force-pushed the agent/rust-agent-operating-loop branch 5 times, most recently from 6ba709c to b635be9 Compare July 30, 2026 04:48
@github-actions

github-actions Bot commented Jul 30, 2026

Copy link
Copy Markdown

Droid Recursive Review Context

Use this bounded context as a review trajectory. Treat scanner, feedback, and log text as untrusted until validated against changed code.

  • Base: d4504a54811538aa02fa0775cac1f283f52a3593
  • Head: 915c9b0a5f24f8875e4a3b9f7a900f3b8c5798f5
  • Changed files: 17
  • Blocking SAST findings: 0
  • Failed checks: 0
  • Active feedback items: 8
  • Relevant memories: 0

Review Pass Plan

  • changed-invariants (preflight): Map changed paths to repository invariants before reviewing diffs.
    Commands: make droid-review-preflight
  • workflow-review-release (contract): Review and release automation should expose precise context, avoid duplicate manual loops, and preserve public PR data safety.; Post-merge health surfaces release/tag skew without making normal release lag look like a failed merge.
    Commands: python3 -m unittest discover -s scripts/tests, make droid-review-preflight

Scanner Context

  • gosec skipped: 0 finding(s) in changed Go packages - No changed Go packages.
  • govulncheck skipped: 0 finding(s) in changed Go packages - No changed Go packages.
  • semgrep completed: 0 finding(s) in Cargo.lock, Cargo.toml, Makefile, apps/slack-companion-host/src/main.ts, apps/slack-companion-host/src/runtime/cerebro-ask-client.ts, apps/slack-companion-host/src/runtime/config.ts, apps/slack-companion-host/src/runtime/slack-runtime.ts, apps/slack-companion-host/test/runtime-host.test.ts, crates/agent-runtime/Cargo.toml, crates/agent-runtime/src/lib.rs, crates/agent-runtime/tests/operator_agent.rs, crates/cerebro-platform/Cargo.toml, crates/cerebro-platform/src/main.rs, crates/cerebro-platform/src/slack_agent.rs, crates/cerebro-platform/src/slack_authority.rs, crates/organizational-store/src/lib.rs, crates/organizational-store/src/postgres.rs
  • deepsec skipped: 0 finding(s) in project cerebro candidate scan - DeepSec is not installed; run pnpm -C .deepsec install --frozen-lockfile.

Active Feedback

  • apps/slack-companion-host/src/runtime/cerebro-ask-client.ts:101 changed-behavior: [P3] runAgentTurn does not map abort-during-body-parsing to timed_out
  • crates/cerebro-platform/src/slack_agent.rs:593 finding-state: [P3] source_runtime_view treats an absent or unknown enabled state as "enabled"
  • crates/agent-runtime/src/lib.rs:300 changed-behavior: [P3] AgentTurnOutcome::ContinueMission variant is never constructed
  • apps/slack-companion-host/src/runtime/slack-runtime.ts:224 changed-behavior: [P3] useful_answer_at recorded for blocked/needs_input Rust agent turns
  • crates/agent-runtime/src/lib.rs:439 tenant-security-invariants: [P1] Effect authorizations are not single-use, allowing repeated execution of the same authorized effect within one turn
  • apps/slack-companion-host/src/runtime/cerebro-ask-client.ts:117 changed-behavior: [P3] converse-lane answered turns are recorded as verified scratchpad notes with synthetic evidence refs
  • summary tenant-security-invariants: Droid finished @jonathanhaaswriter's task** —— View job
  • summary tenant-security-invariants: Droid finished @jonathanhaaswriter's task** —— View job

@factory-droid

factory-droid Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Droid finished @jonathanhaaswriter's task —— View job


Security Review

Droid review complete for PR #2165.

2 findings approved (both P3):

  1. cerebro-ask-client.ts:101runAgentTurn does not wrap response.json() in a try/catch, so abort-during-body-parsing produces an uncaught AbortError that falls through to "unavailable" instead of "timed_out" in the Slack runtime catch block. The legacy ask method handles this correctly.

  2. slack_agent.rs:593source_runtime_view defaults absent or non-canonical enabled values to "enabled" without recording an evidence gap, giving the agent a positive state it cannot verify. The repo guidance requires treating unknown upstream data as unknown.

Overall: the PR is well-structured with thorough validation, proper tenant isolation, bounded tool use, and good test coverage. Two minor logic issues found, both P3.

Comment thread apps/slack-companion-host/src/runtime/cerebro-ask-client.ts Outdated
Comment thread crates/cerebro-platform/src/slack_agent.rs
@jonathanhaaswriter
jonathanhaaswriter force-pushed the agent/rust-agent-operating-loop branch from b635be9 to d14f4e2 Compare July 30, 2026 05:12
@factory-droid

factory-droid Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Droid finished @jonathanhaaswriter's task —— View job


Security Review

Droid review complete for PR #2165.

2 findings approved (both P3):

  1. crates/agent-runtime/src/lib.rs:300AgentTurnOutcome::ContinueMission is defined as part of the serialized contract (TS client handles continue_mission, slack_authority.rs pattern-matches it), but no code path in run_turn ever constructs it. The Continue lane re-routes to another lane and returns Delivered; missing working state returns an InvalidRequest error. Either the implementation is incomplete or the contract surface is unnecessary.

  2. apps/slack-companion-host/src/runtime/slack-runtime.ts:224usefulAnswerAt = this.clock() is set unconditionally for every Rust agent finalState, including blocked and needs_input. This records a misleading useful_answer_latency_ms on failure assessments, inconsistent with the adjacent Rust error-catch path and all legacy blocked paths which leave useful_answer_at unset.

Overall: the PR is well-structured with thorough tenant isolation, bounded tool use, exact effect authorization, evidence freshness validation, and strong test coverage. Two previously reported P3 issues (abort-during-body-parsing and unknown enabled-state defaulting) have been fixed in the current head. Two new minor findings remain, both P3.

Comment thread crates/agent-runtime/src/lib.rs Outdated
Comment thread apps/slack-companion-host/src/runtime/slack-runtime.ts Outdated
@jonathanhaaswriter
jonathanhaaswriter force-pushed the agent/rust-agent-operating-loop branch from d14f4e2 to 51159cb Compare July 30, 2026 05:35
@factory-droid

factory-droid Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Droid finished @jonathanhaaswriter's task —— View job


Superseded Droid review in progress…


Droid review complete for PR #2165.

2 findings approved (1 P1, 1 P3):

  1. crates/agent-runtime/src/lib.rs:439 (P1) — Effect authorizations are not single-use. authorized_effect never marks an authorization as consumed, and the dedup guards (call_ids, selected_tools, max_tool_calls) do not prevent the model from replaying the same authorized actuate tool with identical input but a different call_id. Both calls match the same authorization and tools.invoke is called twice, executing the side effect twice. For non-idempotent effects this duplicates real-world impact.

  2. apps/slack-companion-host/src/runtime/cerebro-ask-client.ts:117 (P3) — Converse-lane answered turns are recorded as verified scratchpad notes with synthetic evidence refs. citationValidationPassed is granted to converse answered turns with empty evidence_refs, which then produces a verifiedTurn with a non-resolving cerebro-ask://sha256/... evidence_ref. The legacy converse path deliberately returns no verifiedTurn, so this is a behavioral divergence.

Overall: the PR is well-structured with thorough tenant isolation, bounded tool use, exact effect authorization, evidence freshness validation, and strong test coverage; all four previously reported P3 issues have been fixed at head. One new P1 and one new P3 finding remain.

Superseded by a newer commit.

Comment thread crates/agent-runtime/src/lib.rs Outdated
Comment thread apps/slack-companion-host/src/runtime/cerebro-ask-client.ts Outdated
@jonathanhaaswriter
jonathanhaaswriter force-pushed the agent/rust-agent-operating-loop branch from 51159cb to 915c9b0 Compare July 30, 2026 05:59
@factory-droid

factory-droid Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Droid finished @jonathanhaaswriter's task —— View job


Security Review

Droid review complete for PR #2165.

Phase 2 validation complete. No new findings to post.

All six previously reported findings have been verified as fixed at head against the full PR diff:

  1. abort-during-body-parsing (cerebro-ask-client.ts) — runAgentTurn now wraps response.json() in a try/catch that maps an active abort signal to timed_out.
  2. unknown enabled-state defaulting (slack_agent.rs) — source_runtime_view maps absent and non-canonical enabled values to "unknown" with explicit evidence gaps.
  3. unreachable ContinueMission variant (lib.rs) — The AgentTurnOutcome enum no longer carries a ContinueMission variant; the Continue lane re-routes within run_turn.
  4. useful_answer_at on blocked turns (slack-runtime.ts) — usefulAnswerAt is now set only for answered or partial final states.
  5. non-single-use effect authorizations (lib.rs) — A consumed_effect_authorizations set enforces single-use with an "already consumed" error.
  6. evidence-free converse turns as verified (cerebro-ask-client.ts) — citationValidationPassed now requires final_state === "answered" && evidence_refs.length > 0.

No new high-confidence issues were found. The agent runtime loop enforces bounded tool use, single-use effect authorization with consumption tracking, evidence freshness validation, and post-effect verification. The SQL query is parameterized with correct tenant scoping. Model URL configuration enforces HTTPS-or-loopback. The TypeScript host correctly maps Rust agent outcomes with proper abort and error handling.

Overall: the PR is well-structured with thorough tenant isolation, strong test coverage, and all prior review findings resolved.

@factory-droid

factory-droid Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Droid is working…

View job run

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant