@telora/daemon 0.13.28 → 0.13.29

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/build-info.json CHANGED
@@ -1,4 +1,4 @@
1
1
  {
2
- "commitSha": "fa429ace",
3
- "builtAt": "2026-03-28T13:25:37.129Z"
2
+ "commitSha": "87364cba",
3
+ "builtAt": "2026-03-29T13:56:51.783Z"
4
4
  }
@@ -1,28 +1,35 @@
1
1
  /**
2
- * PMEngine -- ExecutionEngine adapter for the PM (Project Manager) monitoring engine.
2
+ * PMEngine -- ExecutionEngine adapter for the PM (Project Manager) engine.
3
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.
4
+ * The PM engine now serves dual roles:
5
+ * 1. Process supervision: Spawns a persistent Claude Code session per product
6
+ * that runs /loop for its PM cycle (report generation, inbox, action plan).
7
+ * 2. Risk monitoring: Polls risk states and dependencies (unchanged from before).
7
8
  *
8
9
  * Lifecycle (called by the process shell):
9
10
  * 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
11
+ * 2. recoverFromCrash() -- detect orphaned PM sessions, restart
12
+ * 3. start() -- spawn PM processes, begin risk poll loop
12
13
  * 4. stop() -- clear intervals, set shutting-down flag
13
- * 5. shutdown() -- no-op (no processes to kill)
14
+ * 5. shutdown() -- terminate PM processes gracefully
14
15
  */
15
16
  import type { ExecutionEngine, EngineHealth, ResourceUsage, BaseConfig, ResourceGovernor } from '@telora/daemon-core';
16
17
  export declare class PMEngine implements ExecutionEngine {
17
18
  readonly name = "pm";
18
19
  /** Daemon config, set during init(). */
19
20
  private config;
20
- /** Optional resource governor (stored but not actively used). */
21
+ /** Resource governor for slot management. */
21
22
  private governor;
22
- /** Poll cadence configuration. */
23
+ /** PM process-specific configuration. */
24
+ private pmProcessConfig;
25
+ /** Poll cadence configuration (for risk monitoring). */
23
26
  private pollCadence;
24
27
  /** Active poll timeout handle (for adaptive interval). */
25
28
  private pollTimeout;
29
+ /** Session status poll interval handle. */
30
+ private sessionPollInterval;
31
+ /** Pending restart timeouts (for backoff). */
32
+ private restartTimeouts;
26
33
  /** Whether the engine is shutting down. */
27
34
  private shuttingDown;
28
35
  /** Count of active (non-resolved, non-draft) risks from last scan. */
@@ -43,6 +50,32 @@ export declare class PMEngine implements ExecutionEngine {
43
50
  shutdown(): Promise<void>;
44
51
  healthCheck(): EngineHealth;
45
52
  getResourceUsage(): ResourceUsage;
53
+ /**
54
+ * Poll pm_sessions.status for each product and spawn/terminate PM processes
55
+ * accordingly. This allows runtime control of the PM agent via UI toggle
56
+ * or MCP tool without requiring a daemon restart.
57
+ *
58
+ * - status=active && no process running → spawn
59
+ * - status=stopped/paused && process running → terminate
60
+ * - no session → no action (user hasn't started PM yet)
61
+ */
62
+ private pollSessionStatuses;
63
+ /**
64
+ * Set up monitoring for a PM process. When it exits, attempt restart
65
+ * with exponential backoff. Also triggers a health restart when the
66
+ * process exceeds maxSessionAgeMs.
67
+ */
68
+ private setupProcessMonitor;
69
+ /**
70
+ * Handle PM process exit -- check session status before scheduling restart.
71
+ * Only restarts if the session is still active. If stopped/paused, the
72
+ * exit is intentional and no restart is scheduled.
73
+ */
74
+ private handleProcessExit;
75
+ /** Restart count tracking (simple in-memory map). */
76
+ private restartCounts;
77
+ private getRestartCount;
78
+ private incrementRestartCount;
46
79
  /**
47
80
  * Run a single poll cycle: scan dependencies, correlate mitigation, log results.
48
81
  */
@@ -53,10 +86,6 @@ export declare class PMEngine implements ExecutionEngine {
53
86
  private pollProduct;
54
87
  /**
55
88
  * 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
89
  */
61
90
  private createFollowupDrafts;
62
91
  /**
@@ -1 +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"}
1
+ {"version":3,"file":"pm-engine.d.ts","sourceRoot":"","sources":["../src/pm-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EACV,eAAe,EACf,YAAY,EACZ,aAAa,EACb,UAAU,EACV,gBAAgB,EACjB,MAAM,qBAAqB,CAAC;AA0D7B,qBAAa,QAAS,YAAW,eAAe;IAC9C,QAAQ,CAAC,IAAI,QAAQ;IAErB,wCAAwC;IACxC,OAAO,CAAC,MAAM,CAA6B;IAE3C,6CAA6C;IAC7C,OAAO,CAAC,QAAQ,CAAiC;IAEjD,yCAAyC;IACzC,OAAO,CAAC,eAAe,CAA8C;IAErE,wDAAwD;IACxD,OAAO,CAAC,WAAW,CAA2C;IAE9D,0DAA0D;IAC1D,OAAO,CAAC,WAAW,CAA8C;IAEjE,2CAA2C;IAC3C,OAAO,CAAC,mBAAmB,CAA+C;IAE1E,8CAA8C;IAC9C,OAAO,CAAC,eAAe,CAAoD;IAE3E,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;IAQlC,IAAI,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAiDjE,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IAsDjC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAkC5B,IAAI,IAAI,IAAI;IAsBN,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAc/B,WAAW,IAAI,YAAY;IA+B3B,gBAAgB,IAAI,aAAa;IAYjC;;;;;;;;OAQG;YACW,mBAAmB;IAoDjC;;;;OAIG;IACH,OAAO,CAAC,mBAAmB;IAmC3B;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IA8DzB,qDAAqD;IACrD,OAAO,CAAC,aAAa,CAA6B;IAElD,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,qBAAqB;IAS7B;;OAEG;YACW,YAAY;IAiB1B;;OAEG;YACW,WAAW;IAuDzB;;OAEG;YACW,oBAAoB;IA4DlC;;OAEG;IACH,OAAO,CAAC,gBAAgB;CAoBzB"}
package/dist/pm-engine.js CHANGED
@@ -1,22 +1,50 @@
1
1
  /**
2
- * PMEngine -- ExecutionEngine adapter for the PM (Project Manager) monitoring engine.
2
+ * PMEngine -- ExecutionEngine adapter for the PM (Project Manager) engine.
3
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.
4
+ * The PM engine now serves dual roles:
5
+ * 1. Process supervision: Spawns a persistent Claude Code session per product
6
+ * that runs /loop for its PM cycle (report generation, inbox, action plan).
7
+ * 2. Risk monitoring: Polls risk states and dependencies (unchanged from before).
7
8
  *
8
9
  * Lifecycle (called by the process shell):
9
10
  * 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
11
+ * 2. recoverFromCrash() -- detect orphaned PM sessions, restart
12
+ * 3. start() -- spawn PM processes, begin risk poll loop
12
13
  * 4. stop() -- clear intervals, set shutting-down flag
13
- * 5. shutdown() -- no-op (no processes to kill)
14
+ * 5. shutdown() -- terminate PM processes gracefully
14
15
  */
16
+ import { DEFAULT_PM_PROCESS_CONFIG } from './types/pm.js';
15
17
  import { initSupabase, callApi } from './queries/shared.js';
16
18
  import { scanRiskDependencies } from './pm/risk-scanner.js';
17
19
  import { correlateMitigationProgress } from './pm/mitigation-correlator.js';
18
20
  import { computePollInterval, DEFAULT_POLL_CADENCE, } from './pm/adaptive-poller.js';
19
21
  import { draftCommunication } from './pm/communication-drafter.js';
22
+ import { spawnPMProcess, terminateAllPMProcesses, terminatePMProcess, getActivePMProcesses, isPMProcessRunning, calculateRestartDelay, } from './pm-process.js';
23
+ // ---------------------------------------------------------------------------
24
+ // Helpers
25
+ // ---------------------------------------------------------------------------
26
+ /** Resolve an integer from env string > file config value > default. */
27
+ function resolveEnvInt(envVal, fileVal, defaultVal) {
28
+ if (envVal !== undefined && envVal !== '') {
29
+ const parsed = parseInt(envVal, 10);
30
+ if (!isNaN(parsed))
31
+ return parsed;
32
+ }
33
+ if (typeof fileVal === 'number')
34
+ return fileVal;
35
+ return defaultVal;
36
+ }
37
+ /** Resolve an env var in minutes to milliseconds, with file fallback (already ms). */
38
+ function resolveEnvMinutesToMs(envMinutes, fileMs, defaultMs) {
39
+ if (envMinutes !== undefined && envMinutes !== '') {
40
+ const parsed = parseInt(envMinutes, 10);
41
+ if (!isNaN(parsed))
42
+ return parsed * 60 * 1000;
43
+ }
44
+ if (typeof fileMs === 'number')
45
+ return fileMs;
46
+ return defaultMs;
47
+ }
20
48
  // ---------------------------------------------------------------------------
21
49
  // PMEngine
22
50
  // ---------------------------------------------------------------------------
@@ -24,12 +52,18 @@ export class PMEngine {
24
52
  name = 'pm';
25
53
  /** Daemon config, set during init(). */
26
54
  config = null;
27
- /** Optional resource governor (stored but not actively used). */
55
+ /** Resource governor for slot management. */
28
56
  governor = null;
29
- /** Poll cadence configuration. */
57
+ /** PM process-specific configuration. */
58
+ pmProcessConfig = DEFAULT_PM_PROCESS_CONFIG;
59
+ /** Poll cadence configuration (for risk monitoring). */
30
60
  pollCadence = DEFAULT_POLL_CADENCE;
31
61
  /** Active poll timeout handle (for adaptive interval). */
32
62
  pollTimeout = null;
63
+ /** Session status poll interval handle. */
64
+ sessionPollInterval = null;
65
+ /** Pending restart timeouts (for backoff). */
66
+ restartTimeouts = new Map();
33
67
  /** Whether the engine is shutting down. */
34
68
  shuttingDown = false;
35
69
  /** Count of active (non-resolved, non-draft) risks from last scan. */
@@ -47,54 +81,111 @@ export class PMEngine {
47
81
  // -----------------------------------------------------------------------
48
82
  setGovernor(gov) {
49
83
  this.governor = gov;
50
- // PM engine does not acquire governor slots (no Claude processes)
51
84
  }
52
85
  // -----------------------------------------------------------------------
53
86
  // init
54
87
  // -----------------------------------------------------------------------
55
88
  async init(config) {
56
89
  this.config = config;
57
- // Resolve poll cadence from config
58
- const pmConfig = config.pm;
59
- if (pmConfig && typeof pmConfig === 'object') {
60
- const pc = pmConfig;
61
- if (pc.pollCadence && typeof pc.pollCadence === 'object') {
62
- const cadence = pc.pollCadence;
63
- this.pollCadence = {
64
- activeIntervalMs: typeof cadence.activeIntervalMs === 'number'
65
- ? cadence.activeIntervalMs : DEFAULT_POLL_CADENCE.activeIntervalMs,
66
- imminentIntervalMs: typeof cadence.imminentIntervalMs === 'number'
67
- ? cadence.imminentIntervalMs : DEFAULT_POLL_CADENCE.imminentIntervalMs,
68
- trackingIntervalMs: typeof cadence.trackingIntervalMs === 'number'
69
- ? cadence.trackingIntervalMs : DEFAULT_POLL_CADENCE.trackingIntervalMs,
70
- defaultIntervalMs: typeof cadence.defaultIntervalMs === 'number'
71
- ? cadence.defaultIntervalMs : DEFAULT_POLL_CADENCE.defaultIntervalMs,
72
- };
73
- }
90
+ // Resolve PM process config from flat engine config + env var overrides.
91
+ // Fields come from daemon.json engines.pm section, spread flat by buildEngineConfig().
92
+ const flat = config;
93
+ const env = process.env;
94
+ this.pmProcessConfig = {
95
+ loopIntervalMinutes: resolveEnvInt(env.TELORA_PM_LOOP_INTERVAL, flat.loopIntervalMinutes, DEFAULT_PM_PROCESS_CONFIG.loopIntervalMinutes),
96
+ maxRestarts: resolveEnvInt(env.TELORA_PM_MAX_RESTARTS, flat.maxRestarts, DEFAULT_PM_PROCESS_CONFIG.maxRestarts),
97
+ processEnabled: typeof flat.processEnabled === 'boolean'
98
+ ? flat.processEnabled : DEFAULT_PM_PROCESS_CONFIG.processEnabled,
99
+ maxSessionAgeMs: resolveEnvMinutesToMs(env.TELORA_PM_MAX_SESSION_AGE, flat.maxSessionAgeMs, DEFAULT_PM_PROCESS_CONFIG.maxSessionAgeMs),
100
+ };
101
+ // Poll cadence config (for risk monitoring)
102
+ if (flat.pollCadence && typeof flat.pollCadence === 'object') {
103
+ const cadence = flat.pollCadence;
104
+ this.pollCadence = {
105
+ activeIntervalMs: typeof cadence.activeIntervalMs === 'number'
106
+ ? cadence.activeIntervalMs : DEFAULT_POLL_CADENCE.activeIntervalMs,
107
+ imminentIntervalMs: typeof cadence.imminentIntervalMs === 'number'
108
+ ? cadence.imminentIntervalMs : DEFAULT_POLL_CADENCE.imminentIntervalMs,
109
+ trackingIntervalMs: typeof cadence.trackingIntervalMs === 'number'
110
+ ? cadence.trackingIntervalMs : DEFAULT_POLL_CADENCE.trackingIntervalMs,
111
+ defaultIntervalMs: typeof cadence.defaultIntervalMs === 'number'
112
+ ? cadence.defaultIntervalMs : DEFAULT_POLL_CADENCE.defaultIntervalMs,
113
+ };
74
114
  }
75
115
  // Initialize API client (reuse shared infrastructure -- may already be
76
116
  // initialized by the strategy engine, but initSupabase is idempotent)
77
117
  initSupabase(this.config);
78
- console.log('[PM] Engine initialized');
118
+ console.log(`[PM] Engine initialized (process supervision: ${this.pmProcessConfig.processEnabled ? 'enabled' : 'disabled'}, ` +
119
+ `loop: ${this.pmProcessConfig.loopIntervalMinutes}m, ` +
120
+ `maxSessionAge: ${this.pmProcessConfig.maxSessionAgeMs > 0 ? `${Math.round(this.pmProcessConfig.maxSessionAgeMs / 60_000)}m` : 'disabled'})`);
79
121
  }
80
122
  // -----------------------------------------------------------------------
81
123
  // recoverFromCrash
82
124
  // -----------------------------------------------------------------------
83
125
  async recoverFromCrash() {
84
- // No-op: PM engine has no worktrees, processes, or persistent state
85
- // to recover. It simply polls the database on start.
86
- console.log('[PM] No crash recovery needed (monitoring-only engine)');
126
+ if (!this.pmProcessConfig.processEnabled) {
127
+ console.log('[PM] Process supervision disabled, skipping crash recovery');
128
+ return;
129
+ }
130
+ // Check for orphaned PM sessions in the database
131
+ const config = this.config;
132
+ if (!config)
133
+ return;
134
+ for (const product of config.products) {
135
+ try {
136
+ // Check if there's an active PM session but no process running
137
+ const result = await callApi('pm_session_list', {
138
+ productId: product.id,
139
+ });
140
+ const session = result?.pmSessions?.[0]; // Most recent session
141
+ if (session && session.status === 'active' && !isPMProcessRunning(product.id)) {
142
+ console.log(`[PM] Found orphaned active PM session for product ${product.id} ` +
143
+ `(last cycle: ${session.lastCycleAt ?? 'never'}), restarting`);
144
+ if (this.governor) {
145
+ try {
146
+ await spawnPMProcess(config, product.id, product.repoPath, this.governor, this.pmProcessConfig);
147
+ this.setupProcessMonitor(product.id, product.repoPath);
148
+ console.log(`[PM] Restarted PM process for product ${product.id}`);
149
+ }
150
+ catch (spawnErr) {
151
+ console.log(`[PM] Failed to restart PM process for product ${product.id}: ` +
152
+ `${spawnErr instanceof Error ? spawnErr.message : String(spawnErr)}`);
153
+ }
154
+ }
155
+ }
156
+ }
157
+ catch {
158
+ // No session found -- will be created on spawn
159
+ }
160
+ }
161
+ console.log('[PM] Crash recovery complete');
87
162
  }
88
163
  // -----------------------------------------------------------------------
89
164
  // start
90
165
  // -----------------------------------------------------------------------
91
166
  async start() {
92
167
  this.shuttingDown = false;
93
- // Run initial poll immediately
168
+ // Check session statuses and spawn PM processes for active sessions
169
+ if (this.pmProcessConfig.processEnabled && this.config && this.governor) {
170
+ await this.pollSessionStatuses();
171
+ // Poll session statuses periodically (30s) to react to UI toggle changes
172
+ this.sessionPollInterval = setInterval(async () => {
173
+ if (this.shuttingDown)
174
+ return;
175
+ try {
176
+ await this.pollSessionStatuses();
177
+ }
178
+ catch (err) {
179
+ console.log(`[PM] Session status poll error: ${err instanceof Error ? err.message : String(err)}`);
180
+ }
181
+ }, 30_000);
182
+ }
183
+ // Run initial risk poll immediately
94
184
  await this.runPollCycle();
95
- // Schedule next poll with adaptive interval
185
+ // Schedule next risk poll with adaptive interval
96
186
  this.scheduleNextPoll();
97
- console.log('[PM] Engine started (adaptive polling active)');
187
+ const processCount = getActivePMProcesses().size;
188
+ console.log(`[PM] Engine started (${processCount} PM process(es), risk polling active)`);
98
189
  }
99
190
  // -----------------------------------------------------------------------
100
191
  // stop
@@ -105,12 +196,24 @@ export class PMEngine {
105
196
  clearTimeout(this.pollTimeout);
106
197
  this.pollTimeout = null;
107
198
  }
199
+ if (this.sessionPollInterval !== null) {
200
+ clearInterval(this.sessionPollInterval);
201
+ this.sessionPollInterval = null;
202
+ }
203
+ // Clear all restart timeouts
204
+ for (const timeout of this.restartTimeouts.values()) {
205
+ clearTimeout(timeout);
206
+ }
207
+ this.restartTimeouts.clear();
108
208
  }
109
209
  // -----------------------------------------------------------------------
110
210
  // shutdown
111
211
  // -----------------------------------------------------------------------
112
212
  async shutdown() {
113
- // No-op: PM engine has no processes to kill or state to drain
213
+ // Terminate all PM processes gracefully
214
+ terminateAllPMProcesses();
215
+ // Wait briefly for processes to exit
216
+ await new Promise(resolve => setTimeout(resolve, 2000));
114
217
  console.log('[PM] Shutdown complete');
115
218
  }
116
219
  // -----------------------------------------------------------------------
@@ -121,6 +224,11 @@ export class PMEngine {
121
224
  if (this.config === null) {
122
225
  status = 'unhealthy';
123
226
  }
227
+ const processes = getActivePMProcesses();
228
+ const processStatuses = {};
229
+ for (const [productId, state] of processes) {
230
+ processStatuses[productId] = state.phase;
231
+ }
124
232
  return {
125
233
  status,
126
234
  activeWorkItems: this.activeRiskCount,
@@ -130,6 +238,8 @@ export class PMEngine {
130
238
  lastFollowupActions: this.lastFollowupActionCount,
131
239
  mitigationSummary: this.lastMitigationSummary,
132
240
  currentPollIntervalMs: computePollInterval(this.lastRiskStages, this.pollCadence),
241
+ pmProcesses: processStatuses,
242
+ processSupervisionEnabled: this.pmProcessConfig.processEnabled,
133
243
  },
134
244
  };
135
245
  }
@@ -137,13 +247,172 @@ export class PMEngine {
137
247
  // getResourceUsage
138
248
  // -----------------------------------------------------------------------
139
249
  getResourceUsage() {
250
+ const processCount = getActivePMProcesses().size;
140
251
  return {
141
- activeClaudeProcesses: 0,
252
+ activeClaudeProcesses: processCount,
142
253
  activeWorktrees: 0,
143
254
  };
144
255
  }
145
256
  // -----------------------------------------------------------------------
146
- // Private: poll cycle
257
+ // Private: session status polling
258
+ // -----------------------------------------------------------------------
259
+ /**
260
+ * Poll pm_sessions.status for each product and spawn/terminate PM processes
261
+ * accordingly. This allows runtime control of the PM agent via UI toggle
262
+ * or MCP tool without requiring a daemon restart.
263
+ *
264
+ * - status=active && no process running → spawn
265
+ * - status=stopped/paused && process running → terminate
266
+ * - no session → no action (user hasn't started PM yet)
267
+ */
268
+ async pollSessionStatuses() {
269
+ const config = this.config;
270
+ const governor = this.governor;
271
+ if (!config || !governor)
272
+ return;
273
+ for (const product of config.products) {
274
+ try {
275
+ const result = await callApi('pm_session_list', {
276
+ productId: product.id,
277
+ });
278
+ const session = result?.pmSessions?.[0]; // Most recent session
279
+ const isRunning = isPMProcessRunning(product.id);
280
+ if (session?.status === 'active' && !isRunning && !this.restartTimeouts.has(product.id)) {
281
+ // Session is active but no process — spawn one
282
+ console.log(`[PM] Session active for product ${product.id}, spawning PM process`);
283
+ this.restartCounts.delete(product.id); // Fresh start, not a crash restart
284
+ try {
285
+ await spawnPMProcess(config, product.id, product.repoPath, governor, this.pmProcessConfig);
286
+ this.setupProcessMonitor(product.id, product.repoPath);
287
+ }
288
+ catch (err) {
289
+ console.log(`[PM] Failed to spawn PM process for product ${product.id}: ` +
290
+ `${err instanceof Error ? err.message : String(err)}`);
291
+ }
292
+ }
293
+ else if (session && session.status !== 'active' && isRunning) {
294
+ // Session is stopped/paused but process is running — terminate
295
+ console.log(`[PM] Session ${session.status} for product ${product.id}, terminating PM process`);
296
+ terminatePMProcess(product.id);
297
+ // Cancel any pending restart for this product
298
+ const pendingRestart = this.restartTimeouts.get(product.id);
299
+ if (pendingRestart) {
300
+ clearTimeout(pendingRestart);
301
+ this.restartTimeouts.delete(product.id);
302
+ }
303
+ }
304
+ }
305
+ catch (err) {
306
+ // Session query failed — skip this product this cycle
307
+ console.log(`[PM] Failed to check session status for product ${product.id}: ` +
308
+ `${err instanceof Error ? err.message : String(err)}`);
309
+ }
310
+ }
311
+ }
312
+ // -----------------------------------------------------------------------
313
+ // Private: process monitoring
314
+ // -----------------------------------------------------------------------
315
+ /**
316
+ * Set up monitoring for a PM process. When it exits, attempt restart
317
+ * with exponential backoff. Also triggers a health restart when the
318
+ * process exceeds maxSessionAgeMs.
319
+ */
320
+ setupProcessMonitor(productId, repoPath) {
321
+ const checkInterval = setInterval(() => {
322
+ if (this.shuttingDown) {
323
+ clearInterval(checkInterval);
324
+ return;
325
+ }
326
+ // Check for age-based health restart
327
+ if (this.pmProcessConfig.maxSessionAgeMs > 0) {
328
+ const proc = getActivePMProcesses().get(productId);
329
+ if (proc && proc.phase === 'running') {
330
+ const age = Date.now() - proc.spawnedAt.getTime();
331
+ if (age >= this.pmProcessConfig.maxSessionAgeMs) {
332
+ console.log(`[PM] Session age (${Math.round(age / 60_000)}m) exceeds maxSessionAge ` +
333
+ `(${Math.round(this.pmProcessConfig.maxSessionAgeMs / 60_000)}m) for product ${productId}. ` +
334
+ `Triggering health restart.`);
335
+ clearInterval(checkInterval);
336
+ terminatePMProcess(productId);
337
+ // Reset restart count -- this is a planned restart, not a crash
338
+ this.restartCounts.delete(productId);
339
+ this.handleProcessExit(productId, repoPath);
340
+ return;
341
+ }
342
+ }
343
+ }
344
+ if (!isPMProcessRunning(productId) && !this.restartTimeouts.has(productId)) {
345
+ clearInterval(checkInterval);
346
+ this.handleProcessExit(productId, repoPath);
347
+ }
348
+ }, 10_000); // Check every 10 seconds
349
+ }
350
+ /**
351
+ * Handle PM process exit -- check session status before scheduling restart.
352
+ * Only restarts if the session is still active. If stopped/paused, the
353
+ * exit is intentional and no restart is scheduled.
354
+ */
355
+ handleProcessExit(productId, repoPath) {
356
+ if (this.shuttingDown)
357
+ return;
358
+ const config = this.config;
359
+ const governor = this.governor;
360
+ if (!config || !governor)
361
+ return;
362
+ // Track restart count (use a simple counter)
363
+ const restartCount = this.getRestartCount(productId);
364
+ if (restartCount >= this.pmProcessConfig.maxRestarts) {
365
+ console.log(`[PM] Max restarts (${this.pmProcessConfig.maxRestarts}) reached for product ${productId}. ` +
366
+ `PM process will not be restarted.`);
367
+ return;
368
+ }
369
+ const delay = calculateRestartDelay(restartCount);
370
+ console.log(`[PM] Scheduling PM process restart for product ${productId} ` +
371
+ `in ${Math.round(delay / 1000)}s (attempt ${restartCount + 1}/${this.pmProcessConfig.maxRestarts})`);
372
+ const timeout = setTimeout(async () => {
373
+ this.restartTimeouts.delete(productId);
374
+ if (this.shuttingDown)
375
+ return;
376
+ // Check session status before restarting — if user stopped/paused, don't restart
377
+ try {
378
+ const result = await callApi('pm_session_list', {
379
+ productId,
380
+ });
381
+ const session = result?.pmSessions?.[0];
382
+ if (session && session.status !== 'active') {
383
+ console.log(`[PM] Session ${session.status} for product ${productId}, skipping restart`);
384
+ return;
385
+ }
386
+ }
387
+ catch {
388
+ // If we can't check status, proceed with restart attempt
389
+ }
390
+ try {
391
+ await spawnPMProcess(config, productId, repoPath, governor, this.pmProcessConfig);
392
+ this.incrementRestartCount(productId);
393
+ this.setupProcessMonitor(productId, repoPath);
394
+ console.log(`[PM] PM process restarted for product ${productId}`);
395
+ }
396
+ catch (err) {
397
+ console.log(`[PM] Failed to restart PM process for product ${productId}: ` +
398
+ `${err instanceof Error ? err.message : String(err)}`);
399
+ // Try again
400
+ this.handleProcessExit(productId, repoPath);
401
+ }
402
+ }, delay);
403
+ this.restartTimeouts.set(productId, timeout);
404
+ }
405
+ /** Restart count tracking (simple in-memory map). */
406
+ restartCounts = new Map();
407
+ getRestartCount(productId) {
408
+ return this.restartCounts.get(productId) ?? 0;
409
+ }
410
+ incrementRestartCount(productId) {
411
+ const current = this.restartCounts.get(productId) ?? 0;
412
+ this.restartCounts.set(productId, current + 1);
413
+ }
414
+ // -----------------------------------------------------------------------
415
+ // Private: risk poll cycle (unchanged from monitoring-only engine)
147
416
  // -----------------------------------------------------------------------
148
417
  /**
149
418
  * Run a single poll cycle: scan dependencies, correlate mitigation, log results.
@@ -205,10 +474,6 @@ export class PMEngine {
205
474
  }
206
475
  /**
207
476
  * Create communication drafts for high-urgency follow-up actions.
208
- *
209
- * Only drafts for 'high' urgency actions with a 'send_followup' recommendation.
210
- * Drafts are stored via the API with status='draft' for human approval.
211
- * Returns the number of drafts successfully created.
212
477
  */
213
478
  async createFollowupDrafts(productId, actions) {
214
479
  const highUrgencyFollowups = actions.filter(a => a.urgency === 'high' && a.action === 'send_followup');
@@ -216,7 +481,6 @@ export class PMEngine {
216
481
  return 0;
217
482
  let created = 0;
218
483
  for (const action of highUrgencyFollowups) {
219
- // Calculate days past due
220
484
  const daysPastDue = action.nextFollowupAt
221
485
  ? Math.max(0, Math.floor((Date.now() - new Date(action.nextFollowupAt).getTime()) / (24 * 60 * 60 * 1000)))
222
486
  : 0;
@@ -230,7 +494,6 @@ export class PMEngine {
230
494
  ownerName: action.ownerName,
231
495
  ownerContact: action.ownerContact,
232
496
  }, 'email');
233
- // Set the dependency ID on the draft
234
497
  draft.riskDependencyId = action.dependencyId;
235
498
  try {
236
499
  await callApi('risk_communication_create', {
@@ -1 +1 @@
1
- {"version":3,"file":"pm-engine.js","sourceRoot":"","sources":["../src/pm-engine.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pm-engine.js","sourceRoot":"","sources":["../src/pm-engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * PM process state and lifecycle management.
3
+ *
4
+ * Manages the spawning, monitoring, and termination of PM Claude Code
5
+ * processes. Each product gets one PM process that runs /loop for its
6
+ * PM cycle.
7
+ */
8
+ import type { ResourceGovernor } from '@telora/daemon-core';
9
+ import type { DaemonConfig } from './types.js';
10
+ import type { PMProcessState, PMProcessConfig } from './types/pm.js';
11
+ /**
12
+ * Spawn a PM Claude Code process for a product.
13
+ *
14
+ * The process runs in the product's repo directory with the PM CLAUDE.md
15
+ * as context, and is given a /loop command to run the PM cycle periodically.
16
+ */
17
+ export declare function spawnPMProcess(config: DaemonConfig, productId: string, repoPath: string, governor: ResourceGovernor, pmConfig?: PMProcessConfig): Promise<PMProcessState>;
18
+ /**
19
+ * Gracefully terminate a PM process for a product.
20
+ */
21
+ export declare function terminatePMProcess(productId: string): boolean;
22
+ /**
23
+ * Terminate all active PM processes.
24
+ */
25
+ export declare function terminateAllPMProcesses(): void;
26
+ /**
27
+ * Get the active PM process for a product, or undefined if none.
28
+ */
29
+ export declare function getPMProcess(productId: string): PMProcessState | undefined;
30
+ /**
31
+ * Get all active PM processes.
32
+ */
33
+ export declare function getActivePMProcesses(): Map<string, PMProcessState>;
34
+ /**
35
+ * Check if a PM process is running for a product.
36
+ */
37
+ export declare function isPMProcessRunning(productId: string): boolean;
38
+ /**
39
+ * Calculate exponential backoff delay for PM process restart.
40
+ *
41
+ * Backoff schedule: 1m, 2m, 4m, 8m, 16m, 30m (capped)
42
+ * Returns delay in milliseconds.
43
+ */
44
+ export declare function calculateRestartDelay(restartCount: number): number;
45
+ //# sourceMappingURL=pm-process.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pm-process.d.ts","sourceRoot":"","sources":["../src/pm-process.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAM5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAgBrE;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,YAAY,EACpB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,gBAAgB,EAC1B,QAAQ,GAAE,eAA2C,GACpD,OAAO,CAAC,cAAc,CAAC,CAwGzB;AAMD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CA0B7D;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,IAAI,CAI9C;AAMD;;GAEG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAE1E;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAElE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAG7D;AAMD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAKlE"}
@@ -0,0 +1,191 @@
1
+ /**
2
+ * PM process state and lifecycle management.
3
+ *
4
+ * Manages the spawning, monitoring, and termination of PM Claude Code
5
+ * processes. Each product gets one PM process that runs /loop for its
6
+ * PM cycle.
7
+ */
8
+ import { spawn } from 'node:child_process';
9
+ import { buildStreamJsonArgs, stripClaudeCodeEnvVars, sendMessage, } from '@telora/daemon-core';
10
+ import { DEFAULT_PM_PROCESS_CONFIG } from './types/pm.js';
11
+ import { buildPMPrompt } from './pm-prompt-builder.js';
12
+ import { callApi } from './queries/shared.js';
13
+ // ---------------------------------------------------------------------------
14
+ // Active processes
15
+ // ---------------------------------------------------------------------------
16
+ /** Map of productId -> PMProcessState for active PM processes. */
17
+ const activeProcesses = new Map();
18
+ // ---------------------------------------------------------------------------
19
+ // Spawn
20
+ // ---------------------------------------------------------------------------
21
+ /**
22
+ * Spawn a PM Claude Code process for a product.
23
+ *
24
+ * The process runs in the product's repo directory with the PM CLAUDE.md
25
+ * as context, and is given a /loop command to run the PM cycle periodically.
26
+ */
27
+ export async function spawnPMProcess(config, productId, repoPath, governor, pmConfig = DEFAULT_PM_PROCESS_CONFIG) {
28
+ // Acquire governor slot
29
+ await governor.acquireSlot('pm');
30
+ // Create PM session in database
31
+ let pmSessionId;
32
+ try {
33
+ const result = await callApi('pm_session_create', {
34
+ productId,
35
+ });
36
+ pmSessionId = result?.session?.id ?? `pm-${productId}`;
37
+ }
38
+ catch {
39
+ // If session creation fails, use a synthetic ID
40
+ pmSessionId = `pm-${productId}`;
41
+ }
42
+ // Fetch product info
43
+ let productName = productId;
44
+ try {
45
+ const productResult = await callApi('product_get', {
46
+ productId,
47
+ });
48
+ productName = productResult?.name ?? productId;
49
+ }
50
+ catch {
51
+ // Use productId as fallback name
52
+ }
53
+ // Build initial prompt
54
+ const initialPrompt = await buildPMPrompt(repoPath, { id: productId, name: productName }, pmConfig.loopIntervalMinutes);
55
+ // Build CLI args
56
+ const args = buildStreamJsonArgs();
57
+ // Build environment (strip inherited Claude Code vars)
58
+ const spawnEnv = stripClaudeCodeEnvVars(process.env, {
59
+ preserve: ['CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS'],
60
+ });
61
+ // Spawn Claude Code process in the product repo
62
+ const proc = spawn(config.claudeCodePath, args, {
63
+ cwd: repoPath,
64
+ env: spawnEnv,
65
+ stdio: ['pipe', 'pipe', 'pipe'],
66
+ });
67
+ const state = {
68
+ productId,
69
+ proc,
70
+ pmSessionId,
71
+ phase: 'starting',
72
+ restartCount: 0,
73
+ lastRestartAt: null,
74
+ stdin: proc.stdin,
75
+ spawnedAt: new Date(),
76
+ };
77
+ activeProcesses.set(productId, state);
78
+ // Send initial prompt
79
+ sendMessage(proc.stdin, initialPrompt);
80
+ state.phase = 'running';
81
+ // Log stdout (simple line-by-line)
82
+ proc.stdout.on('data', (data) => {
83
+ const lines = data.toString().split('\n').filter(Boolean);
84
+ for (const line of lines) {
85
+ try {
86
+ const event = JSON.parse(line);
87
+ // Capture Claude session ID from init event
88
+ if (event.type === 'system' && event.sessionId) {
89
+ state.claudeSessionId = event.sessionId;
90
+ }
91
+ }
92
+ catch {
93
+ // Non-JSON output -- log as-is
94
+ }
95
+ }
96
+ });
97
+ proc.stderr.on('data', (data) => {
98
+ console.log(`[PM] stderr (${productId}): ${data.toString().trim()}`);
99
+ });
100
+ // Handle process exit
101
+ proc.on('close', (code) => {
102
+ console.log(`[PM] Process exited for product ${productId} (code: ${code})`);
103
+ state.phase = 'crashed';
104
+ governor.releaseSlot('pm');
105
+ activeProcesses.delete(productId);
106
+ });
107
+ proc.on('error', (err) => {
108
+ console.log(`[PM] Process error for product ${productId}: ${err.message}`);
109
+ state.phase = 'crashed';
110
+ governor.releaseSlot('pm');
111
+ activeProcesses.delete(productId);
112
+ });
113
+ console.log(`[PM] Spawned process for product ${productId} (pid: ${proc.pid})`);
114
+ return state;
115
+ }
116
+ // ---------------------------------------------------------------------------
117
+ // Terminate
118
+ // ---------------------------------------------------------------------------
119
+ /**
120
+ * Gracefully terminate a PM process for a product.
121
+ */
122
+ export function terminatePMProcess(productId) {
123
+ const state = activeProcesses.get(productId);
124
+ if (!state)
125
+ return false;
126
+ state.phase = 'stopping';
127
+ // Try graceful shutdown: close stdin, then SIGTERM
128
+ try {
129
+ state.stdin.end();
130
+ }
131
+ catch {
132
+ // Already closed
133
+ }
134
+ setTimeout(() => {
135
+ if (state.proc.exitCode === null) {
136
+ state.proc.kill('SIGTERM');
137
+ }
138
+ }, 5000);
139
+ setTimeout(() => {
140
+ if (state.proc.exitCode === null) {
141
+ state.proc.kill('SIGKILL');
142
+ }
143
+ }, 15000);
144
+ return true;
145
+ }
146
+ /**
147
+ * Terminate all active PM processes.
148
+ */
149
+ export function terminateAllPMProcesses() {
150
+ for (const productId of activeProcesses.keys()) {
151
+ terminatePMProcess(productId);
152
+ }
153
+ }
154
+ // ---------------------------------------------------------------------------
155
+ // Query
156
+ // ---------------------------------------------------------------------------
157
+ /**
158
+ * Get the active PM process for a product, or undefined if none.
159
+ */
160
+ export function getPMProcess(productId) {
161
+ return activeProcesses.get(productId);
162
+ }
163
+ /**
164
+ * Get all active PM processes.
165
+ */
166
+ export function getActivePMProcesses() {
167
+ return activeProcesses;
168
+ }
169
+ /**
170
+ * Check if a PM process is running for a product.
171
+ */
172
+ export function isPMProcessRunning(productId) {
173
+ const state = activeProcesses.get(productId);
174
+ return state !== undefined && state.phase === 'running';
175
+ }
176
+ // ---------------------------------------------------------------------------
177
+ // Backoff
178
+ // ---------------------------------------------------------------------------
179
+ /**
180
+ * Calculate exponential backoff delay for PM process restart.
181
+ *
182
+ * Backoff schedule: 1m, 2m, 4m, 8m, 16m, 30m (capped)
183
+ * Returns delay in milliseconds.
184
+ */
185
+ export function calculateRestartDelay(restartCount) {
186
+ const baseMs = 60_000; // 1 minute
187
+ const maxMs = 30 * 60_000; // 30 minutes
188
+ const delay = Math.min(baseMs * Math.pow(2, restartCount), maxMs);
189
+ return delay;
190
+ }
191
+ //# sourceMappingURL=pm-process.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pm-process.js","sourceRoot":"","sources":["../src/pm-process.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * PM prompt builder -- builds the initial prompt for a PM Claude Code process.
3
+ *
4
+ * Reads pm/CLAUDE.md from the product repo, fetches product details and PM
5
+ * session state, and composes the initial prompt that boots the PM agent
6
+ * with /loop at the configured interval.
7
+ */
8
+ interface ProductInfo {
9
+ id: string;
10
+ name: string;
11
+ }
12
+ /**
13
+ * Build the initial prompt for a PM Claude Code process.
14
+ *
15
+ * The prompt includes:
16
+ * 1. pm/CLAUDE.md contents (the PM agent's system instructions)
17
+ * 2. Product context (name, ID)
18
+ * 3. PM session state (last assessment, pending items)
19
+ * 4. /loop instruction at the configured interval
20
+ */
21
+ export declare function buildPMPrompt(repoPath: string, product: ProductInfo, loopIntervalMinutes: number): Promise<string>;
22
+ export {};
23
+ //# sourceMappingURL=pm-prompt-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pm-prompt-builder.d.ts","sourceRoot":"","sources":["../src/pm-prompt-builder.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAUH,UAAU,WAAW;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AAYD;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,WAAW,EACpB,mBAAmB,EAAE,MAAM,GAC1B,OAAO,CAAC,MAAM,CAAC,CA+CjB"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * PM prompt builder -- builds the initial prompt for a PM Claude Code process.
3
+ *
4
+ * Reads pm/CLAUDE.md from the product repo, fetches product details and PM
5
+ * session state, and composes the initial prompt that boots the PM agent
6
+ * with /loop at the configured interval.
7
+ */
8
+ import { readFile } from 'node:fs/promises';
9
+ import { join } from 'node:path';
10
+ import { callApi } from './queries/shared.js';
11
+ // ---------------------------------------------------------------------------
12
+ // Builder
13
+ // ---------------------------------------------------------------------------
14
+ /**
15
+ * Build the initial prompt for a PM Claude Code process.
16
+ *
17
+ * The prompt includes:
18
+ * 1. pm/CLAUDE.md contents (the PM agent's system instructions)
19
+ * 2. Product context (name, ID)
20
+ * 3. PM session state (last assessment, pending items)
21
+ * 4. /loop instruction at the configured interval
22
+ */
23
+ export async function buildPMPrompt(repoPath, product, loopIntervalMinutes) {
24
+ const parts = [];
25
+ // 1. Read pm/CLAUDE.md from the product repo
26
+ const pmClaudeMdPath = join(repoPath, 'pm', 'CLAUDE.md');
27
+ let pmInstructions = '';
28
+ try {
29
+ pmInstructions = await readFile(pmClaudeMdPath, 'utf-8');
30
+ }
31
+ catch {
32
+ // If pm/CLAUDE.md doesn't exist, use a minimal fallback
33
+ pmInstructions = '# PM Agent\n\nYou are a PM agent. Run your cycle to check inbox, review action plan, and generate reports.';
34
+ }
35
+ parts.push(pmInstructions);
36
+ // 2. Product context
37
+ parts.push(`\n## Product\n\n- **Name**: ${product.name}\n- **ID**: ${product.id}`);
38
+ // 3. PM session state
39
+ let sessionState = null;
40
+ try {
41
+ const sessionResult = await callApi('pm_session_get', {
42
+ productId: product.id,
43
+ });
44
+ sessionState = sessionResult?.session ?? null;
45
+ }
46
+ catch {
47
+ // Session may not exist yet -- PM will create it during first cycle
48
+ }
49
+ if (sessionState) {
50
+ parts.push('\n## Session State\n');
51
+ if (sessionState.lastCycleAt) {
52
+ parts.push(`- **Last cycle**: ${sessionState.lastCycleAt}`);
53
+ }
54
+ if (sessionState.lastAssessment) {
55
+ parts.push(`- **Last assessment**: ${JSON.stringify(sessionState.lastAssessment, null, 2)}`);
56
+ }
57
+ }
58
+ // 4. /loop instruction
59
+ parts.push(`\n## Instructions\n\n` +
60
+ `Run the PM cycle now, then continue running it on a loop.\n\n` +
61
+ `/loop ${loopIntervalMinutes}m /pm-cycle`);
62
+ return parts.join('\n');
63
+ }
64
+ //# sourceMappingURL=pm-prompt-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pm-prompt-builder.js","sourceRoot":"","sources":["../src/pm-prompt-builder.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAiB9C,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,QAAgB,EAChB,OAAoB,EACpB,mBAA2B;IAE3B,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,6CAA6C;IAC7C,MAAM,cAAc,GAAG,IAAI,CAAC,QAAQ,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC;IACzD,IAAI,cAAc,GAAG,EAAE,CAAC;IACxB,IAAI,CAAC;QACH,cAAc,GAAG,MAAM,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;IAC3D,CAAC;IAAC,MAAM,CAAC;QACP,wDAAwD;QACxD,cAAc,GAAG,4GAA4G,CAAC;IAChI,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAE3B,qBAAqB;IACrB,KAAK,CAAC,IAAI,CAAC,+BAA+B,OAAO,CAAC,IAAI,eAAe,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;IAEnF,sBAAsB;IACtB,IAAI,YAAY,GAA0B,IAAI,CAAC;IAC/C,IAAI,CAAC;QACH,MAAM,aAAa,GAAG,MAAM,OAAO,CAAC,gBAAgB,EAAE;YACpD,SAAS,EAAE,OAAO,CAAC,EAAE;SACtB,CAAiC,CAAC;QACnC,YAAY,GAAG,aAAa,EAAE,OAAO,IAAI,IAAI,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,oEAAoE;IACtE,CAAC;IAED,IAAI,YAAY,EAAE,CAAC;QACjB,KAAK,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;QACnC,IAAI,YAAY,CAAC,WAAW,EAAE,CAAC;YAC7B,KAAK,CAAC,IAAI,CAAC,qBAAqB,YAAY,CAAC,WAAW,EAAE,CAAC,CAAC;QAC9D,CAAC;QACD,IAAI,YAAY,CAAC,cAAc,EAAE,CAAC;YAChC,KAAK,CAAC,IAAI,CAAC,0BAA0B,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,cAAc,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QAC/F,CAAC;IACH,CAAC;IAED,uBAAuB;IACvB,KAAK,CAAC,IAAI,CACR,uBAAuB;QACvB,+DAA+D;QAC/D,SAAS,mBAAmB,aAAa,CAC1C,CAAC;IAEF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -12,4 +12,5 @@ export * from './delivery.js';
12
12
  export * from './strategy.js';
13
13
  export * from './dag.js';
14
14
  export * from './merge.js';
15
+ export * from './pm.js';
15
16
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC"}
@@ -12,4 +12,5 @@ export * from './delivery.js';
12
12
  export * from './strategy.js';
13
13
  export * from './dag.js';
14
14
  export * from './merge.js';
15
+ export * from './pm.js';
15
16
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * PM process supervision types.
3
+ */
4
+ import type { ChildProcess } from 'node:child_process';
5
+ import type { Writable } from 'node:stream';
6
+ /**
7
+ * State of a supervised PM Claude Code process.
8
+ */
9
+ export interface PMProcessState {
10
+ /** Product this PM process manages. */
11
+ productId: string;
12
+ /** Spawned child process handle. */
13
+ proc: ChildProcess;
14
+ /** PM session ID from the database. */
15
+ pmSessionId: string;
16
+ /** Claude Code session ID (set after stream init event). */
17
+ claudeSessionId?: string;
18
+ /** Current phase of the PM process. */
19
+ phase: 'starting' | 'running' | 'stopping' | 'crashed';
20
+ /** Number of times this process has been restarted. */
21
+ restartCount: number;
22
+ /** Timestamp of last restart (for backoff calculation). */
23
+ lastRestartAt: Date | null;
24
+ /** Stdin writable for sending messages. */
25
+ stdin: Writable;
26
+ /** Timestamp when this process was spawned (for maxSessionAge checks). */
27
+ spawnedAt: Date;
28
+ }
29
+ /**
30
+ * PM-specific configuration fields (resolved from daemon.json engines.pm section).
31
+ *
32
+ * Fields resolve with priority: env var > daemon.json engines.pm > default.
33
+ * - loopIntervalMinutes: TELORA_PM_LOOP_INTERVAL (in minutes)
34
+ * - maxRestarts: TELORA_PM_MAX_RESTARTS
35
+ * - maxSessionAgeMs: TELORA_PM_MAX_SESSION_AGE (in minutes, converted to ms)
36
+ */
37
+ export interface PMProcessConfig {
38
+ /** Interval for the /loop command in minutes. Default: 240 (4 hours). */
39
+ loopIntervalMinutes: number;
40
+ /** Maximum restart attempts before giving up. Default: 5. */
41
+ maxRestarts: number;
42
+ /** Whether process supervision is enabled. Default: true. */
43
+ processEnabled: boolean;
44
+ /**
45
+ * Maximum age (ms) of a PM session before a health restart is triggered.
46
+ * When a running PM process exceeds this age, the engine terminates and
47
+ * respawns it to keep the session fresh. Default: 86400000 (24 hours).
48
+ * Set to 0 to disable age-based restarts.
49
+ */
50
+ maxSessionAgeMs: number;
51
+ }
52
+ export declare const DEFAULT_PM_PROCESS_CONFIG: PMProcessConfig;
53
+ //# sourceMappingURL=pm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pm.d.ts","sourceRoot":"","sources":["../../src/types/pm.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,uCAAuC;IACvC,SAAS,EAAE,MAAM,CAAC;IAElB,oCAAoC;IACpC,IAAI,EAAE,YAAY,CAAC;IAEnB,uCAAuC;IACvC,WAAW,EAAE,MAAM,CAAC;IAEpB,4DAA4D;IAC5D,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,uCAAuC;IACvC,KAAK,EAAE,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,CAAC;IAEvD,uDAAuD;IACvD,YAAY,EAAE,MAAM,CAAC;IAErB,2DAA2D;IAC3D,aAAa,EAAE,IAAI,GAAG,IAAI,CAAC;IAE3B,2CAA2C;IAC3C,KAAK,EAAE,QAAQ,CAAC;IAEhB,0EAA0E;IAC1E,SAAS,EAAE,IAAI,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,eAAe;IAC9B,yEAAyE;IACzE,mBAAmB,EAAE,MAAM,CAAC;IAE5B,6DAA6D;IAC7D,WAAW,EAAE,MAAM,CAAC;IAEpB,6DAA6D;IAC7D,cAAc,EAAE,OAAO,CAAC;IAExB;;;;;OAKG;IACH,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,eAAO,MAAM,yBAAyB,EAAE,eAKvC,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * PM process supervision types.
3
+ */
4
+ export const DEFAULT_PM_PROCESS_CONFIG = {
5
+ loopIntervalMinutes: 240,
6
+ maxRestarts: 5,
7
+ processEnabled: true,
8
+ maxSessionAgeMs: 24 * 60 * 60 * 1000, // 24 hours
9
+ };
10
+ //# sourceMappingURL=pm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pm.js","sourceRoot":"","sources":["../../src/types/pm.ts"],"names":[],"mappings":"AAAA;;GAEG;AAgEH,MAAM,CAAC,MAAM,yBAAyB,GAAoB;IACxD,mBAAmB,EAAE,GAAG;IACxB,WAAW,EAAE,CAAC;IACd,cAAc,EAAE,IAAI;IACpB,eAAe,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,WAAW;CAClD,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@telora/daemon",
3
- "version": "0.13.28",
3
+ "version": "0.13.29",
4
4
  "description": "Agent orchestration daemon for Telora - spawns and manages Claude Code instances",
5
5
  "type": "module",
6
6
  "bin": {