Skip to content

Parked idea: personal sprintx — per-owner sprint metric/goal model (removed as dead code) #438

Description

@bdelanghe

Context

While pruning knip-flagged dead code we removed packages/prx/src/pr-state/personal_sprintx.ts — a complete, never-wired feature (no verb, no surface, zero importers). It's a real idea worth keeping on the backlog, so capturing it here before it's only recoverable from git archaeology.

The full implementation is recoverable from git history at the commit just before the pruning commit (branch claude/prune-dead-machine-shims). Path: packages/prx/src/pr-state/personal_sprintx.ts.

The idea

A personal sprint layered over the unit-of-work surface: tie a set of UoWs to a single weekly outcome and a measurable metric, then derive live progress from board state.

Config (zod personalSprintxSchema, .strict()):

  • sprintId, owner
  • weeklyGoal: { outcome, metric, targetDelta, assignedUowIds: CanonicalId[] }
  • sprintGoal: { outcome, metric }
  • metric: { baseline, current } (nullable)
  • bindings: Record<CanonicalId, { metric, expectedDelta? }> — which UoW moves which metric
  • velocity: { pointsCompleted? }

Derivation (derivePersonalSprintx(surface, config) → PersonalSprintxDerived):

  • Assigned rollup from board state: total / contributing / merged / blocked / running, where
    • merged-like = merged | cleaned | merge_ready
    • blocked-like = changes_requested | no_worktree | worktree_created
    • running = row.agent.state === "running"
    • contributing = the row's binding metric matches the weekly-goal metric (vs. "non-goal")
  • Metric status (metricStatus): deltaPercent = (current-baseline)/baseline*100; metTarget honors sign of targetDelta (improvement can be negative-is-better); progressPercent clamped 0–100; status ∈ met_target | on_track | at_risk | failed_target (with a "moved wrong direction" → failed_target rule). Null-safe (missing baseline/current ⇒ at_risk).
  • goalRows: per-UoW { id, board, prNumber, contribution }.
  • ID normalization throughout (trim().toUpperCase(), canonical ^[A-Z][A-Z0-9]+-\d+$).

Why it's interesting (and why it was parked)

It connects the work-unit surface to an outcome layer — "did this week's PRs move the number I said they would?" — rather than just counting throughput. That's aligned with the value-props/forcing-function framing.

It was never given a CLI verb or a surface projection, so it sat as dead code. To revive for real:

  • Add a prx sprintx (or surface-axis) verb that loads the config (loadPersonalSprintxConfig(path)) and renders derivePersonalSprintx.
  • Decide where metric.current comes from (manual config vs. a metrics source).
  • Tests + a changeset + docs/cli.md entry.

Also removed (no capture needed)

The machine/{index,events,state,derive-phase,invariants}.ts files were pure re-export shims (a convenience barrel aliasing @bounded-systems/machine-schema + machines/pr.ts) with zero importers — no design to preserve. If a single machine/ facade import path is wanted later, it's a one-line barrel to recreate.

https://claude.ai/code/session_01LPzb9h4TgS7zCB4vWtNiS4

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions