@claudecam/server 0.1.0
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/dist/db/index.js +68 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/queries.js +658 -0
- package/dist/db/queries.js.map +1 -0
- package/dist/db/schema.sql +259 -0
- package/dist/index.js +128 -0
- package/dist/index.js.map +1 -0
- package/dist/routes/agents.js +68 -0
- package/dist/routes/agents.js.map +1 -0
- package/dist/routes/correlation-audit.js +31 -0
- package/dist/routes/correlation-audit.js.map +1 -0
- package/dist/routes/events.js +81 -0
- package/dist/routes/events.js.map +1 -0
- package/dist/routes/files.js +24 -0
- package/dist/routes/files.js.map +1 -0
- package/dist/routes/parse-prd.js +38 -0
- package/dist/routes/parse-prd.js.map +1 -0
- package/dist/routes/projects.js +96 -0
- package/dist/routes/projects.js.map +1 -0
- package/dist/routes/registry.js +88 -0
- package/dist/routes/registry.js.map +1 -0
- package/dist/routes/session-groups.js +182 -0
- package/dist/routes/session-groups.js.map +1 -0
- package/dist/routes/sessions.js +109 -0
- package/dist/routes/sessions.js.map +1 -0
- package/dist/routes/sprints.js +58 -0
- package/dist/routes/sprints.js.map +1 -0
- package/dist/routes/stats.js +63 -0
- package/dist/routes/stats.js.map +1 -0
- package/dist/routes/stream.js +21 -0
- package/dist/routes/stream.js.map +1 -0
- package/dist/routes/tasks.js +198 -0
- package/dist/routes/tasks.js.map +1 -0
- package/dist/services/correlation-engine.js +577 -0
- package/dist/services/correlation-engine.js.map +1 -0
- package/dist/services/event-processor.js +857 -0
- package/dist/services/event-processor.js.map +1 -0
- package/dist/services/prd-parser.js +142 -0
- package/dist/services/prd-parser.js.map +1 -0
- package/dist/services/project-manager.js +351 -0
- package/dist/services/project-manager.js.map +1 -0
- package/dist/services/project-router.js +56 -0
- package/dist/services/project-router.js.map +1 -0
- package/dist/services/session-manager.js +76 -0
- package/dist/services/session-manager.js.map +1 -0
- package/dist/services/sse-manager.js +115 -0
- package/dist/services/sse-manager.js.map +1 -0
- package/dist/services/string-similarity.js +256 -0
- package/dist/services/string-similarity.js.map +1 -0
- package/dist/services/task-completion.js +251 -0
- package/dist/services/task-completion.js.map +1 -0
- package/package.json +59 -0
|
@@ -0,0 +1,577 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { TASK_TOOLS } from '@claudecam/shared';
|
|
3
|
+
import { prdTaskQueries, taskActivityQueries, projectQueries, correlationAuditQueries, sessionProjectBindingQueries, agentTaskBindingQueries, sprintQueries, } from '../db/queries.js';
|
|
4
|
+
import { updateTask } from './project-manager.js';
|
|
5
|
+
import { sseManager } from './sse-manager.js';
|
|
6
|
+
import { combinedSimilarity } from './string-similarity.js';
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
// Backlog sprint protection
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
/** Check if a task belongs to a backlog sprint (order > 1). Backlog tasks
|
|
11
|
+
* should never have their status changed automatically by the correlation engine. */
|
|
12
|
+
function isBacklogSprintTask(task) {
|
|
13
|
+
if (!task.sprint_id)
|
|
14
|
+
return false;
|
|
15
|
+
const sprint = sprintQueries.getById().get(task.sprint_id);
|
|
16
|
+
return sprint !== undefined && sprint.order > 1;
|
|
17
|
+
}
|
|
18
|
+
// Minimum confidence threshold for a match to trigger a status update
|
|
19
|
+
const CONFIDENCE_THRESHOLD = 0.6;
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
// Session-Project Binding
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
/**
|
|
24
|
+
* Bind a session to a project based on working directory matching.
|
|
25
|
+
*
|
|
26
|
+
* Heuristics (in order of priority):
|
|
27
|
+
* 1. The project's `prd_source` path is contained within `workingDirectory`
|
|
28
|
+
* (e.g. prd_source = `/home/dev/myproject/PRD.md` and workDir starts with
|
|
29
|
+
* `/home/dev/myproject`).
|
|
30
|
+
* 2. The project name matches one of the directory segments in `workingDirectory`.
|
|
31
|
+
*/
|
|
32
|
+
function bindSessionToProject(sessionId, workingDirectory) {
|
|
33
|
+
if (!workingDirectory)
|
|
34
|
+
return;
|
|
35
|
+
const projects = projectQueries.getAll().all();
|
|
36
|
+
if (projects.length === 0)
|
|
37
|
+
return;
|
|
38
|
+
// Normalise path separators to forward slashes for comparison
|
|
39
|
+
const workDirNorm = workingDirectory.replace(/\\/g, '/').toLowerCase();
|
|
40
|
+
for (const project of projects) {
|
|
41
|
+
let matched = false;
|
|
42
|
+
// Strategy 1: prd_source directory match
|
|
43
|
+
if (project.prd_source) {
|
|
44
|
+
const prdSourceNorm = project.prd_source.replace(/\\/g, '/').toLowerCase();
|
|
45
|
+
// Extract the directory containing the PRD file
|
|
46
|
+
const prdDir = prdSourceNorm.includes('/')
|
|
47
|
+
? prdSourceNorm.substring(0, prdSourceNorm.lastIndexOf('/'))
|
|
48
|
+
: prdSourceNorm;
|
|
49
|
+
if (prdDir && workDirNorm.includes(prdDir)) {
|
|
50
|
+
matched = true;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// Strategy 2: project name matches a directory segment
|
|
54
|
+
if (!matched && project.name) {
|
|
55
|
+
const projectNameNorm = project.name.toLowerCase().replace(/[\s_-]+/g, '-');
|
|
56
|
+
const segments = workDirNorm.split('/').filter(s => s.length > 0);
|
|
57
|
+
if (segments.some(seg => seg === projectNameNorm || seg.includes(projectNameNorm))) {
|
|
58
|
+
matched = true;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (matched) {
|
|
62
|
+
const now = new Date().toISOString();
|
|
63
|
+
sessionProjectBindingQueries.bind().run(sessionId, project.id, now);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Get the project ID bound to a session, if any.
|
|
70
|
+
* Returns null when the session has not been bound to any project.
|
|
71
|
+
*/
|
|
72
|
+
function getProjectForSession(sessionId) {
|
|
73
|
+
const row = sessionProjectBindingQueries.getBySession().get(sessionId);
|
|
74
|
+
return row ? row.project_id : null;
|
|
75
|
+
}
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
// Agent-Task Binding
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
/**
|
|
80
|
+
* Create an active binding between an agent and a PRD task.
|
|
81
|
+
* This allows subsequent events from the same agent to receive a confidence
|
|
82
|
+
* boost towards this task, drastically reducing false-positive task switches.
|
|
83
|
+
*/
|
|
84
|
+
function bindAgentToTask(agentId, sessionId, taskId, confidence) {
|
|
85
|
+
agentTaskBindingQueries.bind().run(randomUUID(), agentId, sessionId, taskId, confidence, new Date().toISOString());
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Get the active (non-expired) agent-task binding for an agent in a session.
|
|
89
|
+
* Returns null when the agent has no active binding.
|
|
90
|
+
*/
|
|
91
|
+
function getAgentBinding(agentId, sessionId) {
|
|
92
|
+
const row = agentTaskBindingQueries.getActiveByAgent().get(agentId, sessionId);
|
|
93
|
+
if (!row)
|
|
94
|
+
return null;
|
|
95
|
+
return { prdTaskId: row.prd_task_id, confidence: row.confidence };
|
|
96
|
+
}
|
|
97
|
+
// ---------------------------------------------------------------------------
|
|
98
|
+
// Helpers
|
|
99
|
+
// ---------------------------------------------------------------------------
|
|
100
|
+
function parseTags(raw) {
|
|
101
|
+
if (!raw)
|
|
102
|
+
return [];
|
|
103
|
+
try {
|
|
104
|
+
const parsed = JSON.parse(raw);
|
|
105
|
+
return Array.isArray(parsed) ? parsed.filter((t) => typeof t === 'string') : [];
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
return [];
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
function logAudit(event, taskId, layer, score, matched, reason) {
|
|
112
|
+
try {
|
|
113
|
+
correlationAuditQueries.insert().run(randomUUID(), event.id, taskId, event.sessionId, event.agentId, layer, score, matched ? 1 : 0, reason, event.timestamp);
|
|
114
|
+
}
|
|
115
|
+
catch { /* audit must never break the pipeline */ }
|
|
116
|
+
}
|
|
117
|
+
// ---------------------------------------------------------------------------
|
|
118
|
+
// Task-tool handlers
|
|
119
|
+
// ---------------------------------------------------------------------------
|
|
120
|
+
function handleTaskCreate(event, input) {
|
|
121
|
+
// Extract ALL fields from TaskCreate input
|
|
122
|
+
const subject = typeof input['subject'] === 'string' ? input['subject'] : '';
|
|
123
|
+
const description = typeof input['description'] === 'string' ? input['description'] : '';
|
|
124
|
+
const priority = typeof input['priority'] === 'string' ? input['priority'] : '';
|
|
125
|
+
const activeForm = typeof input['activeForm'] === 'string' ? input['activeForm'] : '';
|
|
126
|
+
const inputTags = Array.isArray(input['tags'])
|
|
127
|
+
? input['tags'].filter((t) => typeof t === 'string')
|
|
128
|
+
: [];
|
|
129
|
+
// Need at least a subject to match against
|
|
130
|
+
if (!subject)
|
|
131
|
+
return;
|
|
132
|
+
// Try to extract the Claude Code taskId from the tool output
|
|
133
|
+
let externalId = null;
|
|
134
|
+
if (event.output) {
|
|
135
|
+
try {
|
|
136
|
+
const output = typeof event.output === 'string' ? JSON.parse(event.output) : event.output;
|
|
137
|
+
externalId = output['taskId']
|
|
138
|
+
?? output['id']
|
|
139
|
+
?? null;
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
const match = event.output.match(/(?:task|id)[:\s]*["']?([a-f0-9-]{8,})["']?/i);
|
|
143
|
+
if (match)
|
|
144
|
+
externalId = match[1] ?? null;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
// Also check input for taskId
|
|
148
|
+
if (!externalId) {
|
|
149
|
+
externalId = (typeof input['taskId'] === 'string' ? input['taskId'] : null)
|
|
150
|
+
?? (typeof input['id'] === 'string' ? input['id'] : null);
|
|
151
|
+
}
|
|
152
|
+
// Store full tool_input for audit (no 500 char truncation)
|
|
153
|
+
const fullInputDetails = JSON.stringify(input);
|
|
154
|
+
const now = new Date().toISOString();
|
|
155
|
+
const projects = projectQueries.getAll().all();
|
|
156
|
+
for (const project of projects) {
|
|
157
|
+
const tasks = prdTaskQueries.getByProject().all(project.id);
|
|
158
|
+
let bestMatch = null;
|
|
159
|
+
let bestScore = 0;
|
|
160
|
+
let bestReason = '';
|
|
161
|
+
for (const task of tasks) {
|
|
162
|
+
const reasons = [];
|
|
163
|
+
// Primary: subject vs title using combinedSimilarity
|
|
164
|
+
const titleScore = combinedSimilarity(subject, task.title);
|
|
165
|
+
if (titleScore >= CONFIDENCE_THRESHOLD)
|
|
166
|
+
reasons.push(`title:${(titleScore * 100).toFixed(0)}%`);
|
|
167
|
+
// Secondary: description vs task description
|
|
168
|
+
let descScore = 0;
|
|
169
|
+
if (description) {
|
|
170
|
+
descScore = combinedSimilarity(description, task.description) * 0.8;
|
|
171
|
+
if (descScore >= CONFIDENCE_THRESHOLD)
|
|
172
|
+
reasons.push(`desc:${(descScore * 100).toFixed(0)}%`);
|
|
173
|
+
}
|
|
174
|
+
// Tertiary: activeForm vs task title
|
|
175
|
+
let activeFormScore = 0;
|
|
176
|
+
if (activeForm) {
|
|
177
|
+
activeFormScore = combinedSimilarity(activeForm, task.title) * 0.9;
|
|
178
|
+
if (activeFormScore >= CONFIDENCE_THRESHOLD)
|
|
179
|
+
reasons.push(`activeForm:${(activeFormScore * 100).toFixed(0)}%`);
|
|
180
|
+
}
|
|
181
|
+
// Tag boost: input tags vs PRD task tags
|
|
182
|
+
let tagBonus = 0;
|
|
183
|
+
if (inputTags.length > 0) {
|
|
184
|
+
const taskTags = parseTags(task.tags);
|
|
185
|
+
if (taskTags.length > 0) {
|
|
186
|
+
let tagMatches = 0;
|
|
187
|
+
for (const inputTag of inputTags) {
|
|
188
|
+
const inputTagLower = inputTag.toLowerCase();
|
|
189
|
+
for (const taskTag of taskTags) {
|
|
190
|
+
const taskTagLower = taskTag.toLowerCase();
|
|
191
|
+
if (taskTagLower === inputTagLower || taskTagLower.includes(inputTagLower) || inputTagLower.includes(taskTagLower)) {
|
|
192
|
+
tagMatches++;
|
|
193
|
+
break;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
tagBonus = (tagMatches / Math.max(inputTags.length, taskTags.length)) * 0.15;
|
|
198
|
+
if (tagBonus > 0)
|
|
199
|
+
reasons.push(`tags:+${(tagBonus * 100).toFixed(0)}%`);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
const score = Math.min(Math.max(titleScore, descScore, activeFormScore) + tagBonus, 1.0);
|
|
203
|
+
// Log every match attempt to correlation audit
|
|
204
|
+
correlationAuditQueries.insert().run(randomUUID(), event.id, task.id, event.sessionId, event.agentId, 'task_create', score, score >= CONFIDENCE_THRESHOLD ? 1 : 0, `TaskCreate "${subject}" vs "${task.title}": ${reasons.join(', ') || 'below threshold'}`, now);
|
|
205
|
+
if (score > bestScore && score >= CONFIDENCE_THRESHOLD) {
|
|
206
|
+
bestMatch = task;
|
|
207
|
+
bestScore = score;
|
|
208
|
+
bestReason = reasons.join(', ');
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
if (bestMatch) {
|
|
212
|
+
// Link via external ID and optionally update priority
|
|
213
|
+
const priorityUpdate = ['critical', 'high', 'medium', 'low'].includes(priority) ? priority : null;
|
|
214
|
+
prdTaskQueries.update().run(null, priorityUpdate, null, null, externalId, null, null, event.sessionId, now, bestMatch.id);
|
|
215
|
+
// Create agent-task binding for the creating agent
|
|
216
|
+
bindAgentToTask(event.agentId, event.sessionId, bestMatch.id, bestScore);
|
|
217
|
+
// Record activity with full input details (no truncation)
|
|
218
|
+
taskActivityQueries.insert().run(randomUUID(), bestMatch.id, event.id, event.sessionId, event.agentId, 'task_created', event.timestamp, `Matched TaskCreate: "${subject}" (confidence: ${(bestScore * 100).toFixed(0)}%, ${bestReason}, externalId: ${externalId ?? 'none'}). Full input: ${fullInputDetails}`);
|
|
219
|
+
sseManager.broadcast('correlation_match', {
|
|
220
|
+
eventId: event.id,
|
|
221
|
+
taskId: bestMatch.id,
|
|
222
|
+
confidence: bestScore,
|
|
223
|
+
reason: `TaskCreate match: "${subject}" (${bestReason})`,
|
|
224
|
+
});
|
|
225
|
+
break;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
function handleTaskUpdate(event, input) {
|
|
230
|
+
const taskId = typeof input['taskId'] === 'string' ? input['taskId'] : '';
|
|
231
|
+
const status = typeof input['status'] === 'string' ? input['status'] : '';
|
|
232
|
+
const owner = typeof input['owner'] === 'string' ? input['owner'] : '';
|
|
233
|
+
const subject = typeof input['subject'] === 'string' ? input['subject'] : '';
|
|
234
|
+
if (!taskId)
|
|
235
|
+
return;
|
|
236
|
+
const now = new Date().toISOString();
|
|
237
|
+
const projects = projectQueries.getAll().all();
|
|
238
|
+
for (const project of projects) {
|
|
239
|
+
const tasks = prdTaskQueries.getByProject().all(project.id);
|
|
240
|
+
// Strategy 1: exact match by external_id
|
|
241
|
+
let matchedTask = tasks.find(t => t.external_id === taskId);
|
|
242
|
+
let matchMethod = 'externalId exact match';
|
|
243
|
+
let confidence = 1.0;
|
|
244
|
+
// Log Strategy 1 attempt
|
|
245
|
+
if (matchedTask) {
|
|
246
|
+
correlationAuditQueries.insert().run(randomUUID(), event.id, matchedTask.id, event.sessionId, event.agentId, 'task_update_s1_exact', 1.0, 1, `TaskUpdate exact externalId match: "${taskId}" -> "${matchedTask.title}"`, now);
|
|
247
|
+
}
|
|
248
|
+
// Strategy 2: similarity match by subject/title (fallback)
|
|
249
|
+
if (!matchedTask && subject) {
|
|
250
|
+
let bestScore = 0;
|
|
251
|
+
for (const task of tasks) {
|
|
252
|
+
if (task.status === 'completed' || task.status === 'deferred')
|
|
253
|
+
continue;
|
|
254
|
+
const score = combinedSimilarity(subject, task.title);
|
|
255
|
+
// Log each attempt
|
|
256
|
+
correlationAuditQueries.insert().run(randomUUID(), event.id, task.id, event.sessionId, event.agentId, 'task_update_s2_subject', score, score >= CONFIDENCE_THRESHOLD ? 1 : 0, `TaskUpdate subject "${subject}" vs "${task.title}": ${(score * 100).toFixed(0)}%`, now);
|
|
257
|
+
if (score > bestScore && score >= CONFIDENCE_THRESHOLD) {
|
|
258
|
+
matchedTask = task;
|
|
259
|
+
bestScore = score;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
if (matchedTask) {
|
|
263
|
+
confidence = bestScore;
|
|
264
|
+
matchMethod = `subject similarity match: "${subject}" (${(bestScore * 100).toFixed(0)}%)`;
|
|
265
|
+
// Link for future exact matches
|
|
266
|
+
prdTaskQueries.update().run(null, null, null, null, taskId, null, null, event.sessionId, now, matchedTask.id);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
// Strategy 3: if we have an activeForm/description, try combinedSimilarity on that
|
|
270
|
+
if (!matchedTask) {
|
|
271
|
+
const activeForm = typeof input['activeForm'] === 'string' ? input['activeForm'] : '';
|
|
272
|
+
const description = typeof input['description'] === 'string' ? input['description'] : '';
|
|
273
|
+
const searchText = activeForm || description || '';
|
|
274
|
+
if (searchText) {
|
|
275
|
+
let bestScore = 0;
|
|
276
|
+
for (const task of tasks) {
|
|
277
|
+
if (task.status === 'completed' || task.status === 'deferred')
|
|
278
|
+
continue;
|
|
279
|
+
const titleScore = combinedSimilarity(searchText, task.title);
|
|
280
|
+
const descScore = combinedSimilarity(searchText, task.description) * 0.8;
|
|
281
|
+
const score = Math.max(titleScore, descScore);
|
|
282
|
+
// Log each attempt
|
|
283
|
+
correlationAuditQueries.insert().run(randomUUID(), event.id, task.id, event.sessionId, event.agentId, 'task_update_s3_desc', score, score >= CONFIDENCE_THRESHOLD ? 1 : 0, `TaskUpdate desc/activeForm "${searchText.slice(0, 80)}" vs "${task.title}": title=${(titleScore * 100).toFixed(0)}% desc=${(descScore * 100).toFixed(0)}%`, now);
|
|
284
|
+
if (score > bestScore && score >= CONFIDENCE_THRESHOLD) {
|
|
285
|
+
matchedTask = task;
|
|
286
|
+
bestScore = score;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
if (matchedTask) {
|
|
290
|
+
confidence = bestScore;
|
|
291
|
+
matchMethod = `description similarity match (${(bestScore * 100).toFixed(0)}%)`;
|
|
292
|
+
// Link for future exact matches
|
|
293
|
+
prdTaskQueries.update().run(null, null, null, null, taskId, null, null, event.sessionId, now, matchedTask.id);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
// Strategy 4: check agent-task bindings for existing binding by owner
|
|
298
|
+
if (!matchedTask && owner) {
|
|
299
|
+
const binding = getAgentBinding(owner, event.sessionId);
|
|
300
|
+
if (binding) {
|
|
301
|
+
const boundTask = tasks.find(t => t.id === binding.prdTaskId);
|
|
302
|
+
if (boundTask && boundTask.status !== 'completed' && boundTask.status !== 'deferred') {
|
|
303
|
+
matchedTask = boundTask;
|
|
304
|
+
confidence = binding.confidence;
|
|
305
|
+
matchMethod = `agent-task binding for owner "${owner}" (confidence: ${(binding.confidence * 100).toFixed(0)}%)`;
|
|
306
|
+
// Log Strategy 4
|
|
307
|
+
correlationAuditQueries.insert().run(randomUUID(), event.id, boundTask.id, event.sessionId, event.agentId, 'task_update_s4_binding', binding.confidence, 1, `TaskUpdate matched via agent-task binding: owner="${owner}" -> "${boundTask.title}"`, now);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
if (!matchedTask)
|
|
312
|
+
continue;
|
|
313
|
+
const updates = {};
|
|
314
|
+
if (status === 'in_progress') {
|
|
315
|
+
updates['status'] = 'in_progress';
|
|
316
|
+
}
|
|
317
|
+
else if (status === 'completed') {
|
|
318
|
+
updates['status'] = 'completed';
|
|
319
|
+
}
|
|
320
|
+
else if (status === 'pending') {
|
|
321
|
+
updates['status'] = 'pending';
|
|
322
|
+
}
|
|
323
|
+
if (owner) {
|
|
324
|
+
updates['assignedAgent'] = owner;
|
|
325
|
+
}
|
|
326
|
+
if (Object.keys(updates).length > 0 && !isBacklogSprintTask(matchedTask)) {
|
|
327
|
+
updateTask(matchedTask.id, updates);
|
|
328
|
+
}
|
|
329
|
+
// --- Agent-Task binding management ---
|
|
330
|
+
if (status === 'in_progress') {
|
|
331
|
+
bindAgentToTask(event.agentId, event.sessionId, matchedTask.id, confidence);
|
|
332
|
+
}
|
|
333
|
+
if (owner) {
|
|
334
|
+
bindAgentToTask(owner, event.sessionId, matchedTask.id, confidence);
|
|
335
|
+
}
|
|
336
|
+
if (status === 'completed') {
|
|
337
|
+
agentTaskBindingQueries.expire().run(now, event.agentId, event.sessionId);
|
|
338
|
+
}
|
|
339
|
+
// Record activity with full input details
|
|
340
|
+
const activityType = status === 'completed' ? 'task_completed'
|
|
341
|
+
: status === 'in_progress' ? 'task_started'
|
|
342
|
+
: owner ? 'agent_assigned'
|
|
343
|
+
: 'manual_update';
|
|
344
|
+
taskActivityQueries.insert().run(randomUUID(), matchedTask.id, event.id, event.sessionId, event.agentId, activityType, event.timestamp, `TaskUpdate: status=${status || 'unchanged'}, owner=${owner || 'unchanged'} (${matchMethod}). Full input: ${JSON.stringify(input)}`);
|
|
345
|
+
sseManager.broadcast('correlation_match', {
|
|
346
|
+
eventId: event.id,
|
|
347
|
+
taskId: matchedTask.id,
|
|
348
|
+
confidence,
|
|
349
|
+
reason: `TaskUpdate ${matchMethod}`,
|
|
350
|
+
});
|
|
351
|
+
break;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
// ---------------------------------------------------------------------------
|
|
355
|
+
// TaskList bulk reconciliation handler
|
|
356
|
+
// ---------------------------------------------------------------------------
|
|
357
|
+
/**
|
|
358
|
+
* Parse and reconcile a TaskList response against PRD tasks.
|
|
359
|
+
*
|
|
360
|
+
* TaskList returns the full list of Claude Code tasks. We parse each entry
|
|
361
|
+
* and try to match it against PRD tasks, updating status and owner when they
|
|
362
|
+
* differ. This provides a periodic "ground truth" sync that corrects drift.
|
|
363
|
+
*/
|
|
364
|
+
function handleTaskList(event) {
|
|
365
|
+
const rawOutput = event.output;
|
|
366
|
+
if (!rawOutput)
|
|
367
|
+
return;
|
|
368
|
+
const now = new Date().toISOString();
|
|
369
|
+
let claudeTasks = [];
|
|
370
|
+
// Try JSON parse first (structured output)
|
|
371
|
+
try {
|
|
372
|
+
const parsed = JSON.parse(rawOutput);
|
|
373
|
+
if (Array.isArray(parsed)) {
|
|
374
|
+
claudeTasks = parsed;
|
|
375
|
+
}
|
|
376
|
+
else if (typeof parsed === 'object' && parsed !== null) {
|
|
377
|
+
// Might be wrapped in { tasks: [...] } or { result: [...] }
|
|
378
|
+
const wrapped = parsed;
|
|
379
|
+
const inner = wrapped['tasks'] ?? wrapped['result'] ?? wrapped['data'];
|
|
380
|
+
if (Array.isArray(inner)) {
|
|
381
|
+
claudeTasks = inner;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
catch {
|
|
386
|
+
// Not JSON - try line-by-line text parsing
|
|
387
|
+
const lines = rawOutput.split('\n').filter(l => l.trim().length > 0);
|
|
388
|
+
for (const line of lines) {
|
|
389
|
+
const trimmed = line.trim();
|
|
390
|
+
// Pattern: "[status] subject (owner: name)"
|
|
391
|
+
const bracketMatch = trimmed.match(/\[(\w+)\]\s+(.+?)(?:\s*\(owner:\s*(.+?)\))?$/);
|
|
392
|
+
if (bracketMatch) {
|
|
393
|
+
claudeTasks.push({
|
|
394
|
+
status: bracketMatch[1],
|
|
395
|
+
subject: bracketMatch[2]?.trim(),
|
|
396
|
+
owner: bracketMatch[3]?.trim(),
|
|
397
|
+
});
|
|
398
|
+
continue;
|
|
399
|
+
}
|
|
400
|
+
// Pattern: "N. subject - status"
|
|
401
|
+
const numberedMatch = trimmed.match(/^\d+\.\s+(.+?)\s*[-|]\s*(\w+)(?:\s*[-|]\s*(.+))?$/);
|
|
402
|
+
if (numberedMatch) {
|
|
403
|
+
claudeTasks.push({
|
|
404
|
+
subject: numberedMatch[1]?.trim(),
|
|
405
|
+
status: numberedMatch[2]?.trim(),
|
|
406
|
+
owner: numberedMatch[3]?.trim(),
|
|
407
|
+
});
|
|
408
|
+
continue;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
if (claudeTasks.length === 0)
|
|
413
|
+
return;
|
|
414
|
+
// Map Claude Code status strings to PRD task status
|
|
415
|
+
const STATUS_MAP = {
|
|
416
|
+
'pending': 'pending',
|
|
417
|
+
'in_progress': 'in_progress',
|
|
418
|
+
'in-progress': 'in_progress',
|
|
419
|
+
'inprogress': 'in_progress',
|
|
420
|
+
'completed': 'completed',
|
|
421
|
+
'done': 'completed',
|
|
422
|
+
'blocked': 'blocked',
|
|
423
|
+
'cancelled': 'deferred',
|
|
424
|
+
'canceled': 'deferred',
|
|
425
|
+
};
|
|
426
|
+
const statusOrder = ['backlog', 'planned', 'pending', 'in_progress', 'in_review', 'completed'];
|
|
427
|
+
const projects = projectQueries.getAll().all();
|
|
428
|
+
for (const project of projects) {
|
|
429
|
+
const prdTasks = prdTaskQueries.getByProject().all(project.id);
|
|
430
|
+
if (prdTasks.length === 0)
|
|
431
|
+
continue;
|
|
432
|
+
let matchCount = 0;
|
|
433
|
+
for (const claudeTask of claudeTasks) {
|
|
434
|
+
const taskSubject = claudeTask.subject ?? '';
|
|
435
|
+
const claudeTaskId = claudeTask.id ?? '';
|
|
436
|
+
if (!taskSubject && !claudeTaskId)
|
|
437
|
+
continue;
|
|
438
|
+
let matchedPrdTask;
|
|
439
|
+
let matchScore = 0;
|
|
440
|
+
let matchReason = '';
|
|
441
|
+
// Try 1: exact match by external_id
|
|
442
|
+
if (claudeTaskId) {
|
|
443
|
+
matchedPrdTask = prdTasks.find(t => t.external_id === claudeTaskId);
|
|
444
|
+
if (matchedPrdTask) {
|
|
445
|
+
matchScore = 1.0;
|
|
446
|
+
matchReason = `externalId exact: "${claudeTaskId}"`;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
// Try 2: match by subject vs title using combinedSimilarity
|
|
450
|
+
if (!matchedPrdTask && taskSubject) {
|
|
451
|
+
let bestScore = 0;
|
|
452
|
+
for (const prdTask of prdTasks) {
|
|
453
|
+
const score = combinedSimilarity(taskSubject, prdTask.title);
|
|
454
|
+
if (score > bestScore && score >= CONFIDENCE_THRESHOLD) {
|
|
455
|
+
matchedPrdTask = prdTask;
|
|
456
|
+
bestScore = score;
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
if (matchedPrdTask) {
|
|
460
|
+
matchScore = bestScore;
|
|
461
|
+
matchReason = `subject similarity: "${taskSubject}" -> "${matchedPrdTask.title}" (${(bestScore * 100).toFixed(0)}%)`;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
// Log the match attempt to correlation audit
|
|
465
|
+
correlationAuditQueries.insert().run(randomUUID(), event.id, matchedPrdTask?.id ?? null, event.sessionId, event.agentId, 'task_list_sync', matchScore, matchedPrdTask ? 1 : 0, `TaskList sync: "${taskSubject || claudeTaskId}" ${matchedPrdTask ? `-> "${matchedPrdTask.title}" (${matchReason})` : '(no match)'}`, now);
|
|
466
|
+
if (!matchedPrdTask)
|
|
467
|
+
continue;
|
|
468
|
+
matchCount++;
|
|
469
|
+
// Reconcile status and owner
|
|
470
|
+
const claudeStatus = claudeTask.status ? STATUS_MAP[claudeTask.status.toLowerCase()] : undefined;
|
|
471
|
+
const updates = {};
|
|
472
|
+
let hasChanges = false;
|
|
473
|
+
if (claudeStatus && claudeStatus !== matchedPrdTask.status) {
|
|
474
|
+
const currentIdx = statusOrder.indexOf(matchedPrdTask.status);
|
|
475
|
+
const newIdx = statusOrder.indexOf(claudeStatus);
|
|
476
|
+
// Don't regress, but allow 'blocked' transitions
|
|
477
|
+
if (matchedPrdTask.status !== 'blocked' && (newIdx > currentIdx || claudeStatus === 'blocked')) {
|
|
478
|
+
updates['status'] = claudeStatus;
|
|
479
|
+
hasChanges = true;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
if (claudeTask.owner && claudeTask.owner !== matchedPrdTask.assigned_agent) {
|
|
483
|
+
updates['assignedAgent'] = claudeTask.owner;
|
|
484
|
+
hasChanges = true;
|
|
485
|
+
}
|
|
486
|
+
if (hasChanges && !isBacklogSprintTask(matchedPrdTask)) {
|
|
487
|
+
updateTask(matchedPrdTask.id, updates);
|
|
488
|
+
const activityType = updates['status'] === 'completed' ? 'task_completed'
|
|
489
|
+
: updates['status'] === 'in_progress' ? 'task_started'
|
|
490
|
+
: updates['assignedAgent'] ? 'agent_assigned'
|
|
491
|
+
: 'manual_update';
|
|
492
|
+
taskActivityQueries.insert().run(randomUUID(), matchedPrdTask.id, event.id, event.sessionId, event.agentId, activityType, event.timestamp, `TaskList sync: status=${updates['status'] ?? 'unchanged'}, owner=${updates['assignedAgent'] ?? 'unchanged'} (${matchReason})`);
|
|
493
|
+
sseManager.broadcast('task_status_changed', {
|
|
494
|
+
taskId: matchedPrdTask.id,
|
|
495
|
+
oldStatus: matchedPrdTask.status,
|
|
496
|
+
newStatus: updates['status'] ?? matchedPrdTask.status,
|
|
497
|
+
agent: updates['assignedAgent'] ?? matchedPrdTask.assigned_agent,
|
|
498
|
+
source: 'task_list_sync',
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
// If we matched tasks in this project, no need to check other projects
|
|
503
|
+
if (matchCount > 0)
|
|
504
|
+
break;
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
// ---------------------------------------------------------------------------
|
|
508
|
+
// Public API
|
|
509
|
+
// ---------------------------------------------------------------------------
|
|
510
|
+
/**
|
|
511
|
+
* Correlate an incoming agent event against PRD tasks.
|
|
512
|
+
*
|
|
513
|
+
* This function is called from the event ingestion route after the event has
|
|
514
|
+
* been persisted. It uses an "Explicit-First" approach with only 2 paths:
|
|
515
|
+
*
|
|
516
|
+
* 0. **Session binding** -- On SessionStart, auto-bind the session to a project
|
|
517
|
+
* based on working directory. This narrows all subsequent matching to the
|
|
518
|
+
* bound project, eliminating cross-project false positives.
|
|
519
|
+
*
|
|
520
|
+
* 1. **Task-tool correlation** -- When the agent uses TaskCreate / TaskUpdate /
|
|
521
|
+
* TaskList tools, we link them to PRD tasks by exact external-id match or
|
|
522
|
+
* by subject/title similarity. This is the GOLD path for auto-completing
|
|
523
|
+
* tasks (TaskUpdate with status=completed).
|
|
524
|
+
*
|
|
525
|
+
* General tool events (Write, Edit, Bash, Read, etc.) are intentionally NOT
|
|
526
|
+
* correlated. They produced too much noise with low-confidence matches.
|
|
527
|
+
* Task status changes should come from explicit signals only.
|
|
528
|
+
*/
|
|
529
|
+
export function correlateEvent(event) {
|
|
530
|
+
try {
|
|
531
|
+
// --- Guard: skip events that can never produce useful correlation ---
|
|
532
|
+
// PreToolUse fires BEFORE the tool runs - no output, no result to correlate.
|
|
533
|
+
// Only PostToolUse has the complete picture (input + output + duration).
|
|
534
|
+
if (event.hookType === 'PreToolUse')
|
|
535
|
+
return;
|
|
536
|
+
// Skip lifecycle events that have no tool context
|
|
537
|
+
if (event.hookType === 'Notification' || event.hookType === 'PreCompact' ||
|
|
538
|
+
event.hookType === 'PostCompact' || event.hookType === 'SubagentStop')
|
|
539
|
+
return;
|
|
540
|
+
// Skip events with no meaningful tool name
|
|
541
|
+
if (event.tool === 'unknown' || event.tool === '')
|
|
542
|
+
return;
|
|
543
|
+
// --- Path 0: Session-Project binding on SessionStart ---
|
|
544
|
+
if (event.hookType === 'SessionStart') {
|
|
545
|
+
const workingDirectory = event.metadata?.['working_directory'] || '';
|
|
546
|
+
if (workingDirectory) {
|
|
547
|
+
bindSessionToProject(event.sessionId, workingDirectory);
|
|
548
|
+
}
|
|
549
|
+
// SessionStart events don't need further correlation
|
|
550
|
+
return;
|
|
551
|
+
}
|
|
552
|
+
// --- Path 1: explicit task tool events (ONLY path for correlation) ---
|
|
553
|
+
if (event.tool && TASK_TOOLS.includes(event.tool)) {
|
|
554
|
+
const meta = event.metadata;
|
|
555
|
+
if (!meta)
|
|
556
|
+
return;
|
|
557
|
+
const toolInput = (meta['tool_input'] ?? meta);
|
|
558
|
+
if (event.tool === 'TaskCreate') {
|
|
559
|
+
handleTaskCreate(event, toolInput);
|
|
560
|
+
}
|
|
561
|
+
else if (event.tool === 'TaskUpdate') {
|
|
562
|
+
handleTaskUpdate(event, toolInput);
|
|
563
|
+
}
|
|
564
|
+
else if (event.tool === 'TaskList' && event.hookType === 'PostToolUse') {
|
|
565
|
+
handleTaskList(event);
|
|
566
|
+
}
|
|
567
|
+
return;
|
|
568
|
+
}
|
|
569
|
+
// General tool events (Write, Edit, Bash, Read, etc.) are intentionally
|
|
570
|
+
// NOT correlated. The removed handleGeneralToolEvent() was the main
|
|
571
|
+
// source of noise with low-confidence fuzzy matches.
|
|
572
|
+
}
|
|
573
|
+
catch {
|
|
574
|
+
// Correlation errors should never break event processing
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
//# sourceMappingURL=correlation-engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"correlation-engine.js","sourceRoot":"","sources":["../../src/services/correlation-engine.ts"],"names":[],"mappings":"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"}
|