Skip to content

.2869047221311500:9d3530f31d51704bbbf0788d65abc457_69e9cad9b964995ded0a5f13.69eb6635af036c7c109c4cd0.69eb663571f280523c1e801f:Trae CN.T(2026/4/24 20:46:45)#99

Open
Juebandoctor wants to merge 3 commits into
TheDevOpsBlueprint:mainfrom
Juebandoctor:Trae_3

Conversation

@Juebandoctor
Copy link
Copy Markdown

PR Checklist

  • Follows single-purpose principle
  • Tests pass locally
  • Documentation updated (if needed)

What does this PR do?

Related Issue

Closes #

Type of change

  • Bug fix
  • New feature
  • Configuration
  • Documentation

扩展Task模型和存储方法以支持团队协作功能,包括:
- 添加任务所有者、审核者字段
- 实现任务状态管理
- 增加任务阻塞关系
- 添加事件标记和交接说明
- 实现截止日期和状态显示方法
- 将 `--task-status` 参数重命名为 `--status` 以保持一致性
- 为 `filter_apply` 命令添加团队协作筛选选项(负责人、评审人、状态等)
- 改进任务列表展示,支持详细视图显示更多信息
- 扩展保存的过滤器功能,支持存储所有新筛选条件
添加新的交接报告文档 handoff.md
修改 CLI 命令参数命名风格,将 --due 改为 --due-at,--handoff 改为 --handoff-note
增加 --blocked-by 参数支持批量设置阻塞任务
优化阻塞任务处理逻辑,支持增量添加和移除
Copilot AI review requested due to automatic review settings April 24, 2026 12:58
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR expands the Task model and CLI to support team-collaboration workflows (owner/reviewer/status/due dates/blockers/incidents), and adds new reporting commands to surface handoff and daily summaries.

Changes:

  • Extend Task with collaboration fields plus status/due/blocker helper methods and serialization support.
  • Update JSON storage and CLI task creation/edit/list/filter flows to accept, persist, and display collaboration metadata.
  • Add new CLI reports (handoff, daily) and supporting parsing/formatting helpers.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 10 comments.

File Description
tix/storage/json_storage.py Extends add_task() to persist new collaboration fields when creating tasks.
tix/models.py Adds collaboration fields, serialization updates, and helper methods (status/blockers/due).
tix/cli.py Adds new CLI flags/filters, due/blocker parsing, enhanced list views, and new handoff/daily commands.
handoff.md Adds a markdown handoff report file that appears to be generated output/example content.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tix/models.py
Comment on lines +79 to +86
# Team collaboration fields with safe defaults
owner=data.get('owner'),
reviewer=data.get('reviewer'),
status=data.get('status', 'todo'),
due_at=data.get('due_at'),
handoff_note=data.get('handoff_note'),
blocked_by=data.get('blocked_by', []),
incident=data.get('incident', False),
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

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

Task.from_dict defaults status to 'todo' even when completed=True for legacy tasks that don't have a status field. That will render completed tasks with a non-done status and may affect filters/sorting. Consider normalizing on load: if data.get('completed') is True and no explicit status is present, set status to 'done' (and/or ensure status='done' implies completed=True).

Copilot uses AI. Check for mistakes.
Comment thread tix/models.py
"""Set which tasks block this one"""
self.blocked_by = task_ids
if task_ids:
self.status = 'blocked'
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

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

set_blocked_by([]) clears blocked_by but leaves status unchanged. This can produce tasks with status='blocked' while blocked_by is empty, which makes is_blocked() return false and creates inconsistent UI/filter behavior. Consider resetting status back to a non-blocked state (e.g., 'todo' or previous status) when the list becomes empty.

Suggested change
self.status = 'blocked'
self.status = 'blocked'
elif self.status == 'blocked':
self.status = 'todo'

