@telora/daemon 0.13.12 → 0.13.15

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 (59) 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/queries/strategies.d.ts +2 -0
  39. package/dist/queries/strategies.d.ts.map +1 -1
  40. package/dist/queries/strategies.js +7 -0
  41. package/dist/queries/strategies.js.map +1 -1
  42. package/dist/state-cascade.d.ts +4 -15
  43. package/dist/state-cascade.d.ts.map +1 -1
  44. package/dist/state-cascade.js +10 -73
  45. package/dist/state-cascade.js.map +1 -1
  46. package/dist/strategy-completion.d.ts.map +1 -1
  47. package/dist/strategy-completion.js +20 -3
  48. package/dist/strategy-completion.js.map +1 -1
  49. package/dist/strategy-executor.d.ts.map +1 -1
  50. package/dist/strategy-executor.js +7 -66
  51. package/dist/strategy-executor.js.map +1 -1
  52. package/dist/strategy-prompt-builder.d.ts.map +1 -1
  53. package/dist/strategy-prompt-builder.js +4 -0
  54. package/dist/strategy-prompt-builder.js.map +1 -1
  55. package/dist/unified-shell.d.ts +1 -1
  56. package/dist/unified-shell.d.ts.map +1 -1
  57. package/dist/unified-shell.js +56 -1
  58. package/dist/unified-shell.js.map +1 -1
  59. package/package.json +1 -1
package/build-info.json CHANGED
@@ -1,4 +1,4 @@
1
1
  {
2
- "commitSha": "7c54a68c",
3
- "builtAt": "2026-03-24T12:44:00.224Z"
2
+ "commitSha": "609c4d36",
3
+ "builtAt": "2026-03-25T15:11:59.317Z"
4
4
  }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Adaptive poll cadence for the PM engine.
