feat(agent): resolve assigned executor — personality / skill / agent (G4+G3)#2970
feat(agent): resolve assigned executor — personality / skill / agent (G4+G3)#2970sanil-23 wants to merge 5 commits into
Conversation
…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>
|
Caution Review failedPull request was closed or merged during review 📝 WalkthroughWalkthroughThis pull request adds human-in-the-loop plan approval for task-board cards and implements a deterministic autonomous task dispatcher. New card statuses ( ChangesPlan Approval Task Card Lifecycle
Deterministic Task Dispatcher Core
Task Sources Integration and Triage Envelope Linking
Startup Initialization and RPC Wiring
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ 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
ESLint skipped: no ESLint configuration detected in root package.json. To enable, add Comment |
|
Superseded by #2974, which consolidates all six proactive-pipeline gap PRs into a single branch (7 ordered commits). Closing in favour of that. |
Summary
assigned_agentto 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_autonomousbuilds viafrom_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
cargo testgreen locally.Related
Summary by CodeRabbit