Skip to content

Commit b280294

Browse files
RMANOVclaude
andcommitted
feat: add Notes type, collaboration, and shared task review
- Add type column (task/note) to tasks table with 5 migrations - Notes are never auto-archived or purged (persistent references) - Add assignee/shared_by columns for cross-account collaboration - New MCP tools: assign_task, review_shared_tasks - bridge_push: cross-account push to assignee's memory-bridge repo - bridge_pull: stage shared_tasks in pending_shared_tasks (security) - UI: Notes tab, type dropdown, Convert context menu, [N] prefix - Kanban: NOTE badge on cards - Digest: filter to tasks only, --include-notes CLI flag - Hook: assign_task added to bridge_auto_sync WRITE_TOOLS BREAKING: shared_tasks from other accounts now require explicit approval via review_shared_tasks(action="approve") before import. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 22edd88 commit b280294

5 files changed

Lines changed: 525 additions & 47 deletions

File tree

daily_digest.py

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ def run_digest(
2626
sections: list[str],
2727
include_overdue: bool,
2828
limit: int,
29+
include_notes: bool = False,
2930
) -> str:
3031
"""Query the DB and return a markdown digest string."""
3132

@@ -35,7 +36,7 @@ def run_digest(
3536
active = conn.execute(
3637
f"SELECT id, title, status, priority, section, due_date, project "
3738
f"FROM tasks "
38-
f"WHERE section IN ({ph}) AND status IN ('not_started', 'in_progress') "
39+
f"WHERE section IN ({ph}) AND status IN ('not_started', 'in_progress') AND type = 'task' "
3940
f"ORDER BY "
4041
f" CASE section WHEN 'today' THEN 0 WHEN 'inbox' THEN 1 "
4142
f" WHEN 'next' THEN 2 WHEN 'waiting' THEN 3 WHEN 'someday' THEN 4 END, "
@@ -50,17 +51,27 @@ def run_digest(
5051
overdue = conn.execute(
5152
"SELECT id, title, status, priority, section, due_date, project "
5253
"FROM tasks "
53-
f"WHERE due_date < date('now') AND status NOT IN ({_EXCL_PH}) "
54+
f"WHERE due_date < date('now') AND status NOT IN ({_EXCL_PH}) AND type = 'task' "
5455
"ORDER BY due_date ASC LIMIT 10",
5556
list(TASK_ACTIVE_EXCLUSIONS),
5657
).fetchall()
5758

5859
# Status counts (active + done, excluding archived/cancelled)
5960
counts = conn.execute(
6061
"SELECT status, COUNT(*) as cnt FROM tasks "
61-
"WHERE status NOT IN ('archived', 'cancelled') GROUP BY status"
62+
"WHERE status NOT IN ('archived', 'cancelled') AND type = 'task' GROUP BY status"
6263
).fetchall()
6364

65+
note_rows: list = []
66+
if include_notes:
67+
note_rows = conn.execute(
68+
"SELECT id, title, priority, updated_at FROM tasks "
69+
"WHERE type = 'note' AND status NOT IN ('archived', 'cancelled') "
70+
f"ORDER BY {build_priority_order_sql()}, updated_at DESC "
71+
"LIMIT ?",
72+
(limit,),
73+
).fetchall()
74+
6475
# ── Format markdown ───────────────────────────────────────────────────────
6576
now_utc = now_iso()
6677
lines = [
@@ -103,6 +114,13 @@ def run_digest(
103114
lines.append(f"- {prio}{t['title']}{due}")
104115
lines.append("")
105116

117+
if note_rows:
118+
lines.append(f"### NOTES ({len(note_rows)})")
119+
for n in note_rows:
120+
prio = f"[{n['priority'].upper()}] " if n["priority"] != "medium" else ""
121+
lines.append(f"- {prio}{n['title']}")
122+
lines.append("")
123+
106124
if not active and not overdue:
107125
lines.append("*No tasks found for the selected sections.*")
108126
lines.append("")
@@ -142,6 +160,12 @@ def main() -> int:
142160
metavar="N",
143161
help="Max tasks to fetch per query (default: 20)",
144162
)
163+
parser.add_argument(
164+
"--include-notes",
165+
action="store_true",
166+
default=False,
167+
help="Include notes in the digest output",
168+
)
145169

146170
args = parser.parse_args()
147171

@@ -161,6 +185,7 @@ def main() -> int:
161185
sections=sections,
162186
include_overdue=args.include_overdue,
163187
limit=args.limit,
188+
include_notes=args.include_notes,
164189
)
165190
print(digest)
166191
return 0

db_utils.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
TASK_SECTIONS = ("inbox", "today", "next", "someday", "waiting")
3131
TASK_PRIORITIES = ("low", "medium", "high", "critical") # ascending rank
3232
TASK_STATUSES = ("not_started", "in_progress", "done", "archived", "cancelled")
33+
TASK_TYPES = ("task", "note")
3334
TASK_HIDDEN_STATUSES = ("archived", "cancelled")
3435
TASK_ACTIVE_EXCLUSIONS = ("done", "archived", "cancelled")
3536

@@ -54,6 +55,9 @@
5455
"parent_id",
5556
"notes",
5657
"recurring",
58+
"type",
59+
"assignee",
60+
"shared_by",
5761
"updated_at",
5862
}
5963
)

0 commit comments

Comments
 (0)