@telora/daemon 0.16.44 → 0.17.2

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.
@@ -0,0 +1,164 @@
1
+ /**
2
+ * PRD obstacle clearance predicate engine -- Staged Assembly: PRD Layer.
3
+ *
4
+ * This module lifts the per-delivery verification engine one altitude up to the
5
+ * PRD Prerequisite Tree (PRT) obstacle. Where `verification-engine.ts` answers
6
+ * "is this delivery's injection cleared?", this answers "is this milestone's
7
+ * obstacle cleared?" -- and, in aggregate, "is the whole milestone complete?".
8
+ *
9
+ * The clearance predicate is BOTH the completion signal AND the divergence
10
+ * detector: a PRD (milestone) is done exactly when every obstacle's verifiable
11
+ * clearance predicate passes. (UDE #4 -> desired effect: milestone completion
12
+ * is computable.)
13
+ *
14
+ * Design constraints (delivery C):
15
+ * - PURE. No DB access, no reality-tree writes, no module-level mutable state.
16
+ * The caller fetches obstacles (from `prd_prt_nodes.clearance_predicate`) and
17
+ * passes them in; this module only computes verdicts.
18
+ * - Command execution is INJECTED via `ClearanceContext.runCommand` so tests
19
+ * never shell out. A `defaultRunCommand` is provided for real callers and
20
+ * mirrors `verification-engine.runDeterministicStrategy` (spawn `sh -c`, tail
21
+ * output at 4000 chars, exit 0 = pass) -- but returns the raw triple rather
22
+ * than a StrategyResult, keeping this module side-effect-light.
23
+ * - NO daemon-loop wiring here. Wiring into the focus/verification loop is a
24
+ * later delivery (D).
25
+ *
26
+ * Predicate kinds mirror the verification engine's strategy taxonomy:
27
+ * deterministic -- run shell checks; all exit 0 => cleared.
28
+ * behavioral -- runtime telemetry observation (deferred; no signal source).
29
+ * ai_inspection -- AI reads code/state and decides (deferred; no driver).
30
+ * human -- a human attests clearance (deferred; out of band).
31
+ *
32
+ * @module prd-clearance-engine
33
+ */
34
+ import { spawn } from 'node:child_process';
35
+ const DEFAULT_CLEARANCE_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes
36
+ const OUTPUT_TAIL_MAX = 4000;
37
+ // ---------------------------------------------------------------------------
38
+ // Default command runner (mirrors runDeterministicStrategy)
39
+ // ---------------------------------------------------------------------------
40
+ /**
41
+ * Real shell runner: spawn `sh -c <cmd>` in `cwd`, capture stdout/stderr tailed
42
+ * to 4000 chars, resolve `{ exitCode, stdoutTail, stderrTail }`. A spawn error
43
+ * resolves with `exitCode: null` (treated as a non-pass by callers). Mirrors
44
+ * `verification-engine.runDeterministicStrategy` but returns the raw triple.
45
+ */
46
+ export const defaultRunCommand = (cmd, cwd) => {
47
+ return new Promise((resolve) => {
48
+ const child = spawn('sh', ['-c', cmd], {
49
+ cwd,
50
+ stdio: ['ignore', 'pipe', 'pipe'],
51
+ });
52
+ let stdout = '';
53
+ let stderr = '';
54
+ const tail = (buf, max = OUTPUT_TAIL_MAX) => buf.length <= max ? buf : buf.slice(buf.length - max);
55
+ child.stdout?.on('data', (chunk) => {
56
+ stdout += chunk.toString('utf8');
57
+ stdout = tail(stdout);
58
+ });
59
+ child.stderr?.on('data', (chunk) => {
60
+ stderr += chunk.toString('utf8');
61
+ stderr = tail(stderr);
62
+ });
63
+ const timer = setTimeout(() => {
64
+ try {
65
+ child.kill('SIGKILL');
66
+ }
67
+ catch { /* ignore */ }
68
+ }, DEFAULT_CLEARANCE_TIMEOUT_MS);
69
+ child.on('error', (err) => {
70
+ clearTimeout(timer);
71
+ resolve({
72
+ exitCode: null,
73
+ stdoutTail: stdout,
74
+ stderrTail: tail(`${stderr}\n${err.message}`),
75
+ });
76
+ });
77
+ child.on('close', (code) => {
78
+ clearTimeout(timer);
79
+ resolve({ exitCode: code, stdoutTail: stdout, stderrTail: stderr });
80
+ });
81
+ });
82
+ };
83
+ // ---------------------------------------------------------------------------
84
+ // Evaluation
85
+ // ---------------------------------------------------------------------------
86
+ const DEFERRAL_REASON = {
87
+ behavioral: 'behavioral clearance deferred -- no runtime telemetry source wired',
88
+ ai_inspection: 'ai_inspection clearance deferred -- no AI inspection driver wired',
89
+ human: 'human clearance deferred -- requires out-of-band human attestation',
90
+ };
91
+ /**
92
+ * Evaluate a single obstacle's clearance predicate. PURE.
93
+ *
94
+ * - deterministic: run each check via `ctx.runCommand ?? defaultRunCommand`.
95
+ * exit 0 = passed. All pass => cleared. No checks (undefined/empty) =>
96
+ * not cleared, not deferred (a deterministic predicate with nothing to check
97
+ * cannot assert clearance).
98
+ * - behavioral | ai_inspection | human: deferred (cleared:false, deferred:true);
99
+ * evidence names the deferral reason.
100
+ */
101
+ export async function evaluateClearance(predicate, ctx) {
102
+ if (predicate.kind !== 'deterministic') {
103
+ return {
104
+ kind: predicate.kind,
105
+ cleared: false,
106
+ deferred: true,
107
+ evidence: DEFERRAL_REASON[predicate.kind],
108
+ };
109
+ }
110
+ const checks = predicate.checks ?? [];
111
+ if (checks.length === 0) {
112
+ return {
113
+ kind: 'deterministic',
114
+ cleared: false,
115
+ deferred: false,
116
+ evidence: 'no checks defined -- deterministic predicate cannot assert clearance',
117
+ checkResults: [],
118
+ };
119
+ }
120
+ const run = ctx.runCommand ?? defaultRunCommand;
121
+ const checkResults = [];
122
+ for (const check of checks) {
123
+ const { exitCode } = await run(check.cmd, ctx.worktreeDir);
124
+ checkResults.push({
125
+ cmd: check.cmd,
126
+ exitCode,
127
+ passed: exitCode === 0,
128
+ });
129
+ }
130
+ const passedCount = checkResults.filter(r => r.passed).length;
131
+ const cleared = passedCount === checkResults.length;
132
+ return {
133
+ kind: 'deterministic',
134
+ cleared,
135
+ deferred: false,
136
+ evidence: cleared
137
+ ? `deterministic clearance passed (${passedCount}/${checkResults.length} checks exit 0)`
138
+ : `deterministic clearance failed (${passedCount}/${checkResults.length} checks exit 0)`,
139
+ checkResults,
140
+ };
141
+ }
142
+ /**
143
+ * Aggregate clearance across all obstacles of a PRT -- the "milestone
144
+ * completion is computable" primitive. PURE; the caller fetches the obstacles
145
+ * (each carrying its `clearance_predicate`).
146
+ *
147
+ * - `allCleared` is true only when there is at least one obstacle AND every
148
+ * obstacle's verdict is cleared. (An empty obstacle set cannot assert a
149
+ * complete milestone.)
150
+ * - `deferredCount` counts obstacles whose predicate could not be evaluated
151
+ * automatically -- these block `allCleared` and flag where human/AI signal
152
+ * is still required.
153
+ */
154
+ export async function evaluatePrtClearance(obstacles, ctx) {
155
+ const nodeVerdicts = [];
156
+ for (const obstacle of obstacles) {
157
+ const verdict = await evaluateClearance(obstacle.predicate, ctx);
158
+ nodeVerdicts.push({ nodeId: obstacle.nodeId, verdict });
159
+ }
160
+ const allCleared = obstacles.length > 0 && nodeVerdicts.every(nv => nv.verdict.cleared);
161
+ const deferredCount = nodeVerdicts.filter(nv => nv.verdict.deferred).length;
162
+ return { nodeVerdicts, allCleared, deferredCount };
163
+ }
164
+ //# sourceMappingURL=prd-clearance-engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prd-clearance-engine.js","sourceRoot":"","sources":["../src/prd-clearance-engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * PRD-lifecycle controller (Delivery D).
3
+ *
4
+ * CARDINAL RULE: this controller adds NO new executor. Its only outputs are
5
+ * (a) materialize an overcome into a focus via the existing
6
+ * prd_overcome_materialize action, (b) arm a focus by setting
7
+ * assigned_agent_role_id via the existing focus_update action (the queue toggle
8
+ * the focus engine already polls), (c) mark obstacles cleared / the PRD done via
9
+ * the existing node/prd update actions. It never spawns agents and never creates
10
+ * a parallel execution path.
11
+ *
12
+ * It computes the Prerequisite-Tree (PRT) frontier for an active PRD and arms
13
+ * the frontier foci; on obstacle clearance it recomputes and arms the next
14
+ * frontier. The whole milestone then runs progressively over the existing
15
+ * Foci -> Delivery -> Issue executor.
16
+ */
17
+ import type { DaemonConfig } from './types.js';
18
+ import { type ClearancePredicate, type ClearanceContext, type ClearanceVerdict } from './prd-clearance-engine.js';
19
+ import { type Prd, type PrtNode, type PrtEdge, type Pathway } from './queries/prd.js';
20
+ import { type FileEscalationInput } from './escalations.js';
21
+ /**
22
+ * Splits the armable overcome frontier into those still needing a focus
23
+ * (materialize) and those already materialized (arm).
24
+ *
25
+ * PRT frontier semantics (implemented exactly):
26
+ * - prerequisite edge P->Q means P must be cleared before Q.
27
+ * - overcome O is ARMABLE iff O.status !== 'cleared' AND every node P with a
28
+ * prerequisite edge P->O is in clearedNodeIds. No incoming prerequisite edge
29
+ * => initial frontier.
30
+ * - needsMaterialize = armable overcomes with focusId == null.
31
+ * - needsArm = armable overcomes with focusId set.
32
+ */
33
+ export declare function computePrtFrontier(nodes: PrtNode[], edges: PrtEdge[], clearedNodeIds: Set<string>): {
34
+ needsMaterialize: PrtNode[];
35
+ needsArm: PrtNode[];
36
+ };
37
+ export interface PrdControllerDeps {
38
+ loadPrtGraph: (prdId: string) => Promise<{
39
+ nodes: PrtNode[];
40
+ edges: PrtEdge[];
41
+ }>;
42
+ evaluateClearance: (predicate: ClearancePredicate, ctx: ClearanceContext) => Promise<ClearanceVerdict>;
43
+ markNodeCleared: (nodeId: string) => Promise<void>;
44
+ materializeOvercome: (nodeId: string) => Promise<{
45
+ focusId: string;
46
+ }>;
47
+ armFocus: (focusId: string, agentRoleId: string) => Promise<void>;
48
+ markPrdDone: (prdId: string) => Promise<void>;
49
+ resolveArmRoleId: (prd: Prd) => Promise<string | null>;
50
+ loadPathways: (prdId: string) => Promise<Pathway[]>;
51
+ commitPathway: (prdId: string, pathwayId: string) => Promise<void>;
52
+ fileEscalation: (input: FileEscalationInput) => Promise<void>;
53
+ /** Org scope used when filing a no-surviving-path escalation. */
54
+ organizationId: string;
55
+ worktreeDir: string;
56
+ }
57
+ export interface PrdControllerTickResult {
58
+ obstaclesEvaluated: number;
59
+ obstaclesCleared: number;
60
+ materialized: number;
61
+ armed: number;
62
+ skippedNoRole: number;
63
+ prdDone: boolean;
64
+ /** True when this tick detected one or more divergence signals. */
65
+ diverged: boolean;
66
+ /** True when realign re-pointed the committed pathway (re-capture). */
67
+ pathSwitched: boolean;
68
+ /** True when divergence had no surviving path and a human was escalated. */
69
+ escalated: boolean;
70
+ }
71
+ export declare function runPrdControllerTick(prd: Prd, deps: PrdControllerDeps): Promise<PrdControllerTickResult>;
72
+ export interface PrdControllerTickAllResult {
73
+ obstaclesEvaluated: number;
74
+ obstaclesCleared: number;
75
+ materialized: number;
76
+ armed: number;
77
+ skippedNoRole: number;
78
+ prdsDone: number;
79
+ /** PRDs that detected divergence this pass. */
80
+ prdsDiverged: number;
81
+ /** PRDs whose committed pathway was re-pointed (re-capture). */
82
+ prdsPathSwitched: number;
83
+ /** PRDs escalated to a human for lack of a surviving path. */
84
+ prdsEscalated: number;
85
+ }
86
+ export declare function runPrdControllerTickAll(config: DaemonConfig, deps?: Partial<PrdControllerDeps>): Promise<PrdControllerTickAllResult>;
87
+ //# sourceMappingURL=prd-controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prd-controller.d.ts","sourceRoot":"","sources":["../src/prd-controller.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,319 @@
1
+ /**
2
+ * PRD-lifecycle controller (Delivery D).
3
+ *
4
+ * CARDINAL RULE: this controller adds NO new executor. Its only outputs are
5
+ * (a) materialize an overcome into a focus via the existing
6
+ * prd_overcome_materialize action, (b) arm a focus by setting
7
+ * assigned_agent_role_id via the existing focus_update action (the queue toggle
8
+ * the focus engine already polls), (c) mark obstacles cleared / the PRD done via
9
+ * the existing node/prd update actions. It never spawns agents and never creates
10
+ * a parallel execution path.
11
+ *
12
+ * It computes the Prerequisite-Tree (PRT) frontier for an active PRD and arms
13
+ * the frontier foci; on obstacle clearance it recomputes and arms the next
14
+ * frontier. The whole milestone then runs progressively over the existing
15
+ * Foci -> Delivery -> Issue executor.
16
+ */
17
+ import { configForProduct } from './config.js';
18
+ import { evaluateClearance, } from './prd-clearance-engine.js';
19
+ import { loadActivePrds, loadPrtGraph, materializeOvercome, armFocus, markNodeCleared, markPrdDone, loadPathways, commitPathway, } from './queries/prd.js';
20
+ import { fileEscalation } from './escalations.js';
21
+ import { detectDivergence, selectSurvivingPath, } from './prd-divergence.js';
22
+ /**
23
+ * Splits the armable overcome frontier into those still needing a focus
24
+ * (materialize) and those already materialized (arm).
25
+ *
26
+ * PRT frontier semantics (implemented exactly):
27
+ * - prerequisite edge P->Q means P must be cleared before Q.
28
+ * - overcome O is ARMABLE iff O.status !== 'cleared' AND every node P with a
29
+ * prerequisite edge P->O is in clearedNodeIds. No incoming prerequisite edge
30
+ * => initial frontier.
31
+ * - needsMaterialize = armable overcomes with focusId == null.
32
+ * - needsArm = armable overcomes with focusId set.
33
+ */
34
+ export function computePrtFrontier(nodes, edges, clearedNodeIds) {
35
+ const needsMaterialize = [];
36
+ const needsArm = [];
37
+ for (const node of nodes) {
38
+ if (node.nodeType !== 'overcome') {
39
+ continue;
40
+ }
41
+ if (node.status === 'cleared') {
42
+ continue;
43
+ }
44
+ const prereqs = edges.filter((edge) => edge.edgeType === 'prerequisite' && edge.toNodeId === node.id);
45
+ const allPrereqsCleared = prereqs.every((edge) => clearedNodeIds.has(edge.fromNodeId));
46
+ if (!allPrereqsCleared) {
47
+ continue;
48
+ }
49
+ if (node.focusId === null) {
50
+ needsMaterialize.push(node);
51
+ }
52
+ else {
53
+ needsArm.push(node);
54
+ }
55
+ }
56
+ return { needsMaterialize, needsArm };
57
+ }
58
+ /**
59
+ * Pure viability check for a pathway, computed from ACTUAL current tree state.
60
+ *
61
+ * A pathway is viable when every obstacle reachable on it is either already
62
+ * cleared OR still has at least one planned overcome that has NOT failed
63
+ * clearance this tick. If any gating obstacle is both uncleared and has no
64
+ * un-failed remedy, the pathway cannot reach the goal -> not viable.
65
+ *
66
+ * Pathway membership is approximated by pathwayId match on the node when the
67
+ * PrtNode carries one; absent per-node pathway tagging in the current schema,
68
+ * the whole tree is treated as the pathway's reachable set (single-pathway
69
+ * default). This stays a conservative, pure read of the tree -- it never
70
+ * mutates and never reverts.
71
+ */
72
+ function isPathwayViable(_pathwayId, nodes, edges, clearedNodeIds, clearanceFailedObstacleIds) {
73
+ void _pathwayId;
74
+ const overcomesEdges = edges.filter((e) => e.edgeType === 'overcomes');
75
+ // Obstacle -> set of overcome ids that target it.
76
+ const remediesByObstacle = new Map();
77
+ for (const edge of overcomesEdges) {
78
+ const list = remediesByObstacle.get(edge.toNodeId) ?? [];
79
+ list.push(edge.fromNodeId);
80
+ remediesByObstacle.set(edge.toNodeId, list);
81
+ }
82
+ const nodeById = new Map(nodes.map((n) => [n.id, n]));
83
+ for (const node of nodes) {
84
+ if (node.nodeType !== 'obstacle') {
85
+ continue;
86
+ }
87
+ if (clearedNodeIds.has(node.id)) {
88
+ continue; // already cleared -> not blocking
89
+ }
90
+ const remedies = remediesByObstacle.get(node.id) ?? [];
91
+ if (remedies.length === 0) {
92
+ // Open obstacle with no planned overcome -> dead end on this pathway.
93
+ return false;
94
+ }
95
+ // Viable only if at least one remedy has not failed clearance this tick.
96
+ const hasUnfailedRemedy = remedies.some((overcomeId) => {
97
+ const overcome = nodeById.get(overcomeId);
98
+ if (!overcome) {
99
+ return false;
100
+ }
101
+ // The remedy "failed" when its overcome cleared yet the obstacle is in
102
+ // the failed set (clearance_fail) -- treat that obstacle as un-remediable
103
+ // by this overcome.
104
+ return !clearanceFailedObstacleIds.has(node.id);
105
+ });
106
+ if (!hasUnfailedRemedy) {
107
+ return false;
108
+ }
109
+ }
110
+ return true;
111
+ }
112
+ export async function runPrdControllerTick(prd, deps) {
113
+ const { nodes, edges } = await deps.loadPrtGraph(prd.id);
114
+ const obstacles = nodes.filter((node) => node.nodeType === 'obstacle');
115
+ const clearedNodeIds = new Set();
116
+ // Pre-seed nodes already marked cleared in the DB.
117
+ for (const node of nodes) {
118
+ if (node.status === 'cleared') {
119
+ clearedNodeIds.add(node.id);
120
+ }
121
+ }
122
+ let obstaclesEvaluated = 0;
123
+ let obstaclesCleared = 0;
124
+ // Obstacles whose predicate ran and definitively did NOT clear (not deferred).
125
+ // Feeds divergence detection (clearance_fail) and pathway viability.
126
+ const clearanceFailedObstacleIds = new Set();
127
+ // Evaluate clearance predicates; newly-cleared obstacles get persisted.
128
+ for (const obstacle of obstacles) {
129
+ if (!obstacle.clearancePredicate) {
130
+ continue;
131
+ }
132
+ obstaclesEvaluated += 1;
133
+ const verdict = await deps.evaluateClearance(obstacle.clearancePredicate, {
134
+ worktreeDir: deps.worktreeDir,
135
+ });
136
+ if (verdict.cleared) {
137
+ clearedNodeIds.add(obstacle.id);
138
+ if (obstacle.status !== 'cleared') {
139
+ await deps.markNodeCleared(obstacle.id);
140
+ obstaclesCleared += 1;
141
+ }
142
+ }
143
+ else if (!verdict.deferred) {
144
+ clearanceFailedObstacleIds.add(obstacle.id);
145
+ }
146
+ }
147
+ const { needsMaterialize, needsArm } = computePrtFrontier(nodes, edges, clearedNodeIds);
148
+ const roleId = await deps.resolveArmRoleId(prd);
149
+ let materialized = 0;
150
+ let armed = 0;
151
+ let skippedNoRole = 0;
152
+ for (const node of needsMaterialize) {
153
+ const { focusId } = await deps.materializeOvercome(node.id);
154
+ materialized += 1;
155
+ if (roleId) {
156
+ await deps.armFocus(focusId, roleId);
157
+ armed += 1;
158
+ }
159
+ else {
160
+ skippedNoRole += 1;
161
+ }
162
+ }
163
+ for (const node of needsArm) {
164
+ if (node.focusId === null) {
165
+ continue;
166
+ }
167
+ if (roleId) {
168
+ await deps.armFocus(node.focusId, roleId);
169
+ armed += 1;
170
+ }
171
+ else {
172
+ skippedNoRole += 1;
173
+ }
174
+ }
175
+ // PRD complete when every obstacle is cleared.
176
+ const allObstaclesCleared = obstacles.length > 0 && obstacles.every((obstacle) => clearedNodeIds.has(obstacle.id));
177
+ let prdDone = false;
178
+ if (allObstaclesCleared) {
179
+ await deps.markPrdDone(prd.id);
180
+ prdDone = true;
181
+ }
182
+ // --- Realign (divergence detection + path-switch / escalate) -------------
183
+ //
184
+ // PLL re-capture. Runs only for a PRD that has a committed (locked) pathway.
185
+ // On divergence we re-acquire the best surviving path from the ACTUAL current
186
+ // tree state, or hand control to the human if none survives.
187
+ //
188
+ // NO-REVERT INVARIANT: this step performs NO revert. Dead-path residue (work
189
+ // already merged on an abandoned pathway) is new reality. We ONLY re-point
190
+ // committed_path_id via commitPathway and let the existing controller re-arm
191
+ // the frontier from the new path. Nothing here deletes focuses, commits, or
192
+ // merged work, and the goal is never lowered to fit a surviving path.
193
+ let diverged = false;
194
+ let pathSwitched = false;
195
+ let escalated = false;
196
+ if (prd.committedPathId) {
197
+ const signals = detectDivergence({
198
+ nodes,
199
+ edges,
200
+ clearedNodeIds,
201
+ clearanceFailedObstacleIds,
202
+ committedPathwayId: prd.committedPathId,
203
+ });
204
+ if (signals.length > 0) {
205
+ diverged = true;
206
+ const pathways = await deps.loadPathways(prd.id);
207
+ const pathwayStates = pathways.map((p) => ({
208
+ id: p.id,
209
+ status: p.status,
210
+ }));
211
+ const { survivor, switched } = selectSurvivingPath(pathwayStates, {
212
+ committedPathwayId: prd.committedPathId,
213
+ isPathwayViable: (pid) => isPathwayViable(pid, nodes, edges, clearedNodeIds, clearanceFailedObstacleIds),
214
+ });
215
+ if (survivor && switched) {
216
+ // Re-point the committed pathway (re-capture). No revert.
217
+ await deps.commitPathway(prd.id, survivor);
218
+ pathSwitched = true;
219
+ }
220
+ else if (!survivor) {
221
+ // No surviving path: the human owns intent -- escalate, never lower the goal.
222
+ escalated = true;
223
+ await deps.fileEscalation({
224
+ organizationId: deps.organizationId,
225
+ productId: prd.productId,
226
+ reason: 'prd_divergence_no_surviving_path',
227
+ kind: 'prd_divergence_no_surviving_path',
228
+ details: { prdId: prd.id, signals },
229
+ });
230
+ }
231
+ }
232
+ }
233
+ return {
234
+ obstaclesEvaluated,
235
+ obstaclesCleared,
236
+ materialized,
237
+ armed,
238
+ skippedNoRole,
239
+ prdDone,
240
+ diverged,
241
+ pathSwitched,
242
+ escalated,
243
+ };
244
+ }
245
+ function defaultDeps(config) {
246
+ return {
247
+ loadPrtGraph: (prdId) => loadPrtGraph(prdId),
248
+ evaluateClearance: (predicate, ctx) => evaluateClearance(predicate, ctx),
249
+ markNodeCleared: (nodeId) => markNodeCleared(nodeId),
250
+ materializeOvercome: (nodeId) => materializeOvercome(nodeId),
251
+ armFocus: (focusId, agentRoleId) => armFocus(focusId, agentRoleId),
252
+ markPrdDone: (prdId) => markPrdDone(prdId),
253
+ resolveArmRoleId: async (_prd) => {
254
+ void _prd;
255
+ // TELORA_PRD_ARM_ROLE_ID must be set to the agent_roles UUID to use when
256
+ // arming frontier foci (sets product_focuses.assigned_agent_role_id).
257
+ // When unset, every frontier overcome is counted as skippedNoRole and no
258
+ // focus is ever armed -- the controller runs but produces no output.
259
+ return process.env.TELORA_PRD_ARM_ROLE_ID ?? null;
260
+ },
261
+ loadPathways: (prdId) => loadPathways(prdId),
262
+ commitPathway: (prdId, pathwayId) => commitPathway(prdId, pathwayId),
263
+ fileEscalation: (input) => fileEscalation(input),
264
+ organizationId: config.organizationId,
265
+ worktreeDir: config.worktreeDir,
266
+ };
267
+ }
268
+ export async function runPrdControllerTickAll(config, deps) {
269
+ const totals = {
270
+ obstaclesEvaluated: 0,
271
+ obstaclesCleared: 0,
272
+ materialized: 0,
273
+ armed: 0,
274
+ skippedNoRole: 0,
275
+ prdsDone: 0,
276
+ prdsDiverged: 0,
277
+ prdsPathSwitched: 0,
278
+ prdsEscalated: 0,
279
+ };
280
+ for (const product of config.products) {
281
+ const productConfig = configForProduct(config, product);
282
+ const merged = { ...defaultDeps(productConfig), ...deps };
283
+ let prds;
284
+ try {
285
+ prds = await loadActivePrds(product.id);
286
+ }
287
+ catch (err) {
288
+ console.warn(`[prd-controller] failed to load active PRDs for product ${product.id}:`, err.message);
289
+ continue;
290
+ }
291
+ for (const prd of prds) {
292
+ try {
293
+ const result = await runPrdControllerTick(prd, merged);
294
+ totals.obstaclesEvaluated += result.obstaclesEvaluated;
295
+ totals.obstaclesCleared += result.obstaclesCleared;
296
+ totals.materialized += result.materialized;
297
+ totals.armed += result.armed;
298
+ totals.skippedNoRole += result.skippedNoRole;
299
+ if (result.prdDone) {
300
+ totals.prdsDone += 1;
301
+ }
302
+ if (result.diverged) {
303
+ totals.prdsDiverged += 1;
304
+ }
305
+ if (result.pathSwitched) {
306
+ totals.prdsPathSwitched += 1;
307
+ }
308
+ if (result.escalated) {
309
+ totals.prdsEscalated += 1;
310
+ }
311
+ }
312
+ catch (err) {
313
+ console.warn(`[prd-controller] tick failed for PRD ${prd.id}:`, err.message);
314
+ }
315
+ }
316
+ }
317
+ return totals;
318
+ }
319
+ //# sourceMappingURL=prd-controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prd-controller.js","sourceRoot":"","sources":["../src/prd-controller.ts"],"names":[],"mappings":"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"}