OmniStacksStaticModules 2.0.0
Loading...
Searching...
No Matches
TaskManager.cppm File Reference
#include <fcntl.h>
#include <sys/file.h>
#include <unistd.h>
#include <algorithm>
#include <atomic>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cstdint>
#include <ctime>
#include <filesystem>
#include <format>
#include <fstream>
#include <optional>
#include <random>
#include <string>
#include <string_view>
#include <unordered_map>
#include <utility>
#include <vector>
#include "json.hpp"
import InterfaceLog;
import std;
Include dependency graph for TaskManager.cppm:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  TaskManager::TargetId
 可创建任务的看板目标 ID。 More...
struct  TaskManager::TaskId
 已校验任务 ID;作为所有任务读写接口的稳定主键。 More...
struct  TaskManager::TaskTitle
 任务标题;create/update 时仍会执行 trim 与空值校验。 More...
struct  TaskManager::TaskDescription
 任务描述;允许空字符串,不改写 Markdown/HTML 内容。 More...
struct  TaskManager::DatabasePaths
 三个运行数据库路径;一次传参避免同类 path 参数顺序错误。 More...
struct  TaskManager::CreateTaskOptions
 创建任务所需的数据库与 Inbox 默认工作区。 More...
struct  TaskManager::TaskInput
 创建任务输入;日期保留用户文本,由 normalize_date 在业务层校验。 More...
struct  TaskManager::TaskPatch
 部分更新任务;optional 表示“未提供”,clear_* 表示“显式清空”。 More...
struct  TaskManager::TaskListOptions
 任务列表的过滤条件;默认保留已完成任务、排除已归档任务。 More...
struct  TaskManager::BoardTarget
 项目或清单的统一展示目标;WorkflowUI 用它构造 Alfred 条目。 More...
struct  TaskManager::TaskRecord
 跨模块使用的任务只读快照;字段名对应 Stacks 文件与 UI 展示语义。 More...
struct  TaskManager::TaskResult
 创建任务的稳定结果,不返回可被后续修改的内部 JSON。 More...
struct  TaskManager::TimerRecord
 Timers.json 中的运行中计时快照。 More...
struct  TaskManager::StopTimerResult
 停止计时结果;timelog_id 可在任务文件中定位新记录。 More...
struct  TaskManager::DeleteResult
 可恢复删除结果;trash_file 指向 tasks/.trash 中的副本。 More...
struct  TaskManager::WeekBounds
 周一至周日的 ISO 日期区间。 More...
struct  TaskManager::anonymous_namespace{TaskManager.cppm}::ProjectNode
 Project.json 节点的内部视图,不进入公开 API。 More...
struct  TaskManager::anonymous_namespace{TaskManager.cppm}::TaskLocation
 任务在项目/清单层级中的成员关系缓存。 More...
struct  TaskManager::anonymous_namespace{TaskManager.cppm}::LoadedTask
 原始 JSON 与展示快照一起返回,编辑时可保留未知 Stacks 字段。 More...
class  TaskManager::anonymous_namespace{TaskManager.cppm}::ScopedFileLock
 进程内排他写锁;析构时自动 flock unlock + close。 More...

Namespaces

namespace  TaskManager
namespace  TaskManager::anonymous_namespace{TaskManager.cppm}

Typedefs

using TaskManager::anonymous_namespace{TaskManager.cppm}::json = nlohmann::json

Enumerations

enum class  TaskManager::TaskError {
  TaskManager::invalid_target_id , TaskManager::invalid_task_id , TaskManager::empty_title , TaskManager::invalid_date ,
  TaskManager::invalid_date_range , TaskManager::invalid_priority , TaskManager::project_db_unreadable , TaskManager::stack_db_unreadable ,
  TaskManager::target_not_found , TaskManager::target_kind_unknown , TaskManager::project_file_not_found , TaskManager::project_file_unreadable ,
  TaskManager::task_not_found , TaskManager::task_file_unreadable , TaskManager::timer_not_running , TaskManager::timer_already_running ,
  TaskManager::timer_db_unreadable , TaskManager::no_inbox_library , TaskManager::invalid_library_path , TaskManager::lock_failure ,
  TaskManager::write_failure , TaskManager::delete_failure
}
 任务业务的可恢复错误分类;UI 只消费 task_error_message。 More...

Functions

TaskId TaskManager::generate_id ()
 生成线程安全的 20 字符任务 ID。
std::expected< TaskResult, TaskError > TaskManager::create_task (TargetId target_id, TaskInput input, const CreateTaskOptions &options)
 在项目或清单下创建任务,并回滚“任务已写、项目未写”的半成功状态。
std::expected< TaskResult, TaskError > TaskManager::create_inbox_task (TaskInput input, const CreateTaskOptions &options)
 在指定/默认工作区创建 Stacks project=inbox 任务。
std::expected< std::vector< BoardTarget >, TaskError > TaskManager::list_boards (const DatabasePaths &paths)
 按项目名排序加载项目与清单的扁平列表。
std::expected< std::vector< TaskRecord >, TaskError > TaskManager::list_tasks (const DatabasePaths &paths, const TaskListOptions &options={})
 扫描所有工作区任务并按目标、完成状态、归档状态和关键词过滤。
std::expected< std::vector< TaskRecord >, TaskError > TaskManager::list_week_due (const DatabasePaths &paths, std::optional< std::string > anchor_date=std::nullopt)
 返回指定自然周内未完成、未归档且有截止日期的任务。
std::expected< TaskRecord, TaskError > TaskManager::get_task (TaskId task_id, const DatabasePaths &paths)
 以任务 ID 在工作区索引中定位并读取任务快照。
std::expected< TaskRecord, TaskError > TaskManager::update_task (TaskId task_id, const TaskPatch &patch, const DatabasePaths &paths)
 应用部分更新;修改前后都会验证日期区间与优先级。
std::expected< TaskRecord, TaskError > TaskManager::set_due_date (TaskId task_id, std::string due_date, const DatabasePaths &paths)
 仅更新截止日期;内部复用 update_task。
std::expected< TaskRecord, TaskError > TaskManager::set_start_date (TaskId task_id, std::string start_date, const DatabasePaths &paths)
 仅更新开始日期;内部复用 update_task。
std::expected< TaskRecord, TaskError > TaskManager::set_schedule (TaskId task_id, std::string start_date, std::string due_date, const DatabasePaths &paths)
 同时更新开始与截止日期,并校验区间顺序。
std::expected< TaskRecord, TaskError > TaskManager::set_task_done (TaskId task_id, bool done, const DatabasePaths &paths)
 写入 Stacks 完成字段或清空完成状态。
std::expected< TaskRecord, TaskError > TaskManager::archive_task (TaskId task_id, const DatabasePaths &paths)
 写入 archived 时间,保留任务文件供后续恢复。
std::expected< DeleteResult, TaskError > TaskManager::delete_task (TaskId task_id, const DatabasePaths &paths)
 从所有项目引用移除任务,并把 .task 移入可恢复 .trash。
std::expected< TimerRecord, TaskError > TaskManager::start_timer (TaskId task_id, const DatabasePaths &paths)
 在 Timers.json 中登记运行中计时;重复启动返回分类错误。
std::expected< StopTimerResult, TaskError > TaskManager::stop_timer (TaskId task_id, const DatabasePaths &paths)
 停止计时、写 Stacks timelog,并在第二步失败时回滚任务文件。
std::expected< std::vector< TimerRecord >, TaskError > TaskManager::list_timers (const DatabasePaths &paths)
 列出 Timers.json 中的运行中计时快照。
std::expected< std::string, TaskError > TaskManager::normalize_date (std::string_view value, std::optional< std::string > anchor_date=std::nullopt)
 将 YYYY-MM-DD、today、tomorrow、+Nd 或英文星期解析为 ISO 日期。
WeekBounds TaskManager::week_bounds (std::optional< std::string > anchor_date=std::nullopt)
 计算锚点日期所在周的周一/周日边界。
std::string_view TaskManager::task_error_message (TaskError error) noexcept
 将 TaskError 映射为稳定的 CLI/Alfred 文本。
template<std::invocable< std::string_view > Visitor>
std::expected< std::size_t, TaskError > TaskManager::for_each_backlog_id (const std::filesystem::path &project_file, Visitor &&visitor)
 以函数对象遍历项目 backlog ID。
std::string TaskManager::anonymous_namespace{TaskManager.cppm}::trim (std::string value)
 去除首尾 ASCII 空白,保留标题/描述内部内容。
std::string TaskManager::anonymous_namespace{TaskManager.cppm}::lower_ascii (std::string value)
 仅做 ASCII 小写化,足够处理命令别名、优先级和任务搜索。
bool TaskManager::anonymous_namespace{TaskManager.cppm}::valid_identifier (std::string_view value)
 校验 Stacks ID 的跨 Alfred token 安全字符集。
std::string TaskManager::anonymous_namespace{TaskManager.cppm}::local_timestamp ()
 本地秒级时间,用于 Stacks UI 可读的 updated/completed/archived 字段。
std::string TaskManager::anonymous_namespace{TaskManager.cppm}::utc_timestamp ()
 UTC 微秒时间,用于 task.created/updated 的 ISO 兼容格式。
std::string TaskManager::anonymous_namespace{TaskManager.cppm}::local_date ()
 从本地时间戳提取 YYYY-MM-DD;转换失败时返回空串。
fs::path TaskManager::anonymous_namespace{TaskManager.cppm}::normalized_path (const fs::path &value)
 规范化绝对路径;不要求目标路径已存在,适配首次创建工作区目录。
std::expected< json, TaskError > TaskManager::anonymous_namespace{TaskManager.cppm}::load_json (const fs::path &file, TaskManager::TaskError parse_error)
 防御性读取 JSON 文件。
bool TaskManager::anonymous_namespace{TaskManager.cppm}::atomic_write_json (const fs::path &target, const json &value)
 以同目录临时文件 + rename 原子替换 JSON。
std::string TaskManager::anonymous_namespace{TaskManager.cppm}::string_value (const json &object, std::string_view key, std::string fallback={})
 只在目标字段为字符串时返回值,避免 nlohmann 类型异常穿透 API。
int TaskManager::anonymous_namespace{TaskManager.cppm}::int_value (const json &object, std::string_view key, int fallback=0)
 只在目标字段为整数时返回值;浮点和字符串一律回退。
bool TaskManager::anonymous_namespace{TaskManager.cppm}::bool_value (const json &object, std::string_view key, bool fallback=false)
 只在目标字段为布尔值时返回值。
void TaskManager::anonymous_namespace{TaskManager.cppm}::erase_json_id (json &array, std::string_view task_id)
 从 JSON 字符串数组中移除指定任务 ID,保留其他元素顺序。
std::optional< std::chrono::year_month_day > TaskManager::anonymous_namespace{TaskManager.cppm}::parse_iso_date (std::string_view value)
 严格解析 YYYY-MM-DD,并借助 year_month_day::ok 拒绝 2 月 30 日等非法日期。
std::string TaskManager::anonymous_namespace{TaskManager.cppm}::format_date (std::chrono::year_month_day date)
 将日历日期格式化为 Alfred/Stacks 共用的 ISO 文本。
std::string TaskManager::anonymous_namespace{TaskManager.cppm}::effective_anchor (const std::optional< std::string > &anchor)
 优先使用显式锚点;锚点非法或缺失时回退到当前本地日期。
std::optional< std::string > TaskManager::anonymous_namespace{TaskManager.cppm}::normalize_priority_value (std::string_view value)
 将用户优先级表达式归一化为 Stacks 值。
std::expected< std::vector< ProjectNode >, TaskError > TaskManager::anonymous_namespace{TaskManager.cppm}::load_projects (const DatabasePaths &paths)
 读取 Project.json,过滤无效/重复节点并恢复项目到工作区的归属。
std::expected< std::set< fs::path >, TaskError > TaskManager::anonymous_namespace{TaskManager.cppm}::load_libraries (const DatabasePaths &paths)
 合并 library_paths 与项目节点推导出的工作区,确保旧索引也能扫描任务。
std::expected< std::vector< BoardTarget >, TaskError > TaskManager::anonymous_namespace{TaskManager.cppm}::load_boards_impl (const DatabasePaths &paths)
 从项目文件恢复项目和清单的扁平看板列表。
std::expected< BoardTarget, TaskError > TaskManager::anonymous_namespace{TaskManager.cppm}::resolve_board (std::string_view id, const DatabasePaths &paths)
 在扁平看板列表中解析项目/清单目标,供创建任务定位 .project 文件。
std::expected< std::unordered_map< std::string, TaskLocation >, TaskError > TaskManager::anonymous_namespace{TaskManager.cppm}::load_memberships (const DatabasePaths &paths)
 建立“任务 ID → 项目/清单位置”缓存。
std::expected< LoadedTask, TaskError > TaskManager::anonymous_namespace{TaskManager.cppm}::load_task_from_file (const fs::path &file, const std::filesystem::path &library_path, const std::unordered_map< std::string, TaskLocation > &memberships)
 读取单个 .task:保留未知字段,并把 Stacks 原生字段映射为 TaskRecord。
std::expected< std::vector< TaskRecord >, TaskError > TaskManager::anonymous_namespace{TaskManager.cppm}::scan_tasks (const DatabasePaths &paths)
 扫描所有已保存工作区的 tasks 目录,跳过重复文件与损坏任务。
std::expected< LoadedTask, TaskError > TaskManager::anonymous_namespace{TaskManager.cppm}::find_task_raw (TaskId task_id, const DatabasePaths &paths)
 通过任务 ID 在所有工作区中查找原始 JSON,避免依赖全局唯一路径索引。
std::expected< TaskRecord, TaskError > TaskManager::anonymous_namespace{TaskManager.cppm}::save_task (TaskId task_id, json &raw, const DatabasePaths &paths)
 原子写回编辑后的任务,并重新读取规范化快照。
bool TaskManager::anonymous_namespace{TaskManager.cppm}::task_matches_query (const TaskRecord &task, std::string_view query)
 对标题、描述、ID、项目名和清单名执行不区分大小写的子串匹配。

Variables

constexpr std::size_t TaskManager::kTaskIdLength = 20
 任务 ID 固定为 20 字符,变异测试会硬编码检查此协议。
std::atomic< std::uint64_t > TaskManager::anonymous_namespace{TaskManager.cppm}::g_sequence {0}
 进程内原子序号,与时间/随机设备一起构成 ID 种子的去重分量。