@telora/factory 0.4.5

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 (301) hide show
  1. package/dist/audit.d.ts +69 -0
  2. package/dist/audit.d.ts.map +1 -0
  3. package/dist/audit.js +376 -0
  4. package/dist/audit.js.map +1 -0
  5. package/dist/builder-completion.d.ts +35 -0
  6. package/dist/builder-completion.d.ts.map +1 -0
  7. package/dist/builder-completion.js +375 -0
  8. package/dist/builder-completion.js.map +1 -0
  9. package/dist/builder-spawner.d.ts +40 -0
  10. package/dist/builder-spawner.d.ts.map +1 -0
  11. package/dist/builder-spawner.js +493 -0
  12. package/dist/builder-spawner.js.map +1 -0
  13. package/dist/completion-gate.d.ts +52 -0
  14. package/dist/completion-gate.d.ts.map +1 -0
  15. package/dist/completion-gate.js +336 -0
  16. package/dist/completion-gate.js.map +1 -0
  17. package/dist/completion-report.d.ts +36 -0
  18. package/dist/completion-report.d.ts.map +1 -0
  19. package/dist/completion-report.js +348 -0
  20. package/dist/completion-report.js.map +1 -0
  21. package/dist/completion.d.ts +58 -0
  22. package/dist/completion.d.ts.map +1 -0
  23. package/dist/completion.js +287 -0
  24. package/dist/completion.js.map +1 -0
  25. package/dist/config.d.ts +16 -0
  26. package/dist/config.d.ts.map +1 -0
  27. package/dist/config.js +57 -0
  28. package/dist/config.js.map +1 -0
  29. package/dist/context-manager.d.ts +152 -0
  30. package/dist/context-manager.d.ts.map +1 -0
  31. package/dist/context-manager.js +421 -0
  32. package/dist/context-manager.js.map +1 -0
  33. package/dist/crash-detection.d.ts +70 -0
  34. package/dist/crash-detection.d.ts.map +1 -0
  35. package/dist/crash-detection.js +123 -0
  36. package/dist/crash-detection.js.map +1 -0
  37. package/dist/crash-recovery.d.ts +83 -0
  38. package/dist/crash-recovery.d.ts.map +1 -0
  39. package/dist/crash-recovery.js +522 -0
  40. package/dist/crash-recovery.js.map +1 -0
  41. package/dist/crash-resolution.d.ts +34 -0
  42. package/dist/crash-resolution.d.ts.map +1 -0
  43. package/dist/crash-resolution.js +382 -0
  44. package/dist/crash-resolution.js.map +1 -0
  45. package/dist/escalation.d.ts +150 -0
  46. package/dist/escalation.d.ts.map +1 -0
  47. package/dist/escalation.js +352 -0
  48. package/dist/escalation.js.map +1 -0
  49. package/dist/execution-target.d.ts +31 -0
  50. package/dist/execution-target.d.ts.map +1 -0
  51. package/dist/execution-target.js +71 -0
  52. package/dist/execution-target.js.map +1 -0
  53. package/dist/execution-unit-init.d.ts +28 -0
  54. package/dist/execution-unit-init.d.ts.map +1 -0
  55. package/dist/execution-unit-init.js +115 -0
  56. package/dist/execution-unit-init.js.map +1 -0
  57. package/dist/execution.d.ts +17 -0
  58. package/dist/execution.d.ts.map +1 -0
  59. package/dist/execution.js +20 -0
  60. package/dist/execution.js.map +1 -0
  61. package/dist/factory-engine.d.ts +100 -0
  62. package/dist/factory-engine.d.ts.map +1 -0
  63. package/dist/factory-engine.js +243 -0
  64. package/dist/factory-engine.js.map +1 -0
  65. package/dist/gap-detection.d.ts +43 -0
  66. package/dist/gap-detection.d.ts.map +1 -0
  67. package/dist/gap-detection.js +149 -0
  68. package/dist/gap-detection.js.map +1 -0
  69. package/dist/gate-context.d.ts +23 -0
  70. package/dist/gate-context.d.ts.map +1 -0
  71. package/dist/gate-context.js +63 -0
  72. package/dist/gate-context.js.map +1 -0
  73. package/dist/gate-engine.d.ts +55 -0
  74. package/dist/gate-engine.d.ts.map +1 -0
  75. package/dist/gate-engine.js +191 -0
  76. package/dist/gate-engine.js.map +1 -0
  77. package/dist/gates/adversarial.d.ts +59 -0
  78. package/dist/gates/adversarial.d.ts.map +1 -0
  79. package/dist/gates/adversarial.js +426 -0
  80. package/dist/gates/adversarial.js.map +1 -0
  81. package/dist/gates/adversary-spawner.d.ts +35 -0
  82. package/dist/gates/adversary-spawner.d.ts.map +1 -0
  83. package/dist/gates/adversary-spawner.js +286 -0
  84. package/dist/gates/adversary-spawner.js.map +1 -0
  85. package/dist/gates/adversary-test-dir.d.ts +41 -0
  86. package/dist/gates/adversary-test-dir.d.ts.map +1 -0
  87. package/dist/gates/adversary-test-dir.js +150 -0
  88. package/dist/gates/adversary-test-dir.js.map +1 -0
  89. package/dist/gates/behavioral-parser.d.ts +32 -0
  90. package/dist/gates/behavioral-parser.d.ts.map +1 -0
  91. package/dist/gates/behavioral-parser.js +190 -0
  92. package/dist/gates/behavioral-parser.js.map +1 -0
  93. package/dist/gates/behavioral-runner.d.ts +36 -0
  94. package/dist/gates/behavioral-runner.d.ts.map +1 -0
  95. package/dist/gates/behavioral-runner.js +306 -0
  96. package/dist/gates/behavioral-runner.js.map +1 -0
  97. package/dist/gates/behavioral.d.ts +37 -0
  98. package/dist/gates/behavioral.d.ts.map +1 -0
  99. package/dist/gates/behavioral.js +485 -0
  100. package/dist/gates/behavioral.js.map +1 -0
  101. package/dist/gates/deterministic.d.ts +24 -0
  102. package/dist/gates/deterministic.d.ts.map +1 -0
  103. package/dist/gates/deterministic.js +186 -0
  104. package/dist/gates/deterministic.js.map +1 -0
  105. package/dist/git-factory.d.ts +59 -0
  106. package/dist/git-factory.d.ts.map +1 -0
  107. package/dist/git-factory.js +102 -0
  108. package/dist/git-factory.js.map +1 -0
  109. package/dist/guard-evaluation.d.ts +48 -0
  110. package/dist/guard-evaluation.d.ts.map +1 -0
  111. package/dist/guard-evaluation.js +416 -0
  112. package/dist/guard-evaluation.js.map +1 -0
  113. package/dist/index.d.ts +30 -0
  114. package/dist/index.d.ts.map +1 -0
  115. package/dist/index.js +39 -0
  116. package/dist/index.js.map +1 -0
  117. package/dist/instance-completion.d.ts +34 -0
  118. package/dist/instance-completion.d.ts.map +1 -0
  119. package/dist/instance-completion.js +366 -0
  120. package/dist/instance-completion.js.map +1 -0
  121. package/dist/instance-lifecycle.d.ts +15 -0
  122. package/dist/instance-lifecycle.d.ts.map +1 -0
  123. package/dist/instance-lifecycle.js +18 -0
  124. package/dist/instance-lifecycle.js.map +1 -0
  125. package/dist/instance-phase-dispatch.d.ts +75 -0
  126. package/dist/instance-phase-dispatch.d.ts.map +1 -0
  127. package/dist/instance-phase-dispatch.js +674 -0
  128. package/dist/instance-phase-dispatch.js.map +1 -0
  129. package/dist/instance-poll-loop.d.ts +43 -0
  130. package/dist/instance-poll-loop.d.ts.map +1 -0
  131. package/dist/instance-poll-loop.js +360 -0
  132. package/dist/instance-poll-loop.js.map +1 -0
  133. package/dist/instance-state-machine.d.ts +52 -0
  134. package/dist/instance-state-machine.d.ts.map +1 -0
  135. package/dist/instance-state-machine.js +235 -0
  136. package/dist/instance-state-machine.js.map +1 -0
  137. package/dist/log-manager.d.ts +28 -0
  138. package/dist/log-manager.d.ts.map +1 -0
  139. package/dist/log-manager.js +71 -0
  140. package/dist/log-manager.js.map +1 -0
  141. package/dist/pipeline-evaluator.d.ts +61 -0
  142. package/dist/pipeline-evaluator.d.ts.map +1 -0
  143. package/dist/pipeline-evaluator.js +107 -0
  144. package/dist/pipeline-evaluator.js.map +1 -0
  145. package/dist/pipeline-metrics.d.ts +52 -0
  146. package/dist/pipeline-metrics.d.ts.map +1 -0
  147. package/dist/pipeline-metrics.js +40 -0
  148. package/dist/pipeline-metrics.js.map +1 -0
  149. package/dist/pipeline-traversal.d.ts +43 -0
  150. package/dist/pipeline-traversal.d.ts.map +1 -0
  151. package/dist/pipeline-traversal.js +68 -0
  152. package/dist/pipeline-traversal.js.map +1 -0
  153. package/dist/plan-parser.d.ts +76 -0
  154. package/dist/plan-parser.d.ts.map +1 -0
  155. package/dist/plan-parser.js +223 -0
  156. package/dist/plan-parser.js.map +1 -0
  157. package/dist/planning-phase.d.ts +52 -0
  158. package/dist/planning-phase.d.ts.map +1 -0
  159. package/dist/planning-phase.js +444 -0
  160. package/dist/planning-phase.js.map +1 -0
  161. package/dist/planning-prompt.d.ts +64 -0
  162. package/dist/planning-prompt.d.ts.map +1 -0
  163. package/dist/planning-prompt.js +251 -0
  164. package/dist/planning-prompt.js.map +1 -0
  165. package/dist/planning.d.ts +16 -0
  166. package/dist/planning.d.ts.map +1 -0
  167. package/dist/planning.js +17 -0
  168. package/dist/planning.js.map +1 -0
  169. package/dist/process-runner.d.ts +41 -0
  170. package/dist/process-runner.d.ts.map +1 -0
  171. package/dist/process-runner.js +81 -0
  172. package/dist/process-runner.js.map +1 -0
  173. package/dist/product-config.d.ts +34 -0
  174. package/dist/product-config.d.ts.map +1 -0
  175. package/dist/product-config.js +43 -0
  176. package/dist/product-config.js.map +1 -0
  177. package/dist/queries/cycle-evaluations.d.ts +23 -0
  178. package/dist/queries/cycle-evaluations.d.ts.map +1 -0
  179. package/dist/queries/cycle-evaluations.js +37 -0
  180. package/dist/queries/cycle-evaluations.js.map +1 -0
  181. package/dist/queries/escalations.d.ts +30 -0
  182. package/dist/queries/escalations.d.ts.map +1 -0
  183. package/dist/queries/escalations.js +42 -0
  184. package/dist/queries/escalations.js.map +1 -0
  185. package/dist/queries/execution-units.d.ts +76 -0
  186. package/dist/queries/execution-units.d.ts.map +1 -0
  187. package/dist/queries/execution-units.js +109 -0
  188. package/dist/queries/execution-units.js.map +1 -0
  189. package/dist/queries/gate-results.d.ts +32 -0
  190. package/dist/queries/gate-results.d.ts.map +1 -0
  191. package/dist/queries/gate-results.js +44 -0
  192. package/dist/queries/gate-results.js.map +1 -0
  193. package/dist/queries/instances.d.ts +51 -0
  194. package/dist/queries/instances.d.ts.map +1 -0
  195. package/dist/queries/instances.js +77 -0
  196. package/dist/queries/instances.js.map +1 -0
  197. package/dist/queries/sessions.d.ts +50 -0
  198. package/dist/queries/sessions.d.ts.map +1 -0
  199. package/dist/queries/sessions.js +81 -0
  200. package/dist/queries/sessions.js.map +1 -0
  201. package/dist/queries/shared.d.ts +38 -0
  202. package/dist/queries/shared.d.ts.map +1 -0
  203. package/dist/queries/shared.js +119 -0
  204. package/dist/queries/shared.js.map +1 -0
  205. package/dist/queries/specs.d.ts +12 -0
  206. package/dist/queries/specs.d.ts.map +1 -0
  207. package/dist/queries/specs.js +21 -0
  208. package/dist/queries/specs.js.map +1 -0
  209. package/dist/queries/strategies.d.ts +14 -0
  210. package/dist/queries/strategies.d.ts.map +1 -0
  211. package/dist/queries/strategies.js +18 -0
  212. package/dist/queries/strategies.js.map +1 -0
  213. package/dist/queries/work-units.d.ts +42 -0
  214. package/dist/queries/work-units.d.ts.map +1 -0
  215. package/dist/queries/work-units.js +57 -0
  216. package/dist/queries/work-units.js.map +1 -0
  217. package/dist/queries/workflows.d.ts +29 -0
  218. package/dist/queries/workflows.d.ts.map +1 -0
  219. package/dist/queries/workflows.js +103 -0
  220. package/dist/queries/workflows.js.map +1 -0
  221. package/dist/remediation-units.d.ts +40 -0
  222. package/dist/remediation-units.d.ts.map +1 -0
  223. package/dist/remediation-units.js +263 -0
  224. package/dist/remediation-units.js.map +1 -0
  225. package/dist/replanning.d.ts +72 -0
  226. package/dist/replanning.d.ts.map +1 -0
  227. package/dist/replanning.js +403 -0
  228. package/dist/replanning.js.map +1 -0
  229. package/dist/resource-limits.d.ts +62 -0
  230. package/dist/resource-limits.d.ts.map +1 -0
  231. package/dist/resource-limits.js +322 -0
  232. package/dist/resource-limits.js.map +1 -0
  233. package/dist/scheduler.d.ts +98 -0
  234. package/dist/scheduler.d.ts.map +1 -0
  235. package/dist/scheduler.js +203 -0
  236. package/dist/scheduler.js.map +1 -0
  237. package/dist/session-adapter.d.ts +89 -0
  238. package/dist/session-adapter.d.ts.map +1 -0
  239. package/dist/session-adapter.js +108 -0
  240. package/dist/session-adapter.js.map +1 -0
  241. package/dist/sop-generator.d.ts +29 -0
  242. package/dist/sop-generator.d.ts.map +1 -0
  243. package/dist/sop-generator.js +235 -0
  244. package/dist/sop-generator.js.map +1 -0
  245. package/dist/spec-profiles.d.ts +41 -0
  246. package/dist/spec-profiles.d.ts.map +1 -0
  247. package/dist/spec-profiles.js +131 -0
  248. package/dist/spec-profiles.js.map +1 -0
  249. package/dist/strategy-design-graph.d.ts +23 -0
  250. package/dist/strategy-design-graph.d.ts.map +1 -0
  251. package/dist/strategy-design-graph.js +205 -0
  252. package/dist/strategy-design-graph.js.map +1 -0
  253. package/dist/strategy-design-prompt.d.ts +28 -0
  254. package/dist/strategy-design-prompt.d.ts.map +1 -0
  255. package/dist/strategy-design-prompt.js +108 -0
  256. package/dist/strategy-design-prompt.js.map +1 -0
  257. package/dist/strategy-design-schema.d.ts +767 -0
  258. package/dist/strategy-design-schema.d.ts.map +1 -0
  259. package/dist/strategy-design-schema.js +126 -0
  260. package/dist/strategy-design-schema.js.map +1 -0
  261. package/dist/strategy-design.d.ts +69 -0
  262. package/dist/strategy-design.d.ts.map +1 -0
  263. package/dist/strategy-design.js +411 -0
  264. package/dist/strategy-design.js.map +1 -0
  265. package/dist/strategy-gating.d.ts +31 -0
  266. package/dist/strategy-gating.d.ts.map +1 -0
  267. package/dist/strategy-gating.js +276 -0
  268. package/dist/strategy-gating.js.map +1 -0
  269. package/dist/team-prompt-builder.d.ts +47 -0
  270. package/dist/team-prompt-builder.d.ts.map +1 -0
  271. package/dist/team-prompt-builder.js +362 -0
  272. package/dist/team-prompt-builder.js.map +1 -0
  273. package/dist/trace-engine.d.ts +40 -0
  274. package/dist/trace-engine.d.ts.map +1 -0
  275. package/dist/trace-engine.js +344 -0
  276. package/dist/trace-engine.js.map +1 -0
  277. package/dist/types.d.ts +612 -0
  278. package/dist/types.d.ts.map +1 -0
  279. package/dist/types.js +9 -0
  280. package/dist/types.js.map +1 -0
  281. package/dist/unit-session-lifecycle.d.ts +78 -0
  282. package/dist/unit-session-lifecycle.d.ts.map +1 -0
  283. package/dist/unit-session-lifecycle.js +141 -0
  284. package/dist/unit-session-lifecycle.js.map +1 -0
  285. package/dist/unit-session.d.ts +30 -0
  286. package/dist/unit-session.d.ts.map +1 -0
  287. package/dist/unit-session.js +370 -0
  288. package/dist/unit-session.js.map +1 -0
  289. package/dist/watchdogs.d.ts +33 -0
  290. package/dist/watchdogs.d.ts.map +1 -0
  291. package/dist/watchdogs.js +170 -0
  292. package/dist/watchdogs.js.map +1 -0
  293. package/dist/work-unit-scheduler.d.ts +34 -0
  294. package/dist/work-unit-scheduler.d.ts.map +1 -0
  295. package/dist/work-unit-scheduler.js +91 -0
  296. package/dist/work-unit-scheduler.js.map +1 -0
  297. package/dist/workflow-transition.d.ts +90 -0
  298. package/dist/workflow-transition.d.ts.map +1 -0
  299. package/dist/workflow-transition.js +340 -0
  300. package/dist/workflow-transition.js.map +1 -0
  301. package/package.json +65 -0
