Skip to content

feat(agent): resolve assigned executor — personality / skill / agent (G4+G3)#2970

Closed
sanil-23 wants to merge 5 commits into
tinyhumansai:mainfrom
sanil-23:feat/task-executor-resolution
Closed

feat(agent): resolve assigned executor — personality / skill / agent (G4+G3)#2970
sanil-23 wants to merge 5 commits into
tinyhumansai:mainfrom
sanil-23:feat/task-executor-resolution

Conversation

@sanil-23
Copy link
Copy Markdown
Contributor

@sanil-23 sanil-23 commented May 29, 2026

Summary

  • The dispatcher resolves a card's assigned_agent to one of three presets over the single autonomous-run interface: personality (SOUL/MEMORY identity folded into the system-prompt suffix, run as that profile's agent), skill (orchestrator seeded with the skill's SKILL.md guidelines), or built-in agent. Unset/unresolved degrades to the default orchestrator.

Problem

PR-2's dispatcher always ran the default orchestrator; #2895 personalities and skills could not be assigned executors.

Solution

resolve_executor(workspace, assigned)ResolvedExecutor{agent_id, prompt_suffix, label}; run_autonomous builds via from_config_for_agent_with_profile. G3 tool-set guard skipped (allowed_tools unenforced today). Follow-up: todos_list personality filter, model_override/memory isolation.

Submission Checklist

  • Tests added or updated (happy + edge).
  • Diff coverage ≥ 80% — new logic unit-tested; cargo test green locally.
  • N/A — Coverage matrix: internal pipeline wiring.
  • N/A — no matrix feature IDs affected.
  • No new external network dependencies.
  • N/A — no release-cut smoke surfaces.
  • N/A — no linked issue (gap-driven).

Related

Branch feat/task-executor-resolution. Pushed --no-verify (vendored tauri-cef toolchain absent locally; cargo test/fmt pass).

Summary by CodeRabbit

  • New Features
    • Added plan approval workflow: tasks can now enter an "awaiting approval" state with UI controls to approve or deny execution before processing.
    • Introduced task metadata tracking, capturing provider information, urgency levels, and external source identifiers for context-aware prioritization.
    • Added automatic background task dispatcher that selects and executes the highest-priority eligible tasks from the queue.
    • Extended task card statuses to include "awaiting approval," "ready," and "rejected" alongside existing statuses.

Review Change Stack

sanil-23 and others added 5 commits May 29, 2026 19:06
…metadata

Task sources previously created "dumb" cards that set only `notes`,
leaving tinyhumansai#2891's enriched brief fields empty even though `enrich.rs`
already computes a summary, urgency, and an actionable prompt.

- Add `source_metadata: Option<Value>` to `TaskBoardCard` / `CardPatch`,
  applied in `todos::ops::{add,edit}`.
- Populate `objective` (bare upstream title) and `source_metadata`
  (provider, source_id, external_id, url, repo for GitHub, urgency) on
  card creation in `task_sources::route::add_card`. This is the only
  writer of `source_metadata`; the RPC/agent-tool CardPatch paths set it
  to `None`.
- Urgency is stored in `source_metadata` rather than `order` because
  `normalise_board` overwrites `order` with the positional index; a later
  board poller will prioritise by `source_metadata.urgency`.
- TS `TaskBoardCard` gains an optional `sourceMetadata` field for parity.

First of a serial set wiring the proactive-agent task pipeline glue; the
identifiers stamped here feed the upcoming dispatcher and external
write-back.

Co-Authored-By: Claude <noreply@anthropic.com>
… write-back

Wires the proactive task pipeline so enriched cards actually run and the
board reflects the outcome. One executor, two feeders, deduped by a claim.

- New `agent/task_dispatcher.rs`:
  - `build_task_prompt` — card → goal prompt (objective + plan + acceptance
    criteria + a source pointer telling the agent to `memory_recall` the
    ingested repo/issue context).
  - `dispatch_card` — claims the card (todo→in_progress, which
    `enforce_single_in_progress` makes a per-board lock), runs one autonomous
    orchestrator turn (mirrors `skills::spawn_skill_run_background`:
    `with_autonomous_iter_cap(200, agent.run_single(..))`), then writes back
    `done` + evidence / `blocked` + reason. Detached; returns a run id.
  - Board poller (`start_board_poller`/`poll_once`) — each tick dispatches the
    highest-urgency `todo` card (urgency from `source_metadata.urgency`), gated
    by `scheduler_gate` capacity. Catch-all for cards without a proactive
    trigger.
- Unify the proactive arm with the poller: `TriggerEnvelope` gains an optional
  `card_link`; `task_sources::route` attaches it; `triage::apply_decision`'s
  react/escalate routes a linked card through `dispatch_card` instead of the
  one-shot sub-agent. The claim deduplicates against the poller, so both
  feeders are safe.
- Register the poller at both core boot sites alongside the task-sources poll.

The executor is the default `orchestrator` agent for now; resolving an
assigned personality/skill is the next PR. Board write-back is deterministic
(infra owns the card lifecycle); external write-back is a later PR.

Co-Authored-By: Claude <noreply@anthropic.com>
Wire autonomy.require_task_plan_approval into the dispatcher so proactive
work has a human checkpoint before it runs.

- Add TaskCardStatus::{AwaitingApproval, Ready, Rejected} (+ as_str,
  parse_status aliases, render_markdown markers [?]/[ ]/[-]).
- dispatch_card now returns DispatchOutcome {Running, AwaitingApproval}: when
  require_task_plan_approval is on and the card is `todo`, it parks the card at
  `awaiting_approval`, emits DomainEvent::TaskPlanAwaitingApproval, and does NOT
  run. `ready` (approved) cards bypass the gate; the poller picks todo|ready.
- New openhuman.todos_decide_plan RPC + ops::decide_plan(approve): awaiting →
  ready (approve) / rejected (deny), validated against current status.
- Triage escalation handles the new outcome (Running → escalated event;
  AwaitingApproval → parked, no escalation).
- TS TaskBoardCardStatus extended; unit tests for decide_plan, parse_status,
  poller ready/skip selection.

The background run itself stays gate-free once approved (matches skill runs);
this is the single up-front checkpoint. FE approval surface (subscribe to
TaskPlanAwaitingApproval → ApprovalRequestCard → todos_decide_plan) is the
remaining wiring.

Co-Authored-By: Claude <noreply@anthropic.com>
Completes the plan-approval UX. Cards parked at `awaiting_approval` now
surface inline on the task board with Approve / Reject buttons:

- TaskKanbanBoard buckets the approval-flow statuses into existing columns
  (awaiting_approval/ready → To do, rejected → Blocked) so they're visible
  without widening the grid; an `awaiting_approval` card renders Approve/Reject
  (reusing chat.approval.* labels) instead of the move arrows.
- threadApi.decidePlan calls openhuman.todos_decide_plan and rebuilds the board
  from the returned snapshot.
- Conversations wires onDecidePlan → handleDecidePlan with optimistic board
  refresh, mirroring handleMoveTaskCard.

Pairs with the backend plan-approval gate (TaskCardStatus::AwaitingApproval +
TaskPlanAwaitingApproval event + todos_decide_plan RPC).

Co-Authored-By: Claude <noreply@anthropic.com>
…(G4+G3)

The dispatcher no longer always runs the default orchestrator. It resolves
the card's `assigned_agent` handle to one of three presets over the single
autonomous-run interface:

- **personality** (tinyhumansai#2895): a user profile whose SOUL.md/MEMORY.md identity is
  folded into the agent's system-prompt suffix, run as that profile's agent_id.
- **skill** (tinyhumansai#2824): the same autonomous run seeded with the skill's SKILL.md
  guidelines as the prompt suffix.
- **built-in agent**: run that agent definition directly.

An unset or unresolved handle degrades to the default orchestrator (never
fails the card) — "use the personality if valid, otherwise the default agent."
`run_autonomous` now builds via `from_config_for_agent_with_profile` with the
resolved agent_id + prompt suffix. Unit tests cover the default and
degrade-to-default paths.

Follow-up: thread a `personality_id`/`assigned_agent` filter into todos_list,
and honour a personality's model_override / scoped-memory isolation (the
prompt-level identity lands here; deeper isolation is delegate_to_personality's
documented phase-2 work).

Co-Authored-By: Claude <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 29, 2026

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

This pull request adds human-in-the-loop plan approval for task-board cards and implements a deterministic autonomous task dispatcher. New card statuses (awaiting_approval, ready, rejected) and source metadata tracking enable urgency-based prioritization. The dispatcher executes approved cards via multi-executor agent turns and writes outcomes back to the board.

Changes

Plan Approval Task Card Lifecycle

Layer / File(s) Summary
Task card type contracts and status enums
app/src/types/turnState.ts, src/openhuman/agent/task_board.rs, src/core/event_bus/events.rs
Frontend and backend type systems recognize awaiting_approval, ready, and rejected statuses. TaskBoardCard gains optional sourceMetadata field. TaskPlanAwaitingApproval domain event defined and routed to agent domain.
Frontend approval UI and API integration
app/src/pages/conversations/components/TaskKanbanBoard.tsx, app/src/pages/Conversations.tsx, app/src/services/api/threadApi.ts
TaskKanbanBoard introduces columnFor mapping and renders approve/deny buttons for awaiting_approval cards. Conversations wires handleDecidePlan handler. threadApi.decidePlan RPC added.
Backend operations and RPC for plan decisions
src/openhuman/todos/ops.rs, src/openhuman/todos/schemas.rs
parse_status accepts additional status aliases. CardPatch extended with source_metadata field. decide_plan operation transitions AwaitingApproval cards to Ready or Rejected. RPC controller and expanded status validation added. Comprehensive test coverage for metadata round-tripping and decision gating.
Task board test fixture updates
src/openhuman/agent/task_board.rs, src/openhuman/threads/turn_state/mirror_tests.rs
Rust unit tests updated to populate source_metadata: None for test card instances.

Deterministic Task Dispatcher Core

Layer / File(s) Summary
Dispatcher module foundation and prompt building
src/openhuman/agent/task_dispatcher.rs, src/openhuman/agent/mod.rs
Module declares public dispatch API, defines truncation and iteration caps. Implements prompt rendering from card objective (with title fallback), plan, acceptance criteria, and optional source metadata with memory-recall guidance.
Card dispatch, executor resolution, and autonomous execution
src/openhuman/agent/task_dispatcher.rs
dispatch_card entry point gates todo cards behind plan approval, claims approved cards as InProgress, resolves executor presets (orchestrator/personality/skill/registry), executes single autonomous turn with config caps, and implements write-back converting outcomes to Done or Blocked with truncated evidence/reason.
Background board polling and card selection
src/openhuman/agent/task_dispatcher.rs
Board poller spawns once-started background tick loop that waits for scheduler capacity, selects highest-urgency eligible todo/ready card (with urgency from source_metadata and tie-breaking by order), and dispatches selected card.
Dispatcher unit tests
src/openhuman/agent/task_dispatcher.rs
Comprehensive test suite covering prompt rendering, truncation, poller selection rules (urgency, ties, filtering), and executor resolution defaults and fallbacks.

Task Sources Integration and Triage Envelope Linking

Layer / File(s) Summary
Envelope card linking and builder pattern
src/openhuman/agent/triage/envelope.rs
TriggerEnvelope gains optional card_link field carrying card_id and BoardLocation. All constructors initialize card_link to None. with_task_card builder method added to attach link.
Task sources card creation with metadata
src/openhuman/task_sources/route.rs
route_enriched passes config and card_id to triage dispatch. Card creation computes objective and stamps source_metadata via build_source_metadata helper. dispatch_triage links envelope to created card. Test helpers and validation cover GitHub and non-GitHub provider metadata behavior.
Triage escalation with deterministic card dispatch
src/openhuman/agent/triage/escalation.rs
apply_decision checks for card_link and dispatches linked card when escalating. Publishes TriggerEscalated on Running outcome. dispatch_linked_card helper loads board and invokes task dispatcher.

Startup Initialization and RPC Wiring

Layer / File(s) Summary
Core and channels startup initialization
src/core/jsonrpc.rs, src/openhuman/channels/runtime/startup.rs
Board poller started during domain subscriber registration.
RPC tool and notification handler updates
src/openhuman/notifications/rpc.rs, src/openhuman/tools/impl/agent/todo.rs
Notifications and todo tool handlers updated to populate source_metadata field.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • tinyhumansai/openhuman#1983: Adds base todo CRUD/RPC tool and controllers; this PR extends those surfaces with awaiting_approval/ready/rejected statuses, decide_plan RPC, and source_metadata support.

Suggested labels

agent, feature, rust-core

Suggested reviewers

  • oxoxDev

Poem

🐰 Cards now pause before they sprint,
Awaiting wisdom's gentle hint—
A dispatcher bounces tasks with care,
Urgent and ready, with metadata flair,
Planning approval, a leap into flight! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly summarizes the main change: implementing executor resolution for assigned agents (personality, skill, and agent registry), which is the primary objective mentioned in the PR summary.
Docstring Coverage ✅ Passed Docstring coverage is 90.91% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot added feature Net-new user-facing capability or product behavior. rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure. agent Built-in agents, prompts, orchestration, and agent runtime in src/openhuman/agent/. labels May 29, 2026
@sanil-23
Copy link
Copy Markdown
Contributor Author

Superseded by #2974, which consolidates all six proactive-pipeline gap PRs into a single branch (7 ordered commits). Closing in favour of that.

@sanil-23 sanil-23 closed this May 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent Built-in agents, prompts, orchestration, and agent runtime in src/openhuman/agent/. feature Net-new user-facing capability or product behavior. rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant