@hasna/todos 0.11.43 → 0.11.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +573 -11
- package/dist/cli/commands/agent-reliability-commands.d.ts +3 -0
- package/dist/cli/commands/agent-reliability-commands.d.ts.map +1 -0
- package/dist/cli/commands/audit-ledger-commands.d.ts +3 -0
- package/dist/cli/commands/audit-ledger-commands.d.ts.map +1 -0
- package/dist/cli/commands/capacity-commands.d.ts +3 -0
- package/dist/cli/commands/capacity-commands.d.ts.map +1 -0
- package/dist/cli/commands/config-serve-commands.d.ts.map +1 -1
- package/dist/cli/commands/environment-snapshots.d.ts +3 -0
- package/dist/cli/commands/environment-snapshots.d.ts.map +1 -0
- package/dist/cli/commands/knowledge-commands.d.ts +3 -0
- package/dist/cli/commands/knowledge-commands.d.ts.map +1 -0
- package/dist/cli/commands/local-snapshot-commands.d.ts +3 -0
- package/dist/cli/commands/local-snapshot-commands.d.ts.map +1 -0
- package/dist/cli/commands/machines.d.ts.map +1 -1
- package/dist/cli/commands/mcp-hooks-commands.d.ts.map +1 -1
- package/dist/cli/commands/onboarding-commands.d.ts +3 -0
- package/dist/cli/commands/onboarding-commands.d.ts.map +1 -0
- package/dist/cli/commands/project-commands.d.ts.map +1 -1
- package/dist/cli/commands/query-commands.d.ts.map +1 -1
- package/dist/cli/commands/release-compatibility-commands.d.ts +3 -0
- package/dist/cli/commands/release-compatibility-commands.d.ts.map +1 -0
- package/dist/cli/commands/retrospective-commands.d.ts +3 -0
- package/dist/cli/commands/retrospective-commands.d.ts.map +1 -0
- package/dist/cli/commands/review-queue-commands.d.ts +3 -0
- package/dist/cli/commands/review-queue-commands.d.ts.map +1 -0
- package/dist/cli/commands/risk-commands.d.ts +3 -0
- package/dist/cli/commands/risk-commands.d.ts.map +1 -0
- package/dist/cli/commands/roadmap-commands.d.ts +3 -0
- package/dist/cli/commands/roadmap-commands.d.ts.map +1 -0
- package/dist/cli/commands/sdk-fixture-commands.d.ts +3 -0
- package/dist/cli/commands/sdk-fixture-commands.d.ts.map +1 -0
- package/dist/cli/commands/task-commands.d.ts.map +1 -1
- package/dist/cli/index.js +26227 -9412
- package/dist/cli-mcp-parity.d.ts +1 -1
- package/dist/cli-mcp-parity.d.ts.map +1 -1
- package/dist/contracts.d.ts +19 -0
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js +10174 -679
- package/dist/db/agent-metrics.d.ts +101 -0
- package/dist/db/agent-metrics.d.ts.map +1 -1
- package/dist/db/boards.d.ts +56 -0
- package/dist/db/boards.d.ts.map +1 -0
- package/dist/db/calendar.d.ts +52 -0
- package/dist/db/calendar.d.ts.map +1 -0
- package/dist/db/comments.d.ts.map +1 -1
- package/dist/db/handoffs.d.ts +25 -0
- package/dist/db/handoffs.d.ts.map +1 -1
- package/dist/db/machines.d.ts +19 -6
- package/dist/db/machines.d.ts.map +1 -1
- package/dist/db/migrations.d.ts.map +1 -1
- package/dist/db/project-knowledge.d.ts +88 -0
- package/dist/db/project-knowledge.d.ts.map +1 -0
- package/dist/db/project-risks.d.ts +139 -0
- package/dist/db/project-risks.d.ts.map +1 -0
- package/dist/db/retrospectives.d.ts +98 -0
- package/dist/db/retrospectives.d.ts.map +1 -0
- package/dist/db/schema.d.ts.map +1 -1
- package/dist/db/task-crud.d.ts.map +1 -1
- package/dist/db/task-relations.d.ts +69 -9
- package/dist/db/task-relations.d.ts.map +1 -1
- package/dist/db/tasks.d.ts +6 -2
- package/dist/db/tasks.d.ts.map +1 -1
- package/dist/index.d.ts +62 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19485 -8856
- package/dist/json-contracts.d.ts.map +1 -1
- package/dist/lib/agent-replay-simulator.d.ts +66 -0
- package/dist/lib/agent-replay-simulator.d.ts.map +1 -0
- package/dist/lib/audit-ledger.d.ts +59 -0
- package/dist/lib/audit-ledger.d.ts.map +1 -0
- package/dist/lib/branch-work-plans.d.ts +46 -0
- package/dist/lib/branch-work-plans.d.ts.map +1 -0
- package/dist/lib/capacity-forecasts.d.ts +70 -0
- package/dist/lib/capacity-forecasts.d.ts.map +1 -0
- package/dist/lib/config.d.ts +179 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/context-packs.d.ts +26 -3
- package/dist/lib/context-packs.d.ts.map +1 -1
- package/dist/lib/environment-snapshots.d.ts +111 -0
- package/dist/lib/environment-snapshots.d.ts.map +1 -0
- package/dist/lib/event-hooks.d.ts +1 -1
- package/dist/lib/event-hooks.d.ts.map +1 -1
- package/dist/lib/external-issue-importers.d.ts +60 -0
- package/dist/lib/external-issue-importers.d.ts.map +1 -0
- package/dist/lib/extract.d.ts +57 -0
- package/dist/lib/extract.d.ts.map +1 -1
- package/dist/lib/local-bridge.d.ts +3 -1
- package/dist/lib/local-bridge.d.ts.map +1 -1
- package/dist/lib/local-extensions.d.ts +75 -0
- package/dist/lib/local-extensions.d.ts.map +1 -0
- package/dist/lib/local-notifications.d.ts +55 -0
- package/dist/lib/local-notifications.d.ts.map +1 -0
- package/dist/lib/local-snapshots.d.ts +66 -0
- package/dist/lib/local-snapshots.d.ts.map +1 -0
- package/dist/lib/mention-resolver.d.ts +43 -0
- package/dist/lib/mention-resolver.d.ts.map +1 -0
- package/dist/lib/natural-language-intake.d.ts +56 -0
- package/dist/lib/natural-language-intake.d.ts.map +1 -0
- package/dist/lib/onboarding-fixtures.d.ts +31 -0
- package/dist/lib/onboarding-fixtures.d.ts.map +1 -0
- package/dist/lib/public-release-gate.d.ts +7 -0
- package/dist/lib/public-release-gate.d.ts.map +1 -1
- package/dist/lib/redaction.d.ts +9 -0
- package/dist/lib/redaction.d.ts.map +1 -1
- package/dist/lib/release-compatibility.d.ts +59 -0
- package/dist/lib/release-compatibility.d.ts.map +1 -0
- package/dist/lib/release-notes.d.ts +81 -0
- package/dist/lib/release-notes.d.ts.map +1 -0
- package/dist/lib/retention-cleanup.d.ts +63 -0
- package/dist/lib/retention-cleanup.d.ts.map +1 -0
- package/dist/lib/review-queues.d.ts +98 -0
- package/dist/lib/review-queues.d.ts.map +1 -0
- package/dist/lib/roadmaps.d.ts +133 -0
- package/dist/lib/roadmaps.d.ts.map +1 -0
- package/dist/lib/sdk-integration-fixtures.d.ts +65 -0
- package/dist/lib/sdk-integration-fixtures.d.ts.map +1 -0
- package/dist/lib/terminal-notifications.d.ts +53 -0
- package/dist/lib/terminal-notifications.d.ts.map +1 -0
- package/dist/lib/todos-md.d.ts.map +1 -1
- package/dist/lib/workflow-prompts.d.ts +38 -0
- package/dist/lib/workflow-prompts.d.ts.map +1 -0
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +20925 -9542
- package/dist/mcp/token-utils.d.ts.map +1 -1
- package/dist/mcp/tools/code-tools.d.ts.map +1 -1
- package/dist/mcp/tools/environment-snapshots.d.ts +8 -0
- package/dist/mcp/tools/environment-snapshots.d.ts.map +1 -0
- package/dist/mcp/tools/machines.d.ts.map +1 -1
- package/dist/mcp/tools/task-adv-tools.d.ts.map +1 -1
- package/dist/mcp/tools/task-auto-tools.d.ts.map +1 -1
- package/dist/mcp/tools/task-crud.d.ts.map +1 -1
- package/dist/mcp/tools/task-meta-tools.d.ts.map +1 -1
- package/dist/mcp/tools/task-project-tools.d.ts.map +1 -1
- package/dist/mcp/tools/task-rel-tools.d.ts.map +1 -1
- package/dist/mcp/tools/task-resources.d.ts.map +1 -1
- package/dist/mcp/tools/workflow-prompts.d.ts +3 -0
- package/dist/mcp/tools/workflow-prompts.d.ts.map +1 -0
- package/dist/mcp.js +97 -2
- package/dist/registry.js +14462 -5998
- package/dist/release-provenance.json +3 -3
- package/dist/server/index.js +493 -123
- package/dist/storage.js +2353 -139
- package/dist/types/index.d.ts +214 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/server/index.js
CHANGED
|
@@ -994,6 +994,152 @@ var init_migrations = __esm(() => {
|
|
|
994
994
|
);
|
|
995
995
|
CREATE INDEX IF NOT EXISTS idx_saved_search_views_scope ON saved_search_views(scope);
|
|
996
996
|
INSERT OR IGNORE INTO _migrations (id) VALUES (55);
|
|
997
|
+
`,
|
|
998
|
+
`
|
|
999
|
+
ALTER TABLE task_time_logs ADD COLUMN run_id TEXT;
|
|
1000
|
+
ALTER TABLE task_time_logs ADD COLUMN focus_session_id TEXT;
|
|
1001
|
+
CREATE INDEX IF NOT EXISTS idx_task_time_logs_run ON task_time_logs(run_id);
|
|
1002
|
+
CREATE INDEX IF NOT EXISTS idx_task_time_logs_focus_session ON task_time_logs(focus_session_id);
|
|
1003
|
+
CREATE TABLE IF NOT EXISTS focus_sessions (
|
|
1004
|
+
id TEXT PRIMARY KEY,
|
|
1005
|
+
task_id TEXT REFERENCES tasks(id) ON DELETE SET NULL,
|
|
1006
|
+
plan_id TEXT REFERENCES plans(id) ON DELETE SET NULL,
|
|
1007
|
+
run_id TEXT,
|
|
1008
|
+
agent_id TEXT,
|
|
1009
|
+
title TEXT,
|
|
1010
|
+
status TEXT NOT NULL DEFAULT 'active' CHECK(status IN ('active', 'paused', 'completed', 'cancelled')),
|
|
1011
|
+
started_at TEXT NOT NULL,
|
|
1012
|
+
last_resumed_at TEXT,
|
|
1013
|
+
paused_at TEXT,
|
|
1014
|
+
ended_at TEXT,
|
|
1015
|
+
actual_minutes INTEGER NOT NULL DEFAULT 0,
|
|
1016
|
+
idle_after_minutes INTEGER,
|
|
1017
|
+
notes TEXT,
|
|
1018
|
+
metadata TEXT DEFAULT '{}',
|
|
1019
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
1020
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
1021
|
+
);
|
|
1022
|
+
CREATE INDEX IF NOT EXISTS idx_focus_sessions_task ON focus_sessions(task_id);
|
|
1023
|
+
CREATE INDEX IF NOT EXISTS idx_focus_sessions_plan ON focus_sessions(plan_id);
|
|
1024
|
+
CREATE INDEX IF NOT EXISTS idx_focus_sessions_run ON focus_sessions(run_id);
|
|
1025
|
+
CREATE INDEX IF NOT EXISTS idx_focus_sessions_agent ON focus_sessions(agent_id);
|
|
1026
|
+
CREATE INDEX IF NOT EXISTS idx_focus_sessions_status ON focus_sessions(status);
|
|
1027
|
+
INSERT OR IGNORE INTO _migrations (id) VALUES (56);
|
|
1028
|
+
`,
|
|
1029
|
+
`
|
|
1030
|
+
CREATE TABLE IF NOT EXISTS task_boards (
|
|
1031
|
+
id TEXT PRIMARY KEY,
|
|
1032
|
+
name TEXT NOT NULL UNIQUE,
|
|
1033
|
+
scope TEXT NOT NULL DEFAULT 'tasks' CHECK(scope IN ('tasks', 'plans')),
|
|
1034
|
+
project_id TEXT REFERENCES projects(id) ON DELETE SET NULL,
|
|
1035
|
+
task_list_id TEXT REFERENCES task_lists(id) ON DELETE SET NULL,
|
|
1036
|
+
plan_id TEXT REFERENCES plans(id) ON DELETE SET NULL,
|
|
1037
|
+
agent_id TEXT,
|
|
1038
|
+
lanes TEXT NOT NULL DEFAULT '[]',
|
|
1039
|
+
filters TEXT NOT NULL DEFAULT '{}',
|
|
1040
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
1041
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
1042
|
+
);
|
|
1043
|
+
CREATE INDEX IF NOT EXISTS idx_task_boards_scope ON task_boards(scope);
|
|
1044
|
+
CREATE INDEX IF NOT EXISTS idx_task_boards_project ON task_boards(project_id);
|
|
1045
|
+
CREATE INDEX IF NOT EXISTS idx_task_boards_plan ON task_boards(plan_id);
|
|
1046
|
+
INSERT OR IGNORE INTO _migrations (id) VALUES (57);
|
|
1047
|
+
`,
|
|
1048
|
+
`
|
|
1049
|
+
CREATE TABLE IF NOT EXISTS local_calendar_items (
|
|
1050
|
+
id TEXT PRIMARY KEY,
|
|
1051
|
+
kind TEXT NOT NULL CHECK(kind IN ('task_due', 'task_sla', 'task_reminder', 'milestone', 'work_block', 'run', 'imported')),
|
|
1052
|
+
title TEXT NOT NULL,
|
|
1053
|
+
description TEXT,
|
|
1054
|
+
starts_at TEXT NOT NULL,
|
|
1055
|
+
ends_at TEXT,
|
|
1056
|
+
timezone TEXT,
|
|
1057
|
+
project_id TEXT REFERENCES projects(id) ON DELETE SET NULL,
|
|
1058
|
+
task_id TEXT REFERENCES tasks(id) ON DELETE SET NULL,
|
|
1059
|
+
plan_id TEXT REFERENCES plans(id) ON DELETE SET NULL,
|
|
1060
|
+
run_id TEXT,
|
|
1061
|
+
recurrence_rule TEXT,
|
|
1062
|
+
metadata TEXT DEFAULT '{}',
|
|
1063
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
1064
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
1065
|
+
);
|
|
1066
|
+
CREATE INDEX IF NOT EXISTS idx_local_calendar_items_time ON local_calendar_items(starts_at, ends_at);
|
|
1067
|
+
CREATE INDEX IF NOT EXISTS idx_local_calendar_items_task ON local_calendar_items(task_id);
|
|
1068
|
+
CREATE INDEX IF NOT EXISTS idx_local_calendar_items_project ON local_calendar_items(project_id);
|
|
1069
|
+
CREATE INDEX IF NOT EXISTS idx_local_calendar_items_kind ON local_calendar_items(kind);
|
|
1070
|
+
INSERT OR IGNORE INTO _migrations (id) VALUES (58);
|
|
1071
|
+
`,
|
|
1072
|
+
`
|
|
1073
|
+
CREATE TABLE IF NOT EXISTS project_knowledge_records (
|
|
1074
|
+
id TEXT PRIMARY KEY,
|
|
1075
|
+
record_type TEXT NOT NULL CHECK(record_type IN ('decision','architecture_note','tradeoff','context_snapshot')),
|
|
1076
|
+
title TEXT NOT NULL,
|
|
1077
|
+
content TEXT,
|
|
1078
|
+
decision TEXT,
|
|
1079
|
+
rationale TEXT,
|
|
1080
|
+
alternatives TEXT DEFAULT '[]',
|
|
1081
|
+
task_id TEXT REFERENCES tasks(id) ON DELETE SET NULL,
|
|
1082
|
+
project_id TEXT REFERENCES projects(id) ON DELETE SET NULL,
|
|
1083
|
+
plan_id TEXT REFERENCES plans(id) ON DELETE SET NULL,
|
|
1084
|
+
agent_id TEXT,
|
|
1085
|
+
snapshot_id TEXT REFERENCES context_snapshots(id) ON DELETE SET NULL,
|
|
1086
|
+
tags TEXT DEFAULT '[]',
|
|
1087
|
+
metadata TEXT DEFAULT '{}',
|
|
1088
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
1089
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
1090
|
+
);
|
|
1091
|
+
CREATE INDEX IF NOT EXISTS idx_project_knowledge_type ON project_knowledge_records(record_type);
|
|
1092
|
+
CREATE INDEX IF NOT EXISTS idx_project_knowledge_project ON project_knowledge_records(project_id);
|
|
1093
|
+
CREATE INDEX IF NOT EXISTS idx_project_knowledge_task ON project_knowledge_records(task_id);
|
|
1094
|
+
CREATE INDEX IF NOT EXISTS idx_project_knowledge_plan ON project_knowledge_records(plan_id);
|
|
1095
|
+
CREATE INDEX IF NOT EXISTS idx_project_knowledge_agent ON project_knowledge_records(agent_id);
|
|
1096
|
+
CREATE INDEX IF NOT EXISTS idx_project_knowledge_snapshot ON project_knowledge_records(snapshot_id);
|
|
1097
|
+
INSERT OR IGNORE INTO _migrations (id) VALUES (59);
|
|
1098
|
+
`,
|
|
1099
|
+
`
|
|
1100
|
+
CREATE TABLE IF NOT EXISTS project_risks (
|
|
1101
|
+
id TEXT PRIMARY KEY,
|
|
1102
|
+
title TEXT NOT NULL,
|
|
1103
|
+
description TEXT,
|
|
1104
|
+
status TEXT NOT NULL DEFAULT 'open' CHECK(status IN ('open','mitigating','resolved','accepted')),
|
|
1105
|
+
severity TEXT NOT NULL DEFAULT 'medium' CHECK(severity IN ('low','medium','high','critical')),
|
|
1106
|
+
probability TEXT NOT NULL DEFAULT 'medium' CHECK(probability IN ('low','medium','high')),
|
|
1107
|
+
owner TEXT,
|
|
1108
|
+
mitigation TEXT,
|
|
1109
|
+
due_at TEXT,
|
|
1110
|
+
project_id TEXT REFERENCES projects(id) ON DELETE SET NULL,
|
|
1111
|
+
plan_id TEXT REFERENCES plans(id) ON DELETE SET NULL,
|
|
1112
|
+
task_id TEXT REFERENCES tasks(id) ON DELETE SET NULL,
|
|
1113
|
+
tags TEXT DEFAULT '[]',
|
|
1114
|
+
metadata TEXT DEFAULT '{}',
|
|
1115
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
1116
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
1117
|
+
closed_at TEXT
|
|
1118
|
+
);
|
|
1119
|
+
CREATE INDEX IF NOT EXISTS idx_project_risks_status ON project_risks(status);
|
|
1120
|
+
CREATE INDEX IF NOT EXISTS idx_project_risks_severity ON project_risks(severity);
|
|
1121
|
+
CREATE INDEX IF NOT EXISTS idx_project_risks_project ON project_risks(project_id);
|
|
1122
|
+
CREATE INDEX IF NOT EXISTS idx_project_risks_plan ON project_risks(plan_id);
|
|
1123
|
+
CREATE INDEX IF NOT EXISTS idx_project_risks_task ON project_risks(task_id);
|
|
1124
|
+
CREATE INDEX IF NOT EXISTS idx_project_risks_due ON project_risks(due_at);
|
|
1125
|
+
INSERT OR IGNORE INTO _migrations (id) VALUES (60);
|
|
1126
|
+
`,
|
|
1127
|
+
`
|
|
1128
|
+
CREATE TABLE IF NOT EXISTS local_retrospectives (
|
|
1129
|
+
id TEXT PRIMARY KEY,
|
|
1130
|
+
title TEXT NOT NULL,
|
|
1131
|
+
scope TEXT NOT NULL CHECK(scope IN ('project','plan')),
|
|
1132
|
+
project_id TEXT REFERENCES projects(id) ON DELETE SET NULL,
|
|
1133
|
+
plan_id TEXT REFERENCES plans(id) ON DELETE SET NULL,
|
|
1134
|
+
agent_id TEXT,
|
|
1135
|
+
report_json TEXT NOT NULL,
|
|
1136
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
1137
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
1138
|
+
);
|
|
1139
|
+
CREATE INDEX IF NOT EXISTS idx_local_retrospectives_project ON local_retrospectives(project_id);
|
|
1140
|
+
CREATE INDEX IF NOT EXISTS idx_local_retrospectives_plan ON local_retrospectives(plan_id);
|
|
1141
|
+
CREATE INDEX IF NOT EXISTS idx_local_retrospectives_agent ON local_retrospectives(agent_id);
|
|
1142
|
+
INSERT OR IGNORE INTO _migrations (id) VALUES (61);
|
|
997
1143
|
`
|
|
998
1144
|
];
|
|
999
1145
|
});
|
|
@@ -1181,6 +1327,89 @@ function ensureSchema(db) {
|
|
|
1181
1327
|
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
1182
1328
|
)`);
|
|
1183
1329
|
ensureIndex("CREATE INDEX IF NOT EXISTS idx_saved_search_views_scope ON saved_search_views(scope)");
|
|
1330
|
+
ensureTable("context_snapshots", `
|
|
1331
|
+
CREATE TABLE context_snapshots (
|
|
1332
|
+
id TEXT PRIMARY KEY,
|
|
1333
|
+
agent_id TEXT,
|
|
1334
|
+
task_id TEXT REFERENCES tasks(id) ON DELETE SET NULL,
|
|
1335
|
+
project_id TEXT REFERENCES projects(id) ON DELETE SET NULL,
|
|
1336
|
+
snapshot_type TEXT NOT NULL CHECK(snapshot_type IN ('interrupt','complete','handoff','checkpoint')),
|
|
1337
|
+
plan_summary TEXT,
|
|
1338
|
+
files_open TEXT DEFAULT '[]',
|
|
1339
|
+
attempts TEXT DEFAULT '[]',
|
|
1340
|
+
blockers TEXT DEFAULT '[]',
|
|
1341
|
+
next_steps TEXT,
|
|
1342
|
+
metadata TEXT DEFAULT '{}',
|
|
1343
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
1344
|
+
)`);
|
|
1345
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_snapshots_agent ON context_snapshots(agent_id)");
|
|
1346
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_snapshots_task ON context_snapshots(task_id)");
|
|
1347
|
+
ensureTable("project_knowledge_records", `
|
|
1348
|
+
CREATE TABLE project_knowledge_records (
|
|
1349
|
+
id TEXT PRIMARY KEY,
|
|
1350
|
+
record_type TEXT NOT NULL CHECK(record_type IN ('decision','architecture_note','tradeoff','context_snapshot')),
|
|
1351
|
+
title TEXT NOT NULL,
|
|
1352
|
+
content TEXT,
|
|
1353
|
+
decision TEXT,
|
|
1354
|
+
rationale TEXT,
|
|
1355
|
+
alternatives TEXT DEFAULT '[]',
|
|
1356
|
+
task_id TEXT REFERENCES tasks(id) ON DELETE SET NULL,
|
|
1357
|
+
project_id TEXT REFERENCES projects(id) ON DELETE SET NULL,
|
|
1358
|
+
plan_id TEXT REFERENCES plans(id) ON DELETE SET NULL,
|
|
1359
|
+
agent_id TEXT,
|
|
1360
|
+
snapshot_id TEXT REFERENCES context_snapshots(id) ON DELETE SET NULL,
|
|
1361
|
+
tags TEXT DEFAULT '[]',
|
|
1362
|
+
metadata TEXT DEFAULT '{}',
|
|
1363
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
1364
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
1365
|
+
)`);
|
|
1366
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_project_knowledge_type ON project_knowledge_records(record_type)");
|
|
1367
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_project_knowledge_project ON project_knowledge_records(project_id)");
|
|
1368
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_project_knowledge_task ON project_knowledge_records(task_id)");
|
|
1369
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_project_knowledge_plan ON project_knowledge_records(plan_id)");
|
|
1370
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_project_knowledge_agent ON project_knowledge_records(agent_id)");
|
|
1371
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_project_knowledge_snapshot ON project_knowledge_records(snapshot_id)");
|
|
1372
|
+
ensureTable("project_risks", `
|
|
1373
|
+
CREATE TABLE project_risks (
|
|
1374
|
+
id TEXT PRIMARY KEY,
|
|
1375
|
+
title TEXT NOT NULL,
|
|
1376
|
+
description TEXT,
|
|
1377
|
+
status TEXT NOT NULL DEFAULT 'open' CHECK(status IN ('open','mitigating','resolved','accepted')),
|
|
1378
|
+
severity TEXT NOT NULL DEFAULT 'medium' CHECK(severity IN ('low','medium','high','critical')),
|
|
1379
|
+
probability TEXT NOT NULL DEFAULT 'medium' CHECK(probability IN ('low','medium','high')),
|
|
1380
|
+
owner TEXT,
|
|
1381
|
+
mitigation TEXT,
|
|
1382
|
+
due_at TEXT,
|
|
1383
|
+
project_id TEXT REFERENCES projects(id) ON DELETE SET NULL,
|
|
1384
|
+
plan_id TEXT REFERENCES plans(id) ON DELETE SET NULL,
|
|
1385
|
+
task_id TEXT REFERENCES tasks(id) ON DELETE SET NULL,
|
|
1386
|
+
tags TEXT DEFAULT '[]',
|
|
1387
|
+
metadata TEXT DEFAULT '{}',
|
|
1388
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
1389
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
1390
|
+
closed_at TEXT
|
|
1391
|
+
)`);
|
|
1392
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_project_risks_status ON project_risks(status)");
|
|
1393
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_project_risks_severity ON project_risks(severity)");
|
|
1394
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_project_risks_project ON project_risks(project_id)");
|
|
1395
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_project_risks_plan ON project_risks(plan_id)");
|
|
1396
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_project_risks_task ON project_risks(task_id)");
|
|
1397
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_project_risks_due ON project_risks(due_at)");
|
|
1398
|
+
ensureTable("local_retrospectives", `
|
|
1399
|
+
CREATE TABLE local_retrospectives (
|
|
1400
|
+
id TEXT PRIMARY KEY,
|
|
1401
|
+
title TEXT NOT NULL,
|
|
1402
|
+
scope TEXT NOT NULL CHECK(scope IN ('project','plan')),
|
|
1403
|
+
project_id TEXT REFERENCES projects(id) ON DELETE SET NULL,
|
|
1404
|
+
plan_id TEXT REFERENCES plans(id) ON DELETE SET NULL,
|
|
1405
|
+
agent_id TEXT,
|
|
1406
|
+
report_json TEXT NOT NULL,
|
|
1407
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
1408
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
1409
|
+
)`);
|
|
1410
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_local_retrospectives_project ON local_retrospectives(project_id)");
|
|
1411
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_local_retrospectives_plan ON local_retrospectives(plan_id)");
|
|
1412
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_local_retrospectives_agent ON local_retrospectives(agent_id)");
|
|
1184
1413
|
ensureTable("task_relationships", `
|
|
1185
1414
|
CREATE TABLE task_relationships (
|
|
1186
1415
|
id TEXT PRIMARY KEY,
|
|
@@ -1517,6 +1746,8 @@ function ensureSchema(db) {
|
|
|
1517
1746
|
CREATE TABLE task_time_logs (
|
|
1518
1747
|
id TEXT PRIMARY KEY,
|
|
1519
1748
|
task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
1749
|
+
run_id TEXT,
|
|
1750
|
+
focus_session_id TEXT,
|
|
1520
1751
|
agent_id TEXT,
|
|
1521
1752
|
started_at TEXT,
|
|
1522
1753
|
ended_at TEXT,
|
|
@@ -1524,9 +1755,77 @@ function ensureSchema(db) {
|
|
|
1524
1755
|
notes TEXT,
|
|
1525
1756
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
1526
1757
|
)`);
|
|
1758
|
+
ensureColumn("task_time_logs", "run_id", "TEXT");
|
|
1759
|
+
ensureColumn("task_time_logs", "focus_session_id", "TEXT");
|
|
1527
1760
|
ensureIndex("CREATE INDEX IF NOT EXISTS idx_task_time_logs_task ON task_time_logs(task_id)");
|
|
1528
1761
|
ensureIndex("CREATE INDEX IF NOT EXISTS idx_task_time_logs_agent ON task_time_logs(agent_id)");
|
|
1762
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_task_time_logs_run ON task_time_logs(run_id)");
|
|
1763
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_task_time_logs_focus_session ON task_time_logs(focus_session_id)");
|
|
1529
1764
|
ensureColumn("tasks", "actual_minutes", "INTEGER");
|
|
1765
|
+
ensureTable("focus_sessions", `
|
|
1766
|
+
CREATE TABLE focus_sessions (
|
|
1767
|
+
id TEXT PRIMARY KEY,
|
|
1768
|
+
task_id TEXT REFERENCES tasks(id) ON DELETE SET NULL,
|
|
1769
|
+
plan_id TEXT REFERENCES plans(id) ON DELETE SET NULL,
|
|
1770
|
+
run_id TEXT,
|
|
1771
|
+
agent_id TEXT,
|
|
1772
|
+
title TEXT,
|
|
1773
|
+
status TEXT NOT NULL DEFAULT 'active' CHECK(status IN ('active', 'paused', 'completed', 'cancelled')),
|
|
1774
|
+
started_at TEXT NOT NULL,
|
|
1775
|
+
last_resumed_at TEXT,
|
|
1776
|
+
paused_at TEXT,
|
|
1777
|
+
ended_at TEXT,
|
|
1778
|
+
actual_minutes INTEGER NOT NULL DEFAULT 0,
|
|
1779
|
+
idle_after_minutes INTEGER,
|
|
1780
|
+
notes TEXT,
|
|
1781
|
+
metadata TEXT DEFAULT '{}',
|
|
1782
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
1783
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
1784
|
+
)`);
|
|
1785
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_focus_sessions_task ON focus_sessions(task_id)");
|
|
1786
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_focus_sessions_plan ON focus_sessions(plan_id)");
|
|
1787
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_focus_sessions_run ON focus_sessions(run_id)");
|
|
1788
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_focus_sessions_agent ON focus_sessions(agent_id)");
|
|
1789
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_focus_sessions_status ON focus_sessions(status)");
|
|
1790
|
+
ensureTable("task_boards", `
|
|
1791
|
+
CREATE TABLE task_boards (
|
|
1792
|
+
id TEXT PRIMARY KEY,
|
|
1793
|
+
name TEXT NOT NULL UNIQUE,
|
|
1794
|
+
scope TEXT NOT NULL DEFAULT 'tasks' CHECK(scope IN ('tasks', 'plans')),
|
|
1795
|
+
project_id TEXT REFERENCES projects(id) ON DELETE SET NULL,
|
|
1796
|
+
task_list_id TEXT REFERENCES task_lists(id) ON DELETE SET NULL,
|
|
1797
|
+
plan_id TEXT REFERENCES plans(id) ON DELETE SET NULL,
|
|
1798
|
+
agent_id TEXT,
|
|
1799
|
+
lanes TEXT NOT NULL DEFAULT '[]',
|
|
1800
|
+
filters TEXT NOT NULL DEFAULT '{}',
|
|
1801
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
1802
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
1803
|
+
)`);
|
|
1804
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_task_boards_scope ON task_boards(scope)");
|
|
1805
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_task_boards_project ON task_boards(project_id)");
|
|
1806
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_task_boards_plan ON task_boards(plan_id)");
|
|
1807
|
+
ensureTable("local_calendar_items", `
|
|
1808
|
+
CREATE TABLE local_calendar_items (
|
|
1809
|
+
id TEXT PRIMARY KEY,
|
|
1810
|
+
kind TEXT NOT NULL CHECK(kind IN ('task_due', 'task_sla', 'task_reminder', 'milestone', 'work_block', 'run', 'imported')),
|
|
1811
|
+
title TEXT NOT NULL,
|
|
1812
|
+
description TEXT,
|
|
1813
|
+
starts_at TEXT NOT NULL,
|
|
1814
|
+
ends_at TEXT,
|
|
1815
|
+
timezone TEXT,
|
|
1816
|
+
project_id TEXT REFERENCES projects(id) ON DELETE SET NULL,
|
|
1817
|
+
task_id TEXT REFERENCES tasks(id) ON DELETE SET NULL,
|
|
1818
|
+
plan_id TEXT REFERENCES plans(id) ON DELETE SET NULL,
|
|
1819
|
+
run_id TEXT,
|
|
1820
|
+
recurrence_rule TEXT,
|
|
1821
|
+
metadata TEXT DEFAULT '{}',
|
|
1822
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
1823
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
1824
|
+
)`);
|
|
1825
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_local_calendar_items_time ON local_calendar_items(starts_at, ends_at)");
|
|
1826
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_local_calendar_items_task ON local_calendar_items(task_id)");
|
|
1827
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_local_calendar_items_project ON local_calendar_items(project_id)");
|
|
1828
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_local_calendar_items_kind ON local_calendar_items(kind)");
|
|
1530
1829
|
ensureTable("task_watchers", `
|
|
1531
1830
|
CREATE TABLE task_watchers (
|
|
1532
1831
|
id TEXT PRIMARY KEY,
|
|
@@ -1606,12 +1905,22 @@ var init_schema = __esm(() => {
|
|
|
1606
1905
|
});
|
|
1607
1906
|
|
|
1608
1907
|
// src/db/machines.ts
|
|
1609
|
-
import { hostname as osHostname, platform as osPlatform } from "os";
|
|
1908
|
+
import { hostname as osHostname, platform as osPlatform, arch as osArch } from "os";
|
|
1909
|
+
function parseMetadata(value) {
|
|
1910
|
+
if (!value)
|
|
1911
|
+
return {};
|
|
1912
|
+
try {
|
|
1913
|
+
const parsed = JSON.parse(value);
|
|
1914
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
1915
|
+
} catch {
|
|
1916
|
+
return {};
|
|
1917
|
+
}
|
|
1918
|
+
}
|
|
1610
1919
|
function rowToMachine(row) {
|
|
1611
1920
|
return {
|
|
1612
1921
|
...row,
|
|
1613
1922
|
is_primary: !!row.is_primary,
|
|
1614
|
-
metadata:
|
|
1923
|
+
metadata: parseMetadata(row.metadata)
|
|
1615
1924
|
};
|
|
1616
1925
|
}
|
|
1617
1926
|
function getOrCreateLocalMachine(db) {
|
|
@@ -1830,7 +2139,7 @@ var LOCK_EXPIRY_MINUTES = 30, _db = null, ALLOWED_TABLES;
|
|
|
1830
2139
|
var init_database = __esm(() => {
|
|
1831
2140
|
init_schema();
|
|
1832
2141
|
init_machines();
|
|
1833
|
-
ALLOWED_TABLES = new Set(["tasks", "projects", "agents", "plans", "task_lists", "task_templates"]);
|
|
2142
|
+
ALLOWED_TABLES = new Set(["tasks", "projects", "agents", "plans", "task_lists", "task_templates", "project_knowledge_records", "project_risks", "local_retrospectives"]);
|
|
1834
2143
|
});
|
|
1835
2144
|
|
|
1836
2145
|
// src/lib/recurrence.ts
|
|
@@ -2622,8 +2931,45 @@ import { dirname as dirname4, resolve as resolve4 } from "path";
|
|
|
2622
2931
|
import { createConnection } from "net";
|
|
2623
2932
|
|
|
2624
2933
|
// src/lib/redaction.ts
|
|
2934
|
+
var DEFAULT_SECRET_PATTERNS = [
|
|
2935
|
+
{ name: "aws-access-key", regex: /\b(AKIA|ASIA)[0-9A-Z]{16}\b/g, replacement: "[REDACTED_AWS_KEY]" },
|
|
2936
|
+
{ name: "private-key", regex: /-----BEGIN (?:RSA |EC |OPENSSH |)PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |OPENSSH |)PRIVATE KEY-----/g, replacement: "[REDACTED_PRIVATE_KEY]" },
|
|
2937
|
+
{ name: "openai-token", regex: /\bsk-[A-Za-z0-9_-]{12,}\b/g, replacement: "[REDACTED_TOKEN]" },
|
|
2938
|
+
{ name: "env-secret-assignment", regex: /\b([A-Za-z0-9_]*(?:API_KEY|TOKEN|SECRET|PASSWORD)[A-Za-z0-9_]*)\s*=\s*['"]?[^'"\s]{8,}/gi, replacement: "$1=[REDACTED]" },
|
|
2939
|
+
{ name: "bearer-token", regex: /\b(bearer)\s+[A-Za-z0-9._~+/=-]{12,}/gi, replacement: "$1 [REDACTED]" }
|
|
2940
|
+
];
|
|
2941
|
+
var DEFAULT_SECRET_KEY_PATTERN = /api[_-]?key|token|secret|password/i;
|
|
2942
|
+
function unique(values) {
|
|
2943
|
+
return Array.from(new Set((values || []).map((value) => value.trim()).filter(Boolean)));
|
|
2944
|
+
}
|
|
2945
|
+
function cloneRegex(regex) {
|
|
2946
|
+
return new RegExp(regex.source, regex.flags.includes("g") ? regex.flags : `${regex.flags}g`);
|
|
2947
|
+
}
|
|
2948
|
+
function customPatterns() {
|
|
2949
|
+
return unique(loadConfig().secret_safety?.redaction_patterns).flatMap((pattern) => {
|
|
2950
|
+
try {
|
|
2951
|
+
return [{ name: `custom:${pattern}`, regex: new RegExp(pattern, "g") }];
|
|
2952
|
+
} catch {
|
|
2953
|
+
return [];
|
|
2954
|
+
}
|
|
2955
|
+
});
|
|
2956
|
+
}
|
|
2957
|
+
function secretPatterns() {
|
|
2958
|
+
return [...customPatterns(), ...DEFAULT_SECRET_PATTERNS];
|
|
2959
|
+
}
|
|
2960
|
+
function isSecretKey(key) {
|
|
2961
|
+
if (DEFAULT_SECRET_KEY_PATTERN.test(key))
|
|
2962
|
+
return true;
|
|
2963
|
+
return unique(loadConfig().secret_safety?.redaction_keys).some((pattern) => key.toLowerCase().includes(pattern.toLowerCase()));
|
|
2964
|
+
}
|
|
2625
2965
|
function redactEvidenceText(value) {
|
|
2626
|
-
|
|
2966
|
+
let redacted = value;
|
|
2967
|
+
for (const pattern of secretPatterns()) {
|
|
2968
|
+
const regex = cloneRegex(pattern.regex);
|
|
2969
|
+
const replacement = pattern.replacement ?? "[REDACTED]";
|
|
2970
|
+
redacted = typeof replacement === "string" ? redacted.replace(regex, replacement) : redacted.replace(regex, replacement);
|
|
2971
|
+
}
|
|
2972
|
+
return redacted;
|
|
2627
2973
|
}
|
|
2628
2974
|
function redactValue(value) {
|
|
2629
2975
|
if (typeof value === "string")
|
|
@@ -2633,7 +2979,7 @@ function redactValue(value) {
|
|
|
2633
2979
|
if (value && typeof value === "object") {
|
|
2634
2980
|
const redacted = {};
|
|
2635
2981
|
for (const [key, child] of Object.entries(value)) {
|
|
2636
|
-
if (
|
|
2982
|
+
if (isSecretKey(key)) {
|
|
2637
2983
|
redacted[key] = "[REDACTED]";
|
|
2638
2984
|
} else {
|
|
2639
2985
|
redacted[key] = redactValue(child);
|
|
@@ -2696,7 +3042,7 @@ var PRESET_DEFAULTS = {
|
|
|
2696
3042
|
function normalizePath(path) {
|
|
2697
3043
|
return resolve2(path);
|
|
2698
3044
|
}
|
|
2699
|
-
function
|
|
3045
|
+
function unique2(values) {
|
|
2700
3046
|
return Array.from(new Set((values || []).map((value) => value.trim()).filter(Boolean)));
|
|
2701
3047
|
}
|
|
2702
3048
|
function defaultProfile(root, preset) {
|
|
@@ -2749,7 +3095,7 @@ function writeAllowed(profile, root, writePath) {
|
|
|
2749
3095
|
function redactedEnvKeys(profile, env) {
|
|
2750
3096
|
if (!env)
|
|
2751
3097
|
return [];
|
|
2752
|
-
const patterns =
|
|
3098
|
+
const patterns = unique2([...DEFAULT_ENV_REDACTIONS, ...profile.env_redactions]).map((item) => item.toUpperCase());
|
|
2753
3099
|
return Object.keys(env).filter((key) => patterns.some((pattern) => key.toUpperCase().includes(pattern)));
|
|
2754
3100
|
}
|
|
2755
3101
|
function checkWorkspacePermission(input = {}) {
|
|
@@ -2788,7 +3134,7 @@ var DEFAULT_ENV_REDACTIONS2 = ["API_KEY", "TOKEN", "SECRET", "PASSWORD", "AUTH"]
|
|
|
2788
3134
|
function normalizePath2(path) {
|
|
2789
3135
|
return resolve3(path);
|
|
2790
3136
|
}
|
|
2791
|
-
function
|
|
3137
|
+
function unique3(values) {
|
|
2792
3138
|
return Array.from(new Set((values || []).map((value) => value.trim()).filter(Boolean)));
|
|
2793
3139
|
}
|
|
2794
3140
|
function configuredProfiles2(config = loadConfig()) {
|
|
@@ -2844,7 +3190,7 @@ function profileByName(name, path) {
|
|
|
2844
3190
|
function redactedEnvKeys2(profile, env) {
|
|
2845
3191
|
if (!env)
|
|
2846
3192
|
return [];
|
|
2847
|
-
const patterns =
|
|
3193
|
+
const patterns = unique3([...DEFAULT_ENV_REDACTIONS2, ...profile.env_redactions]).map((item) => item.toUpperCase());
|
|
2848
3194
|
return Object.keys(env).filter((key) => patterns.some((pattern) => key.toUpperCase().includes(pattern)));
|
|
2849
3195
|
}
|
|
2850
3196
|
function omittedEnvKeys(profile, env) {
|
|
@@ -2896,7 +3242,7 @@ function checkRunnerSandbox(input = {}) {
|
|
|
2896
3242
|
const redacted = redactedEnvKeys2(profile, input.env);
|
|
2897
3243
|
const omitted = omittedEnvKeys(profile, input.env);
|
|
2898
3244
|
const effective = Object.keys(input.env || {}).filter((key) => !omitted.includes(key));
|
|
2899
|
-
const uniqueReasons =
|
|
3245
|
+
const uniqueReasons = unique3(reasons);
|
|
2900
3246
|
const allowed = uniqueReasons.length === 0;
|
|
2901
3247
|
return {
|
|
2902
3248
|
allowed,
|
|
@@ -3333,8 +3679,8 @@ function createTask(input, db) {
|
|
|
3333
3679
|
let id = uuid();
|
|
3334
3680
|
for (let attempt = 0;attempt < 3; attempt++) {
|
|
3335
3681
|
try {
|
|
3336
|
-
d.run(`INSERT INTO tasks (id, short_id, project_id, parent_id, plan_id, task_list_id, cycle_id, title, description, status, priority, agent_id, assigned_to, session_id, working_dir, tags, metadata, version, created_at, updated_at, due_at, estimated_minutes, confidence, retry_count, max_retries, retry_after, requires_approval, approved_by, approved_at, recurrence_rule, recurrence_parent_id, spawns_template_id, reason, spawned_from_session, assigned_by, assigned_from_project, task_type)
|
|
3337
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
3682
|
+
d.run(`INSERT INTO tasks (id, short_id, project_id, parent_id, plan_id, task_list_id, cycle_id, title, description, status, priority, agent_id, assigned_to, session_id, working_dir, tags, metadata, version, created_at, updated_at, due_at, estimated_minutes, sla_minutes, confidence, retry_count, max_retries, retry_after, requires_approval, approved_by, approved_at, recurrence_rule, recurrence_parent_id, spawns_template_id, reason, spawned_from_session, assigned_by, assigned_from_project, task_type)
|
|
3683
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
3338
3684
|
id,
|
|
3339
3685
|
null,
|
|
3340
3686
|
input.project_id || null,
|
|
@@ -3356,6 +3702,7 @@ function createTask(input, db) {
|
|
|
3356
3702
|
timestamp,
|
|
3357
3703
|
input.due_at || null,
|
|
3358
3704
|
input.estimated_minutes || null,
|
|
3705
|
+
input.sla_minutes ?? null,
|
|
3359
3706
|
input.confidence ?? null,
|
|
3360
3707
|
input.retry_count ?? 0,
|
|
3361
3708
|
input.max_retries ?? 3,
|
|
@@ -3635,6 +3982,10 @@ function updateTask(id, input, db) {
|
|
|
3635
3982
|
sets.push("estimated_minutes = ?");
|
|
3636
3983
|
params.push(input.estimated_minutes);
|
|
3637
3984
|
}
|
|
3985
|
+
if (input.sla_minutes !== undefined) {
|
|
3986
|
+
sets.push("sla_minutes = ?");
|
|
3987
|
+
params.push(input.sla_minutes);
|
|
3988
|
+
}
|
|
3638
3989
|
if (input.actual_minutes !== undefined) {
|
|
3639
3990
|
sets.push("actual_minutes = ?");
|
|
3640
3991
|
params.push(input.actual_minutes);
|
|
@@ -3716,6 +4067,7 @@ function updateTask(id, input, db) {
|
|
|
3716
4067
|
version: task.version + 1,
|
|
3717
4068
|
updated_at: timestamp,
|
|
3718
4069
|
completed_at: input.status === "completed" ? completionTimestamp : input.completed_at !== undefined ? input.completed_at : task.completed_at,
|
|
4070
|
+
sla_minutes: input.sla_minutes !== undefined ? input.sla_minutes : task.sla_minutes,
|
|
3719
4071
|
actual_minutes: input.actual_minutes ?? task.actual_minutes,
|
|
3720
4072
|
confidence: input.confidence !== undefined ? input.confidence : task.confidence,
|
|
3721
4073
|
retry_count: input.retry_count ?? task.retry_count,
|
|
@@ -3957,7 +4309,7 @@ function completeTask(id, agentId, db, options) {
|
|
|
3957
4309
|
emitLocalEventHooksQuiet({ type: "task.completed", payload: { id, agent_id: agentId, title: task.title, completed_at: timestamp } });
|
|
3958
4310
|
let spawnedTask = null;
|
|
3959
4311
|
if (task.recurrence_rule && !options?.skip_recurrence) {
|
|
3960
|
-
spawnedTask = spawnNextRecurrence(task, d);
|
|
4312
|
+
spawnedTask = spawnNextRecurrence(task, d, timestamp);
|
|
3961
4313
|
}
|
|
3962
4314
|
let spawnedFromTemplate = null;
|
|
3963
4315
|
if (task.spawns_template_id) {
|
|
@@ -4176,8 +4528,9 @@ function getStaleTasks(staleQuery = 30, filters, db) {
|
|
|
4176
4528
|
const rows = d.query(`SELECT * FROM tasks WHERE ${where} ORDER BY updated_at ASC`).all(...params);
|
|
4177
4529
|
return rows.map(rowToTask);
|
|
4178
4530
|
}
|
|
4179
|
-
function spawnNextRecurrence(completedTask, db) {
|
|
4180
|
-
const
|
|
4531
|
+
function spawnNextRecurrence(completedTask, db, completedAt) {
|
|
4532
|
+
const recurrenceBase = completedTask.due_at ? new Date(completedTask.due_at) : new Date(completedAt);
|
|
4533
|
+
const dueAt = nextOccurrence(completedTask.recurrence_rule, recurrenceBase);
|
|
4181
4534
|
let title = completedTask.title;
|
|
4182
4535
|
if (completedTask.short_id && title.startsWith(completedTask.short_id + ": ")) {
|
|
4183
4536
|
title = title.slice(completedTask.short_id.length + 2);
|
|
@@ -4194,6 +4547,7 @@ function spawnNextRecurrence(completedTask, db) {
|
|
|
4194
4547
|
tags: completedTask.tags,
|
|
4195
4548
|
metadata: completedTask.metadata,
|
|
4196
4549
|
estimated_minutes: completedTask.estimated_minutes ?? undefined,
|
|
4550
|
+
sla_minutes: completedTask.sla_minutes ?? undefined,
|
|
4197
4551
|
recurrence_rule: completedTask.recurrence_rule,
|
|
4198
4552
|
recurrence_parent_id: recurrenceParentId,
|
|
4199
4553
|
due_at: dueAt
|
|
@@ -4285,6 +4639,130 @@ function getTaskStats(filters, db) {
|
|
|
4285
4639
|
}
|
|
4286
4640
|
// src/db/task-relations.ts
|
|
4287
4641
|
init_database();
|
|
4642
|
+
// src/db/boards.ts
|
|
4643
|
+
init_database();
|
|
4644
|
+
|
|
4645
|
+
// src/db/plans.ts
|
|
4646
|
+
init_database();
|
|
4647
|
+
function createPlan(input, db) {
|
|
4648
|
+
const d = db || getDatabase();
|
|
4649
|
+
const id = uuid();
|
|
4650
|
+
const timestamp = now();
|
|
4651
|
+
d.run(`INSERT INTO plans (id, project_id, task_list_id, agent_id, name, description, status, created_at, updated_at)
|
|
4652
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
4653
|
+
id,
|
|
4654
|
+
input.project_id || null,
|
|
4655
|
+
input.task_list_id || null,
|
|
4656
|
+
input.agent_id || null,
|
|
4657
|
+
input.name,
|
|
4658
|
+
input.description || null,
|
|
4659
|
+
input.status || "active",
|
|
4660
|
+
timestamp,
|
|
4661
|
+
timestamp
|
|
4662
|
+
]);
|
|
4663
|
+
return getPlan(id, d);
|
|
4664
|
+
}
|
|
4665
|
+
function getPlan(id, db) {
|
|
4666
|
+
const d = db || getDatabase();
|
|
4667
|
+
const row = d.query("SELECT * FROM plans WHERE id = ?").get(id);
|
|
4668
|
+
return row;
|
|
4669
|
+
}
|
|
4670
|
+
function listPlans(projectId, db) {
|
|
4671
|
+
const d = db || getDatabase();
|
|
4672
|
+
if (projectId) {
|
|
4673
|
+
return d.query("SELECT * FROM plans WHERE project_id = ? ORDER BY created_at DESC").all(projectId);
|
|
4674
|
+
}
|
|
4675
|
+
return d.query("SELECT * FROM plans ORDER BY created_at DESC").all();
|
|
4676
|
+
}
|
|
4677
|
+
function updatePlan(id, input, db) {
|
|
4678
|
+
const d = db || getDatabase();
|
|
4679
|
+
const plan = getPlan(id, d);
|
|
4680
|
+
if (!plan)
|
|
4681
|
+
throw new PlanNotFoundError(id);
|
|
4682
|
+
const sets = ["updated_at = ?"];
|
|
4683
|
+
const params = [now()];
|
|
4684
|
+
if (input.name !== undefined) {
|
|
4685
|
+
sets.push("name = ?");
|
|
4686
|
+
params.push(input.name);
|
|
4687
|
+
}
|
|
4688
|
+
if (input.description !== undefined) {
|
|
4689
|
+
sets.push("description = ?");
|
|
4690
|
+
params.push(input.description);
|
|
4691
|
+
}
|
|
4692
|
+
if (input.status !== undefined) {
|
|
4693
|
+
sets.push("status = ?");
|
|
4694
|
+
params.push(input.status);
|
|
4695
|
+
}
|
|
4696
|
+
if (input.task_list_id !== undefined) {
|
|
4697
|
+
sets.push("task_list_id = ?");
|
|
4698
|
+
params.push(input.task_list_id);
|
|
4699
|
+
}
|
|
4700
|
+
if (input.agent_id !== undefined) {
|
|
4701
|
+
sets.push("agent_id = ?");
|
|
4702
|
+
params.push(input.agent_id);
|
|
4703
|
+
}
|
|
4704
|
+
params.push(id);
|
|
4705
|
+
d.run(`UPDATE plans SET ${sets.join(", ")} WHERE id = ?`, params);
|
|
4706
|
+
const updated = getPlan(id, d);
|
|
4707
|
+
emitLocalEventHooksQuiet({
|
|
4708
|
+
type: "plan.updated",
|
|
4709
|
+
payload: { id, old_status: plan.status, new_status: updated.status, name: updated.name, project_id: updated.project_id }
|
|
4710
|
+
});
|
|
4711
|
+
return updated;
|
|
4712
|
+
}
|
|
4713
|
+
function deletePlan(id, db) {
|
|
4714
|
+
const d = db || getDatabase();
|
|
4715
|
+
const result = d.run("DELETE FROM plans WHERE id = ?", [id]);
|
|
4716
|
+
return result.changes > 0;
|
|
4717
|
+
}
|
|
4718
|
+
// src/db/calendar.ts
|
|
4719
|
+
init_database();
|
|
4720
|
+
|
|
4721
|
+
// src/lib/artifact-store.ts
|
|
4722
|
+
init_database();
|
|
4723
|
+
|
|
4724
|
+
// src/db/comments.ts
|
|
4725
|
+
init_database();
|
|
4726
|
+
function addComment(input, db) {
|
|
4727
|
+
const d = db || getDatabase();
|
|
4728
|
+
if (!getTask(input.task_id, d)) {
|
|
4729
|
+
throw new TaskNotFoundError(input.task_id);
|
|
4730
|
+
}
|
|
4731
|
+
const id = uuid();
|
|
4732
|
+
const timestamp = now();
|
|
4733
|
+
d.run(`INSERT INTO task_comments (id, task_id, agent_id, session_id, content, type, progress_pct, created_at)
|
|
4734
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
4735
|
+
id,
|
|
4736
|
+
input.task_id,
|
|
4737
|
+
input.agent_id || null,
|
|
4738
|
+
input.session_id || null,
|
|
4739
|
+
redactEvidenceText(input.content),
|
|
4740
|
+
input.type || "comment",
|
|
4741
|
+
input.progress_pct ?? null,
|
|
4742
|
+
timestamp
|
|
4743
|
+
]);
|
|
4744
|
+
return getComment(id, d);
|
|
4745
|
+
}
|
|
4746
|
+
function logProgress(taskId, message, pct, agentId, db) {
|
|
4747
|
+
return addComment({ task_id: taskId, content: message, type: "progress", progress_pct: pct, agent_id: agentId }, db);
|
|
4748
|
+
}
|
|
4749
|
+
function getComment(id, db) {
|
|
4750
|
+
const d = db || getDatabase();
|
|
4751
|
+
return d.query("SELECT * FROM task_comments WHERE id = ?").get(id);
|
|
4752
|
+
}
|
|
4753
|
+
function listComments(taskId, db) {
|
|
4754
|
+
const d = db || getDatabase();
|
|
4755
|
+
return d.query("SELECT * FROM task_comments WHERE task_id = ? ORDER BY created_at").all(taskId);
|
|
4756
|
+
}
|
|
4757
|
+
|
|
4758
|
+
// src/db/task-runs.ts
|
|
4759
|
+
init_database();
|
|
4760
|
+
|
|
4761
|
+
// src/db/task-files.ts
|
|
4762
|
+
init_database();
|
|
4763
|
+
|
|
4764
|
+
// src/db/task-commits.ts
|
|
4765
|
+
init_database();
|
|
4288
4766
|
// src/db/agents.ts
|
|
4289
4767
|
init_database();
|
|
4290
4768
|
|
|
@@ -4686,80 +5164,6 @@ function getOrgChart(db) {
|
|
|
4686
5164
|
return buildTree(null);
|
|
4687
5165
|
}
|
|
4688
5166
|
|
|
4689
|
-
// src/db/plans.ts
|
|
4690
|
-
init_database();
|
|
4691
|
-
function createPlan(input, db) {
|
|
4692
|
-
const d = db || getDatabase();
|
|
4693
|
-
const id = uuid();
|
|
4694
|
-
const timestamp = now();
|
|
4695
|
-
d.run(`INSERT INTO plans (id, project_id, task_list_id, agent_id, name, description, status, created_at, updated_at)
|
|
4696
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
4697
|
-
id,
|
|
4698
|
-
input.project_id || null,
|
|
4699
|
-
input.task_list_id || null,
|
|
4700
|
-
input.agent_id || null,
|
|
4701
|
-
input.name,
|
|
4702
|
-
input.description || null,
|
|
4703
|
-
input.status || "active",
|
|
4704
|
-
timestamp,
|
|
4705
|
-
timestamp
|
|
4706
|
-
]);
|
|
4707
|
-
return getPlan(id, d);
|
|
4708
|
-
}
|
|
4709
|
-
function getPlan(id, db) {
|
|
4710
|
-
const d = db || getDatabase();
|
|
4711
|
-
const row = d.query("SELECT * FROM plans WHERE id = ?").get(id);
|
|
4712
|
-
return row;
|
|
4713
|
-
}
|
|
4714
|
-
function listPlans(projectId, db) {
|
|
4715
|
-
const d = db || getDatabase();
|
|
4716
|
-
if (projectId) {
|
|
4717
|
-
return d.query("SELECT * FROM plans WHERE project_id = ? ORDER BY created_at DESC").all(projectId);
|
|
4718
|
-
}
|
|
4719
|
-
return d.query("SELECT * FROM plans ORDER BY created_at DESC").all();
|
|
4720
|
-
}
|
|
4721
|
-
function updatePlan(id, input, db) {
|
|
4722
|
-
const d = db || getDatabase();
|
|
4723
|
-
const plan = getPlan(id, d);
|
|
4724
|
-
if (!plan)
|
|
4725
|
-
throw new PlanNotFoundError(id);
|
|
4726
|
-
const sets = ["updated_at = ?"];
|
|
4727
|
-
const params = [now()];
|
|
4728
|
-
if (input.name !== undefined) {
|
|
4729
|
-
sets.push("name = ?");
|
|
4730
|
-
params.push(input.name);
|
|
4731
|
-
}
|
|
4732
|
-
if (input.description !== undefined) {
|
|
4733
|
-
sets.push("description = ?");
|
|
4734
|
-
params.push(input.description);
|
|
4735
|
-
}
|
|
4736
|
-
if (input.status !== undefined) {
|
|
4737
|
-
sets.push("status = ?");
|
|
4738
|
-
params.push(input.status);
|
|
4739
|
-
}
|
|
4740
|
-
if (input.task_list_id !== undefined) {
|
|
4741
|
-
sets.push("task_list_id = ?");
|
|
4742
|
-
params.push(input.task_list_id);
|
|
4743
|
-
}
|
|
4744
|
-
if (input.agent_id !== undefined) {
|
|
4745
|
-
sets.push("agent_id = ?");
|
|
4746
|
-
params.push(input.agent_id);
|
|
4747
|
-
}
|
|
4748
|
-
params.push(id);
|
|
4749
|
-
d.run(`UPDATE plans SET ${sets.join(", ")} WHERE id = ?`, params);
|
|
4750
|
-
const updated = getPlan(id, d);
|
|
4751
|
-
emitLocalEventHooksQuiet({
|
|
4752
|
-
type: "plan.updated",
|
|
4753
|
-
payload: { id, old_status: plan.status, new_status: updated.status, name: updated.name, project_id: updated.project_id }
|
|
4754
|
-
});
|
|
4755
|
-
return updated;
|
|
4756
|
-
}
|
|
4757
|
-
function deletePlan(id, db) {
|
|
4758
|
-
const d = db || getDatabase();
|
|
4759
|
-
const result = d.run("DELETE FROM plans WHERE id = ?", [id]);
|
|
4760
|
-
return result.changes > 0;
|
|
4761
|
-
}
|
|
4762
|
-
|
|
4763
5167
|
// src/db/orgs.ts
|
|
4764
5168
|
init_database();
|
|
4765
5169
|
function rowToOrg(row) {
|
|
@@ -4809,40 +5213,6 @@ function deleteOrg(id, db) {
|
|
|
4809
5213
|
return d.run("DELETE FROM orgs WHERE id = ?", [id]).changes > 0;
|
|
4810
5214
|
}
|
|
4811
5215
|
|
|
4812
|
-
// src/db/comments.ts
|
|
4813
|
-
init_database();
|
|
4814
|
-
function addComment(input, db) {
|
|
4815
|
-
const d = db || getDatabase();
|
|
4816
|
-
if (!getTask(input.task_id, d)) {
|
|
4817
|
-
throw new TaskNotFoundError(input.task_id);
|
|
4818
|
-
}
|
|
4819
|
-
const id = uuid();
|
|
4820
|
-
const timestamp = now();
|
|
4821
|
-
d.run(`INSERT INTO task_comments (id, task_id, agent_id, session_id, content, type, progress_pct, created_at)
|
|
4822
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
4823
|
-
id,
|
|
4824
|
-
input.task_id,
|
|
4825
|
-
input.agent_id || null,
|
|
4826
|
-
input.session_id || null,
|
|
4827
|
-
input.content,
|
|
4828
|
-
input.type || "comment",
|
|
4829
|
-
input.progress_pct ?? null,
|
|
4830
|
-
timestamp
|
|
4831
|
-
]);
|
|
4832
|
-
return getComment(id, d);
|
|
4833
|
-
}
|
|
4834
|
-
function logProgress(taskId, message, pct, agentId, db) {
|
|
4835
|
-
return addComment({ task_id: taskId, content: message, type: "progress", progress_pct: pct, agent_id: agentId }, db);
|
|
4836
|
-
}
|
|
4837
|
-
function getComment(id, db) {
|
|
4838
|
-
const d = db || getDatabase();
|
|
4839
|
-
return d.query("SELECT * FROM task_comments WHERE id = ?").get(id);
|
|
4840
|
-
}
|
|
4841
|
-
function listComments(taskId, db) {
|
|
4842
|
-
const d = db || getDatabase();
|
|
4843
|
-
return d.query("SELECT * FROM task_comments WHERE task_id = ? ORDER BY created_at").all(taskId);
|
|
4844
|
-
}
|
|
4845
|
-
|
|
4846
5216
|
// src/server/routes.ts
|
|
4847
5217
|
import { join as join5, resolve as resolve5, sep } from "path";
|
|
4848
5218
|
function parseFieldsParam(url) {
|