@bpmsoftwaresolutions/ai-engine-client 1.1.70 → 1.1.71
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/README.md +2 -1
- package/package.json +1 -1
- package/src/index.js +124 -0
package/README.md
CHANGED
|
@@ -654,7 +654,7 @@ Generated scripts are ephemeral helpers, not source-of-truth. The server keeps S
|
|
|
654
654
|
|
|
655
655
|
### Governed Implementation
|
|
656
656
|
|
|
657
|
-
Current package version: `1.
|
|
657
|
+
Current package version: `1.1.71`.
|
|
658
658
|
|
|
659
659
|
| Method | Description |
|
|
660
660
|
|---|---|
|
|
@@ -763,6 +763,7 @@ Engine returns the required gate and next action.
|
|
|
763
763
|
| `getPortfolioProject(projectId)` | Project detail via portfolio. |
|
|
764
764
|
| `getPortfolioReport()` | Full portfolio report. |
|
|
765
765
|
| `getPortfolioBundle()` | Portfolio bundle. |
|
|
766
|
+
| `getPortfolioClosureReadiness({ projectLimit, includeInactive, includeLogaPortfolioProjection, includeLogaRoadmapProjections })` | Read-only portfolio readiness view that composes bundle, project list, roadmap summaries, active items, and open task counts into a conservative closure-ready flag. |
|
|
766
767
|
|
|
767
768
|
### Self-Learning
|
|
768
769
|
| Method | Description |
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -5767,6 +5767,130 @@ export class AIEngineClient {
|
|
|
5767
5767
|
return this._request('/api/operator/portfolio/bundle');
|
|
5768
5768
|
}
|
|
5769
5769
|
|
|
5770
|
+
async getPortfolioClosureReadiness({
|
|
5771
|
+
projectLimit = 25,
|
|
5772
|
+
includeInactive = false,
|
|
5773
|
+
includeLogaPortfolioProjection = false,
|
|
5774
|
+
includeLogaRoadmapProjections = false,
|
|
5775
|
+
} = {}) {
|
|
5776
|
+
const portfolioBundle = await this.getPortfolioBundle();
|
|
5777
|
+
const projectListPayload = await this.listProjects({
|
|
5778
|
+
limit: projectLimit,
|
|
5779
|
+
includeInactive,
|
|
5780
|
+
});
|
|
5781
|
+
|
|
5782
|
+
const bundleProjects = Array.isArray(portfolioBundle?.projects)
|
|
5783
|
+
? portfolioBundle.projects.filter((project) => isPlainObject(project))
|
|
5784
|
+
: [];
|
|
5785
|
+
const listedProjects = Array.isArray(projectListPayload?.projects)
|
|
5786
|
+
? projectListPayload.projects.filter((project) => isPlainObject(project))
|
|
5787
|
+
: Array.isArray(projectListPayload)
|
|
5788
|
+
? projectListPayload.filter((project) => isPlainObject(project))
|
|
5789
|
+
: [];
|
|
5790
|
+
const activeProjects = listedProjects.length > 0 ? listedProjects : bundleProjects;
|
|
5791
|
+
const logaPortfolioProjection = includeLogaPortfolioProjection
|
|
5792
|
+
? await this.getLogaProjectPortfolioProjection()
|
|
5793
|
+
: null;
|
|
5794
|
+
const logaRoadmapProjections = {};
|
|
5795
|
+
|
|
5796
|
+
const projectReadiness = [];
|
|
5797
|
+
for (const project of activeProjects) {
|
|
5798
|
+
const projectId = cleanText(project.project_id) || cleanText(project.projectId);
|
|
5799
|
+
if (!projectId) {
|
|
5800
|
+
continue;
|
|
5801
|
+
}
|
|
5802
|
+
|
|
5803
|
+
const roadmapSummaryPayload = await this.getProjectRoadmapSummary(projectId);
|
|
5804
|
+
const roadmapSummary = isPlainObject(roadmapSummaryPayload?.summary) ? roadmapSummaryPayload.summary : {};
|
|
5805
|
+
const activeItemPayload = await this.getProjectRoadmapActiveItem(projectId);
|
|
5806
|
+
const activeItem = isPlainObject(activeItemPayload?.active_item)
|
|
5807
|
+
? activeItemPayload.active_item
|
|
5808
|
+
: isPlainObject(activeItemPayload)
|
|
5809
|
+
? activeItemPayload
|
|
5810
|
+
: {};
|
|
5811
|
+
const openTasksPayload = await this.listProjectOpenTasks(projectId);
|
|
5812
|
+
const openTasks = Array.isArray(openTasksPayload?.tasks)
|
|
5813
|
+
? openTasksPayload.tasks.filter((task) => isPlainObject(task))
|
|
5814
|
+
: Array.isArray(openTasksPayload)
|
|
5815
|
+
? openTasksPayload.filter((task) => isPlainObject(task))
|
|
5816
|
+
: [];
|
|
5817
|
+
|
|
5818
|
+
const activeItemStatus = cleanText(activeItem.item_status) || cleanText(activeItem.status);
|
|
5819
|
+
const completionPercentage = Number(
|
|
5820
|
+
roadmapSummary.completion_percentage
|
|
5821
|
+
?? roadmapSummary.completion_pct
|
|
5822
|
+
?? roadmapSummary.progress_percentage
|
|
5823
|
+
?? 0,
|
|
5824
|
+
);
|
|
5825
|
+
const totalItems = Number(
|
|
5826
|
+
roadmapSummary.total_items
|
|
5827
|
+
?? roadmapSummary.item_count
|
|
5828
|
+
?? roadmapSummary.total_count
|
|
5829
|
+
?? 0,
|
|
5830
|
+
);
|
|
5831
|
+
const openItems = Number(
|
|
5832
|
+
roadmapSummary.open_items
|
|
5833
|
+
?? roadmapSummary.open_item_count
|
|
5834
|
+
?? roadmapSummary.remaining_items
|
|
5835
|
+
?? openTasks.length,
|
|
5836
|
+
);
|
|
5837
|
+
const terminalStatuses = new Set(['accepted', 'verified', 'done', 'completed', 'closed']);
|
|
5838
|
+
const activeItemReady = !activeItemStatus || terminalStatuses.has(activeItemStatus.toLowerCase());
|
|
5839
|
+
const projectReady = openItems === 0 && openTasks.length === 0 && activeItemReady && completionPercentage >= 100;
|
|
5840
|
+
const blockingReason = projectReady
|
|
5841
|
+
? null
|
|
5842
|
+
: [
|
|
5843
|
+
openTasks.length > 0 ? `${openTasks.length} open task(s) remain` : null,
|
|
5844
|
+
openItems > 0 ? `${openItems} roadmap item(s) remain open` : null,
|
|
5845
|
+
!activeItemReady ? `active item status is ${activeItemStatus || 'missing'}` : null,
|
|
5846
|
+
completionPercentage < 100 ? `completion is ${completionPercentage.toFixed(1)}%` : null,
|
|
5847
|
+
].filter(Boolean).join('; ') || 'portfolio closure readiness is not satisfied';
|
|
5848
|
+
|
|
5849
|
+
const roadmapCompletion = {
|
|
5850
|
+
completion_percentage: completionPercentage,
|
|
5851
|
+
total_items: totalItems,
|
|
5852
|
+
open_items: openItems,
|
|
5853
|
+
completed_items: Math.max(totalItems - openItems, 0),
|
|
5854
|
+
};
|
|
5855
|
+
const projectReadinessEntry = {
|
|
5856
|
+
project: {
|
|
5857
|
+
project_id: projectId,
|
|
5858
|
+
project_name: cleanText(project.project_name) || cleanText(project.projectName) || null,
|
|
5859
|
+
project_slug: cleanText(project.project_slug) || cleanText(project.projectSlug) || null,
|
|
5860
|
+
process_status: cleanText(project.process_status) || cleanText(project.processStatus) || null,
|
|
5861
|
+
charter_status: cleanText(project.charter_status) || cleanText(project.charterStatus) || null,
|
|
5862
|
+
},
|
|
5863
|
+
roadmap_completion: roadmapCompletion,
|
|
5864
|
+
active_item: activeItem,
|
|
5865
|
+
open_task_count: openTasks.length,
|
|
5866
|
+
closure_ready: projectReady,
|
|
5867
|
+
blocking_reason: blockingReason,
|
|
5868
|
+
};
|
|
5869
|
+
if (includeLogaRoadmapProjections) {
|
|
5870
|
+
projectReadinessEntry.loga_roadmap_projection = await this.getLogaProjectRoadmapProjection(projectId);
|
|
5871
|
+
logaRoadmapProjections[projectId] = projectReadinessEntry.loga_roadmap_projection;
|
|
5872
|
+
}
|
|
5873
|
+
projectReadiness.push(projectReadinessEntry);
|
|
5874
|
+
}
|
|
5875
|
+
|
|
5876
|
+
const closureReady = projectReadiness.length === 0 || projectReadiness.every((project) => project.closure_ready === true);
|
|
5877
|
+
const blockingProject = projectReadiness.find((project) => project.closure_ready !== true);
|
|
5878
|
+
|
|
5879
|
+
return {
|
|
5880
|
+
portfolio_summary: isPlainObject(portfolioBundle?.summary) ? portfolioBundle.summary : {},
|
|
5881
|
+
portfolio_bundle: portfolioBundle,
|
|
5882
|
+
active_projects: projectReadiness,
|
|
5883
|
+
closure_readiness: closureReady,
|
|
5884
|
+
blocking_reason: closureReady ? null : `${cleanText(blockingProject?.project?.project_name) || cleanText(blockingProject?.project?.project_id) || 'project'}: ${blockingProject?.blocking_reason || 'closure readiness is not satisfied'}`,
|
|
5885
|
+
blocking_project_id: closureReady ? null : cleanText(blockingProject?.project?.project_id),
|
|
5886
|
+
blocking_project_name: closureReady ? null : cleanText(blockingProject?.project?.project_name),
|
|
5887
|
+
project_count: projectReadiness.length,
|
|
5888
|
+
open_task_count: projectReadiness.reduce((total, project) => total + Number(project.open_task_count || 0), 0),
|
|
5889
|
+
loga_portfolio_projection: logaPortfolioProjection,
|
|
5890
|
+
loga_roadmap_projections: includeLogaRoadmapProjections ? logaRoadmapProjections : null,
|
|
5891
|
+
};
|
|
5892
|
+
}
|
|
5893
|
+
|
|
5770
5894
|
// ─── Self-Learning ─────────────────────────────────────────────────────────
|
|
5771
5895
|
|
|
5772
5896
|
async getSelfLearningPosture({ workflowRunId, limit } = {}) {
|