Skip to content

feat(workforce-planning): prep staffing meetings for project staff with an interactive plan - #5

Merged
mikeastock merged 2 commits into
mainfrom
feat/workforce-staffing-plan
Oct 5, 2026
Merged

mikeastock merged 2 commits into
mainfrom
feat/workforce-staffing-plan

Conversation

@mikeastock-bot

@mikeastock-bot mikeastock-bot commented Oct 5, 2026 •

Copy link
Copy Markdown

Reframes workforce-planning from a weekly crew-hours calculator into what commercial GC ops teams actually do: prep the staffing meeting for salaried project staff (PMs, supers, PEs, APMs, assistant supers), allocated by month, with pursuits weighted by win probability.

  • In: the files ops already keeps: a messy people × month staffing sheet, the project list, the CRM pursuit export, and the HR roster
  • Out: a meeting brief (Markdown), plus one self-contained interactive HTML plan:
    • mark pursuits weighted, won, or lost
    • try what-if moves (the Try button on each unfilled seat pre-fills one)
    • export a scenario and import it next meeting
  • Crew scheduling, payroll, and performance ranking are out of scope
Preview (Decisions for the meeting)
Preview
Preview (Who is where (pencilled pursuit work dashed))
Preview
Preview (Unfilled seats with ranked options and Try)
Preview
flowchart LR
  A[staffing sheet<br>project list<br>CRM export<br>roster] -->|agent normalizes,<br>logs open questions| B[staffing-data.json]
  B --> C[plan.mjs]
  C --> D[staffing-brief.md]
  C --> E[staffing-plan.html]
  E -->|toggle pursuits,<br>what-if moves| E
  E -->|export / import| F[scenario.json]
  F -->|--scenario| C
Loading

How it works

  • scripts/staffing-core.mjs is a pure module with no dependencies that does validation, analysis, and rendering. plan.mjs inlines it into the HTML, so the browser recalculates with the exact same code. The HTML is pre-rendered, so it still reads correctly with scripts disabled (for example in the marketing site's sandboxed preview).
  • Analysis:
    • load against capacity (leave, start and end dates)
    • overloads over any rolling 3 months against role limits (PM 120%, super 100%)
    • assigned-while-unavailable conflicts
    • unfilled seats from each job's planned team
    • certification gaps (for example, no ICRA on a hospital tie-in)
    • ranked internal candidates with a suggested move
    • roll-offs
    • role balance and hiring signals
    • pencilled people who would go over if a pursuit is won
node scripts/plan.mjs staffing-data.json staffing-plan.html --brief staffing-brief.md
node scripts/plan.mjs staffing-data.json --json --scenario exported-scenario.json

Sample

The sample company is "Halvorsen Builders" (invented): 34 staff, 9 jobs, 6 pursuits, Denver. The inputs have real-world mess:

  • nickname job codes, bare codes meaning 100%, pencilled RIV? work, a GS split with no percentages, and a "TBD Super" row
  • a substantial completion that slipped from April to July while the sheet still rolls the team off in April
  • a retirement, a new hire, parental leave, and a pursuit whose start date moved

The brief surfaces what an ops VP would ask about:

  • Wash Park has no superintendent
  • Tony retires mid-job on Arvada
  • the Union Station slip leaves 6 seats empty
  • Megan is staffed during her leave
  • Dave is pencilled for Riverside without ICRA

Also

  • Removes capacity.py, capacity-rules.md, and the old weekly samples and test
  • Adds node --test evals/tasks/workforce-planning/staffing-core.test.mjs to CI. The previous Python test never ran in CI.
  • Version 3.0.0 (outputs change); marketplace 0.5.0; catalog rebuilt

Note

Reframe workforce-planning skill to produce an interactive monthly staffing plan

  • Replaces the weekly capacity calculator (Python, weekly ledger) with a monthly project-staffing meeting prep workflow for salaried roles (PM, superintendent, PE, APM). The skill now normalizes a staffing sheet, project list, pursuits, and HR roster into a JSON data contract, then runs a Node.js script to generate a self-contained interactive HTML plan plus a Markdown brief.
  • Adds a dependency-free shared core (staffing-core.mjs) used by both the Node CLI (plan.mjs) and the generated browser app; it handles validation, scenario analysis, overloads (rolling 3-month average), unfilled seats, certification conflicts, roll-offs, and hiring signals.
  • The browser app (templates/app.js) supports pursuit-mode toggles, what-if moves, JSON scenario export/import, and CSV export. Embedded data is escaped to prevent script-tag breakout.
  • Adds a large Node test suite (staffing-core.test.mjs) and a CI validation step in validate.yml; the bundled sample outputs are compared byte-for-byte.
  • Behavioral Change: catalog version bumps from 2.0.0 to 3.0.0 and the old weekly assets (scripts/capacity.py, samples/input-week.json, references/capacity-rules.md) are removed; consumers of those package paths can no longer retrieve them.

Macroscope summarized ca927e8.

@macroscopeapp

macroscopeapp Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

Macroscope skipped reviewing this pull request. Per-review cost limit exceeded (workspace setting).

This review would cost an estimated $7.51, which exceeds your per-review limit of $3.00.

The top 3 files driving up this estimate:

File Diff Size Estimate
skills/workforce-planning/samples/staffing-data.json 48.45KB $2.42
skills/workforce-planning/scripts/staffing-core.mjs 45.39KB $2.27
skills/workforce-planning/SKILL.md 10.82KB $0.54

Tip

To get this pull request reviewed, you can:

  1. Comment @macroscope-app on this PR to request a manual review (monthly spend limits still apply).
  2. Exclude the file(s) above from review by adding a pattern to your .macroscope/ignore.md — note that creating this file replaces Macroscope's built-in default ignores rather than extending them.
  3. Raise your cost limit in your workspace billing settings.

Turn off this reminder going forward

@mikeastock
mikeastock merged commit 50f8d3f into main Oct 5, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants