@telora/daemon 0.13.12 → 0.13.13

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.
Files changed (49) hide show
  1. package/build-info.json +2 -2
  2. package/dist/pm/adaptive-poller.d.ts +26 -0
  3. package/dist/pm/adaptive-poller.d.ts.map +1 -0
  4. package/dist/pm/adaptive-poller.js +53 -0
  5. package/dist/pm/adaptive-poller.js.map +1 -0
  6. package/dist/pm/cascade-evaluator.d.ts +29 -0
  7. package/dist/pm/cascade-evaluator.d.ts.map +1 -0
  8. package/dist/pm/cascade-evaluator.js +135 -0
  9. package/dist/pm/cascade-evaluator.js.map +1 -0
  10. package/dist/pm/channel-email.d.ts +42 -0
  11. package/dist/pm/channel-email.d.ts.map +1 -0
  12. package/dist/pm/channel-email.js +47 -0
  13. package/dist/pm/channel-email.js.map +1 -0
  14. package/dist/pm/channel-slack.d.ts +40 -0
  15. package/dist/pm/channel-slack.d.ts.map +1 -0
  16. package/dist/pm/channel-slack.js +46 -0
  17. package/dist/pm/channel-slack.js.map +1 -0
  18. package/dist/pm/communication-drafter.d.ts +44 -0
  19. package/dist/pm/communication-drafter.d.ts.map +1 -0
  20. package/dist/pm/communication-drafter.js +84 -0
  21. package/dist/pm/communication-drafter.js.map +1 -0
  22. package/dist/pm/dialog-handler.d.ts +32 -0
  23. package/dist/pm/dialog-handler.d.ts.map +1 -0
  24. package/dist/pm/dialog-handler.js +107 -0
  25. package/dist/pm/dialog-handler.js.map +1 -0
  26. package/dist/pm/mitigation-correlator.d.ts +29 -0
  27. package/dist/pm/mitigation-correlator.d.ts.map +1 -0
  28. package/dist/pm/mitigation-correlator.js +147 -0
  29. package/dist/pm/mitigation-correlator.js.map +1 -0
  30. package/dist/pm/risk-scanner.d.ts +28 -0
  31. package/dist/pm/risk-scanner.d.ts.map +1 -0
  32. package/dist/pm/risk-scanner.js +112 -0
  33. package/dist/pm/risk-scanner.js.map +1 -0
  34. package/dist/pm-engine.d.ts +67 -0
  35. package/dist/pm-engine.d.ts.map +1 -0
  36. package/dist/pm-engine.js +277 -0
  37. package/dist/pm-engine.js.map +1 -0
  38. package/dist/state-cascade.d.ts +3 -2
  39. package/dist/state-cascade.d.ts.map +1 -1
  40. package/dist/state-cascade.js +3 -2
  41. package/dist/state-cascade.js.map +1 -1
  42. package/dist/strategy-prompt-builder.d.ts.map +1 -1
  43. package/dist/strategy-prompt-builder.js +4 -0
  44. package/dist/strategy-prompt-builder.js.map +1 -1
  45. package/dist/unified-shell.d.ts +1 -1
  46. package/dist/unified-shell.d.ts.map +1 -1
  47. package/dist/unified-shell.js +56 -1
  48. package/dist/unified-shell.js.map +1 -1
  49. package/package.json +1 -1
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Dialog update handler -- parses human input about external conversations.
3
+ *
4
+ * Provides simple keyword-based matching to extract structured updates from
5
+ * free-text human messages. This is intentionally simple; LLM-enhanced
6
+ * parsing will replace the keyword approach later.
7
+ */
8
+ // ---------------------------------------------------------------------------
9
+ // Internal helpers
10
+ // ---------------------------------------------------------------------------
11
+ /** Status keywords mapped to normalized status values. */
12
+ const STATUS_KEYWORDS = {
13
+ done: 'resolved',
14
+ resolved: 'resolved',
15
+ completed: 'resolved',
16
+ fixed: 'resolved',
17
+ closed: 'resolved',
18
+ delayed: 'delayed',
19
+ postponed: 'delayed',
20
+ 'pushed back': 'delayed',
21
+ blocked: 'blocked',
22
+ stuck: 'blocked',
23
+ 'working on it': 'in_progress',
24
+ 'in progress': 'in_progress',
25
+ started: 'in_progress',
26
+ 'no update': 'waiting',
27
+ 'no change': 'waiting',
28
+ };
29
+ /** Patterns that precede a contact name. */
30
+ const CONTACT_PATTERNS = [
31
+ /talked?\s+(?:to|with)\s+([A-Z][a-z]+(?:\s+[A-Z][a-z]+)?)/,
32
+ /spoke\s+(?:to|with)\s+([A-Z][a-z]+(?:\s+[A-Z][a-z]+)?)/,
33
+ /heard\s+(?:from|back\s+from)\s+([A-Z][a-z]+(?:\s+[A-Z][a-z]+)?)/,
34
+ /(?:met|meeting)\s+(?:with)\s+([A-Z][a-z]+(?:\s+[A-Z][a-z]+)?)/,
35
+ /email(?:ed)?\s+(?:from|by)\s+([A-Z][a-z]+(?:\s+[A-Z][a-z]+)?)/,
36
+ ];
37
+ /**
38
+ * Find the best matching item by title within a message.
39
+ * Uses case-insensitive substring matching, preferring longer matches.
40
+ */
41
+ function findBestMatch(message, items) {
42
+ const lowerMsg = message.toLowerCase();
43
+ let bestMatch = null;
44
+ let bestLength = 0;
45
+ for (const item of items) {
46
+ const lowerTitle = item.title.toLowerCase();
47
+ if (lowerMsg.includes(lowerTitle) && lowerTitle.length > bestLength) {
48
+ bestMatch = item;
49
+ bestLength = lowerTitle.length;
50
+ }
51
+ }
52
+ return bestMatch;
53
+ }
54
+ /**
55
+ * Extract a status keyword from the message.
56
+ * Checks multi-word phrases first (longer matches win).
57
+ */
58
+ function extractStatus(message) {
59
+ const lowerMsg = message.toLowerCase();
60
+ // Sort keywords by length descending so multi-word phrases match first
61
+ const sortedKeywords = Object.keys(STATUS_KEYWORDS).sort((a, b) => b.length - a.length);
62
+ for (const keyword of sortedKeywords) {
63
+ if (lowerMsg.includes(keyword)) {
64
+ return STATUS_KEYWORDS[keyword] ?? null;
65
+ }
66
+ }
67
+ return null;
68
+ }
69
+ /**
70
+ * Extract a contact name from the message using known patterns.
71
+ */
72
+ function extractContactName(message) {
73
+ for (const pattern of CONTACT_PATTERNS) {
74
+ const match = message.match(pattern);
75
+ if (match?.[1]) {
76
+ return match[1];
77
+ }
78
+ }
79
+ return null;
80
+ }
81
+ // ---------------------------------------------------------------------------
82
+ // Public API
83
+ // ---------------------------------------------------------------------------
84
+ /**
85
+ * Parse a human dialog message to extract structured risk/dependency updates.
86
+ *
87
+ * Matches the message against known risk and dependency titles, extracts
88
+ * status keywords, and identifies contact names. This is a best-effort
89
+ * keyword parser; unmatched fields return null.
90
+ */
91
+ export function parseDialogUpdate(humanMessage, risks, dependencies) {
92
+ // Match dependency first (more specific), then risk
93
+ const matchedDep = findBestMatch(humanMessage, dependencies);
94
+ const matchedRisk = matchedDep
95
+ ? risks.find(r => r.id === matchedDep.riskId) ?? findBestMatch(humanMessage, risks)
96
+ : findBestMatch(humanMessage, risks);
97
+ const statusUpdate = extractStatus(humanMessage);
98
+ const contactName = extractContactName(humanMessage);
99
+ return {
100
+ riskId: matchedRisk?.id ?? matchedDep?.riskId ?? null,
101
+ dependencyId: matchedDep?.id ?? null,
102
+ statusUpdate,
103
+ notes: humanMessage,
104
+ contactName,
105
+ };
106
+ }
107
+ //# sourceMappingURL=dialog-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dialog-handler.js","sourceRoot":"","sources":["../../src/pm/dialog-handler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Mitigation strategy progress correlator.
3
+ *
4
+ * For each risk with linked strategies (via risk_strategy_links), computes
5
+ * issue-level completion percentages and produces an overall assessment of
6
+ * whether the mitigation work is on track.
7
+ */
8
+ export interface MitigationProgressReport {
9
+ riskId: string;
10
+ riskTitle: string;
11
+ riskStage: string;
12
+ strategies: Array<{
13
+ strategyId: string;
14
+ strategyName: string;
15
+ totalIssues: number;
16
+ doneIssues: number;
17
+ completionPct: number;
18
+ }>;
19
+ overallCompletionPct: number;
20
+ assessment: 'on_track' | 'at_risk' | 'behind' | 'no_mitigation';
21
+ }
22
+ /**
23
+ * Correlate mitigation progress across all risks for a product.
24
+ *
25
+ * For each risk, looks up linked strategies, counts total and done issues
26
+ * across all deliveries in those strategies, and produces an assessment.
27
+ */
28
+ export declare function correlateMitigationProgress(productId: string): Promise<MitigationProgressReport[]>;
29
+ //# sourceMappingURL=mitigation-correlator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mitigation-correlator.d.ts","sourceRoot":"","sources":["../../src/pm/mitigation-correlator.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,KAAK,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,EAAE,MAAM,CAAC;QACrB,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,EAAE,MAAM,CAAC;QACnB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC,CAAC;IACH,oBAAoB,EAAE,MAAM,CAAC;IAC7B,UAAU,EAAE,UAAU,GAAG,SAAS,GAAG,QAAQ,GAAG,eAAe,CAAC;CACjE;AAuDD;;;;;GAKG;AACH,wBAAsB,2BAA2B,CAC/C,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,wBAAwB,EAAE,CAAC,CA2IrC"}
@@ -0,0 +1,147 @@
1
+ /**
2
+ * Mitigation strategy progress correlator.
3
+ *
4
+ * For each risk with linked strategies (via risk_strategy_links), computes
5
+ * issue-level completion percentages and produces an overall assessment of
6
+ * whether the mitigation work is on track.
7
+ */
8
+ import { callApi } from '../queries/shared.js';
9
+ // ---------------------------------------------------------------------------
10
+ // Public API
11
+ // ---------------------------------------------------------------------------
12
+ /**
13
+ * Correlate mitigation progress across all risks for a product.
14
+ *
15
+ * For each risk, looks up linked strategies, counts total and done issues
16
+ * across all deliveries in those strategies, and produces an assessment.
17
+ */
18
+ export async function correlateMitigationProgress(productId) {
19
+ // 1. Get all risks
20
+ const risksResponse = await callApi('risk_list', {
21
+ productId,
22
+ limit: 500,
23
+ offset: 0,
24
+ });
25
+ const risks = risksResponse.risks;
26
+ if (risks.length === 0)
27
+ return [];
28
+ const reports = [];
29
+ for (const risk of risks) {
30
+ // Skip resolved risks
31
+ const stageName = risk.workflow_stage?.name ?? 'draft';
32
+ if (stageName === 'resolved')
33
+ continue;
34
+ // 2. Get strategy links for this risk
35
+ let riskDetail;
36
+ try {
37
+ riskDetail = await callApi('risk_get', { riskId: risk.id });
38
+ }
39
+ catch {
40
+ continue; // Non-fatal
41
+ }
42
+ const strategyLinks = riskDetail.strategyLinks;
43
+ if (strategyLinks.length === 0) {
44
+ reports.push({
45
+ riskId: risk.id,
46
+ riskTitle: risk.title,
47
+ riskStage: stageName,
48
+ strategies: [],
49
+ overallCompletionPct: 0,
50
+ assessment: 'no_mitigation',
51
+ });
52
+ continue;
53
+ }
54
+ // 3. For each linked strategy, count issues
55
+ const strategies = [];
56
+ let totalIssuesAll = 0;
57
+ let doneIssuesAll = 0;
58
+ for (const link of strategyLinks) {
59
+ try {
60
+ // Get deliveries for this strategy
61
+ const deliveries = await callApi('delivery_list', {
62
+ productId,
63
+ strategyId: link.strategy_id,
64
+ limit: 500,
65
+ offset: 0,
66
+ });
67
+ let strategyTotalIssues = 0;
68
+ let strategyDoneIssues = 0;
69
+ let strategyName = link.strategy_id;
70
+ // Count issues across all deliveries
71
+ for (const delivery of deliveries.deliveries) {
72
+ try {
73
+ const issues = await callApi('issue_list', {
74
+ deliveryId: delivery.id,
75
+ limit: 500,
76
+ offset: 0,
77
+ });
78
+ // Only count task/bug issues, not context groups
79
+ for (const issue of issues.issues) {
80
+ if (issue.issue_type === 'context_group')
81
+ continue;
82
+ strategyTotalIssues++;
83
+ if (issue.status === 'done') {
84
+ strategyDoneIssues++;
85
+ }
86
+ }
87
+ }
88
+ catch {
89
+ // Non-fatal: skip this delivery's issues
90
+ }
91
+ }
92
+ // Try to get strategy name from the first delivery response
93
+ if (deliveries.deliveries.length > 0) {
94
+ try {
95
+ const strategyResponse = await callApi('strategy_get', { strategyId: link.strategy_id });
96
+ strategyName = strategyResponse.strategy.name;
97
+ }
98
+ catch {
99
+ // Non-fatal: use ID as name
100
+ }
101
+ }
102
+ const completionPct = strategyTotalIssues > 0
103
+ ? Math.round((strategyDoneIssues / strategyTotalIssues) * 100)
104
+ : 0;
105
+ strategies.push({
106
+ strategyId: link.strategy_id,
107
+ strategyName,
108
+ totalIssues: strategyTotalIssues,
109
+ doneIssues: strategyDoneIssues,
110
+ completionPct,
111
+ });
112
+ totalIssuesAll += strategyTotalIssues;
113
+ doneIssuesAll += strategyDoneIssues;
114
+ }
115
+ catch {
116
+ // Non-fatal: skip this strategy
117
+ }
118
+ }
119
+ const overallCompletionPct = totalIssuesAll > 0
120
+ ? Math.round((doneIssuesAll / totalIssuesAll) * 100)
121
+ : 0;
122
+ // Assess mitigation progress
123
+ let assessment;
124
+ if (strategies.length === 0) {
125
+ assessment = 'no_mitigation';
126
+ }
127
+ else if (overallCompletionPct >= 75) {
128
+ assessment = 'on_track';
129
+ }
130
+ else if (overallCompletionPct >= 40) {
131
+ assessment = 'at_risk';
132
+ }
133
+ else {
134
+ assessment = 'behind';
135
+ }
136
+ reports.push({
137
+ riskId: risk.id,
138
+ riskTitle: risk.title,
139
+ riskStage: stageName,
140
+ strategies,
141
+ overallCompletionPct,
142
+ assessment,
143
+ });
144
+ }
145
+ return reports;
146
+ }
147
+ //# sourceMappingURL=mitigation-correlator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mitigation-correlator.js","sourceRoot":"","sources":["../../src/pm/mitigation-correlator.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAsE/C,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAC/C,SAAiB;IAEjB,mBAAmB;IACnB,MAAM,aAAa,GAAG,MAAM,OAAO,CAAmB,WAAW,EAAE;QACjE,SAAS;QACT,KAAK,EAAE,GAAG;QACV,MAAM,EAAE,CAAC;KACV,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,CAAC;IAClC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAElC,MAAM,OAAO,GAA+B,EAAE,CAAC;IAE/C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,sBAAsB;QACtB,MAAM,SAAS,GAAG,IAAI,CAAC,cAAc,EAAE,IAAI,IAAI,OAAO,CAAC;QACvD,IAAI,SAAS,KAAK,UAAU;YAAE,SAAS;QAEvC,sCAAsC;QACtC,IAAI,UAA2B,CAAC;QAChC,IAAI,CAAC;YACH,UAAU,GAAG,MAAM,OAAO,CAAkB,UAAU,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;QAC/E,CAAC;QAAC,MAAM,CAAC;YACP,SAAS,CAAC,YAAY;QACxB,CAAC;QAED,MAAM,aAAa,GAAG,UAAU,CAAC,aAAa,CAAC;QAC/C,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/B,OAAO,CAAC,IAAI,CAAC;gBACX,MAAM,EAAE,IAAI,CAAC,EAAE;gBACf,SAAS,EAAE,IAAI,CAAC,KAAK;gBACrB,SAAS,EAAE,SAAS;gBACpB,UAAU,EAAE,EAAE;gBACd,oBAAoB,EAAE,CAAC;gBACvB,UAAU,EAAE,eAAe;aAC5B,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QAED,4CAA4C;QAC5C,MAAM,UAAU,GAA2C,EAAE,CAAC;QAC9D,IAAI,cAAc,GAAG,CAAC,CAAC;QACvB,IAAI,aAAa,GAAG,CAAC,CAAC;QAEtB,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;YACjC,IAAI,CAAC;gBACH,mCAAmC;gBACnC,MAAM,UAAU,GAAG,MAAM,OAAO,CAAuB,eAAe,EAAE;oBACtE,SAAS;oBACT,UAAU,EAAE,IAAI,CAAC,WAAW;oBAC5B,KAAK,EAAE,GAAG;oBACV,MAAM,EAAE,CAAC;iBACV,CAAC,CAAC;gBAEH,IAAI,mBAAmB,GAAG,CAAC,CAAC;gBAC5B,IAAI,kBAAkB,GAAG,CAAC,CAAC;gBAC3B,IAAI,YAAY,GAAG,IAAI,CAAC,WAAW,CAAC;gBAEpC,qCAAqC;gBACrC,KAAK,MAAM,QAAQ,IAAI,UAAU,CAAC,UAAU,EAAE,CAAC;oBAC7C,IAAI,CAAC;wBACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAoB,YAAY,EAAE;4BAC5D,UAAU,EAAE,QAAQ,CAAC,EAAE;4BACvB,KAAK,EAAE,GAAG;4BACV,MAAM,EAAE,CAAC;yBACV,CAAC,CAAC;wBAEH,iDAAiD;wBACjD,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;4BAClC,IAAI,KAAK,CAAC,UAAU,KAAK,eAAe;gCAAE,SAAS;4BACnD,mBAAmB,EAAE,CAAC;4BACtB,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;gCAC5B,kBAAkB,EAAE,CAAC;4BACvB,CAAC;wBACH,CAAC;oBACH,CAAC;oBAAC,MAAM,CAAC;wBACP,yCAAyC;oBAC3C,CAAC;gBACH,CAAC;gBAED,4DAA4D;gBAC5D,IAAI,UAAU,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACrC,IAAI,CAAC;wBACH,MAAM,gBAAgB,GAAG,MAAM,OAAO,CACpC,cAAc,EACd,EAAE,UAAU,EAAE,IAAI,CAAC,WAAW,EAAE,CACjC,CAAC;wBACF,YAAY,GAAG,gBAAgB,CAAC,QAAQ,CAAC,IAAI,CAAC;oBAChD,CAAC;oBAAC,MAAM,CAAC;wBACP,4BAA4B;oBAC9B,CAAC;gBACH,CAAC;gBAED,MAAM,aAAa,GAAG,mBAAmB,GAAG,CAAC;oBAC3C,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,kBAAkB,GAAG,mBAAmB,CAAC,GAAG,GAAG,CAAC;oBAC9D,CAAC,CAAC,CAAC,CAAC;gBAEN,UAAU,CAAC,IAAI,CAAC;oBACd,UAAU,EAAE,IAAI,CAAC,WAAW;oBAC5B,YAAY;oBACZ,WAAW,EAAE,mBAAmB;oBAChC,UAAU,EAAE,kBAAkB;oBAC9B,aAAa;iBACd,CAAC,CAAC;gBAEH,cAAc,IAAI,mBAAmB,CAAC;gBACtC,aAAa,IAAI,kBAAkB,CAAC;YACtC,CAAC;YAAC,MAAM,CAAC;gBACP,gCAAgC;YAClC,CAAC;QACH,CAAC;QAED,MAAM,oBAAoB,GAAG,cAAc,GAAG,CAAC;YAC7C,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,aAAa,GAAG,cAAc,CAAC,GAAG,GAAG,CAAC;YACpD,CAAC,CAAC,CAAC,CAAC;QAEN,6BAA6B;QAC7B,IAAI,UAAkD,CAAC;QACvD,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC5B,UAAU,GAAG,eAAe,CAAC;QAC/B,CAAC;aAAM,IAAI,oBAAoB,IAAI,EAAE,EAAE,CAAC;YACtC,UAAU,GAAG,UAAU,CAAC;QAC1B,CAAC;aAAM,IAAI,oBAAoB,IAAI,EAAE,EAAE,CAAC;YACtC,UAAU,GAAG,SAAS,CAAC;QACzB,CAAC;aAAM,CAAC;YACN,UAAU,GAAG,QAAQ,CAAC;QACxB,CAAC;QAED,OAAO,CAAC,IAAI,CAAC;YACX,MAAM,EAAE,IAAI,CAAC,EAAE;YACf,SAAS,EAAE,IAAI,CAAC,KAAK;YACrB,SAAS,EAAE,SAAS;YACpB,UAAU;YACV,oBAAoB;YACpB,UAAU;SACX,CAAC,CAAC;IACL,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Risk dependency scanner -- core poll logic for the PM engine.
3
+ *
4
+ * Queries risk_dependencies for items needing follow-up or escalation,
5
+ * then produces prioritized RiskFollowupAction items that the PM engine
6
+ * can act on (log, notify, or surface to the UI).
7
+ */
8
+ export interface RiskFollowupAction {
9
+ riskId: string;
10
+ riskTitle: string;
11
+ dependencyId: string;
12
+ dependencyTitle: string;
13
+ ownerName: string | null;
14
+ ownerContact: string | null;
15
+ status: string;
16
+ nextFollowupAt: string | null;
17
+ lastContactAt: string | null;
18
+ action: 'send_followup' | 'escalate' | 'update_status';
19
+ urgency: 'low' | 'medium' | 'high';
20
+ }
21
+ /**
22
+ * Scan all risk dependencies for a product and return prioritized follow-up actions.
23
+ *
24
+ * Queries all non-resolved dependencies, then evaluates each against the
25
+ * urgency and action rules to produce a sorted list of recommended actions.
26
+ */
27
+ export declare function scanRiskDependencies(productId: string): Promise<RiskFollowupAction[]>;
28
+ //# sourceMappingURL=risk-scanner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"risk-scanner.d.ts","sourceRoot":"","sources":["../../src/pm/risk-scanner.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,MAAM,EAAE,eAAe,GAAG,UAAU,GAAG,eAAe,CAAC;IACvD,OAAO,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;CACpC;AAgCD;;;;;GAKG;AACH,wBAAsB,oBAAoB,CACxC,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAgG/B"}
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Risk dependency scanner -- core poll logic for the PM engine.
3
+ *
4
+ * Queries risk_dependencies for items needing follow-up or escalation,
5
+ * then produces prioritized RiskFollowupAction items that the PM engine
6
+ * can act on (log, notify, or surface to the UI).
7
+ */
8
+ import { callApi } from '../queries/shared.js';
9
+ // ---------------------------------------------------------------------------
10
+ // Public API
11
+ // ---------------------------------------------------------------------------
12
+ /**
13
+ * Scan all risk dependencies for a product and return prioritized follow-up actions.
14
+ *
15
+ * Queries all non-resolved dependencies, then evaluates each against the
16
+ * urgency and action rules to produce a sorted list of recommended actions.
17
+ */
18
+ export async function scanRiskDependencies(productId) {
19
+ // 1. Get all risks for the product
20
+ const risksResponse = await callApi('risk_list', {
21
+ productId,
22
+ limit: 500,
23
+ offset: 0,
24
+ });
25
+ const risks = risksResponse.risks;
26
+ if (risks.length === 0)
27
+ return [];
28
+ // Build risk lookup
29
+ const riskMap = new Map();
30
+ for (const risk of risks) {
31
+ riskMap.set(risk.id, { id: risk.id, title: risk.title });
32
+ }
33
+ // 2. Get all dependencies for each risk (batch by risk)
34
+ const actions = [];
35
+ const now = Date.now();
36
+ const oneDayFromNow = now + 24 * 60 * 60 * 1000;
37
+ for (const risk of risks) {
38
+ let deps;
39
+ try {
40
+ deps = await callApi('risk_dependency_list', {
41
+ riskId: risk.id,
42
+ limit: 500,
43
+ offset: 0,
44
+ });
45
+ }
46
+ catch {
47
+ // Non-fatal: skip this risk if dependency query fails
48
+ console.log(`[PM] Failed to fetch dependencies for risk ${risk.id}, skipping`);
49
+ continue;
50
+ }
51
+ for (const dep of deps.dependencies) {
52
+ // Skip resolved/wont_fix dependencies
53
+ if (dep.status === 'resolved' || dep.status === 'wont_fix') {
54
+ continue;
55
+ }
56
+ const followupTime = dep.next_followup_at ? new Date(dep.next_followup_at).getTime() : null;
57
+ const isPastDue = followupTime !== null && followupTime <= now;
58
+ const isWithin24h = followupTime !== null && followupTime <= oneDayFromNow && followupTime > now;
59
+ const neverContacted = dep.last_contact_at === null;
60
+ // Determine action
61
+ let action;
62
+ if (dep.status === 'in_progress' && isPastDue) {
63
+ action = 'escalate';
64
+ }
65
+ else if (dep.status === 'waiting' && (isPastDue || neverContacted)) {
66
+ action = 'send_followup';
67
+ }
68
+ else if (dep.status === 'waiting' && isWithin24h) {
69
+ action = 'send_followup';
70
+ }
71
+ else {
72
+ // No action needed for this dependency right now
73
+ continue;
74
+ }
75
+ // Determine urgency
76
+ let urgency;
77
+ if (isPastDue) {
78
+ urgency = 'high';
79
+ }
80
+ else if (isWithin24h) {
81
+ urgency = 'medium';
82
+ }
83
+ else {
84
+ urgency = 'low';
85
+ }
86
+ actions.push({
87
+ riskId: risk.id,
88
+ riskTitle: risk.title,
89
+ dependencyId: dep.id,
90
+ dependencyTitle: dep.title,
91
+ ownerName: dep.owner_name,
92
+ ownerContact: dep.owner_contact,
93
+ status: dep.status,
94
+ nextFollowupAt: dep.next_followup_at,
95
+ lastContactAt: dep.last_contact_at,
96
+ action,
97
+ urgency,
98
+ });
99
+ }
100
+ }
101
+ // Sort by urgency (high first), then by action priority (escalate > send_followup > update_status)
102
+ const urgencyOrder = { high: 0, medium: 1, low: 2 };
103
+ const actionOrder = { escalate: 0, send_followup: 1, update_status: 2 };
104
+ actions.sort((a, b) => {
105
+ const urgDiff = (urgencyOrder[a.urgency] ?? 3) - (urgencyOrder[b.urgency] ?? 3);
106
+ if (urgDiff !== 0)
107
+ return urgDiff;
108
+ return (actionOrder[a.action] ?? 3) - (actionOrder[b.action] ?? 3);
109
+ });
110
+ return actions;
111
+ }
112
+ //# sourceMappingURL=risk-scanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"risk-scanner.js","sourceRoot":"","sources":["../../src/pm/risk-scanner.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AA8C/C,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,SAAiB;IAEjB,mCAAmC;IACnC,MAAM,aAAa,GAAG,MAAM,OAAO,CAAmB,WAAW,EAAE;QACjE,SAAS;QACT,KAAK,EAAE,GAAG;QACV,MAAM,EAAE,CAAC;KACV,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,CAAC;IAClC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAElC,oBAAoB;IACpB,MAAM,OAAO,GAAG,IAAI,GAAG,EAAyC,CAAC;IACjE,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,wDAAwD;IACxD,MAAM,OAAO,GAAyB,EAAE,CAAC;IACzC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,MAAM,aAAa,GAAG,GAAG,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAEhD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAA4B,CAAC;QACjC,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,OAAO,CAAyB,sBAAsB,EAAE;gBACnE,MAAM,EAAE,IAAI,CAAC,EAAE;gBACf,KAAK,EAAE,GAAG;gBACV,MAAM,EAAE,CAAC;aACV,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,sDAAsD;YACtD,OAAO,CAAC,GAAG,CAAC,8CAA8C,IAAI,CAAC,EAAE,YAAY,CAAC,CAAC;YAC/E,SAAS;QACX,CAAC;QAED,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACpC,sCAAsC;YACtC,IAAI,GAAG,CAAC,MAAM,KAAK,UAAU,IAAI,GAAG,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;gBAC3D,SAAS;YACX,CAAC;YAED,MAAM,YAAY,GAAG,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;YAC5F,MAAM,SAAS,GAAG,YAAY,KAAK,IAAI,IAAI,YAAY,IAAI,GAAG,CAAC;YAC/D,MAAM,WAAW,GAAG,YAAY,KAAK,IAAI,IAAI,YAAY,IAAI,aAAa,IAAI,YAAY,GAAG,GAAG,CAAC;YACjG,MAAM,cAAc,GAAG,GAAG,CAAC,eAAe,KAAK,IAAI,CAAC;YAEpD,mBAAmB;YACnB,IAAI,MAAoC,CAAC;YACzC,IAAI,GAAG,CAAC,MAAM,KAAK,aAAa,IAAI,SAAS,EAAE,CAAC;gBAC9C,MAAM,GAAG,UAAU,CAAC;YACtB,CAAC;iBAAM,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,SAAS,IAAI,cAAc,CAAC,EAAE,CAAC;gBACrE,MAAM,GAAG,eAAe,CAAC;YAC3B,CAAC;iBAAM,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,WAAW,EAAE,CAAC;gBACnD,MAAM,GAAG,eAAe,CAAC;YAC3B,CAAC;iBAAM,CAAC;gBACN,iDAAiD;gBACjD,SAAS;YACX,CAAC;YAED,oBAAoB;YACpB,IAAI,OAAsC,CAAC;YAC3C,IAAI,SAAS,EAAE,CAAC;gBACd,OAAO,GAAG,MAAM,CAAC;YACnB,CAAC;iBAAM,IAAI,WAAW,EAAE,CAAC;gBACvB,OAAO,GAAG,QAAQ,CAAC;YACrB,CAAC;iBAAM,CAAC;gBACN,OAAO,GAAG,KAAK,CAAC;YAClB,CAAC;YAED,OAAO,CAAC,IAAI,CAAC;gBACX,MAAM,EAAE,IAAI,CAAC,EAAE;gBACf,SAAS,EAAE,IAAI,CAAC,KAAK;gBACrB,YAAY,EAAE,GAAG,CAAC,EAAE;gBACpB,eAAe,EAAE,GAAG,CAAC,KAAK;gBAC1B,SAAS,EAAE,GAAG,CAAC,UAAU;gBACzB,YAAY,EAAE,GAAG,CAAC,aAAa;gBAC/B,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,cAAc,EAAE,GAAG,CAAC,gBAAgB;gBACpC,aAAa,EAAE,GAAG,CAAC,eAAe;gBAClC,MAAM;gBACN,OAAO;aACR,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,mGAAmG;IACnG,MAAM,YAAY,GAA2B,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;IAC5E,MAAM,WAAW,GAA2B,EAAE,QAAQ,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,CAAC;IAChG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACpB,MAAM,OAAO,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QAChF,IAAI,OAAO,KAAK,CAAC;YAAE,OAAO,OAAO,CAAC;QAClC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * PMEngine -- ExecutionEngine adapter for the PM (Project Manager) monitoring engine.
3
+ *
4
+ * The PM engine is a monitoring-only engine that does NOT spawn Claude Code
5
+ * processes. It polls the database for risk states and dependencies, evaluates
6
+ * transitions, and produces action recommendations via structured logging.
7
+ *
8
+ * Lifecycle (called by the process shell):
9
+ * 1. init(config) -- validate config, initialize API client
10
+ * 2. recoverFromCrash() -- no-op (no worktrees or processes to recover)
11
+ * 3. start() -- begin adaptive poll loop
12
+ * 4. stop() -- clear intervals, set shutting-down flag
13
+ * 5. shutdown() -- no-op (no processes to kill)
14
+ */
15
+ import type { ExecutionEngine, EngineHealth, ResourceUsage, BaseConfig, ResourceGovernor } from '@telora/daemon-core';
16
+ export declare class PMEngine implements ExecutionEngine {
17
+ readonly name = "pm";
18
+ /** Daemon config, set during init(). */
19
+ private config;
20
+ /** Optional resource governor (stored but not actively used). */
21
+ private governor;
22
+ /** Poll cadence configuration. */
23
+ private pollCadence;
24
+ /** Active poll timeout handle (for adaptive interval). */
25
+ private pollTimeout;
26
+ /** Whether the engine is shutting down. */
27
+ private shuttingDown;
28
+ /** Count of active (non-resolved, non-draft) risks from last scan. */
29
+ private activeRiskCount;
30
+ /** Last poll timestamp for health reporting. */
31
+ private lastPollAt;
32
+ /** Last set of risk stages seen (for adaptive polling). */
33
+ private lastRiskStages;
34
+ /** Total follow-up actions from last scan. */
35
+ private lastFollowupActionCount;
36
+ /** Mitigation assessment summary from last scan. */
37
+ private lastMitigationSummary;
38
+ setGovernor(gov: ResourceGovernor): void;
39
+ init(config: BaseConfig & Record<string, unknown>): Promise<void>;
40
+ recoverFromCrash(): Promise<void>;
41
+ start(): Promise<void>;
42
+ stop(): void;
43
+ shutdown(): Promise<void>;
44
+ healthCheck(): EngineHealth;
45
+ getResourceUsage(): ResourceUsage;
46
+ /**
47
+ * Run a single poll cycle: scan dependencies, correlate mitigation, log results.
48
+ */
49
+ private runPollCycle;
50
+ /**
51
+ * Poll a single product for risk states and follow-up actions.
52
+ */
53
+ private pollProduct;
54
+ /**
55
+ * Create communication drafts for high-urgency follow-up actions.
56
+ *
57
+ * Only drafts for 'high' urgency actions with a 'send_followup' recommendation.
58
+ * Drafts are stored via the API with status='draft' for human approval.
59
+ * Returns the number of drafts successfully created.
60
+ */
61
+ private createFollowupDrafts;
62
+ /**
63
+ * Schedule the next poll cycle using the adaptive interval based on current risk stages.
64
+ */
65
+ private scheduleNextPoll;
66
+ }
67
+ //# sourceMappingURL=pm-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pm-engine.d.ts","sourceRoot":"","sources":["../src/pm-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EACV,eAAe,EACf,YAAY,EACZ,aAAa,EACb,UAAU,EACV,gBAAgB,EACjB,MAAM,qBAAqB,CAAC;AAgB7B,qBAAa,QAAS,YAAW,eAAe;IAC9C,QAAQ,CAAC,IAAI,QAAQ;IAErB,wCAAwC;IACxC,OAAO,CAAC,MAAM,CAA6B;IAE3C,iEAAiE;IACjE,OAAO,CAAC,QAAQ,CAAiC;IAEjD,kCAAkC;IAClC,OAAO,CAAC,WAAW,CAA2C;IAE9D,0DAA0D;IAC1D,OAAO,CAAC,WAAW,CAA8C;IAEjE,2CAA2C;IAC3C,OAAO,CAAC,YAAY,CAAS;IAE7B,sEAAsE;IACtE,OAAO,CAAC,eAAe,CAAK;IAE5B,gDAAgD;IAChD,OAAO,CAAC,UAAU,CAAqB;IAEvC,2DAA2D;IAC3D,OAAO,CAAC,cAAc,CAAgB;IAEtC,8CAA8C;IAC9C,OAAO,CAAC,uBAAuB,CAAK;IAEpC,oDAAoD;IACpD,OAAO,CAAC,qBAAqB,CAA8B;IAM3D,WAAW,CAAC,GAAG,EAAE,gBAAgB,GAAG,IAAI;IASlC,IAAI,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAiCjE,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IAUjC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAgB5B,IAAI,IAAI,IAAI;IAYN,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAS/B,WAAW,IAAI,YAAY;IAuB3B,gBAAgB,IAAI,aAAa;IAWjC;;OAEG;YACW,YAAY;IAiB1B;;OAEG;YACW,WAAW;IAuDzB;;;;;;OAMG;YACW,oBAAoB;IA8DlC;;OAEG;IACH,OAAO,CAAC,gBAAgB;CAoBzB"}