feat: capacity-aware scheduling (#8) — real focus factors drive every forecast
Turns the single-serial-worker scheduler into a capacity-aware, multi-lane one. Configured team members become lanes; an issue runs on its assignee's lane (or the earliest-free lane), its duration scaled by that lane's throughput (focusFactor × allocation). Every forecast — Focus cone, Runway, milestone drill-in — is now capacity-aware. core (@commitea/core): - capacity/capacity-v0: CapacityMember + capacityPerWorkday + parseCapacityConfig (clamps, drops invalid; degrades to []). - scheduler/scheduler-capacity-v0: scheduleWithCapacity reuses the v0 topo order + critical path, re-lays work across lanes (layoutOnLanes, resolveLanes, makespan). Empty workers → the single serial plan verbatim. - forecast() gains options.workers: each MC trial lays sampled durations across the lanes and takes the makespan; serial path unchanged. SchedulableIssue gains assignee; ScheduledItem gains worker. - 11 new tests (parse/clamp, parallelism halves makespan, speed scaling, assignee routing, cross-lane deps, forecast makespan shrinks with lanes). app: - pm-state capacity/members.json read (readCapacity + pmstate:capacity bridge); useCapacity hook → workers; forecastBacklog/runwayView/milestoneView pass workers. - Runway Capacity card shows the real config (person · focus · alloc · pd/day). Config lives in pm-state (D4); seeded christian(0.8)/stephen(0.6×0.5). Degrades to the fixture/serial when absent. Verified: 128 core tests green, desktop typecheck clean, 14 fixture e2e green. Live: the capacity card is real, and the P2 forecast shifts 32d→37d — honest, since real focus factors (<1) replace the v0 focus-1.0 assumption. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -21,6 +21,8 @@ export interface SchedulableIssue {
|
||||
estimateDays: number | null
|
||||
/** 1 (most urgent) … 4; null when unset. */
|
||||
priority: number | null
|
||||
/** gitea assignee login, for capacity-aware lane routing; optional. */
|
||||
assignee?: string | null
|
||||
}
|
||||
|
||||
export interface DependencyEdge {
|
||||
@@ -45,6 +47,8 @@ export interface ScheduledItem {
|
||||
/** On a longest-duration dependency chain. */
|
||||
critical: boolean
|
||||
rationale: string
|
||||
/** Lane it's scheduled on, when capacity-aware; absent for the single-worker plan. */
|
||||
worker?: string
|
||||
}
|
||||
|
||||
export interface SchedulePlan {
|
||||
|
||||
Reference in New Issue
Block a user