Skip to content

feat: dynamic policy listing, network/package caps, SSH fleet orchestration, TUI approval widget#3

Merged
marcuspat merged 4 commits into
mainfrom
feat/p1-p2-p3-completion
Jun 16, 2026
Merged

feat: dynamic policy listing, network/package caps, SSH fleet orchestration, TUI approval widget#3
marcuspat merged 4 commits into
mainfrom
feat/p1-p2-p3-completion

Conversation

@marcuspat

Copy link
Copy Markdown
Owner

Summary

Completes four work items (P3, P2a, P2b, P1) on feat/p1-p2-p3-completion. Each is an isolated commit; the full workspace builds, tests, and passes clippy -D warnings.

P3 — Dynamic policy listing (cd6f63b)

  • Added PolicyEvaluator::rules(&self) -> &[PolicyRule] getter (+ unit test).
  • Rewrote show_policy() in the TUI to enumerate default_policy().rules() dynamically — prints each rule's priority, id, effect, enabled-state, a rendered condition expression, and description (via a new recursive describe_condition() helper). No more hardcoded table.

P2a — Network & package capabilities (2934e9e)

  • Audit result: network.rs and packages.rs were already fully implemented (real invoke(), correct manifests, registered in all_capabilities()); no stubs. The gap was test coverage — existing tests only exercised validate_args via a panicking dummy executor.
  • Added a recording MockExecutor and 8 new invoke()/invoke_inverse() tests covering NetworkConnections (ss/netstat), NetworkInterfaces (ip/ifconfig), PackageList (apt list), PackageUpgrade (apt upgrade/install), and the intentional non-recoverable inverse of PackageUpgrade.

P2b — SSH multi-host orchestration (2f105e6)

  • New sentinel-fleet::fleet_exec module: HostConfig ([user@]host[:port] parsing), FleetConfig, FleetResult, a HostExecutor trait, and the production SshHostExecutor (agentless — shells out to ssh via tokio::process, no native dep).
  • execute_on_fleet() / execute_on_fleet_with() fan out across hosts in parallel via JoinSet and aggregate hostname → CapabilityResult, with per-host error isolation (one bad host never aborts the rest).
  • New sentinel fleet <goal> --hosts h1,h2 --capability <id> --args <json> subcommand prints per-host results + a summary.
  • 5 unit tests (host parsing, ssh argv build, single-host, multi-host parallel, error isolation).

P1 — TUI interactive approval widget (d3a527d)

  • app.rs: new AppState { Normal, ApprovingPlan(PlanStep) }, an ApprovalOutcome { Approve, Abort } enum, and an ApprovalRequest (PlanStep + oneshot responder). The agent emits requests on an mpsc channel that the TUI polls each event (poll_approval); begin_approval/submit_approval manage the modal lifecycle and reply to the agent.
  • event_handler.rs: while a modal is active it owns all input — y/Y approves, n/N/Esc aborts, any other key is ignored.
  • ui.rs: renders a centered, bordered modal (with Clear) showing capability id, risk tier, action description, arguments, and an Approve? [y] / [n/Esc] prompt.
  • 9 new tests across app.rs + event_handler.rs.

The CLI sentinel run keeps its existing stdin y/N approval path unchanged (per spec).

Notes / scope

  • SshHostExecutor is exercised via the HostExecutor mock in tests (a live SSH host can't run in CI). Running the fleet subcommand here yields isolated per-host failures because ssh isn't installed in the sandbox — which itself demonstrates the error-isolation path.
  • The approval channel mechanism is complete and tested; wiring a background agent task into the TUI event loop to produce ApprovalRequests is the remaining integration point (the TUI is not yet driven by the live reasoning loop).

Testing

  • cargo build --workspace — clean
  • cargo test --workspace — all passing (policy 60, capabilities 68, fleet 45, tui 38, agent-llm 53 + 6 integration)
  • cargo clippy --workspace --all-targets -- -D warnings — no warnings

Please review; do not merge without sign-off.

https://claude.ai/code/session_01PrvrHsArvuyDmDvn5Cuvri


Generated by Claude Code

@marcuspat marcuspat merged commit 2173722 into main Jun 16, 2026
3 checks passed
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.

2 participants