mirror of
https://github.com/kuhyx/todo-app.git
synced 2026-11-10 18:07:03 +01:00
Some checks are pending
dependency freshness / dependencies on newest stable (push) Waiting to run
file-length / file length <= 250 lines (push) Waiting to run
md-naming / markdown naming convention (push) Waiting to run
release-apk / release (APK) (push) Waiting to run
repo-contract / repo contract (push) Waiting to run
New optional note field created_by (kuhy|claude), stored like by/repo and omitted when unset so older builds stay wire-compatible. App UI stamps kuhy; MCP add_task and the CLI stamp claude. list/get/search output includes it. Human notes sort above Claude's; Claude notes are hidden behind a per-device eye toggle. CLI --backfill-created-by [--dry-run] classifies old notes by the node that wrote created_at, writing only the created_by field. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
68 lines
2.2 KiB
Dart
68 lines
2.2 KiB
Dart
/// `add_task` with `new_note: true`: the separate note, the guard merge and
|
|
/// the board Start that follows a merge, as one reply text.
|
|
library;
|
|
|
|
import 'package:todo/data/note.dart';
|
|
import 'package:todo/data/note_repository.dart';
|
|
import 'package:todo/data/repo_note_split.dart';
|
|
import 'package:todo/mcp/board_client.dart';
|
|
|
|
/// Saves [note] and returns `<verb> <id>` plus its list line.
|
|
typedef SaveNote = Future<String> Function(Note note, String verb);
|
|
|
|
/// A saved split add: its reply so far, and the board Start still to run.
|
|
/// The caller runs [start] after releasing its lock, since the board learns
|
|
/// about the merged section by calling this same server (T1865).
|
|
typedef SplitReply = ({String reply, Future<String> Function()? start});
|
|
|
|
/// Adds a separate task, merging into a duplicate's note when it is idle;
|
|
/// a merge that may run comes back with the Start to click on the board.
|
|
Future<SplitReply> addSplit(
|
|
NoteRepository repository,
|
|
BoardClient? board,
|
|
SaveNote save, {
|
|
required String repo,
|
|
required String title,
|
|
required String body,
|
|
required String? doneCheck,
|
|
required Priority priority,
|
|
}) async {
|
|
final added = await addSeparateTask(
|
|
repository,
|
|
repo: repo,
|
|
title: title,
|
|
body: body,
|
|
doneCheck: doneCheck,
|
|
priority: priority,
|
|
by: 'claude',
|
|
createdBy: 'claude',
|
|
busy: board == null ? null : (n) => board.running(n.id),
|
|
);
|
|
if (added.kind != SplitKind.merged) {
|
|
final reply = await save(added.note, 'added');
|
|
return (
|
|
reply: added.why == null ? reply : '$reply\n${added.why}',
|
|
start: null,
|
|
);
|
|
}
|
|
final reply = await save(added.note, 'merged into');
|
|
final block = startBlock(doneCheck, body);
|
|
if (block != null) {
|
|
return (reply: '$reply\nstart: skipped ($block)', start: null);
|
|
}
|
|
Future<String> start() async {
|
|
final s = board == null
|
|
? (ok: false, reason: 'no board configured', item: null)
|
|
: await board.start(
|
|
added.note.id,
|
|
title.trim(),
|
|
sections: sectionCount(added.note.text),
|
|
);
|
|
if (s.ok) return 'start: ok ${s.item}';
|
|
return 'start: {ok: false, reason: "${s.reason}"}; '
|
|
'the merge is saved, click Start on the board by hand';
|
|
}
|
|
|
|
return (reply: reply, start: start);
|
|
}
|