@@ -0,0 +1,235 @@
1
+ /**
2
+ * Factory instance state machine -- workflow-governed status transitions,
3
+ * error handling, pause timeout enforcement, and resume recovery.
4
+ *
5
+ * This module is a leaf in the dependency graph: it does not import from
6
+ * the sibling instance-* modules, so it cannot create circular imports.
7
+ */
8
+ import { getInstanceBlueprint, getInstanceStatus, updateInstanceStatus, updateInstanceWorkflowStage } from './queries/instances.js';
9
+ import { updateStrategyExecutionStatus } from './queries/strategies.js';
10
+ import { getInstanceWorkUnits, updateWorkUnitStatus } from './queries/work-units.js';
11
+ import { restoreExecutionUnits } from './execution-unit-init.js';
12
+ import { cleanupAdversaryTestDir } from './gates/adversarial.js';
13
+ import { attemptTransition, getOrResolveWorkflow } from './workflow-transition.js';
14
+ // ============================================================================
15
+ // Workflow-governed instance status transitions
16
+ // ============================================================================
17
+ /**
18
+ * Build a minimal EvaluationContext from the current instance state.
19
+ * Used for guard condition evaluation during workflow transitions.
20
+ */
21
+ export function buildInstanceEvalContext(state) {
22
+ if (!state) {
23
+ return {
24
+ deliveryId: '',
25
+ openIssueCount: 0,
26
+ totalIssueCount: 0,
27
+ issuesByStatus: {},
28
+ issuesByPriority: {},
29
+ lastExitCode: 0,
30
+ sessionCount: 0,
31
+ };
32
+ }
33
+ const elapsedSeconds = Math.floor((Date.now() - state.startedAt.getTime()) / 1000);
34
+ return {
35
+ deliveryId: '',
36
+ openIssueCount: 0,
37
+ totalIssueCount: 0,
38
+ issuesByStatus: {},
39
+ issuesByPriority: {},
40
+ lastExitCode: 0,
41
+ sessionCount: state.activeBuilderSessions.size,
42
+ tokensUsed: state.tokensUsed,
43
+ tokenBudget: state.blueprint.maxTokenBudget,
44
+ cycleCount: state.completionGateIterations,
45
+ wallClockSeconds: elapsedSeconds,
46
+ wallClockLimitSeconds: state.blueprint.maxWallClockHours
47
+ ? state.blueprint.maxWallClockHours * 3600
48
+ : null,
49
+ };
50
+ }
51
+ /**
52
+ * Transition a factory instance through the workflow state machine.
53
+ *
54
+ * Attempts a workflow-governed transition from the current status to the
55
+ * target status. If the workflow allows the transition (or no workflow
56
+ * exists), updates both the in-memory state and the database.
57
+ *
58
+ * @param state The in-memory instance state
59
+ * @param targetStatus The target instance status
60
+ * @param reason Optional reason (used for failed/completed messages)
61
+ */
62
+ export async function transitionInstanceStatus(state, targetStatus, reason) {
63
+ const currentStatus = state.status;
64
+ // Attempt workflow transition
65
+ const ctx = buildInstanceEvalContext(state);
66
+ const transResult = await attemptTransition(state.workflow, currentStatus, targetStatus, state.productId, // organizationId placeholder -- factory uses productId for scoping
67
+ 'factory_instance', state.instanceId, ctx);
68
+ if (!transResult.allowed) {
69
+ console.log(`[factory] Instance ${state.instanceId} transition ${currentStatus} -> ${targetStatus} ` +
70
+ `blocked by workflow guards`);
71
+ return;
72
+ }
73
+ // Update in-memory state
74
+ state.status = targetStatus;
75
+ if (transResult.newStageId) {
76
+ state.currentWorkflowStageId = transResult.newStageId;
77
+ }
78
+ // Build DB update fields
79
+ const fields = {};
80
+ if (transResult.newStageId) {
81
+ await updateInstanceWorkflowStage(state.instanceId, transResult.newStageId, targetStatus);
82
+ }
83
+ if (reason && (targetStatus === 'failed' || targetStatus === 'completed')) {
84
+ fields.completionMessage = reason;
85
+ fields.completedAt = new Date().toISOString();
86
+ }
87
+ // Only call updateInstanceStatus if we have extra fields to set
88
+ // (workflow stage is already updated above)
89
+ if (Object.keys(fields).length > 0 || !transResult.newStageId) {
90
+ await updateInstanceStatus(state.instanceId, targetStatus, fields);
91
+ }
92
+ // Clean up external adversary test directory at terminal states
93
+ if ((targetStatus === 'completed' || targetStatus === 'failed') && state.worktreePath) {
94
+ cleanupAdversaryTestDir(state.worktreePath);
95
+ }
96
+ // Leave in the map -- monitorActiveInstances will clean it up on the next poll
97
+ if (targetStatus === 'failed') {
98
+ console.error(`[factory] Instance ${state.instanceId} failed: ${reason ?? 'unknown'}`);
99
+ }
100
+ }
101
+ // ============================================================================
102
+ // Error handling
103
+ // ============================================================================
104
+ /**
105
+ * Transition an instance to "failed" and remove it from active tracking.
106
+ */
107
+ export function handleInstanceFailure(state, reason) {
108
+ transitionInstanceStatus(state, 'failed', reason).catch((error) => {
109
+ console.error(`[factory] Failed to persist failure status for instance ${state.instanceId}:`, error.message);
110
+ });
111
+ }
112
+ // ============================================================================
113
+ // Pause timeout enforcement
114
+ // ============================================================================
115
+ /**
116
+ * Recover execution state when a paused instance is resumed.
117
+ *
118
+ * When a factory instance is paused (e.g., resource limit hit), its sessions
119
+ * are terminated but work units and strategies remain in their mid-flight states
120
+ * (in_progress). The scheduler only picks up 'pending' strategies, so without
121
+ * this recovery the instance is deadlocked after resume.
122
+ *
123
+ * Mirrors the orphan-reset logic in adoptActiveInstance but runs live (no
124
+ * daemon restart required).
125
+ */
126
+ export async function recoverResumedInstance(state) {
127
+ console.log(`[factory] Resume recovery: restoring execution state for instance ${state.instanceId}`);
128
+ // 1. Restore execution units from DB (handles the case where the daemon
129
+ // restarted while the instance was paused and state.executionUnits is empty).
130
+ try {
131
+ await restoreExecutionUnits(state);
132
+ }
133
+ catch (err) {
134
+ console.error(`[factory] Resume recovery: failed to restore execution units:`, err.message);
135
+ }
136
+ // 2. Reset in_progress work units back to ready so the scheduler can
137
+ // re-dispatch them to a fresh session.
138
+ try {
139
+ const workUnits = await getInstanceWorkUnits(state.instanceId);
140
+ // Only reset agent-owned work units; infrastructure-owned units are
141
+ // managed by the engine and should not be re-dispatched to agents.
142
+ const orphaned = workUnits.filter((wu) => wu.status === 'in_progress' && !wu.infrastructureOwned);
143
+ for (const wu of orphaned) {
144
+ await updateWorkUnitStatus(wu.id, 'ready');
145
+ console.log(`[factory] Resume recovery: reset work unit ${wu.id} (${wu.title}) in_progress -> ready`);
146
+ }
147
+ if (orphaned.length > 0) {
148
+ console.log(`[factory] Resume recovery: reset ${orphaned.length} work unit(s) to ready`);
149
+ }
150
+ }
151
+ catch (err) {
152
+ console.error(`[factory] Resume recovery: failed to reset work units:`, err.message);
153
+ }
154
+ // 3. Reset in_progress / gate_fix_pending strategies back to pending so the
155
+ // scheduler is eligible to assign execution units to them again.
156
+ try {
157
+ const { getStrategiesByFactoryInstance } = await import('./strategy-design.js');
158
+ const strategies = await getStrategiesByFactoryInstance(state.instanceId);
159
+ let resetCount = 0;
160
+ for (const strategy of strategies) {
161
+ if (strategy.executionStatus === 'in_progress' || strategy.executionStatus === 'gate_fix_pending') {
162
+ await updateStrategyExecutionStatus(strategy.id, 'pending');
163
+ resetCount++;
164
+ console.log(`[factory] Resume recovery: reset strategy "${strategy.name}" ` +
165
+ `${strategy.executionStatus} -> pending`);
166
+ }
167
+ }
168
+ if (resetCount > 0) {
169
+ console.log(`[factory] Resume recovery: reset ${resetCount} strategy/strategies to pending`);
170
+ }
171
+ }
172
+ catch (err) {
173
+ console.error(`[factory] Resume recovery: failed to reset strategies:`, err.message);
174
+ }
175
+ }
176
+ /**
177
+ * Check whether a paused instance has exceeded its pause timeout.
178
+ *
179
+ * If `blueprint.pauseTimeoutHours` is set and the instance has been paused
180
+ * longer than that, auto-fail it. This prevents paused instances from sitting
181
+ * indefinitely when humans forget about them.
182
+ */
183
+ export async function checkPauseTimeout(state) {
184
+ // Re-read status from DB to detect UI-driven resume
185
+ try {
186
+ const dbStatus = await getInstanceStatus(state.instanceId);
187
+ if (dbStatus !== 'paused') {
188
+ console.log(`[factory] Instance ${state.instanceId} status changed in DB: paused -> ${dbStatus}`);
189
+ state.status = dbStatus;
190
+ state.escalatedAt = null;
191
+ // If resumed to building, refresh blueprint (user may have updated limits)
192
+ // and restore execution state so the scheduler can continue.
193
+ if (dbStatus === 'building') {
194
+ try {
195
+ const { blueprint: freshBlueprint } = await getInstanceBlueprint(state.instanceId);
196
+ state.blueprint = freshBlueprint;
197
+ console.log(`[factory] Instance ${state.instanceId} blueprint refreshed on resume ` +
198
+ `(maxWorkUnits: ${freshBlueprint.maxWorkUnits})`);
199
+ }
200
+ catch (bpErr) {
201
+ console.error(`[factory] Failed to refresh blueprint on resume for instance ${state.instanceId}:`, bpErr.message);
202
+ }
203
+ await recoverResumedInstance(state);
204
+ }
205
+ // Next poll cycle will handle the instance in its new status
206
+ return;
207
+ }
208
+ }
209
+ catch (error) {
210
+ console.error(`[factory] Failed to re-read status for paused instance ${state.instanceId}:`, error.message);
211
+ }
212
+ const { pauseTimeoutHours } = state.blueprint;
213
+ // No timeout configured -- paused instances sit indefinitely (legacy behavior)
214
+ if (pauseTimeoutHours === null) {
215
+ return;
216
+ }
217
+ // Need escalatedAt to know when the pause started
218
+ if (!state.escalatedAt) {
219
+ return;
220
+ }
221
+ const escalatedAtMs = new Date(state.escalatedAt).getTime();
222
+ const elapsedHours = (Date.now() - escalatedAtMs) / (1000 * 60 * 60);
223
+ if (elapsedHours > pauseTimeoutHours) {
224
+ const reason = `Paused instance timed out after ${elapsedHours.toFixed(1)} hours ` +
225
+ `(pause timeout: ${pauseTimeoutHours} hours). ` +
226
+ `The escalation was not resolved in time.`;
227
+ console.log(`[factory] Instance ${state.instanceId} pause timeout exceeded: ` +
228
+ `${elapsedHours.toFixed(1)}h > ${pauseTimeoutHours}h -- auto-failing`);
229
+ handleInstanceFailure(state, reason);
230
+ }
231
+ }
232
+ // Re-export getOrResolveWorkflow so transitionToPending can use it without
233
+ // importing workflow-transition directly (keeps the dependency direction clean).
234
+ export { getOrResolveWorkflow };
235
+ //# sourceMappingURL=instance-state-machine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instance-state-machine.js","sourceRoot":"","sources":["../src/instance-state-machine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Factory-specific log manager -- thin wrapper around @telora/daemon-core.
3
+ *
4
+ * Re-exports the shared types and provides a factory-specific pruneFactoryLogs
5
+ * overload that accepts FactoryConfig (which has logDir but not the retention
6
+ * thresholds). Defaults match the daemon's defaults (7 days, 1 GB, 500 files).
7
+ */
8
+ import { type LogManagerDeps, type PruneResult } from '@telora/daemon-core';
9
+ import type { FactoryConfig } from './types.js';
10
+ export type { LogManagerDeps, LogRetentionConfig, PruneResult } from '@telora/daemon-core';
11
+ /**
12
+ * Create LogManagerDeps that preserve logs for escalated factory instances.
13
+ *
14
+ * Bridges factory instance IDs (from active escalations) to log session keys
15
+ * by scanning the log directory and matching session keys whose prefix contains
16
+ * the escalated instance ID (first 8 chars, matching the log filename pattern
17
+ * `factory-{instanceId:8}-wu-{workUnitId:8}-{timestamp}`).
18
+ */
19
+ export declare function createFactoryLogManagerDeps(config: FactoryConfig): LogManagerDeps;
20
+ /**
21
+ * Prune old factory log files using factory configuration.
22
+ *
23
+ * Applies the same retention algorithm as the daemon: age-based, then
24
+ * file-count, then total-size pruning -- with escalation-aware preservation
25
+ * when deps.getActiveEscalationSessionIds is provided.
26
+ */
27
+ export declare function pruneFactoryLogs(config: FactoryConfig, deps?: LogManagerDeps): Promise<PruneResult>;
28
+ //# sourceMappingURL=log-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-manager.d.ts","sourceRoot":"","sources":["../src/log-manager.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAGL,KAAK,cAAc,EAEnB,KAAK,WAAW,EACjB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAGhD,YAAY,EAAE,cAAc,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAyB3F;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,aAAa,GAAG,cAAc,CA2BjF;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,aAAa,EACrB,IAAI,CAAC,EAAE,cAAc,GACpB,OAAO,CAAC,WAAW,CAAC,CAEtB"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Factory-specific log manager -- thin wrapper around @telora/daemon-core.
3
+ *
4
+ * Re-exports the shared types and provides a factory-specific pruneFactoryLogs
5
+ * overload that accepts FactoryConfig (which has logDir but not the retention
6
+ * thresholds). Defaults match the daemon's defaults (7 days, 1 GB, 500 files).
7
+ */
8
+ import { pruneOldLogs as corePruneOldLogs, scanLogDirectory, } from '@telora/daemon-core';
9
+ import { getActiveEscalationInstanceIds } from './queries/escalations.js';
10
+ // ---------------------------------------------------------------------------
11
+ // Default retention thresholds (match daemon defaults)
12
+ // ---------------------------------------------------------------------------
13
+ const DEFAULT_LOG_MAX_AGE_DAYS = 7;
14
+ const DEFAULT_LOG_MAX_TOTAL_BYTES = 1_073_741_824; // 1 GB
15
+ const DEFAULT_LOG_MAX_FILES = 500;
16
+ /**
17
+ * Build a LogRetentionConfig from FactoryConfig with sensible defaults.
18
+ *
19
+ * FactoryConfig provides logDir; retention thresholds use daemon-equivalent
20
+ * defaults since BaseConfig does not include them.
21
+ */
22
+ function buildRetentionConfig(config) {
23
+ return {
24
+ logDir: config.logDir,
25
+ logMaxAgeDays: DEFAULT_LOG_MAX_AGE_DAYS,
26
+ logMaxTotalBytes: DEFAULT_LOG_MAX_TOTAL_BYTES,
27
+ logMaxFiles: DEFAULT_LOG_MAX_FILES,
28
+ };
29
+ }
30
+ /**
31
+ * Create LogManagerDeps that preserve logs for escalated factory instances.
32
+ *
33
+ * Bridges factory instance IDs (from active escalations) to log session keys
34
+ * by scanning the log directory and matching session keys whose prefix contains
35
+ * the escalated instance ID (first 8 chars, matching the log filename pattern
36
+ * `factory-{instanceId:8}-wu-{workUnitId:8}-{timestamp}`).
37
+ */
38
+ export function createFactoryLogManagerDeps(config) {
39
+ return {
40
+ getActiveEscalationSessionIds: async () => {
41
+ const instanceIds = await getActiveEscalationInstanceIds();
42
+ if (instanceIds.length === 0)
43
+ return new Set();
44
+ // Build set of instance ID prefixes for matching (first 8 chars)
45
+ const prefixes = new Set(instanceIds.map((id) => `factory-${id.slice(0, 8)}`));
46
+ // Scan log directory and collect session keys that match any prefix
47
+ const logFiles = scanLogDirectory(config.logDir);
48
+ const preserved = new Set();
49
+ for (const file of logFiles) {
50
+ for (const prefix of prefixes) {
51
+ if (file.sessionKey.startsWith(prefix)) {
52
+ preserved.add(file.sessionKey);
53
+ break;
54
+ }
55
+ }
56
+ }
57
+ return preserved;
58
+ },
59
+ };
60
+ }
61
+ /**
62
+ * Prune old factory log files using factory configuration.
63
+ *
64
+ * Applies the same retention algorithm as the daemon: age-based, then
65
+ * file-count, then total-size pruning -- with escalation-aware preservation
66
+ * when deps.getActiveEscalationSessionIds is provided.
67
+ */
68
+ export async function pruneFactoryLogs(config, deps) {
69
+ return corePruneOldLogs(buildRetentionConfig(config), deps);
70
+ }
71
+ //# sourceMappingURL=log-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-manager.js","sourceRoot":"","sources":["../src/log-manager.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,YAAY,IAAI,gBAAgB,EAChC,gBAAgB,GAIjB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,8BAA8B,EAAE,MAAM,0BAA0B,CAAC;AAI1E,8EAA8E;AAC9E,uDAAuD;AACvD,8EAA8E;AAE9E,MAAM,wBAAwB,GAAG,CAAC,CAAC;AACnC,MAAM,2BAA2B,GAAG,aAAa,CAAC,CAAC,OAAO;AAC1D,MAAM,qBAAqB,GAAG,GAAG,CAAC;AAElC;;;;;GAKG;AACH,SAAS,oBAAoB,CAAC,MAAqB;IACjD,OAAO;QACL,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,aAAa,EAAE,wBAAwB;QACvC,gBAAgB,EAAE,2BAA2B;QAC7C,WAAW,EAAE,qBAAqB;KACnC,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,2BAA2B,CAAC,MAAqB;IAC/D,OAAO;QACL,6BAA6B,EAAE,KAAK,IAA0B,EAAE;YAC9D,MAAM,WAAW,GAAG,MAAM,8BAA8B,EAAE,CAAC;YAC3D,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,IAAI,GAAG,EAAE,CAAC;YAE/C,iEAAiE;YACjE,MAAM,QAAQ,GAAG,IAAI,GAAG,CACtB,WAAW,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CACrD,CAAC;YAEF,oEAAoE;YACpE,MAAM,QAAQ,GAAG,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACjD,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;YAEpC,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;gBAC5B,KAAK,MAAM,MAAM,IAAI,QAAQ,EAAE,CAAC;oBAC9B,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;wBACvC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;wBAC/B,MAAM;oBACR,CAAC;gBACH,CAAC;YACH,CAAC;YAED,OAAO,SAAS,CAAC;QACnB,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,MAAqB,EACrB,IAAqB;IAErB,OAAO,gBAAgB,CAAC,oBAAoB,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC;AAC9D,CAAC"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Pipeline Condition Evaluator
3
+ *
4
+ * Evaluates edge conditions against execution metrics to determine
5
+ * which pipeline node to advance to next.
6
+ */
7
+ import type { PipelineExecutionMetrics } from './pipeline-metrics.js';
8
+ /** A single condition from JSONB (matches the existing EdgeCondition type). */
9
+ interface SingleDbCondition {
10
+ field: string;
11
+ operator: string;
12
+ value: string | number | boolean;
13
+ }
14
+ /** A compound condition from JSONB (AND/OR combinator). */
15
+ interface CompoundDbCondition {
16
+ combinator: 'AND' | 'OR';
17
+ conditions: SingleDbCondition[];
18
+ }
19
+ /** Edge condition as stored in JSONB (can be either format). */
20
+ type DbEdgeCondition = SingleDbCondition | CompoundDbCondition;
21
+ /** An edge from the pipeline graph. */
22
+ interface PipelineEdgeForEval {
23
+ id: string;
24
+ from: string;
25
+ to: string;
26
+ condition?: DbEdgeCondition | null;
27
+ }
28
+ /**
29
+ * Evaluate an edge condition against execution metrics.
30
+ *
31
+ * @param condition - The edge condition (null means unconditional = always true)
32
+ * @param metrics - Current execution metrics
33
+ * @returns true if the condition is satisfied
34
+ */
35
+ export declare function evaluateCondition(condition: DbEdgeCondition | null | undefined, metrics: PipelineExecutionMetrics): boolean;
36
+ /**
37
+ * Find the next pipeline node to advance to.
38
+ *
39
+ * Evaluates all outgoing edges from the current node in order.
40
+ * Returns the target node ID of the first edge whose condition is satisfied,
41
+ * or null if no edge matches (triggers escalation).
42
+ *
43
+ * @param currentNodeId - The current pipeline node ID
44
+ * @param edges - All edges in the pipeline graph
45
+ * @param metrics - Current execution metrics
46
+ * @returns The target node ID, or null if no match
47
+ */
48
+ export declare function findNextNode(currentNodeId: string, edges: PipelineEdgeForEval[], metrics: PipelineExecutionMetrics): string | null;
49
+ /**
50
+ * Check if a node is a terminal node (has no outgoing edges).
51
+ */
52
+ export declare function isTerminalNode(nodeId: string, edges: PipelineEdgeForEval[]): boolean;
53
+ /**
54
+ * Find the entry node of a pipeline (the node with no incoming edges).
55
+ * Returns the first such node found, or null if none exists.
56
+ */
57
+ export declare function findEntryNode(nodes: Array<{
58
+ id: string;
59
+ }>, edges: PipelineEdgeForEval[]): string | null;
60
+ export {};
61
+ //# sourceMappingURL=pipeline-evaluator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline-evaluator.d.ts","sourceRoot":"","sources":["../src/pipeline-evaluator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAEtE,+EAA+E;AAC/E,UAAU,iBAAiB;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;CAClC;AAED,2DAA2D;AAC3D,UAAU,mBAAmB;IAC3B,UAAU,EAAE,KAAK,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,iBAAiB,EAAE,CAAC;CACjC;AAED,gEAAgE;AAChE,KAAK,eAAe,GAAG,iBAAiB,GAAG,mBAAmB,CAAC;AAE/D,uCAAuC;AACvC,UAAU,mBAAmB;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;CACpC;AA6CD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,eAAe,GAAG,IAAI,GAAG,SAAS,EAC7C,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAeT;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAC1B,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,mBAAmB,EAAE,EAC5B,OAAO,EAAE,wBAAwB,GAChC,MAAM,GAAG,IAAI,CAiBf;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,mBAAmB,EAAE,GAC3B,OAAO,CAET;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC,EAC5B,KAAK,EAAE,mBAAmB,EAAE,GAC3B,MAAM,GAAG,IAAI,CAIf"}
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Pipeline Condition Evaluator
3
+ *
4
+ * Evaluates edge conditions against execution metrics to determine
5
+ * which pipeline node to advance to next.
6
+ */
7
+ /**
8
+ * Check if a raw condition object is a compound condition.
9
+ */
10
+ function isCompoundCondition(condition) {
11
+ return (typeof condition === 'object' &&
12
+ condition !== null &&
13
+ 'combinator' in condition &&
14
+ Array.isArray(condition.conditions));
15
+ }
16
+ /**
17
+ * Evaluate a single condition against metrics.
18
+ */
19
+ function evaluateSingleCondition(condition, metrics) {
20
+ const metricValue = metrics[condition.field];
21
+ if (metricValue === undefined)
22
+ return false;
23
+ const actual = metricValue;
24
+ const expected = condition.value;
25
+ switch (condition.operator) {
26
+ case 'eq':
27
+ return actual === expected;
28
+ case 'neq':
29
+ return actual !== expected;
30
+ case 'gt':
31
+ return actual > expected;
32
+ case 'gte':
33
+ return actual >= expected;
34
+ case 'lt':
35
+ return actual < expected;
36
+ case 'lte':
37
+ return actual <= expected;
38
+ default:
39
+ return false;
40
+ }
41
+ }
42
+ /**
43
+ * Evaluate an edge condition against execution metrics.
44
+ *
45
+ * @param condition - The edge condition (null means unconditional = always true)
46
+ * @param metrics - Current execution metrics
47
+ * @returns true if the condition is satisfied
48
+ */
49
+ export function evaluateCondition(condition, metrics) {
50
+ // Null/undefined = unconditional (always true)
51
+ if (!condition)
52
+ return true;
53
+ // Compound condition
54
+ if (isCompoundCondition(condition)) {
55
+ if (condition.combinator === 'AND') {
56
+ return condition.conditions.every((c) => evaluateSingleCondition(c, metrics));
57
+ }
58
+ // OR
59
+ return condition.conditions.some((c) => evaluateSingleCondition(c, metrics));
60
+ }
61
+ // Single condition
62
+ return evaluateSingleCondition(condition, metrics);
63
+ }
64
+ /**
65
+ * Find the next pipeline node to advance to.
66
+ *
67
+ * Evaluates all outgoing edges from the current node in order.
68
+ * Returns the target node ID of the first edge whose condition is satisfied,
69
+ * or null if no edge matches (triggers escalation).
70
+ *
71
+ * @param currentNodeId - The current pipeline node ID
72
+ * @param edges - All edges in the pipeline graph
73
+ * @param metrics - Current execution metrics
74
+ * @returns The target node ID, or null if no match
75
+ */
76
+ export function findNextNode(currentNodeId, edges, metrics) {
77
+ // Get outgoing edges from current node
78
+ const outgoing = edges.filter((e) => e.from === currentNodeId);
79
+ // No outgoing edges = terminal node
80
+ if (outgoing.length === 0)
81
+ return null;
82
+ // Evaluate edges in order, return first match
83
+ for (const edge of outgoing) {
84
+ if (evaluateCondition(edge.condition, metrics)) {
85
+ return edge.to;
86
+ }
87
+ }
88
+ // No edge matched - this is the "escalation" case
89
+ // Return null to signal that no valid transition was found
90
+ return null;
91
+ }
92
+ /**
93
+ * Check if a node is a terminal node (has no outgoing edges).
94
+ */
95
+ export function isTerminalNode(nodeId, edges) {
96
+ return !edges.some((e) => e.from === nodeId);
97
+ }
98
+ /**
99
+ * Find the entry node of a pipeline (the node with no incoming edges).
100
+ * Returns the first such node found, or null if none exists.
101
+ */
102
+ export function findEntryNode(nodes, edges) {
103
+ const nodesWithIncoming = new Set(edges.map((e) => e.to));
104
+ const entryNode = nodes.find((n) => !nodesWithIncoming.has(n.id));
105
+ return entryNode?.id ?? null;
106
+ }
107
+ //# sourceMappingURL=pipeline-evaluator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline-evaluator.js","sourceRoot":"","sources":["../src/pipeline-evaluator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA4BH;;GAEG;AACH,SAAS,mBAAmB,CAAC,SAAkB;IAC7C,OAAO,CACL,OAAO,SAAS,KAAK,QAAQ;QAC7B,SAAS,KAAK,IAAI;QAClB,YAAY,IAAI,SAAS;QACzB,KAAK,CAAC,OAAO,CAAE,SAAqC,CAAC,UAAU,CAAC,CACjE,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,uBAAuB,CAC9B,SAA4B,EAC5B,OAAiC;IAEjC,MAAM,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC,KAAuC,CAAC,CAAC;IAC/E,IAAI,WAAW,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IAE5C,MAAM,MAAM,GAAG,WAAW,CAAC;IAC3B,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC;IAEjC,QAAQ,SAAS,CAAC,QAAQ,EAAE,CAAC;QAC3B,KAAK,IAAI;YACP,OAAO,MAAM,KAAK,QAAQ,CAAC;QAC7B,KAAK,KAAK;YACR,OAAO,MAAM,KAAK,QAAQ,CAAC;QAC7B,KAAK,IAAI;YACP,OAAO,MAAM,GAAG,QAAQ,CAAC;QAC3B,KAAK,KAAK;YACR,OAAO,MAAM,IAAI,QAAQ,CAAC;QAC5B,KAAK,IAAI;YACP,OAAO,MAAM,GAAG,QAAQ,CAAC;QAC3B,KAAK,KAAK;YACR,OAAO,MAAM,IAAI,QAAQ,CAAC;QAC5B;YACE,OAAO,KAAK,CAAC;IACjB,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAC/B,SAA6C,EAC7C,OAAiC;IAEjC,+CAA+C;IAC/C,IAAI,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC;IAE5B,qBAAqB;IACrB,IAAI,mBAAmB,CAAC,SAAS,CAAC,EAAE,CAAC;QACnC,IAAI,SAAS,CAAC,UAAU,KAAK,KAAK,EAAE,CAAC;YACnC,OAAO,SAAS,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,uBAAuB,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;QAChF,CAAC;QACD,KAAK;QACL,OAAO,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,uBAAuB,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;IAC/E,CAAC;IAED,mBAAmB;IACnB,OAAO,uBAAuB,CAAC,SAA8B,EAAE,OAAO,CAAC,CAAC;AAC1E,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,YAAY,CAC1B,aAAqB,EACrB,KAA4B,EAC5B,OAAiC;IAEjC,uCAAuC;IACvC,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,aAAa,CAAC,CAAC;IAE/D,oCAAoC;IACpC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEvC,8CAA8C;IAC9C,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC5B,IAAI,iBAAiB,CAAC,IAAI,CAAC,SAAmC,EAAE,OAAO,CAAC,EAAE,CAAC;YACzE,OAAO,IAAI,CAAC,EAAE,CAAC;QACjB,CAAC;IACH,CAAC;IAED,kDAAkD;IAClD,2DAA2D;IAC3D,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAC5B,MAAc,EACd,KAA4B;IAE5B,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;AAC/C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAC3B,KAA4B,EAC5B,KAA4B;IAE5B,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1D,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAClE,OAAO,SAAS,EAAE,EAAE,IAAI,IAAI,CAAC;AAC/B,CAAC"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Pipeline Metrics Collector
3
+ *
4
+ * Assembles execution metrics from factory instance state
5
+ * for edge condition evaluation.
6
+ */
7
+ /** All metrics available for pipeline edge condition evaluation. */
8
+ export interface PipelineExecutionMetrics {
9
+ gap_count: number;
10
+ gap_severity: string;
11
+ gate_pass_rate: number;
12
+ gates_failed: number;
13
+ cycle_count: number;
14
+ delivery_completion_pct: number;
15
+ qa_critical_failures: number;
16
+ qa_pass_rate: number;
17
+ wall_clock_minutes: number;
18
+ }
19
+ /** Default metrics when no data is available. */
20
+ export declare const DEFAULT_METRICS: PipelineExecutionMetrics;
21
+ /**
22
+ * Input data for metric collection. These come from various parts
23
+ * of the factory instance and gate results.
24
+ */
25
+ export interface MetricCollectorInput {
26
+ /** Number of gaps/issues found in the current cycle. */
27
+ gapCount?: number;
28
+ /** Highest severity of gaps found. */
29
+ gapSeverity?: string;
30
+ /** Total gate checks run in this cycle. */
31
+ totalGateChecks?: number;
32
+ /** Number of gate checks that passed. */
33
+ passedGateChecks?: number;
34
+ /** Current build-gate cycle count. */
35
+ cycleCount?: number;
36
+ /** Percentage of work units completed (0-100). */
37
+ deliveryCompletionPct?: number;
38
+ /** Number of critical QA failures. */
39
+ qaCriticalFailures?: number;
40
+ /** Total QA checks run. */
41
+ totalQaChecks?: number;
42
+ /** Number of QA checks that passed. */
43
+ passedQaChecks?: number;
44
+ /** Wall clock minutes since instance started. */
45
+ wallClockMinutes?: number;
46
+ }
47
+ /**
48
+ * Collect execution metrics from available data.
49
+ * Metrics not provided default to safe values.
50
+ */
51
+ export declare function collectMetrics(input: MetricCollectorInput): PipelineExecutionMetrics;
52
+ //# sourceMappingURL=pipeline-metrics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline-metrics.d.ts","sourceRoot":"","sources":["../src/pipeline-metrics.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,oEAAoE;AACpE,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,uBAAuB,EAAE,MAAM,CAAC;IAChC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED,iDAAiD;AACjD,eAAO,MAAM,eAAe,EAAE,wBAU7B,CAAC;AAEF;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,wDAAwD;IACxD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sCAAsC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2CAA2C;IAC3C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,yCAAyC;IACzC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,sCAAsC;IACtC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kDAAkD;IAClD,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,sCAAsC;IACtC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,2BAA2B;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uCAAuC;IACvC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iDAAiD;IACjD,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,oBAAoB,GAAG,wBAAwB,CAiBpF"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Pipeline Metrics Collector
3
+ *
4
+ * Assembles execution metrics from factory instance state
5
+ * for edge condition evaluation.
6
+ */
7
+ /** Default metrics when no data is available. */
8
+ export const DEFAULT_METRICS = {
9
+ gap_count: 0,
10
+ gap_severity: 'low',
11
+ gate_pass_rate: 1,
12
+ gates_failed: 0,
13
+ cycle_count: 0,
14
+ delivery_completion_pct: 0,
15
+ qa_critical_failures: 0,
16
+ qa_pass_rate: 1,
17
+ wall_clock_minutes: 0,
18
+ };
19
+ /**
20
+ * Collect execution metrics from available data.
21
+ * Metrics not provided default to safe values.
22
+ */
23
+ export function collectMetrics(input) {
24
+ const totalGates = input.totalGateChecks ?? 0;
25
+ const passedGates = input.passedGateChecks ?? 0;
26
+ const totalQa = input.totalQaChecks ?? 0;
27
+ const passedQa = input.passedQaChecks ?? 0;
28
+ return {
29
+ gap_count: input.gapCount ?? 0,
30
+ gap_severity: input.gapSeverity ?? 'low',
31
+ gate_pass_rate: totalGates > 0 ? passedGates / totalGates : 1,
32
+ gates_failed: totalGates > 0 ? totalGates - passedGates : 0,
33
+ cycle_count: input.cycleCount ?? 0,
34
+ delivery_completion_pct: input.deliveryCompletionPct ?? 0,
35
+ qa_critical_failures: input.qaCriticalFailures ?? 0,
36
+ qa_pass_rate: totalQa > 0 ? passedQa / totalQa : 1,
37
+ wall_clock_minutes: input.wallClockMinutes ?? 0,
38
+ };
39
+ }
40
+ //# sourceMappingURL=pipeline-metrics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline-metrics.js","sourceRoot":"","sources":["../src/pipeline-metrics.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAeH,iDAAiD;AACjD,MAAM,CAAC,MAAM,eAAe,GAA6B;IACvD,SAAS,EAAE,CAAC;IACZ,YAAY,EAAE,KAAK;IACnB,cAAc,EAAE,CAAC;IACjB,YAAY,EAAE,CAAC;IACf,WAAW,EAAE,CAAC;IACd,uBAAuB,EAAE,CAAC;IAC1B,oBAAoB,EAAE,CAAC;IACvB,YAAY,EAAE,CAAC;IACf,kBAAkB,EAAE,CAAC;CACtB,CAAC;AA6BF;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,KAA2B;IACxD,MAAM,UAAU,GAAG,KAAK,CAAC,eAAe,IAAI,CAAC,CAAC;IAC9C,MAAM,WAAW,GAAG,KAAK,CAAC,gBAAgB,IAAI,CAAC,CAAC;IAChD,MAAM,OAAO,GAAG,KAAK,CAAC,aAAa,IAAI,CAAC,CAAC;IACzC,MAAM,QAAQ,GAAG,KAAK,CAAC,cAAc,IAAI,CAAC,CAAC;IAE3C,OAAO;QACL,SAAS,EAAE,KAAK,CAAC,QAAQ,IAAI,CAAC;QAC9B,YAAY,EAAE,KAAK,CAAC,WAAW,IAAI,KAAK;QACxC,cAAc,EAAE,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;QAC7D,YAAY,EAAE,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;QAC3D,WAAW,EAAE,KAAK,CAAC,UAAU,IAAI,CAAC;QAClC,uBAAuB,EAAE,KAAK,CAAC,qBAAqB,IAAI,CAAC;QACzD,oBAAoB,EAAE,KAAK,CAAC,kBAAkB,IAAI,CAAC;QACnD,YAAY,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QAClD,kBAAkB,EAAE,KAAK,CAAC,gBAAgB,IAAI,CAAC;KAChD,CAAC;AACJ,CAAC"}