196 lines
6.8 KiB
JavaScript
196 lines
6.8 KiB
JavaScript
/**
|
|
* PR-37 Delivery Planning — Entry Point
|
|
*
|
|
* Parts F, G, H, I:
|
|
* - F: Sprint Planner
|
|
* - G: Release Planner
|
|
* - H: Batch Planner
|
|
* - I: Capacity Planner
|
|
*
|
|
* Consumes SF-02 Requirement Package output and generates delivery
|
|
* planning artifacts. Compatible with PR-36 Factory Registry.
|
|
*
|
|
* @module pr-37-delivery-planning
|
|
* @since PR-37
|
|
*/
|
|
|
|
import { generateSprintPlan, defaultSprintConfig } from "./sprint-planner.mjs";
|
|
import { generateReleasePlan } from "./release-planner.mjs";
|
|
import { generateBatchPlan } from "./batch-planner.mjs";
|
|
import { generateCapacityPlan, defaultCapacityConfig } from "./capacity-planner.mjs";
|
|
|
|
import { alignRoadmapWithPlans } from "./roadmap-aligner.mjs";
|
|
|
|
// ═══════════════════════════════════════════════════════
|
|
// PR-37 Artifact Constants
|
|
// ═══════════════════════════════════════════════════════
|
|
|
|
export const PR37_ARTIFACTS = Object.freeze({
|
|
SPRINT_PLAN: "sprint-plan",
|
|
RELEASE_PLAN: "release-plan",
|
|
BATCH_PLAN: "batch-plan",
|
|
CAPACITY_PLAN: "capacity-plan",
|
|
ALIGNMENT_REPORT: "alignment-report",
|
|
});
|
|
|
|
// ═══════════════════════════════════════════════════════
|
|
// Factory Integration
|
|
// ═══════════════════════════════════════════════════════
|
|
|
|
/**
|
|
* Create a delivery planning factory that consumes SF-02 upstream artifacts
|
|
* and produces all 4 delivery plans.
|
|
*
|
|
* The factory accepts a PR-36 FactoryInput object (or a simplified upstream
|
|
* artifacts object) and returns all plans bundled as a FactoryOutput.
|
|
*
|
|
* @param {object} upstreamArtifacts — SF-02 output containing:
|
|
* - epics: object[]
|
|
* - features: object[]
|
|
* - userStories: object[]
|
|
* - dependencies / graph: dependency graph
|
|
* - priorities: priority matrix entries
|
|
* - mvpScope: MVP scope definition
|
|
* @param {object} [config] — Optional config overrides
|
|
* @param {object} [config.sprint] — Sprint planner config
|
|
* @param {object} [config.capacity] — Capacity planner config
|
|
* @returns {object} FactoryOutput with all delivery plans
|
|
*
|
|
* @example
|
|
* ```js
|
|
* const factory = createDeliveryPlanningFactory();
|
|
* const output = factory(sf02Output, {
|
|
* sprint: { teamVelocity: 20, maxStoryPointsPerSprint: 25 },
|
|
* capacity: { teamSize: 5, availabilityFactor: 0.8 },
|
|
* });
|
|
* // output.sprintPlan, output.releasePlan, output.batchPlan, output.capacityPlan
|
|
* ```
|
|
*/
|
|
export function createDeliveryPlanningFactory(upstreamArtifacts, config = {}) {
|
|
if (!upstreamArtifacts) {
|
|
return {
|
|
factoryId: "PR-37",
|
|
status: "failed",
|
|
error: "No upstream artifacts provided. Provide SF-02 output.",
|
|
};
|
|
}
|
|
|
|
const warnings = [];
|
|
|
|
// ── 1. Extract SF-02 artifacts ──
|
|
const stories = upstreamArtifacts.userStories || upstreamArtifacts.stories || [];
|
|
const epics = upstreamArtifacts.epics || [];
|
|
const features = upstreamArtifacts.features || [];
|
|
|
|
// Support both { graph: { nodes, edges } } and flat { nodes, edges }
|
|
const dependencies = upstreamArtifacts.dependencies
|
|
|| upstreamArtifacts.graph
|
|
|| { nodes: [], edges: [] };
|
|
|
|
const priorities = upstreamArtifacts.priorities || [];
|
|
const mvpScope = upstreamArtifacts.mvpScope || null;
|
|
|
|
// ── 2. Validate data ──
|
|
if (stories.length === 0) {
|
|
warnings.push("No user stories found in upstream artifacts");
|
|
}
|
|
|
|
// ── 3. Generate Sprint Plan (Part F) ──
|
|
const sprintConfig = defaultSprintConfig(config.sprint || {});
|
|
const sprintPlan = generateSprintPlan({
|
|
stories,
|
|
dependencies,
|
|
priorities,
|
|
config: sprintConfig,
|
|
});
|
|
|
|
if (sprintPlan.warnings && sprintPlan.warnings.length > 0) {
|
|
warnings.push(...sprintPlan.warnings.map(w => `[Sprint] ${w}`));
|
|
}
|
|
|
|
// ── 4. Generate Release Plan (Part G) ──
|
|
const releasePlan = generateReleasePlan({
|
|
mvpScope,
|
|
priorities,
|
|
dependencies,
|
|
stories,
|
|
epics,
|
|
features,
|
|
});
|
|
|
|
if (releasePlan.warnings && releasePlan.warnings.length > 0) {
|
|
warnings.push(...releasePlan.warnings.map(w => `[Release] ${w}`));
|
|
}
|
|
|
|
// ── 5. Generate Batch Plan (Part H) ──
|
|
const batchPlan = generateBatchPlan({
|
|
stories,
|
|
dependencies,
|
|
priorities,
|
|
sprints: sprintPlan,
|
|
releases: releasePlan,
|
|
});
|
|
|
|
if (batchPlan.warnings && batchPlan.warnings.length > 0) {
|
|
warnings.push(...batchPlan.warnings.map(w => `[Batch] ${w}`));
|
|
}
|
|
|
|
// ── 6. Generate Capacity Plan (Part I) ──
|
|
const capacityConfig = defaultCapacityConfig(config.capacity || {});
|
|
const capacityPlan = generateCapacityPlan({
|
|
sprints: sprintPlan,
|
|
releases: releasePlan,
|
|
config: capacityConfig,
|
|
});
|
|
|
|
if (capacityPlan.warnings && capacityPlan.warnings.length > 0) {
|
|
warnings.push(...capacityPlan.warnings.map(w => `[Capacity] ${w}`));
|
|
}
|
|
|
|
// ── 7. Align with Roadmap (Part J) ──
|
|
const roadmap = upstreamArtifacts.roadmap || mvpScope?.phases;
|
|
const alignmentReport = roadmap
|
|
? alignRoadmapWithPlans({
|
|
roadmap: { phases: Array.isArray(roadmap) ? roadmap : (roadmap.phases || []) },
|
|
sprintPlan,
|
|
releasePlan,
|
|
batchPlan,
|
|
mvpScope,
|
|
})
|
|
: null;
|
|
|
|
// ── 8. Assemble output ──
|
|
const output = {
|
|
factoryId: "PR-37",
|
|
status: warnings.length > 0 && stories.length === 0 ? "blocked" : "passed",
|
|
sprintPlan,
|
|
releasePlan,
|
|
batchPlan,
|
|
capacityPlan,
|
|
alignmentReport,
|
|
warnings: warnings.length > 0 ? warnings : undefined,
|
|
metadata: {
|
|
factoryId: "PR-37",
|
|
upstreamArtifactId: upstreamArtifacts.id || "SF-02",
|
|
generatedAt: new Date().toISOString(),
|
|
totalStories: stories.length,
|
|
totalEpics: epics.length,
|
|
totalFeatures: features.length,
|
|
totalSprints: sprintPlan.metrics.totalSprints,
|
|
totalReleases: releasePlan.releases ? releasePlan.releases.length : 0,
|
|
},
|
|
};
|
|
|
|
return output;
|
|
}
|
|
|
|
// ═══════════════════════════════════════════════════════
|
|
// Barrel Re-exports
|
|
// ═══════════════════════════════════════════════════════
|
|
|
|
export { generateSprintPlan, defaultSprintConfig } from "./sprint-planner.mjs";
|
|
export { generateReleasePlan } from "./release-planner.mjs";
|
|
export { generateBatchPlan } from "./batch-planner.mjs";
|
|
export { generateCapacityPlan, defaultCapacityConfig } from "./capacity-planner.mjs";
|
|
export { alignRoadmapWithPlans } from "./roadmap-aligner.mjs";
|