Skip to content

Per-phase agent assignment in run plans (prd-role-foundations Phase 4) - #106

Merged
suprie merged 3 commits into
mainfrom
run/role-foundations-phase-assignment-model-plus2-b100a50e8e45
Oct 8, 2026
Merged

suprie merged 3 commits into
mainfrom
run/role-foundations-phase-assignment-model-plus2-b100a50e8e45

Conversation

@suprie

@suprie suprie commented Sep 4, 2026

Copy link
Copy Markdown
Owner

Summary

Per-phase agent assignment end to end (prd-role-foundations Phase 4): run-plan phases can be staffed with a specific roster agent at queue time, the run-queue executor spawns each staffing batch with that agent's resolved config and charter, and the morning report attributes each phase to its role. Unassigned phases keep running on the default agent, so pre-assignment plans load and execute unchanged.

What changed

  • runplan.rs — RunPhase.assigned_agent_id / assigned_agent_name (serde-default optional; pre-assignment run-plan.yaml files load unchanged), new PhaseAgentAssignment payload struct, PhaseReportEntry.assigned_agent_name filled in RunReport::from_plan
  • commands/run_queue.rs — create_run_plan validates the sparse assignments payload against the roster and captures the roster name at queue time; next_queued_batch splits the combined turn at staffing changes; execute_run resolves assigned batches via resolve_agent_config_by_id (parks the batch when the roster entry is missing, blocks dependents), spawns through start_fresh_and_record_streaming_in_root_with_config; pre-flight interviews run with the phase's agent
  • run_executor.rs — build_run_plan staffs phases from assignments (+2 tests)
  • role_assignment_tests.rs (new) — deterministic two-phase dev/QA demo: staffing split, per-role charter argv capture via the fake-binary harness, report attribution Dev/QA; unassigned-phase and unknown-agent cases
  • PlanTonightWizard.tsx — per-phase "runs with" agent picker; sparse assignment payload into createRunPlan; consent summary shows the agent
  • MorningReportTab.tsx — new Agent column (assigned_agent_name ?? "default")
  • types/index.ts, lib/tauri.ts — typed IPC surface for assignments
  • PRD Phase 4 checkboxes checked; .loopdeck/ decisions/loops updated

PRD

docs/epics/role-based-orchestration/prd-role-foundations.md

Decisions

  • 2026-09-05 — Per-phase agent assignment: staffing fields on RunPhase, executor honors them, report attributes by role (accepted): staffing captured at queue time (name included, durable across roster renames); staffing change splits the combined turn; missing roster entry parks the batch instead of failing or silently falling back; unassigned phases stay on the default agent
  • 2026-09-01 — Role charter rides AgentConfig through one spawn choke point (accepted): assigned phases resolve to their roster entry's config, so charter injection and role rules ride along unchanged
  • 2026-09-01 — Role rules grant autonomy only; the destructive floor always wins (accepted): per-role permission rules apply to assigned spawns above the unchanged destructive floor

Test plan

  • cd src-tauri && cargo test
  • cd src-tauri && cargo clippy -- -D warnings
  • npm test (npm run test:frontend)
  • npx tsc --noEmit
  • Manual: plan a two-phase run in the plan-tonight wizard with different agents per phase, run it, confirm the morning report's Agent column attributes each phase to its role

Verify Verdict

PRD Verification — prd-role-foundations.md

Verdict: PASS

# Criterion Status Evidence
1 role-foundations/phase-assignment-model Add assigned-agent fields to RunPhase and the create_run_plan selection surface PASS src-tauri/src/runplan.rs:156,162 — pub assigned_agent_id: Option<String> / pub assigned_agent_name: Option<String> (serde-default optional, pre-assignment plans load unchanged); src-tauri/src/runplan.rs:169 — pub struct PhaseAgentAssignment; src-tauri/src/commands/run_queue.rs:437,466-490 — create_run_plan takes assignments, resolves each against the roster (find_agent_config), rejects unknown ids, captures the roster name; src/components/detail/PlanTonightWizard.tsx:123,191-194,219 — per-phase agentByPhase picker, sparse assignmentsFromSelection() into createRunPlan; src/types/index.ts + src/lib/tauri.ts — typed IPC surface
2 role-foundations/phase-assignment-exec Make the run-queue executor spawn each phase with its assigned agent instead of the default config PASS src-tauri/src/commands/run_queue.rs:1178-1198 — next_queued_batch returns the maximal prefix sharing one assigned_agent_id (staffing change splits the combined turn); run_queue.rs:1277-1304 — execute_run resolves resolve_agent_config_by_id for assigned batches, default config when unassigned, spawns via start_fresh_and_record_streaming_in_root_with_config; run_queue.rs:1624 — missing roster entry parks the batch (assigned agent "…" is not on the roster) and blocks dependents instead of failing silently; run_queue.rs:1397-1409 — interviews run with the lead phase's agent
3 role-foundations/role-demo Run an end-to-end two-phase plan where a dev-role agent builds and a QA-role agent verifies, with per-role attribution in the run report PASS src-tauri/src/role_assignment_tests.rs:79 — two_phase_role_demo_attributes_each_phase_to_its_role: queues a dev/QA-staffed plan, asserts the staffing split (Some(vec![0])), spawns each batch through resolve_agent_config_by_id + spawn_fresh_with_config with the fake-binary harness capturing argv, asserts each child saw only its own persona, and reads RunReport::from_plan attribution Some("Dev")/Some("QA"); report field at src-tauri/src/runplan.rs:267,306; surfaced in src/components/detail/MorningReportTab.tsx:153 (Agent column). Deterministic harness per the run's pre-answered clarification — ran as cargo test --lib (669 passed, 0 failed)

Non-goals audit

  • No scope creep detected. No parallel phase execution (batches stay sequential), no handoff store/artifacts, no arbitration/decision-maker runs, no runtime skill-file injection.

Roll-up: PASS — 0 FAIL, 0 PARTIAL, 3 PASS.

Run metadata

  • Phases:
    • role-foundations/phase-assignment-model — "Add assigned-agent fields to RunPhase and the create_run_plan selection surface" (role-based-orchestration / prd-role-foundations / Phase 4)
    • role-foundations/phase-assignment-exec — "Make the run-queue executor spawn each phase with its assigned agent instead of the default config" (role-based-orchestration / prd-role-foundations / Phase 4)
    • role-foundations/role-demo — "Run an end-to-end two-phase plan where a dev-role agent builds and a QA-role agent verifies, with per-role attribution in the run report" (role-based-orchestration / prd-role-foundations / Phase 4)
  • Budgets: 1500000 tokens total · 16200s wall-clock cap for this turn · 28800s total-run wall-clock cap

suprie and others added 3 commits September 5, 2026 06:06
RunPhase gains assigned_agent_id/assigned_agent_name (serde-default optional, pre-assignment plans load unchanged); create_run_plan takes a sparse PhaseAgentAssignment payload validated against the roster with the name captured at queue time; the plan-tonight wizard adds a per-phase agent picker. The executor's next_queued_batch splits the combined turn at staffing changes, spawns each batch through resolve_agent_config_by_id (default agent when unassigned, parks the batch when the roster entry is missing), and runs pre-flight interviews with the phase's agent. The run report carries assigned_agent_name into a new morning-report Agent column. Deterministic two-phase dev/QA demo in role_assignment_tests.rs proves per-role charter injection and report attribution.

Rubric: PASS — 3/3 criteria
@suprie
suprie marked this pull request as ready for review October 8, 2026 08:28
@suprie
suprie merged commit 56edb78 into main Oct 8, 2026
2 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.

1 participant