Skip to content

t1001: Add DB-TODO reconciliation pulse phase to supervisor#1275

Merged
marcusquinn merged 1 commit intomainfrom
feature/t1001
Feb 12, 2026
Merged

t1001: Add DB-TODO reconciliation pulse phase to supervisor#1275
marcusquinn merged 1 commit intomainfrom
feature/t1001

Conversation

@marcusquinn
Copy link
Owner

@marcusquinn marcusquinn commented Feb 12, 2026

Summary

  • Adds Phase 7b to the supervisor pulse cycle — bidirectional DB<->TODO.md reconciliation that fills three gaps not covered by the existing Phase 7 (which only syncs DB-complete → TODO.md-open)
  • New function cmd_reconcile_db_todo() in todo-sync.sh, also available as CLI command supervisor-helper.sh reconcile-db-todo [--batch id] [--dry-run]

Gaps Filled

Gap Scenario Fix
1 DB failed/blocked but TODO.md has no annotation Calls update_todo_on_blocked() to add Notes line
2 TODO.md [x] but DB still in non-terminal state (queued/running/etc.) Transitions DB to complete with reconciliation reason
3 DB orphans — tasks in DB with no TODO.md entry at all Logs warnings for human review (no auto-fix)

Design Decisions

  • Runs only when total_running == 0 && total_queued == 0 to avoid interfering with active workers (chose same guard as Phase 7 minus the total_complete > 0 requirement since Gap 1 targets failed/blocked tasks)
  • Gap 3 (DB orphans) is report-only — auto-deleting DB entries could lose state for tasks managed in other repos
  • Reuses existing update_todo_on_blocked() and cmd_transition() rather than duplicating logic

Ref #1274

Summary by CodeRabbit

  • New Features
    • Added reconcile-db-todo command for bidirectional database and TODO.md file synchronization.
    • Supports dry-run mode to preview changes before applying.
    • Automatically handles task state synchronization (completed, failed, blocked).
    • Includes optional batch filtering and detailed logging.
    • Identifies and logs orphaned tasks for manual review.

Adds Phase 7b to the supervisor pulse cycle — bidirectional DB<->TODO.md
reconciliation that fills gaps not covered by Phase 7:

1. DB failed/blocked tasks with no annotation in TODO.md — annotates them
2. Tasks marked [x] in TODO.md but DB still in non-terminal state — transitions DB to complete
3. DB orphans with no TODO.md entry — logs warnings for human review

New function cmd_reconcile_db_todo() in todo-sync.sh, invocable as
supervisor-helper.sh reconcile-db-todo [--batch id] [--dry-run].
Runs during pulse when no workers are active to avoid mid-flight interference.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 12, 2026

Walkthrough

This PR introduces a bidirectional database-to-TODO.md reconciliation command (reconcile-db-todo) into the supervisor framework. Phase 7b automatically triggers reconciliation when no tasks are running or queued but completed tasks exist. The implementation validates consistency, applies gap-filling strategies, and supports dry-run mode with detailed logging.

Changes

Cohort / File(s) Summary
Supervisor CLI Wiring
.agents/scripts/supervisor-helper.sh
Added public command reconcile-db-todo with handler dispatch, help text, and command listing (t1001 designator) to expose bidirectional DB<->TODO.md reconciliation capability.
Reconciliation Logic
.agents/scripts/supervisor/todo-sync.sh
Implemented cmd_reconcile_db_todo() function executing Phase 7b logic: validates repository and TODO.md, applies three gap-filling strategies (annotate failed/blocked tasks, transition marked-complete tasks, warn on orphans), supports dry-run and per-batch filtering with aggregated reporting.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Possibly related PRs

Poem

🔄 Database whispers to TODO's tune,
Phase 7b arrives right on cue,
When tasks lay still and silence reigns,
The reconciler sweeps the plains—
DB and Markdown, finally in sync! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding a DB-TODO reconciliation phase (7b) to the supervisor's pulse cycle. It is specific, concise, and directly reflects the primary objective of the changeset.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/t1001

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@github-actions
Copy link

