Headless Project Management: A Status Report That Cannot Lie
- #ai-governance
- #autonomous-agents
- #mechanical-enforcement
- #project-management
- #case-study
- #driftless
Project management software assumes a human at a screen. Take the human away — let an agent loop run the process — and most of what remains is theater: status fields someone types, dashboards someone reconciles, documents someone forgets to update. driftless is an internal service built on the opposite assumption. It is project management as a system of record with no screen required, and it applies the same principle this journal keeps returning to: behavioral rules are suggestions; structure is a constraint.
The Failure Mode Is Drift, Not Laziness
Every PM tool degrades the same way. The plan says one thing, the tracker another, the weekly status deck a third. Nobody lied on purpose. Three copies of the truth existed, each hand-maintained, and they drifted — the same way a CLAUDE.md rule drifts from what the hook actually enforces.
The conventional fix is process: reconciliation meetings, report reviews, a rule that says “update the tracker before standup.” Those are behavioral rules. They hold exactly as long as nobody is under pressure, which is to say they do not hold.
driftless takes the mechanical route. There is one normalized store. Dashboards, rollups, and generated documents are queries over it — never stored copies. The design rule inside the repo is blunt: if a “reconciliation” or “sync check” job ever looks necessary, the schema is wrong. Fix the schema.
Honesty by Construction
The interesting parts are the places where a dishonest state is not forbidden but unrepresentable.
| Surface | Structural rule |
|---|---|
| Percent complete | A status snapshot stamps its percent from the calculation core. The API refuses to accept one from the request — typed progress does not exist. |
| Baselines | Re-baselining inserts a new version; the old plan is never edited. Plan history is additive by construction. |
| Audit trail | An append-only ChangeLog is written by a SQLAlchemy flush listener, not by calls at each write site — no path that writes through a session can skip it. |
| Sign-offs | Append-only ledger. A reversal is a new row, not an edit. |
| Threat feed | A sign-off suppresses a threat only while its score stays no worse than at sign-off. A regression re-surfaces it automatically — a sign-off cannot bury a slide. |
| Generated documents | Every report takes an explicit as-of date and regenerates byte-identical from live data. Human narrative is a first-class field on the record, so it survives regeneration. |
That last row is the tell for the whole design. Templates never read the wall clock. “Generate twice, get identical bytes” is a tested property, which means a report can be deleted at will — it was never the artifact. The store is the artifact.
Where the Agents Come In
The service models the 49 PMBOK processes — inputs, tools, outputs — as a versioned in-code catalog. Each project’s state on each process is computed from which artifacts actually exist in the store plus the sign-off ledger: not-started, in-progress, produced, signed-off, or waived. There is no ProcessInstance table to update, so process state cannot disagree with reality. Tailoring a process out is itself a ledger entry.
On top of that sits a wizard that is deliberately agent-drivable:
driftless wizard next --project Xreturns the next incomplete process as JSON — which inputs exist, which are missing, what output can be produced.driftless wizard applyproduces that output through the same validated API boundary the HTTP endpoints use — schema validation, parent checks, audit trail.
An agent loop can stand a project up end to end with no human in the loop, and the ChangeLog proves every write went through the boundary. This is the part I mean by headless: not “no UI exists” — there is a small server-rendered dashboard — but that the UI is a reader, not a privileged writer. The human and the agent go through the same gate, and the gate is the only door.
The governance parallel is exact. A PreToolUse hook does not trust the agent to use the Read tool; it rejects cat. This store does not trust anyone — human or agent — to type an honest percent complete; it computes one. Same move, different layer.
What This Buys Under Pressure
Pressure is when project reporting fails. The week the numbers are bad is precisely the week someone smooths the status deck. An agent under context pressure does the equivalent: it summarizes optimistically, marks the task done, moves on.
Here, the bad week is structurally identical to the good week. Earned value, forecasts, and the threat ranking are pure functions over stored rows. The Monte Carlo completion forecast is seeded — same seed, same percentiles. The number on the dashboard and the number in the generated document come from the same calculation module and cannot disagree. Nobody smooths anything, because there is nowhere to type.
Status
driftless runs Back Road Creative’s actual portfolio, program, and project management — it is an internal service, not yet a public tool. The code is private today; if that changes it will get the rigscore treatment: a public repo, versioned releases, and a product page here. The service was renamed from its working name this week, which is its own small case study in why generic names are unrecoverable once the niche is crowded.
The principle travels regardless of the code: wherever an agent (or a tired human) reports on work, find the field they can type a comfortable lie into — and delete the field.
Configuration details reflect a production environment at time of writing. Implementation specifics vary based on tooling versions, platform updates, and organizational requirements. Validate approaches against current documentation before deployment.