Copilot uses AI. Check for mistakes.
Comment thread tix/models.py
Comment on lines +201 to +211
def needs_handoff(self) -> bool:
"""Check if task needs handoff note (blocked but no note, or due soon without note)"""
if self.completed:
return False
# Blocked tasks should have handoff notes
if self.is_blocked() and not self.handoff_note:
return True
# Cross-person collaboration needs reviewer
if self.owner and not self.reviewer and self.status == 'review':
return True
return False
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

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

The needs_handoff docstring says it checks "blocked but no note, or due soon without note", but the implementation does not include any due-soon logic. Either add the due-soon condition or update the docstring so it matches the actual behavior (blocked-without-note and review-without-reviewer).

Copilot uses AI. Check for mistakes.
Comment thread tix/cli.py
- Tasks needing handoff
- Incident tasks
"""
from datetime import datetime, timedelta
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

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

daily_report() imports timedelta but never uses it. With the current flake8 settings this will raise F401. Remove the unused import (or add logic that uses it).

Suggested change
from datetime import datetime, timedelta
from datetime import datetime

Copilot uses AI. Check for mistakes.
Comment thread tix/cli.py
Comment on lines +2324 to +2326
for task in stats['overdue']:
lines.append(f"- [ ] #{task.id} {task.text} (Due: {task.get_due_date_display()})")
lines.append("")
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

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

The markdown daily report also embeds Rich markup via task.get_due_date_display(), which will render as literal [red]...[/red] text in a saved .md. Consider using a plain-text due-date formatter for markdown outputs.

Copilot uses AI. Check for mistakes.
Comment thread handoff.md
Comment on lines +1 to +39
# 📋 Handoff Report

**Generated:** 2026-04-24 20:55

## 🔴 Tasks Due Today (Need Handoff)

- [ ] **#2** TC full incident task
- Owner: alice
- Handoff Note: Check auth logs before next shift

## ⚠️ Unassigned High-Priority Tasks

- [ ] **#1** first task

- [ ] **#3** TC unassigned high bug
- Due: [yellow]Soon: 2026-04-24[/yellow]

## ✅ Blocked Tasks

All blocked tasks have handoff notes.

## 👀 Tasks Needing Reviewer

- [ ] **#5** TC reviewer missing
- Owner: alice

## ⏰ Overdue Incomplete Tasks

- [ ] **#6** TC overdue unfinished
- Owner: carol
- Due: [red]OVERDUE: 2020-01-01[/red]

## 📊 Summary

- Tasks due today: 1
- Unassigned high-priority: 2
- Blocked without notes: 0
- Needs reviewer: 1
- Overdue incomplete: 1
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

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

This file looks like generated output from the new tix handoff --format markdown command (it includes a specific "Generated" timestamp and sample task content). If it’s not intended as a checked-in example, it should be removed from the repo (or moved under a docs/examples location and made generic so it doesn’t change every run).

Suggested change
# 📋 Handoff Report
**Generated:** 2026-04-24 20:55
## 🔴 Tasks Due Today (Need Handoff)
- [ ] **#2** TC full incident task
- Owner: alice
- Handoff Note: Check auth logs before next shift
## ⚠️ Unassigned High-Priority Tasks
- [ ] **#1** first task
- [ ] **#3** TC unassigned high bug
- Due: [yellow]Soon: 2026-04-24[/yellow]
## ✅ Blocked Tasks
All blocked tasks have handoff notes.
## 👀 Tasks Needing Reviewer
- [ ] **#5** TC reviewer missing
- Owner: alice
## ⏰ Overdue Incomplete Tasks
- [ ] **#6** TC overdue unfinished
- Owner: carol
- Due: [red]OVERDUE: 2020-01-01[/red]
## 📊 Summary
- Tasks due today: 1
- Unassigned high-priority: 2
- Blocked without notes: 0
- Needs reviewer: 1
- Overdue incomplete: 1
# 📋 Handoff Report Example
**Generated:** `<timestamp>`
> Example output for documentation purposes. Replace with real command output when generating a handoff report.
## 🔴 Tasks Due Today (Need Handoff)
- [ ] **#<id>** Example due-today task
- Owner: `<owner>`
- Handoff Note: `<handoff note>`
## ⚠️ Unassigned High-Priority Tasks
- [ ] **#<id>** Example unassigned high-priority task
- Due: `<due date>`
## ✅ Blocked Tasks
All blocked tasks in this example have handoff notes.
## 👀 Tasks Needing Reviewer
- [ ] **#<id>** Example task needing reviewer
- Owner: `<owner>`
## ⏰ Overdue Incomplete Tasks
- [ ] **#<id>** Example overdue incomplete task
- Owner: `<owner>`
- Due: `<overdue date>`
## 📊 Summary
- Tasks due today: `<count>`
- Unassigned high-priority: `<count>`
- Blocked without notes: `<count>`
- Needs reviewer: `<count>`
- Overdue incomplete: `<count>`

Copilot uses AI. Check for mistakes.
Comment on lines +108 to 113
status=status,
due_at=due_at,
handoff_note=handoff_note,
blocked_by=blocked_by or [],
incident=incident,
)
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

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

TaskStorage.add_task passes status straight into the Task constructor without validation/normalization. This can create inconsistent tasks (e.g., status='done' but completed=False and completed_at=None). Consider validating via Task.set_status(status) after instantiation (or normalize completed/completed_at when status is done) so storage-level APIs always produce consistent tasks, not just the CLI path.

Suggested change
status=status,
due_at=due_at,
handoff_note=handoff_note,
blocked_by=blocked_by or [],
incident=incident,
)
due_at=due_at,
handoff_note=handoff_note,
blocked_by=blocked_by or [],
incident=incident,
)
new_task.set_status(status)

Copilot uses AI. Check for mistakes.
Comment thread tix/cli.py
Comment on lines +1929 to +1931
from datetime import datetime, timedelta
from collections import defaultdict

Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

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

handoff() has unused imports (timedelta, defaultdict). The repo’s flake8 config doesn’t ignore F401 outside __init__.py, so this will fail linting. Remove the unused imports or use them.

Copilot uses AI. Check for mistakes.
Comment thread tix/cli.py
Comment on lines +2002 to +2004
if task.due_at:
lines.append(f" - Due: {task.get_due_date_display()}")
lines.append("")
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

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

In markdown output, the report uses task.get_due_date_display(), which returns Rich markup like [red]...[/red]. When writing to a .md file this markup will be embedded verbatim (see the committed handoff.md). Consider emitting plain text for markdown (e.g., a separate get_due_date_display_plain() or a rich: bool flag).

Copilot uses AI. Check for mistakes.
Comment thread tix/models.py
Comment on lines +229 to +238
# If marking as done, also mark completed
if new_status == 'done' and not self.completed:
self.mark_done()
else:
self.status = new_status
# If reactivating a done task
if self.completed and new_status != 'done':
self.completed = False
self.completed_at = None

Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

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

A large amount of new collaboration logic was added to Task (status transitions, blocker handling, due-date calculations). There are existing model tests in tests/test_models.py, but none cover the new behaviors. Adding targeted tests for set_status, set_blocked_by/remove_blocker, and is_overdue/is_due_soon would help prevent regressions.

Suggested change
# If marking as done, also mark completed
if new_status == 'done' and not self.completed:
self.mark_done()
else:
self.status = new_status
# If reactivating a done task
if self.completed and new_status != 'done':
self.completed = False
self.completed_at = None
# If marking as done, keep completion fields in sync.
if new_status == 'done':
if not self.completed:
self.mark_done()
self.status = 'done'
return
# Reactivating a completed task should clear completion metadata.
was_completed = self.completed
self.status = new_status
if was_completed:
self.completed = False
self.completed_at = None

Copilot uses AI. Check for mistakes.
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.

2 participants