Make task manager route tasks by role-owner mapping
Problem
When a tasks owner is a role slug (e.g. data-viz-designer-engineer), resolve it through the role definition files in tasks/team/roles/ to determine the actual person identity for routing. Use filled_by if present, otherwise fall back to the role's owner field.
Context
owner_matches()inscripts/task_manager_lib.pypreviously used hardcoded identity sets (RJ_IDENTITIES,DAVE_IDENTITIES) to route tasks to managers.- Tasks can have
ownerset to a role slug likedata-viz-designer-engineerinstead of a person identity likedave. - Role definitions live in
tasks/team/roles/*.mdwith frontmatter containingslug,owner(manager), and optionallyfilled_by(person doing the work). - Example:
data-viz-designer-engineerhasowner: daveandfilled_by: rjso tasks owned by this role should route to RJ's manager. - Before this fix, role-slug owners did not match either manager identity set, so these tasks were dropped from heartbeat output.
Possible Solutions
A. Resolve role slugs at match time (Recommended)
Add a resolve_role_owner() function that loads role definitions and maps role slugs to person identities (filled_by if present, else owner). Call it in owner_matches() before comparing identities.
- Pro: Minimal change surface, role definitions stay the single source of truth.
- Pro: Caches role map per process because role files rarely change.
- Con: Adds file I/O on first call, mitigated by caching.
B. Resolve role slugs at task collection time
Resolve in effective_owner() before owner_matches() is called.
- Pro:
owner_matches()stays identity-only. - Con: Changes the
ownerfield semantics inTaskInfo, so downstream code would see the resolved identity instead of the original role slug.
Plan
- Write failing tests for role-based routing in
test_task_manager_scripts.py. - Add
load_role_map()returningdict[str, str]that readstasks/team/roles/*.mdand returns{role_slug: filled_by or owner}. - Add
resolve_role_owner(task_owner: str) -> strthat checks the role map and returns the resolved identity or the original string. - Update
owner_matches()to callresolve_role_owner()ontask_ownerbefore comparing. - Validate the task file and run focused task-manager tests.
Files to modify:
- scripts/task_manager_lib.py
- tests/scripts/test_task_manager_scripts.py
Implementation Progress
- Added
load_role_map()toscripts/task_manager_lib.pyto readtasks/team/roles/*.mdand build a cached{normalized_role_slug: person_identity}map usingfilled_byfirst andowneras fallback. - Added
resolve_role_owner()as a thin lookup wrapper that returns the resolved person for a role slug and otherwise passes the owner through unchanged. - Updated
owner_matches()to resolve role slugs before applying the existing Dave-versus-RJ manager routing logic. - Added
test_owner_matches_resolves_role_slugs_via_role_definitionsto verify thatdata-viz-designer-engineerroutes to RJ throughfilled_by,sr-engineer-architectfalls back to Dave viaowner, and direct identity owners still route as before.
QA Exploration
- [x] QA exploration completed — N/A, backend-only routing logic change with no UI impact
Review Feedback
- [ ] Review cleared