3
+ *
4
+ * The PM engine adjusts its poll interval based on the highest-severity
5
+ * risk stage present across all monitored risks. More urgent risk stages
6
+ * trigger more frequent polling; quiescent states allow long intervals.
7
+ */
8
+ export interface PollCadenceConfig {
9
+ /** Interval when any risk is in `active` stage. Default: 5 min. */
10
+ activeIntervalMs: number;
11
+ /** Interval when highest risk is `imminent`. Default: 15 min. */
12
+ imminentIntervalMs: number;
13
+ /** Interval when highest risk is `tracking`. Default: 60 min. */
14
+ trackingIntervalMs: number;
15
+ /** Interval when only draft/confirmed risks exist. Default: 4 hours. */
16
+ defaultIntervalMs: number;
17
+ }
18
+ export declare const DEFAULT_POLL_CADENCE: PollCadenceConfig;
19
+ /**
20
+ * Compute the appropriate poll interval given the current risk stage set.
21
+ *
22
+ * Scans all provided stage names and returns the interval corresponding
23
+ * to the highest severity stage present.
24
+ */
25
+ export declare function computePollInterval(riskStages: string[], config?: PollCadenceConfig): number;
26
+ //# sourceMappingURL=adaptive-poller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adaptive-poller.d.ts","sourceRoot":"","sources":["../../src/pm/adaptive-poller.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,MAAM,WAAW,iBAAiB;IAChC,mEAAmE;IACnE,gBAAgB,EAAE,MAAM,CAAC;IACzB,iEAAiE;IACjE,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iEAAiE;IACjE,kBAAkB,EAAE,MAAM,CAAC;IAC3B,wEAAwE;IACxE,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAMD,eAAO,MAAM,oBAAoB,EAAE,iBAKlC,CAAC;AAmBF;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,MAAM,EAAE,EACpB,MAAM,GAAE,iBAAwC,GAC/C,MAAM,CAaR"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Adaptive poll cadence for the PM engine.
3
+ *
4
+ * The PM engine adjusts its poll interval based on the highest-severity
5
+ * risk stage present across all monitored risks. More urgent risk stages
6
+ * trigger more frequent polling; quiescent states allow long intervals.
7
+ */
8
+ // ---------------------------------------------------------------------------
9
+ // Defaults
10
+ // ---------------------------------------------------------------------------
11
+ export const DEFAULT_POLL_CADENCE = {
12
+ activeIntervalMs: 5 * 60 * 1000,
13
+ imminentIntervalMs: 15 * 60 * 1000,
14
+ trackingIntervalMs: 60 * 60 * 1000,
15
+ defaultIntervalMs: 4 * 60 * 60 * 1000,
16
+ };
17
+ // ---------------------------------------------------------------------------
18
+ // Severity ordering (higher index = more urgent)
19
+ // ---------------------------------------------------------------------------
20
+ const STAGE_SEVERITY = {
21
+ draft: 0,
22
+ confirmed: 1,
23
+ tracking: 2,
24
+ imminent: 3,
25
+ active: 4,
26
+ // resolved is terminal -- not included in severity ranking
27
+ };
28
+ // ---------------------------------------------------------------------------
29
+ // Public API
30
+ // ---------------------------------------------------------------------------
31
+ /**
32
+ * Compute the appropriate poll interval given the current risk stage set.
33
+ *
34
+ * Scans all provided stage names and returns the interval corresponding
35
+ * to the highest severity stage present.
36
+ */
37
+ export function computePollInterval(riskStages, config = DEFAULT_POLL_CADENCE) {
38
+ let maxSeverity = -1;
39
+ for (const stage of riskStages) {
40
+ const severity = STAGE_SEVERITY[stage];
41
+ if (severity !== undefined && severity > maxSeverity) {
42
+ maxSeverity = severity;
43
+ }
44
+ }
45
+ if (maxSeverity >= 4)
46
+ return config.activeIntervalMs;
47
+ if (maxSeverity >= 3)
48
+ return config.imminentIntervalMs;
49
+ if (maxSeverity >= 2)
50
+ return config.trackingIntervalMs;
51
+ return config.defaultIntervalMs;
52
+ }
53
+ //# sourceMappingURL=adaptive-poller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adaptive-poller.js","sourceRoot":"","sources":["../../src/pm/adaptive-poller.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAiBH,8EAA8E;AAC9E,WAAW;AACX,8EAA8E;AAE9E,MAAM,CAAC,MAAM,oBAAoB,GAAsB;IACrD,gBAAgB,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI;IAC/B,kBAAkB,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI;IAClC,kBAAkB,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI;IAClC,iBAAiB,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI;CACtC,CAAC;AAEF,8EAA8E;AAC9E,iDAAiD;AACjD,8EAA8E;AAE9E,MAAM,cAAc,GAA2B;IAC7C,KAAK,EAAE,CAAC;IACR,SAAS,EAAE,CAAC;IACZ,QAAQ,EAAE,CAAC;IACX,QAAQ,EAAE,CAAC;IACX,MAAM,EAAE,CAAC;IACT,2DAA2D;CAC5D,CAAC;AAEF,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CACjC,UAAoB,EACpB,SAA4B,oBAAoB;IAEhD,IAAI,WAAW,GAAG,CAAC,CAAC,CAAC;IACrB,KAAK,MAAM,KAAK,IAAI,UAAU,EAAE,CAAC;QAC/B,MAAM,QAAQ,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;QACvC,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,GAAG,WAAW,EAAE,CAAC;YACrD,WAAW,GAAG,QAAQ,CAAC;QACzB,CAAC;IACH,CAAC;IAED,IAAI,WAAW,IAAI,CAAC;QAAE,OAAO,MAAM,CAAC,gBAAgB,CAAC;IACrD,IAAI,WAAW,IAAI,CAAC;QAAE,OAAO,MAAM,CAAC,kBAAkB,CAAC;IACvD,IAAI,WAAW,IAAI,CAAC;QAAE,OAAO,MAAM,CAAC,kBAAkB,CAAC;IACvD,OAAO,MAAM,CAAC,iBAAiB,CAAC;AAClC,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Cascade impact evaluator -- analyzes downstream effects of risk stage transitions.
3
+ *
4
+ * When a risk transitions to a more severe stage, downstream risks linked via
5
+ * risk_risk_links may need to be flagged for review or stage advancement.
6
+ * This module walks the dependency graph (BFS) to identify the full cascade.
7
+ */
8
+ export interface CascadeImpactReport {
9
+ triggerRiskId: string;
10
+ triggerRiskTitle: string;
11
+ fromStage: string;
12
+ toStage: string;
13
+ affectedRisks: Array<{
14
+ riskId: string;
15
+ riskTitle: string;
16
+ currentStage: string;
17
+ recommendedStage: string | null;
18
+ reason: string;
19
+ }>;
20
+ }
21
+ /**
22
+ * Evaluate the cascade impact of a risk transitioning between stages.
23
+ *
24
+ * Walks the risk_risk_links graph (BFS) to find all downstream dependents,
25
+ * then evaluates each for recommended stage transitions based on the trigger's
26
+ * new stage.
27
+ */
28
+ export declare function evaluateCascadeImpact(riskId: string, fromStage: string, toStage: string): Promise<CascadeImpactReport>;
29
+ //# sourceMappingURL=cascade-evaluator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cascade-evaluator.d.ts","sourceRoot":"","sources":["../../src/pm/cascade-evaluator.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH,MAAM,WAAW,mBAAmB;IAClC,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,KAAK,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,EAAE,MAAM,CAAC;QACrB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;QAChC,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC,CAAC;CACJ;AAgDD;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,mBAAmB,CAAC,CAyG9B"}
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Cascade impact evaluator -- analyzes downstream effects of risk stage transitions.
3
+ *
4
+ * When a risk transitions to a more severe stage, downstream risks linked via
5
+ * risk_risk_links may need to be flagged for review or stage advancement.
6
+ * This module walks the dependency graph (BFS) to identify the full cascade.
7
+ */
8
+ import { callApi } from '../queries/shared.js';
9
+ // ---------------------------------------------------------------------------
10
+ // Stage severity for cascade logic
11
+ // ---------------------------------------------------------------------------
12
+ const STAGE_SEVERITY = {
13
+ draft: 0,
14
+ confirmed: 1,
15
+ tracking: 2,
16
+ imminent: 3,
17
+ active: 4,
18
+ resolved: 5,
19
+ };
20
+ // ---------------------------------------------------------------------------
21
+ // Public API
22
+ // ---------------------------------------------------------------------------
23
+ /**
24
+ * Evaluate the cascade impact of a risk transitioning between stages.
25
+ *
26
+ * Walks the risk_risk_links graph (BFS) to find all downstream dependents,
27
+ * then evaluates each for recommended stage transitions based on the trigger's
28
+ * new stage.
29
+ */
30
+ export async function evaluateCascadeImpact(riskId, fromStage, toStage) {
31
+ // Get trigger risk details
32
+ let triggerRisk;
33
+ try {
34
+ triggerRisk = await callApi('risk_get', { riskId });
35
+ }
36
+ catch (_err) {
37
+ // Return empty report if risk can't be fetched
38
+ return {
39
+ triggerRiskId: riskId,
40
+ triggerRiskTitle: '[unknown]',
41
+ fromStage,
42
+ toStage,
43
+ affectedRisks: [],
44
+ };
45
+ }
46
+ // BFS to find all downstream dependents (risks that depend on this one)
47
+ const visited = new Set([riskId]);
48
+ const queue = [riskId];
49
+ const downstreamRiskIds = [];
50
+ while (queue.length > 0) {
51
+ const currentId = queue.shift();
52
+ // Find risks that depend on currentId
53
+ let dependents;
54
+ try {
55
+ dependents = await callApi('risk_link_list', {
56
+ dependsOnRiskId: currentId,
57
+ });
58
+ }
59
+ catch {
60
+ continue; // Non-fatal
61
+ }
62
+ for (const link of dependents.links) {
63
+ if (!visited.has(link.risk_id)) {
64
+ visited.add(link.risk_id);
65
+ queue.push(link.risk_id);
66
+ downstreamRiskIds.push(link.risk_id);
67
+ }
68
+ }
69
+ }
70
+ // Evaluate each downstream risk
71
+ const affectedRisks = [];
72
+ for (const downstreamId of downstreamRiskIds) {
73
+ let downstream;
74
+ try {
75
+ downstream = await callApi('risk_get', { riskId: downstreamId });
76
+ }
77
+ catch {
78
+ continue; // Non-fatal
79
+ }
80
+ const currentStage = downstream.risk.workflow_stage?.name ?? 'unknown';
81
+ const currentSeverity = STAGE_SEVERITY[currentStage] ?? -1;
82
+ let recommendedStage = null;
83
+ let reason;
84
+ if (toStage === 'active') {
85
+ // Trigger became active -- downstream tracking risks should consider imminent
86
+ if (currentStage === 'tracking') {
87
+ recommendedStage = 'imminent';
88
+ reason = `Upstream risk "${triggerRisk.risk.title}" became active; this tracking risk may be imminent`;
89
+ }
90
+ else if (currentSeverity < STAGE_SEVERITY.tracking) {
91
+ recommendedStage = 'tracking';
92
+ reason = `Upstream risk "${triggerRisk.risk.title}" became active; this risk should be tracked`;
93
+ }
94
+ else {
95
+ reason = `Upstream risk "${triggerRisk.risk.title}" became active (downstream already at ${currentStage})`;
96
+ }
97
+ }
98
+ else if (toStage === 'imminent') {
99
+ // Trigger became imminent -- downstream tracking risks should be flagged
100
+ if (currentStage === 'tracking') {
101
+ recommendedStage = null; // flag for review, no automatic promotion
102
+ reason = `Upstream risk "${triggerRisk.risk.title}" is imminent; review this tracking risk`;
103
+ }
104
+ else if (currentSeverity < STAGE_SEVERITY.tracking) {
105
+ recommendedStage = 'tracking';
106
+ reason = `Upstream risk "${triggerRisk.risk.title}" is imminent; this risk should be tracked`;
107
+ }
108
+ else {
109
+ reason = `Upstream risk "${triggerRisk.risk.title}" became imminent (downstream already at ${currentStage})`;
110
+ }
111
+ }
112
+ else if (toStage === 'resolved') {
113
+ // Trigger resolved -- informational only, no automatic demotion
114
+ reason = `Upstream risk "${triggerRisk.risk.title}" resolved; review if this risk is still relevant`;
115
+ }
116
+ else {
117
+ reason = `Upstream risk "${triggerRisk.risk.title}" transitioned from ${fromStage} to ${toStage}`;
118
+ }
119
+ affectedRisks.push({
120
+ riskId: downstreamId,
121
+ riskTitle: downstream.risk.title,
122
+ currentStage,
123
+ recommendedStage,
124
+ reason,
125
+ });
126
+ }
127
+ return {
128
+ triggerRiskId: riskId,
129
+ triggerRiskTitle: triggerRisk.risk.title,
130
+ fromStage,
131
+ toStage,
132
+ affectedRisks,
133
+ };
134
+ }
135
+ //# sourceMappingURL=cascade-evaluator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cascade-evaluator.js","sourceRoot":"","sources":["../../src/pm/cascade-evaluator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Email channel adapter for the PM engine.
3
+ *
4
+ * Currently a stub implementation that logs outbound emails and returns
5
+ * fake message IDs. The actual provider integration (SendGrid, SES, SMTP)
6
+ * will be configured later. This stub allows the PM engine to test the
7
+ * full draft-approve-send flow without external dependencies.
8
+ */
9
+ export interface EmailConfig {
10
+ provider: 'sendgrid' | 'ses' | 'smtp';
11
+ apiKey?: string;
12
+ fromAddress: string;
13
+ replyToPrefix?: string;
14
+ }
15
+ export interface EmailSendResult {
16
+ success: boolean;
17
+ messageId?: string;
18
+ error?: string;
19
+ }
20
+ export interface InboundEmailPayload {
21
+ from: string | null;
22
+ to: string | null;
23
+ subject: string | null;
24
+ body: string | null;
25
+ trackingRef: string | null;
26
+ }
27
+ /**
28
+ * Send an email via the configured provider.
29
+ *
30
+ * STUB: Logs the email details and returns a fake messageId.
31
+ * Replace with real provider call when integration is ready.
32
+ */
33
+ export declare function sendEmail(config: EmailConfig, to: string, subject: string, body: string, trackingRef?: string): Promise<EmailSendResult>;
34
+ /**
35
+ * Parse an inbound email webhook payload into a structured object.
36
+ *
37
+ * STUB: Extracts basic fields from the payload. Real implementation
38
+ * will handle provider-specific webhook formats (SendGrid Inbound Parse,
39
+ * SES notifications, etc.).
40
+ */
41
+ export declare function parseInboundEmail(payload: Record<string, unknown>): InboundEmailPayload;
42
+ //# sourceMappingURL=channel-email.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel-email.d.ts","sourceRoot":"","sources":["../../src/pm/channel-email.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,UAAU,GAAG,KAAK,GAAG,MAAM,CAAC;IACtC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAClB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAMD;;;;;GAKG;AACH,wBAAsB,SAAS,CAC7B,MAAM,EAAE,WAAW,EACnB,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,eAAe,CAAC,CAU1B;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,mBAAmB,CAcrB"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Email channel adapter for the PM engine.
3
+ *
4
+ * Currently a stub implementation that logs outbound emails and returns
5
+ * fake message IDs. The actual provider integration (SendGrid, SES, SMTP)
6
+ * will be configured later. This stub allows the PM engine to test the
7
+ * full draft-approve-send flow without external dependencies.
8
+ */
9
+ // ---------------------------------------------------------------------------
10
+ // Public API
11
+ // ---------------------------------------------------------------------------
12
+ /**
13
+ * Send an email via the configured provider.
14
+ *
15
+ * STUB: Logs the email details and returns a fake messageId.
16
+ * Replace with real provider call when integration is ready.
17
+ */
18
+ export async function sendEmail(config, to, subject, body, trackingRef) {
19
+ console.log(`[PM:Email] Would send to=${to} subject="${subject}" ref=${trackingRef ?? 'none'} ` +
20
+ `from=${config.fromAddress} provider=${config.provider}`);
21
+ return {
22
+ success: true,
23
+ messageId: `stub-${Date.now()}`,
24
+ };
25
+ }
26
+ /**
27
+ * Parse an inbound email webhook payload into a structured object.
28
+ *
29
+ * STUB: Extracts basic fields from the payload. Real implementation
30
+ * will handle provider-specific webhook formats (SendGrid Inbound Parse,
31
+ * SES notifications, etc.).
32
+ */
33
+ export function parseInboundEmail(payload) {
34
+ console.log('[PM:Email] parseInboundEmail stub called');
35
+ return {
36
+ from: typeof payload.from === 'string' ? payload.from : null,
37
+ to: typeof payload.to === 'string' ? payload.to : null,
38
+ subject: typeof payload.subject === 'string' ? payload.subject : null,
39
+ body: typeof payload.body === 'string'
40
+ ? payload.body
41
+ : typeof payload.text === 'string'
42
+ ? payload.text
43
+ : null,
44
+ trackingRef: typeof payload.trackingRef === 'string' ? payload.trackingRef : null,
45
+ };
46
+ }
47
+ //# sourceMappingURL=channel-email.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel-email.js","sourceRoot":"","sources":["../../src/pm/channel-email.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AA2BH,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,MAAmB,EACnB,EAAU,EACV,OAAe,EACf,IAAY,EACZ,WAAoB;IAEpB,OAAO,CAAC,GAAG,CACT,4BAA4B,EAAE,aAAa,OAAO,SAAS,WAAW,IAAI,MAAM,GAAG;QACnF,QAAQ,MAAM,CAAC,WAAW,aAAa,MAAM,CAAC,QAAQ,EAAE,CACzD,CAAC;IAEF,OAAO;QACL,OAAO,EAAE,IAAI;QACb,SAAS,EAAE,QAAQ,IAAI,CAAC,GAAG,EAAE,EAAE;KAChC,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAC/B,OAAgC;IAEhC,OAAO,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC;IAExD,OAAO;QACL,IAAI,EAAE,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI;QAC5D,EAAE,EAAE,OAAO,OAAO,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI;QACtD,OAAO,EAAE,OAAO,OAAO,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI;QACrE,IAAI,EAAE,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ;YACpC,CAAC,CAAC,OAAO,CAAC,IAAI;YACd,CAAC,CAAC,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ;gBAChC,CAAC,CAAC,OAAO,CAAC,IAAI;gBACd,CAAC,CAAC,IAAI;QACV,WAAW,EAAE,OAAO,OAAO,CAAC,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI;KAClF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Slack channel adapter for the PM engine.
3
+ *
4
+ * Currently a stub implementation that logs outbound Slack messages and
5
+ * returns fake thread timestamps. The actual Slack API integration will
6
+ * be configured later. This stub allows the PM engine to test the full
7
+ * draft-approve-send flow without external dependencies.
8
+ */
9
+ export interface SlackConfig {
10
+ botToken?: string;
11
+ defaultChannelId?: string;
12
+ }
13
+ export interface SlackSendResult {
14
+ success: boolean;
15
+ threadTs?: string;
16
+ error?: string;
17
+ }
18
+ export interface SlackEventPayload {
19
+ type: string | null;
20
+ userId: string | null;
21
+ channelId: string | null;
22
+ text: string | null;
23
+ threadTs: string | null;
24
+ }
25
+ /**
26
+ * Send a Slack message to a channel or user.
27
+ *
28
+ * STUB: Logs the message details and returns a fake thread timestamp.
29
+ * Replace with real Slack Web API call when integration is ready.
30
+ */
31
+ export declare function sendSlackMessage(config: SlackConfig, channelOrUserId: string, text: string, threadTs?: string): Promise<SlackSendResult>;
32
+ /**
33
+ * Parse a Slack event webhook payload into a structured object.
34
+ *
35
+ * STUB: Extracts basic fields from the payload. Real implementation
36
+ * will handle Slack Events API verification, challenge responses,
37
+ * and event type dispatching.
38
+ */
39
+ export declare function parseSlackEvent(payload: Record<string, unknown>): SlackEventPayload;
40
+ //# sourceMappingURL=channel-slack.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel-slack.d.ts","sourceRoot":"","sources":["../../src/pm/channel-slack.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAMD;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,WAAW,EACnB,eAAe,EAAE,MAAM,EACvB,IAAI,EAAE,MAAM,EACZ,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,eAAe,CAAC,CAU1B;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,iBAAiB,CAcnB"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Slack channel adapter for the PM engine.
3
+ *
4
+ * Currently a stub implementation that logs outbound Slack messages and
5
+ * returns fake thread timestamps. The actual Slack API integration will
6
+ * be configured later. This stub allows the PM engine to test the full
7
+ * draft-approve-send flow without external dependencies.
8
+ */
9
+ // ---------------------------------------------------------------------------
10
+ // Public API
11
+ // ---------------------------------------------------------------------------
12
+ /**
13
+ * Send a Slack message to a channel or user.
14
+ *
15
+ * STUB: Logs the message details and returns a fake thread timestamp.
16
+ * Replace with real Slack Web API call when integration is ready.
17
+ */
18
+ export async function sendSlackMessage(config, channelOrUserId, text, threadTs) {
19
+ console.log(`[PM:Slack] Would send to=${channelOrUserId} thread=${threadTs ?? 'new'} ` +
20
+ `text="${text.slice(0, 80)}${text.length > 80 ? '...' : ''}"`);
21
+ return {
22
+ success: true,
23
+ threadTs: threadTs ?? `stub-${Date.now()}.000000`,
24
+ };
25
+ }
26
+ /**
27
+ * Parse a Slack event webhook payload into a structured object.
28
+ *
29
+ * STUB: Extracts basic fields from the payload. Real implementation
30
+ * will handle Slack Events API verification, challenge responses,
31
+ * and event type dispatching.
32
+ */
33
+ export function parseSlackEvent(payload) {
34
+ console.log('[PM:Slack] parseSlackEvent stub called');
35
+ const event = typeof payload.event === 'object' && payload.event !== null
36
+ ? payload.event
37
+ : payload;
38
+ return {
39
+ type: typeof event.type === 'string' ? event.type : null,
40
+ userId: typeof event.user === 'string' ? event.user : null,
41
+ channelId: typeof event.channel === 'string' ? event.channel : null,
42
+ text: typeof event.text === 'string' ? event.text : null,
43
+ threadTs: typeof event.thread_ts === 'string' ? event.thread_ts : null,
44
+ };
45
+ }
46
+ //# sourceMappingURL=channel-slack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel-slack.js","sourceRoot":"","sources":["../../src/pm/channel-slack.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAyBH,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,MAAmB,EACnB,eAAuB,EACvB,IAAY,EACZ,QAAiB;IAEjB,OAAO,CAAC,GAAG,CACT,4BAA4B,eAAe,WAAW,QAAQ,IAAI,KAAK,GAAG;QAC1E,SAAS,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,CAC9D,CAAC;IAEF,OAAO;QACL,OAAO,EAAE,IAAI;QACb,QAAQ,EAAE,QAAQ,IAAI,QAAQ,IAAI,CAAC,GAAG,EAAE,SAAS;KAClD,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAC7B,OAAgC;IAEhC,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC;IAEtD,MAAM,KAAK,GAAG,OAAO,OAAO,CAAC,KAAK,KAAK,QAAQ,IAAI,OAAO,CAAC,KAAK,KAAK,IAAI;QACvE,CAAC,CAAC,OAAO,CAAC,KAAgC;QAC1C,CAAC,CAAC,OAAO,CAAC;IAEZ,OAAO;QACL,IAAI,EAAE,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI;QACxD,MAAM,EAAE,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI;QAC1D,SAAS,EAAE,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI;QACnE,IAAI,EAAE,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI;QACxD,QAAQ,EAAE,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI;KACvE,CAAC;AACJ,CAAC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Communication drafter -- generates draft outbound messages based on risk events.
3
+ *
4
+ * Template-based drafting that produces DraftCommunication objects for human
5
+ * approval before sending. The PM engine stores these via the API with
6
+ * status='draft'; actual sending happens only after approval.
7
+ */
8
+ export interface DraftCommunication {
9
+ riskDependencyId: string;
10
+ direction: 'outbound';
11
+ channel: 'email' | 'slack';
12
+ subject: string;
13
+ body: string;
14
+ sender: string;
15
+ recipient: string;
16
+ status: 'draft';
17
+ }
18
+ export type CommunicationTrigger = {
19
+ type: 'risk_transition';
20
+ riskTitle: string;
21
+ fromStage: string;
22
+ toStage: string;
23
+ } | {
24
+ type: 'followup_due';
25
+ dependencyTitle: string;
26
+ ownerName: string;
27
+ daysPastDue: number;
28
+ } | {
29
+ type: 'resolution_summary';
30
+ riskTitle: string;
31
+ };
32
+ export interface DependencyContext {
33
+ title: string;
34
+ ownerName: string | null;
35
+ ownerContact: string | null;
36
+ }
37
+ /**
38
+ * Generate a draft communication for a given trigger and dependency context.
39
+ *
40
+ * Returns a DraftCommunication ready to be stored via the API. The draft
41
+ * uses the dependency's ownerContact as recipient (falls back to 'unknown').
42
+ */
43
+ export declare function draftCommunication(trigger: CommunicationTrigger, dependency: DependencyContext, channel: 'email' | 'slack'): DraftCommunication;
44
+ //# sourceMappingURL=communication-drafter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"communication-drafter.d.ts","sourceRoot":"","sources":["../../src/pm/communication-drafter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,MAAM,WAAW,kBAAkB;IACjC,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,UAAU,CAAC;IACtB,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,MAAM,oBAAoB,GAC5B;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAClF;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,eAAe,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GACzF;IAAE,IAAI,EAAE,oBAAoB,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtD,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AA+DD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,oBAAoB,EAC7B,UAAU,EAAE,iBAAiB,EAC7B,OAAO,EAAE,OAAO,GAAG,OAAO,GACzB,kBAAkB,CAmCpB"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Communication drafter -- generates draft outbound messages based on risk events.
3
+ *
4
+ * Template-based drafting that produces DraftCommunication objects for human
5
+ * approval before sending. The PM engine stores these via the API with
6
+ * status='draft'; actual sending happens only after approval.
7
+ */
8
+ // ---------------------------------------------------------------------------
9
+ // Template helpers
10
+ // ---------------------------------------------------------------------------
11
+ function buildRiskTransitionBody(trigger, dependency) {
12
+ const subject = `[Risk Alert] ${trigger.riskTitle} moved to ${trigger.toStage}`;
13
+ const ownerLine = dependency.ownerName
14
+ ? `\n\nAs the owner of "${dependency.title}", please review the updated risk status and confirm whether any adjustments to your timeline or approach are needed.`
15
+ : '';
16
+ const body = `The risk "${trigger.riskTitle}" has transitioned from "${trigger.fromStage}" to "${trigger.toStage}".` +
17
+ `\n\nThis transition may affect the dependency "${dependency.title}". ` +
18
+ `Please review any downstream impacts and take appropriate action.` +
19
+ ownerLine +
20
+ `\n\nIf you have questions or need to escalate, reply to this message.`;
21
+ return { subject, body };
22
+ }
23
+ function buildFollowupBody(trigger, dependency) {
24
+ const subject = `Followup: ${trigger.dependencyTitle}`;
25
+ const daysLabel = trigger.daysPastDue === 1 ? '1 day' : `${trigger.daysPastDue} days`;
26
+ const body = `We're checking in on "${dependency.title}". ` +
27
+ `Last contact was ${daysLabel} ago.` +
28
+ `\n\nCould you provide an update on the current status? ` +
29
+ `Any changes to timeline or blockers would be helpful to know about.` +
30
+ `\n\nThank you.`;
31
+ return { subject, body };
32
+ }
33
+ function buildResolutionBody(trigger, dependency) {
34
+ const subject = `[Resolved] ${trigger.riskTitle}`;
35
+ const body = `The risk "${trigger.riskTitle}" has been resolved.` +
36
+ `\n\nThe dependency "${dependency.title}" is no longer tracked as an active concern. ` +
37
+ `No further action is required unless new information surfaces.` +
38
+ `\n\nThank you for your involvement in tracking this item.`;
39
+ return { subject, body };
40
+ }
41
+ // ---------------------------------------------------------------------------
42
+ // Public API
43
+ // ---------------------------------------------------------------------------
44
+ /**
45
+ * Generate a draft communication for a given trigger and dependency context.
46
+ *
47
+ * Returns a DraftCommunication ready to be stored via the API. The draft
48
+ * uses the dependency's ownerContact as recipient (falls back to 'unknown').
49
+ */
50
+ export function draftCommunication(trigger, dependency, channel) {
51
+ let subject;
52
+ let body;
53
+ switch (trigger.type) {
54
+ case 'risk_transition': {
55
+ const result = buildRiskTransitionBody(trigger, dependency);
56
+ subject = result.subject;
57
+ body = result.body;
58
+ break;
59
+ }
60
+ case 'followup_due': {
61
+ const result = buildFollowupBody(trigger, dependency);
62
+ subject = result.subject;
63
+ body = result.body;
64
+ break;
65
+ }
66
+ case 'resolution_summary': {
67
+ const result = buildResolutionBody(trigger, dependency);
68
+ subject = result.subject;
69
+ body = result.body;
70
+ break;
71
+ }
72
+ }
73
+ return {
74
+ riskDependencyId: '', // Caller sets this based on the dependency being processed
75
+ direction: 'outbound',
76
+ channel,
77
+ subject,
78
+ body,
79
+ sender: 'pm-engine',
80
+ recipient: dependency.ownerContact ?? 'unknown',
81
+ status: 'draft',
82
+ };
83
+ }
84
+ //# sourceMappingURL=communication-drafter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"communication-drafter.js","sourceRoot":"","sources":["../../src/pm/communication-drafter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
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
+ export interface DialogUpdate {
9
+ riskId: string | null;
10
+ dependencyId: string | null;
11
+ statusUpdate: string | null;
12
+ notes: string;
13
+ contactName: string | null;
14
+ }
15
+ export interface RiskRef {
16
+ id: string;
17
+ title: string;
18
+ }
19
+ export interface DependencyRef {
20
+ id: string;
21
+ title: string;
22
+ riskId: string;
23
+ }
24
+ /**
25
+ * Parse a human dialog message to extract structured risk/dependency updates.
26
+ *
27
+ * Matches the message against known risk and dependency titles, extracts
28
+ * status keywords, and identifies contact names. This is a best-effort
29
+ * keyword parser; unmatched fields return null.
30
+ */
31
+ export declare function parseDialogUpdate(humanMessage: string, risks: RiskRef[], dependencies: DependencyRef[]): DialogUpdate;
32
+ //# sourceMappingURL=dialog-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dialog-handler.d.ts","sourceRoot":"","sources":["../../src/pm/dialog-handler.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAgGD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,OAAO,EAAE,EAChB,YAAY,EAAE,aAAa,EAAE,GAC5B,YAAY,CAiBd"}