Dataface Tasks

Route manager updates for active tasks into the running worktree or a follow-up task

IDINFRA_TOOLING-ROUTE_MANAGER_UPDATES_FOR_ACTIVE_TASKS_INTO_THE_RUNNING_WORKTREE_OR_A_FOLLOW_UP_TASK
Statuscompleted
Priorityp1
Milestonem1-ft-analytics-analyst-pilot
Ownersr-engineer-architect

Problem

Prevent manager-side edits to already-running root task files on main. Detect when a task already has an active worktree/worker, provide a safe path to send updates to that same task context or create a follow-up task instead, and document/encode the rule so active tasks do not accumulate merge-conflict churn from main-branch task edits.

Context

  • We keep seeing the same conflict pattern:
  • a task is already running in its own worktree/branch/PR
  • manager-side edits on main mutate that same task markdown file
  • the task branch later rebases and conflicts on task text, started_at, PR metadata, or checklists
  • The desired behavior is not just “be more careful.” The system should make the safe path obvious:
  • if the task is already active, send updates into that same task context
  • if the change is materially new scope, create a follow-up task
  • do not silently fork the task story by editing the root task file on main
  • Relevant surfaces:
  • scripts/task_manager_lib.py — core classification/detection functions
  • scripts/task-manager-heartbeat — heartbeat cycle that runs detection
  • .codex/skills/task-manager/SKILL.md — operator-facing docs
  • Manager registry (.tasks/task_manager/task-manager-{owner}.register.json) tracks which tasks are active with registered_at timestamps

Possible Solutions

  • Chosen: add is_task_active() query + detect_root_edits_to_active_tasks() escalation signal. The heartbeat warns when a root task file was edited after dispatch started (root_task_edited signal, tier1). An operator-facing scripts/task-system/is-active <slug> command tells the operator whether a task is active and suggests the correct path (work in the worktree or create a follow-up task).
  • Docs-only approach: already present in SKILL.md “Do Not Edit Running Tasks On Main” section, but insufficient under pressure.
  • Hard-block: too blunt; some reconciliation edits are valid after PR lands.

Plan

  1. [x] Add is_task_active(slug, owner) to task_manager_lib.py — returns structured dict with active status, worktree path, dispatch state.
  2. [x] Add detect_root_edits_to_active_tasks(tasks) to task_manager_lib.py — compares root task file mtime against registered_at timestamp, flags tasks edited after dispatch with root_task_edited escalation signal (tier1).
  3. [x] Create scripts/task-manager-is-active + scripts/task-system/is-active CLI wrapper for operator queries.
  4. [x] Hook detect_root_edits_to_active_tasks into heartbeat cycle alongside existing detect_metadata_drift and detect_dispatch_completed_unreconciled.
  5. [x] Add root_task_edited to SKILL.md watchdog signal codes.
  6. [x] Write 7 tests (TDD): 4 for is_task_active, 3 for detect_root_edits_to_active_tasks.

Implementation Progress

  • 2026-03-24: Task created from repeated merge conflicts caused by manager-side edits to active root task files after work had already started in a dedicated worktree.
  • 2026-03-24: Implemented is_task_active() and detect_root_edits_to_active_tasks() in task_manager_lib.py. Created scripts/task-system/is-active CLI. Hooked root-edit detection into heartbeat. Added root_task_edited signal to SKILL.md. All 7 new tests pass.
  • 2026-03-25: Rebases onto current origin/main, resolved the task-file conflict by keeping the completed worksheet, hardened detect_metadata_drift() against vanishing files, tightened is_task_active() to require a real registration timestamp, made task-manager-is-active return exit code 1 for inactive tasks, and added regression tests for those review-driven fixes.

QA Exploration

  • [x] N/A — non-UI task (pure library + CLI + heartbeat changes)

Review Feedback

  • [x] Review cleared
  • 2026-03-25: just review approved after follow-up fixes for inactive CLI exit codes, detect_metadata_drift() OSError handling, and is_task_active() registration semantics. Review artifact: .tmp/pr-review-branch-20260325-083224.md