🔍 Code Quality Report

�[0;35m[MONITOR]�[0m Code Review Monitoring Report

�[0;34m[INFO]�[0m Latest Quality Status:
SonarCloud: 0 bugs, 0 vulnerabilities, 15 code smells

�[0;34m[INFO]�[0m Recent monitoring activity:
Thu Feb 12 16:57:49 UTC 2026: Code review monitoring started
Thu Feb 12 16:57:50 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 15

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 15
  • VULNERABILITIES: 0

Generated on: Thu Feb 12 16:57:52 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

@sonarqubecloud
Copy link

@marcusquinn marcusquinn merged commit ccc33b8 into main Feb 12, 2026
10 of 11 checks passed
@marcusquinn marcusquinn deleted the feature/t1001 branch February 12, 2026 16:59
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @.agents/scripts/supervisor/todo-sync.sh:
- Around line 1016-1026: Gap 2's SQL list of terminal states omits "merged" (and
possibly related states), causing tasks marked [x] in TODO.md and with status
"merged" to be pulled as non-terminal and regress; update the NOT IN clause used
to populate all_db_tasks so it includes 'merged' (and, after review, consider
adding 'deploying', 'verifying', 'verify_failed' if those should be terminal) to
match how cmd_reconcile_todo and cmd_update_todo treat merged as a completed
state.
🧹 Nitpick comments (1)
.agents/scripts/supervisor/todo-sync.sh (1)

987-987: Unescaped dots in task IDs used as regex patterns.

Task IDs can contain dots (e.g., t123.4 for subtasks). When used directly in grep -E patterns, the dot matches any character — so t123.4 would also match t12304 or t123x4. This could cause false positives in all three gap checks.

The existing update_todo_on_blocked (line 614) and update_todo_on_complete (line 418) have the same pattern, so this is a pre-existing issue, but since this is a new function it's worth hardening.

🛡️ Proposed fix — escape dots in task IDs before grep

Add near line 970 (before the gap checks begin):

+	# Escape dots in task IDs for safe use in grep -E patterns
+	_escape_tid() { printf '%s' "$1" | sed 's/\./\\./g'; }
+
 	# --- Gap 1: DB failed/blocked but TODO.md has no annotation ---

Then use it in each grep, e.g.:

-			line_num=$(grep -nE "^[[:space:]]*- \[ \] ${tid}( |$)" "$todo_file" | head -1 | cut -d: -f1)
+			local etid; etid=$(_escape_tid "$tid")
+			line_num=$(grep -nE "^[[:space:]]*- \[ \] ${etid}( |$)" "$todo_file" | head -1 | cut -d: -f1)

Apply similarly at lines 1033 and 1069.

Also applies to: 1033-1033, 1069-1069

Comment on lines +1016 to +1026
# --- Gap 2: TODO.md [x] but DB still in non-terminal state ---
# Terminal states: complete, deployed, verified, failed, blocked, cancelled
# Non-terminal: queued, dispatched, running, evaluating, retrying,
# pr_review, review_triage, merging, merged, deploying, verifying, verify_failed
local all_db_tasks
all_db_tasks=$(db -separator '|' "$SUPERVISOR_DB" "
SELECT t.id, t.status FROM tasks t
WHERE t.status NOT IN ('complete', 'deployed', 'verified', 'failed', 'blocked', 'cancelled')
$batch_filter
ORDER BY t.id;
")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

merged (and possibly deploying, verifying) may be incorrectly classified as non-terminal.

cmd_reconcile_todo (line 738) and cmd_update_todo (line 684) both treat merged as a completed/terminal state. However, Gap 2's SQL excludes only complete, deployed, verified, failed, blocked, cancelled — meaning a task in merged state that's [x] in TODO.md would be transitioned back to complete, which is likely a state regression.

Consider adding merged (and review whether deploying, verifying, verify_failed should also be terminal) to the exclusion list:

🐛 Proposed fix
-		WHERE t.status NOT IN ('complete', 'deployed', 'verified', 'failed', 'blocked', 'cancelled')
+		WHERE t.status NOT IN ('complete', 'deployed', 'verified', 'merged', 'failed', 'blocked', 'cancelled')
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# --- Gap 2: TODO.md [x] but DB still in non-terminal state ---
# Terminal states: complete, deployed, verified, failed, blocked, cancelled
# Non-terminal: queued, dispatched, running, evaluating, retrying,
# pr_review, review_triage, merging, merged, deploying, verifying, verify_failed
local all_db_tasks
all_db_tasks=$(db -separator '|' "$SUPERVISOR_DB" "
SELECT t.id, t.status FROM tasks t
WHERE t.status NOT IN ('complete', 'deployed', 'verified', 'failed', 'blocked', 'cancelled')
$batch_filter
ORDER BY t.id;
")
# --- Gap 2: TODO.md [x] but DB still in non-terminal state ---
# Terminal states: complete, deployed, verified, failed, blocked, cancelled
# Non-terminal: queued, dispatched, running, evaluating, retrying,
# pr_review, review_triage, merging, merged, deploying, verifying, verify_failed
local all_db_tasks
all_db_tasks=$(db -separator '|' "$SUPERVISOR_DB" "
SELECT t.id, t.status FROM tasks t
WHERE t.status NOT IN ('complete', 'deployed', 'verified', 'merged', 'failed', 'blocked', 'cancelled')
$batch_filter
ORDER BY t.id;
")
🤖 Prompt for AI Agents
In @.agents/scripts/supervisor/todo-sync.sh around lines 1016 - 1026, Gap 2's
SQL list of terminal states omits "merged" (and possibly related states),
causing tasks marked [x] in TODO.md and with status "merged" to be pulled as
non-terminal and regress; update the NOT IN clause used to populate all_db_tasks
so it includes 'merged' (and, after review, consider adding 'deploying',
'verifying', 'verify_failed' if those should be terminal) to match how
cmd_reconcile_todo and cmd_update_todo treat merged as a completed state.

@gemini-code-assist
Copy link

Summary of Changes

Hello @marcusquinn, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the robustness and consistency of task management by introducing a new reconciliation phase. It ensures that the database and TODO.md file accurately reflect each other's state, addressing several scenarios where discrepancies could arise. This improves the reliability of task tracking and reduces manual intervention for common synchronization issues, making the system more resilient to out-of-sync states.

Highlights

  • New Reconciliation Phase: Introduced a new Phase 7b in the supervisor's pulse cycle for bidirectional database and TODO.md reconciliation, running when no tasks are active to prevent interference.
  • New CLI Command: Added a new CLI command supervisor-helper.sh reconcile-db-todo with options for batch filtering and dry-run mode, allowing manual or scheduled execution of the reconciliation logic.
  • DB to TODO.md Annotation: Implemented logic to automatically annotate failed or blocked tasks in TODO.md with their status and error details if they lack existing notes.
  • TODO.md to DB Completion: Included functionality to transition database tasks to a complete state if they are marked as [x] in TODO.md but remain in a non-terminal state in the database.
  • DB Orphan Detection: Added logging for 'DB orphan' tasks (tasks present in the database without a corresponding TODO.md entry) to alert for human review, without automatic modification.
Changelog
  • .agents/scripts/supervisor-helper.sh
    • Added reconcile-db-todo to the supervisor-helper.sh usage instructions.
    • Integrated cmd_reconcile_db_todo into the cmd_pulse function as "Phase 7b" for automated execution.
    • Mapped reconcile-db-todo to cmd_reconcile_db_todo in the main command dispatch for CLI access.
  • .agents/scripts/supervisor/todo-sync.sh
    • Implemented the cmd_reconcile_db_todo function, which handles three types of synchronization gaps between the database and TODO.md.
    • Added logic to identify and annotate failed/blocked tasks in TODO.md that are missing notes.
    • Included logic to mark database tasks as complete if they are checked off in TODO.md but are still in a non-terminal DB state.
    • Implemented logging for database tasks that have no corresponding entry in TODO.md to flag potential orphans.
Activity
  • No human activity has been recorded on this pull request since its creation.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new supervisor pulse phase (7b) and the reconcile-db-todo command for bidirectional reconciliation between the database and TODO.md, aiming to synchronize tasks and address discrepancies. My review identified a potential SQL injection risk, a couple of shell style guide violations regarding error suppression, and an opportunity to optimize the database access pattern.

if [[ -n "$batch_id" ]]; then
local escaped_batch
escaped_batch=$(sql_escape "$batch_id")
batch_filter="AND EXISTS (SELECT 1 FROM batch_tasks bt WHERE bt.task_id = t.id AND bt.batch_id = '$escaped_batch')"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Constructing SQL queries by embedding variables, even after escaping, can be vulnerable to SQL injection. This pattern is used in three separate database queries within this function. If the db helper function supports parameterized queries, that would be a more secure approach. If not, consider adding strict validation for batch_id to ensure it only contains expected characters before it's used in the query.

References
  1. The style guide recommends using parameterized queries where possible to prevent SQL injection vulnerabilities. (link)


# Determine repo path
if [[ -z "$repo_path" ]]; then
repo_path=$(db "$SUPERVISOR_DB" "SELECT DISTINCT repo FROM tasks LIMIT 1;" 2>/dev/null || echo "")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This line uses 2>/dev/null to suppress stderr, which violates the repository style guide. While || echo "" handles a non-zero exit code, suppressing the error message hides potentially useful diagnostic information. The error output should be allowed to pass through or be redirected to a log file like $SUPERVISOR_LOG.

Suggested change
repo_path=$(db "$SUPERVISOR_DB" "SELECT DISTINCT repo FROM tasks LIMIT 1;" 2>/dev/null || echo "")
repo_path=$(db "$SUPERVISOR_DB" "SELECT DISTINCT repo FROM tasks LIMIT 1;" || echo "")
References
  1. The style guide prohibits blanket stderr suppression with 2>/dev/null, allowing it only when redirecting to a log file. (link)

Comment on lines +972 to +1081
# --- Gap 1: DB failed/blocked but TODO.md has no annotation ---
local failed_tasks
failed_tasks=$(db -separator '|' "$SUPERVISOR_DB" "
SELECT t.id, t.status, t.error FROM tasks t
WHERE t.status IN ('failed', 'blocked')
$batch_filter
ORDER BY t.id;
")

if [[ -n "$failed_tasks" ]]; then
while IFS='|' read -r tid tstatus terror; do
[[ -z "$tid" ]] && continue

# Check if task is open in TODO.md with no Notes annotation
local line_num
line_num=$(grep -nE "^[[:space:]]*- \[ \] ${tid}( |$)" "$todo_file" | head -1 | cut -d: -f1)
[[ -z "$line_num" ]] && continue

# Check if a Notes line already exists below
local next_line_num=$((line_num + 1))
local next_line
next_line=$(sed -n "${next_line_num}p" "$todo_file" 2>/dev/null || echo "")

if echo "$next_line" | grep -qE "^[[:space:]]*- Notes:"; then
# Notes already present — skip
continue
fi

issue_count=$((issue_count + 1))

if [[ "$dry_run" == "true" ]]; then
log_warn "[dry-run] $tid: DB status=$tstatus but TODO.md has no annotation"
else
log_info "Phase 7b: Annotating $tid ($tstatus) in TODO.md"
local reason="${terror:-no error details}"
update_todo_on_blocked "$tid" "$reason" 2>>"${SUPERVISOR_LOG:-/dev/null}" || {
log_warn "Phase 7b: Failed to annotate $tid"
continue
}
fixed_count=$((fixed_count + 1))
fi
done <<<"$failed_tasks"
fi

# --- Gap 2: TODO.md [x] but DB still in non-terminal state ---
# Terminal states: complete, deployed, verified, failed, blocked, cancelled
# Non-terminal: queued, dispatched, running, evaluating, retrying,
# pr_review, review_triage, merging, merged, deploying, verifying, verify_failed
local all_db_tasks
all_db_tasks=$(db -separator '|' "$SUPERVISOR_DB" "
SELECT t.id, t.status FROM tasks t
WHERE t.status NOT IN ('complete', 'deployed', 'verified', 'failed', 'blocked', 'cancelled')
$batch_filter
ORDER BY t.id;
")

if [[ -n "$all_db_tasks" ]]; then
while IFS='|' read -r tid tstatus; do
[[ -z "$tid" ]] && continue

# Check if this task is marked [x] in TODO.md
if grep -qE "^[[:space:]]*- \[x\] ${tid}( |$)" "$todo_file"; then
issue_count=$((issue_count + 1))

if [[ "$dry_run" == "true" ]]; then
log_warn "[dry-run] $tid: marked [x] in TODO.md but DB status=$tstatus"
else
log_info "Phase 7b: Transitioning $tid from $tstatus to complete (TODO.md shows [x])"
cmd_transition "$tid" "complete" \
--reason "Reconciled: TODO.md marked [x] but DB was $tstatus (t1001)" \
2>>"${SUPERVISOR_LOG:-/dev/null}" || {
log_warn "Phase 7b: Failed to transition $tid to complete"
continue
}
fixed_count=$((fixed_count + 1))
fi
fi
done <<<"$all_db_tasks"
fi

# --- Gap 3: DB orphans — tasks in DB with no TODO.md entry at all ---
local orphan_tasks
orphan_tasks=$(db -separator '|' "$SUPERVISOR_DB" "
SELECT t.id, t.status FROM tasks t
WHERE t.status NOT IN ('cancelled')
$batch_filter
ORDER BY t.id;
")

local orphan_count=0
local orphan_ids=""

if [[ -n "$orphan_tasks" ]]; then
while IFS='|' read -r tid tstatus; do
[[ -z "$tid" ]] && continue

# Check if task ID appears anywhere in TODO.md (open, closed, or in notes)
if ! grep -qE "(^|[[:space:]])${tid}([[:space:]]|$)" "$todo_file"; then
orphan_count=$((orphan_count + 1))
orphan_ids="${orphan_ids}${orphan_ids:+, }${tid}(${tstatus})"
fi
done <<<"$orphan_tasks"
fi

if [[ "$orphan_count" -gt 0 ]]; then
issue_count=$((issue_count + orphan_count))
log_warn "Phase 7b: $orphan_count DB orphan(s) with no TODO.md entry: $orphan_ids"
# Orphans are logged but not auto-fixed — they may be from other repos
# or manually managed tasks. The warning enables human review.
fi

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This function executes three separate queries against the database to handle the three reconciliation gaps. This could be optimized by fetching all potentially relevant tasks in a single query and then processing them in memory within Bash. This would reduce the number of round-trips to the database and could improve performance, especially if the tasks table is large.

For example:

Fetch all non-cancelled tasks once

all_tasks=$(db -separator '|' "$SUPERVISOR_DB" "
SELECT t.id, t.status, t.error FROM tasks t
WHERE t.status NOT IN ('cancelled')
$batch_filter
ORDER BY t.id;
")

Then process all gaps in one or two passes in Bash

...

# Check if a Notes line already exists below
local next_line_num=$((line_num + 1))
local next_line
next_line=$(sed -n "${next_line_num}p" "$todo_file" 2>/dev/null || echo "")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This line uses 2>/dev/null to suppress stderr from sed, which violates the repository style guide. While || echo "" handles a non-zero exit code, suppressing the error message hides potentially useful diagnostic information, for example if sed fails for some reason.

Suggested change
next_line=$(sed -n "${next_line_num}p" "$todo_file" 2>/dev/null || echo "")
next_line=$(sed -n "${next_line_num}p" "$todo_file" || echo "")
References
  1. The style guide prohibits blanket stderr suppression with 2>/dev/null, allowing it only when redirecting to a log file. (link)

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