← All entries
Web app

FTE Capacity Dashboard

Level-of-effort / FTE capacity matrix per person, role and Program Increment, with a what-if PI editor and trend charts.

Web app capacityfteprogram-incrementreactrechartscsvprojects-v2

◎ What it solves

Ends the Word-doc ↔ GitHub double-entry. The issue becomes the only place FTE is written down, and the capacity view is generated from it — so there is nothing left to keep aligned.

⚠ Limitations & Risks

Every catalog entry must acknowledge at least one limitation or risk.

What it solves

Capacity used to be written down twice. The loop went:

  1. Edit the Word document with the objectives and everyone’s FTE.
  2. Update the GitHub ticket with the same information.
  3. Keep the two aligned — again, and again, on every change.

Step 3 is the one that never ends. Two sources of truth for the same numbers means they only agree for as long as someone keeps re-typing, and the moment they drift there is no way to tell which one is right — the document that got edited in the meeting, or the ticket the work actually hangs off.

This removes the second copy. The GitHub issue is where FTE is written, once; the capacity matrix, the per-person and per-role rollups and the trend charts are generated from it. There is no document to re-align, because there is no document.

From a two-way sync loop to a one-way generated view

Before: a Word document and a GitHub issue hold the same FTE numbers and must be re-aligned in both directions, forever, and drift apart in between. After: the GitHub issue is the single source, an Action reads it, and the dashboard is generated output.

BEFORE📄 Objectives.docxobjectives + FTE per person🎫 GitHub issue## LOE/FTE tablere-typere-align⚠ drifts in betweenAFTER🎫 GitHub issuesingle source of truthActioncapacity matrixgenerated — nothing to keep in sync

Left: the same numbers in two places, re-aligned by hand in both directions, drifting in between. Right: written once in the issue, read by the Action, rendered as output. The second copy is gone rather than automated.

What it does

Turns the Objective issues on a Projects v2 board into a capacity picture: who is allocated to what, at what fraction of an FTE, in which Program Increment. It joins each issue’s ## LOE/FTE body table with that issue’s PI and date fields from the board, then renders

Where the data comes from

The FTE Capacity Report composite action (the repo’s root action.yml) generates fte_allocations_*.csv, fte_by_person_*.csv, fte_by_role_*.csv and fte_summary_*.md, and publishes them to the fte-report/all-pis branch. The SPA fetches those CSVs at runtime and falls back to the snapshot bundled in public/data/. The header shows ● live or ○ snapshot so you can tell which you are looking at.

Reading a Projects v2 board needs PROJECT_TOKEN_FOR_BOARD_READS — a token with repo + read:org + project. The default GITHUB_TOKEN cannot do it.

Run it locally

cd fte-dashboard
npm install
npm run dev

# Regenerate the report offline, without a token or network:
python .github/scripts/generate_fte_report.py \
  --issues-json seed/sample_issues.json --out-dir reports