Schedule view
The Schedule view is TruePPM’s project-timeline surface — what the rest of the industry calls a Gantt chart. The product’s canonical name is Schedule (per ADR-0030 and the wave/1 rename in #204) because the view does more than the historical Gantt: critical path, baselines, milestones, the unscheduled gutter, and live CPM re-forecast off sprint velocity all live in the same canvas.
Where this lives in the story
Section titled “Where this lives in the story”Step 2 (Schedule the skeleton — CPM, milestones, baseline) and Step 6 (Execute) of the hybrid PM flow — Raj’s home; the view that auto-re-forecasts when the team moves a card on the board.
Where to find it in the app
Section titled “Where to find it in the app”- Route:
/projects/:projectId/schedule - Tab: Schedule (visible by default for HYBRID and WATERFALL projects per methodology preset)
Layout
Section titled “Layout”Split-pane: a virtualized task list on the left (seven columns — WBS, Task, Dur, Start, Finish, %, Owner — all but Task hideable and resizable, persisted via localStorage), and the canvas timeline on the right. Scroll is synchronized in both directions.
Task detail drawer
Section titled “Task detail drawer”Clicking a task row opens a right-side drawer (a bottom sheet on mobile). The header shows the WBS number, a readiness chip, a CP marker when the task is on the critical path, and the task name as an inline-editable field. Below it, the drawer groups everything about the task into four tabs:
- Details — a schedule strip (Start, Finish, Duration, Float, with a critical-path banner when float is zero), status and progress, assignees, the description, dependencies, and the secondary planning sections (sprint, estimates, recurrence).
- Subtasks — the checklist breakdown, with a done/total count on the tab.
- Activity — comments, the activity timeline, field history, and baseline.
- Files — attachments and external links.
Most fields autosave the moment you change them — picking a status, nudging progress, ticking a subtask, posting a comment, or attaching a file all take effect immediately. The one exception is the free-text Description: it edits locally and a save bar appears while you have unsaved changes, so a half-typed note is never committed by accident. That edit still flushes automatically when you blur the field, switch tabs, or close the drawer, and a notice warns you if someone else changed the description while you were typing.
The tabs are extension points: each section registers against the
task_detail.section slot with a priority and a tab, so TruePPM Enterprise can
add its own sections without the community edition knowing about them.
Canvas renderer
Section titled “Canvas renderer”TruePPM ships its own canvas Schedule renderer in packages/web/src/features/schedule/engine/. It replaced an earlier SVAR React Gantt integration to remove third-party constraints on drag UX, accessibility (ARIA grid overlay), and dark-mode rendering. Three layered canvases (background, bars, interaction) are dirty-rect repainted; row virtualization is mandatory from the first commit. See ADR-0040 for the full rationale.
Bar types
Section titled “Bar types”| Bar type | Token | Meaning |
|---|---|---|
| Normal | barNormal | Standard task, not on the critical path |
| Critical | barCritical (semantic-critical) | Task is on the critical path (total float = 0) |
| Complete | barComplete (semantic-on-track) | Task marked as 100% complete |
| Summary | barSummary 8px tall | WBS parent / summary row |
| Milestone | Diamond | Zero-duration event (is_milestone=true) |
| Baseline ghost | ghost-fill/ghost-border 6px | Original planned dates rendered below the live bar |
Bar labels use COLOR.text (#1A1917 light / palette swap in dark mode). The canvas font is set once at engine init to the Tailwind font-sans stack so labels match the task list typography.
Dependency types
Section titled “Dependency types”Finish-to-Start dependencies render as collision-avoiding Manhattan-routed arrows; the other three (SS, FF, SF) render as cubic-Bézier curves:
| Type | Name | Meaning |
|---|---|---|
| FS | Finish-to-Start | Successor starts after predecessor finishes |
| SS | Start-to-Start | Successor starts after predecessor starts |
| FF | Finish-to-Finish | Successor finishes after predecessor finishes |
| SF | Start-to-Finish | Successor finishes after predecessor starts |
All dependency arrows are drawn in charcoal (COLOR.arrowNormal) — critical-path state is conveyed by the bar color, not the arrow. Arrows route orthogonally and divert around intervening task bars and milestone diamonds, so a line never visually pierces another row’s object on its way to the successor.
You can zoom smoothly from hour-level detail all the way out to a multi-year overview — there are no fixed steps to click through. As you zoom, the two-row date header automatically changes the unit it emphasizes (day → week → month → quarter → year) so the timeline always stays readable.
Three ways to zoom:
- Toolbar stepper — the −, current-level, and + controls, plus a Fit to project button that frames the whole project in the viewport.
- Wheel / pinch — hold Ctrl/Cmd and scroll the mouse wheel, or pinch on a trackpad, while pointing at the timeline. The zoom centers on the cursor: the date under your pointer stays put while everything else scales around it.
- Keyboard —
⌘/Ctrl+=zooms in,-zooms out, and0fits the project to the viewport.
Interaction
Section titled “Interaction”- Drag-to-reschedule with a 4-pixel hover threshold and FSM (
IDLE → HOVER_WAIT → DRAG_STARTED → DRAGGING → DROP/CANCELLED) - Drag-to-pan — hold Space and drag, or drag with the middle mouse button, to pan the timeline in any direction. The cursor shows a grab/grabbing hand while you pan, and task-bar dragging is paused so a pan never moves a task by accident. The hint is documented in the schedule legend.
- Snap-to-day is applied inside the renderer before emitting
drag-task-move; hold Shift to suspend snap - Pointer events throughout (no mouse/touch branching); pinch-to-zoom via two simultaneous active pointers
- Keyboard reschedule as a WCAG 2.1.1 alternative (left/right arrows nudge dates; Enter confirms; Esc cancels) — see issue #34
Scheduling before the project start
Section titled “Scheduling before the project start”The project start date is the floor for the schedule: the critical-path engine never plans a task to begin before it. But the floor is elastic in the earlier direction. When you place a task on a date before the project start — by typing a date, creating the task, importing from MS Project, or writing through the API — TruePPM keeps the floor honest by pulling the project start back to fit the task, in the same change. The task lands where you put it, and the project boundary follows; nothing is silently clamped or discarded.
Only the earlier direction is automatic. Moving the project start later (past tasks that already begin before the new date) stays a deliberate Project Settings edit. Pulling the start earlier to fit a task needs only the permission to edit that task — the project boundary is treated as a derived artifact of its tasks — so it isn’t gated behind project administration, and collaborators see the new start update in real time.
Because this lives at the API layer, every write path behaves the same way, including integrations and imports that set task dates directly.
Promote a backlog idea onto the schedule
Section titled “Promote a backlog idea onto the schedule”The Unscheduled gutter beneath the timeline now includes a Backlog section listing tasks that have been captured but not yet scheduled. Backlog cards are visually distinct — a dashed edge and a readiness label — so it’s clear that placing one on the timeline does more than move it.
To pull a backlog item into your plan, drag its card from the gutter up onto the timeline. Dropping it adds the idea to the sprint at the drop date — a confirmation reads “Added ‘{name}’ to the sprint, starting {date}” — and CPM cascades the rest of the plan automatically, so any successors re-forecast in the same motion. The drop dialog speaks in sprint terms (“Add to a sprint”, a Target date) rather than CPM vocabulary, so you don’t need to know about early start or float to commit an idea.
If you’d rather not drag — or you’re working from the keyboard — every backlog card has an Add to a sprint action (both in the gutter and on the Board). It opens a target-date picker and does exactly the same thing: add the idea to the sprint at the chosen date.
Live re-forecast
Section titled “Live re-forecast”When a teammate edits a dependency or reschedules a task, the recalculation propagates to everyone over WebSocket — the Gantt bars slide into their new positions in real time as CPM finishes, with no manual refresh. See Real-time collaboration for the underlying broadcast model.
When a confirmed reschedule moves a task’s planned start, the people it affects also get a targeted inbox notification — not just a silent bar shift. The task’s assignee is told their committed date moved (with the old and new dates, deep-linked to the task), and if the task is in an active sprint, the rest of the sprint team is notified that a sprint task was rescheduled. You are never notified about your own edit.
Forecast & sensitivity
Section titled “Forecast & sensitivity”Below the timeline, a collapsible Forecast & sensitivity bar surfaces the Monte Carlo result inline. Collapsed, it shows a one-line summary (P50 · P80 · P95 · the top driver). Expanded, it has two columns:
- Finish-date forecast — the simulated finish-date histogram with the P50–P80 band and the P50/P80/P95 commit dates.
- What’s holding the date — a sensitivity ranking of the tasks whose duration moves the project finish most, shown as labeled percent bars (critical-path tasks in red). This is a real duration-sensitivity tornado from the simulation, not a guess based on estimate spread — a high-variance task with plenty of float ranks low, while a task on the binding path ranks high. See the scheduler reference for the underlying metric.
Run a simulation from the Monte Carlo row to populate it; the expand/collapse choice is remembered per user.
Export to PDF
Section titled “Export to PDF”To export the schedule as a PDF, open the Project actions (⋯) overflow menu — the same menu that holds Export to MS Project (.xml) — and choose Export schedule as PDF. The result is a single-page, landscape, one-page Gantt of the entire project timeline: a boardroom-clean artifact for a deck, a client, or a stakeholder with no portal access.
The PDF is not a screenshot. It is a light-themed static re-projection of the live (dark) canvas — redrawn for paper — so the lines stay crisp and the colors read on a printed page. It carries:
- The full project timeline — task bars, milestone diamonds, and dependency arrows, framed to fit one landscape sheet.
- A KPI strip — the schedule window, the critical path, the P80 forecast, overall progress, and the milestone count.
- A “Critical path chain” box — the activities that drive the finish date, listed in order, so a reader sees what is holding the date without reading every bar.
- A footer — a content-fingerprint checksum (two identical schedules export the same stamp, so you can tell at a glance whether a printout is current) and a Community-edition watermark line.
The document is rasterized entirely in your browser (html-to-image + jsPDF) — nothing is uploaded, and the export is private to the person who runs it. The action is desktop-only: it is hidden below the 768px breakpoint, mirroring the board PDF export. An options dialog (paper-size picker, page setup) and a keyboard shortcut are coming next.
Accessibility
Section titled “Accessibility”The canvas is aria-hidden="true"; a transparent DOM overlay (ScheduleAriaOverlay) provides the WCAG 2.1 grid structure (role="grid" → role="row" → role="gridcell"). Roving tabindex; engine.scrollToDate() is called before .focus() so virtualized rows scroll into view before keyboard focus lands.
Schedule deep-link
Section titled “Schedule deep-link”The Advancing-to-Milestone card on the Sprints view links into this Schedule view scrolled to a specific milestone task via the URL hash (#task-<uuid>). That’s how the Sprints workspace bridges back to the Schedule without forcing the user to find the milestone manually.
Related ADRs
Section titled “Related ADRs”- ADR-0030 — Schedule rename (Gantt → Schedule), tab order
- ADR-0040 — Wave/3 Schedule: bar render, task drawer, unscheduled gutter, canvas rationale
- ADR-0027 — Incremental CPM recompute (subgraph delta strategy)
If you are…
Section titled “If you are…”- Raj (PM) — this is your home. The critical path lights up automatically; baselines overlay as ghosts; the milestone diamonds are your contractual signal.
- Maya (Scrum Master) — you don’t open this. The deep-link from the Sprints workspace’s milestone card is the rare case you’d land here.
- Tom (engineer) — you don’t open this either. The Schedule auto-re-forecasts off your board moves.