Skip to content

feat: banded context layer — cited typical ranges under every KPI #48

Description

@gkanitz

Context

Slice A of the v0.2 "Meaning" wave. Shared design context:
docs/superpowers/specs/2026-07-04-impact-roadmap-design.md (PR #47).

Raw numbers ("median time to merge: 18.5h") are verifiable but not legible to
a recruiter. This slice gives every headline KPI a cited, caveated typical
range
sourced from published research/industry benchmarks — banded context,
never percentiles, never judgments.

Goal (vertical slice)

Embedded bands data → report schema block → rendered context lines, end to end.

In scope

  • metrics/bands/bands.json embedded via go:embed, with top-level version
    and one entry per metric key: time_to_first_review, time_to_merge,
    rework_share, deep_review_share, pr_size_lines (dormant until the
    PR-size slice lands). Each entry: key, range (lo, hi, unit), label copy,
    source (title, url, year), caveat copy.
  • Starting band values from the spec's research-grounding section (re-verify
    sources when transcribing): TTFR median 7–12h (LinearB 2025) / ~15h org
    median (Code Climate Velocity); PR size 200–400 lines recommended
    (arXiv 2203.05045 + industry guidance); revert/rework framing per spec.
  • metrics/bands package: Lookup(key) (Band, bool).
  • Report schema: optional top-level bands block {version, entries[]}
    populated with exactly the entries whose metrics are present in the report.
  • Render: context line under each KPI that has a band — range + citation +
    "ranges vary by team size and workflow" caveat. Neutral styling only.
  • Golden-file updates; JSON round-trip.

Out of scope

  • PR-size metric itself (separate slice), narrative copy (separate slice),
    any new API fetching.

Design constraints

  • Privacy safeguards catalog (spec): GitLab provider adapter with cross-adapter parity tests #7 no-judgment copy.
  • schema_version stays v0; block is omitempty; Validate() must keep
    accepting reports without it.
  • The rendered context must be derived from the report's own bands block,
    not re-read from the embedded file at render time — what is shown is what
    is attested.

Acceptance criteria — TDD

Success (write these tests first; all must pass)

  1. Lookup returns the entry for every key in bands.json; unknown key →
    ok == false.
  2. Every bands.json entry has non-empty key, range, unit, label, source
    title+url+year, caveat (schema-completeness test over the embedded file).
  3. report.Build populates bands with exactly the entries for metrics
    present in the report: a report without time_to_first_review carries no
    TTFR band entry.
  4. report.Parse on the existing pre-bands sample JSON still validates
    (backward compat).
  5. A report with a bands block round-trips through JSON marshal → Parse →
    Validate.
  6. Rendered HTML for the full sample report shows one context line per banded
    KPI, containing the range, at least one citation (source title + year),
    and the caveat sentence — asserted against updated goldens.
  7. Sparse report (metric absent) renders no orphan context line for it.
  8. Metric present but no band entry → no context line, no error.
  9. Context-line markup carries no judgment/state styling: rendered HTML
    contains none of success, danger, warning, error classes on
    context elements, and band/label/caveat copy contains no word from the
    grading wordlist (excellent, strong, weak, slow, fast, top,
    elite, poor).
  10. Prohibited-strings golden test (seeded colleague/PR-title/branch strings)
    still passes over the new output.

Failure — QA red flags (any one observed → reject the PR)

  • A context line rendered without a resolvable citation, or with values that
    differ from the report's bands block (e.g. hardcoded in the template).
  • Band presented as a percentile, score, grade, or colored judgment.
  • Validate() rejects pre-v0.2 report JSON, or the schema version was bumped.
  • Bands rendered for metrics that are absent from the report.
  • Band values transcribed without their source, or sources invented.

Parallel-work contract

  • Territory: metrics/bands/ (new), render/templates/ (new partial +
    additive includes), render/testdata/ goldens.
  • Shared, additive-only: report/report.go (new optional block only),
    render/render.go (wiring only), render/templates/layout.tmpl.
  • Depends on: nothing — start immediately. Slices C/E consume this via
    the band keys; coupling is via the key strings only.

Definition of done

TDD skill followed (tests first); all success criteria green; goldens
updated; go test ./... passes; PR references this issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    readyLoop-ready: this org's picker reads this labelready-for-agentTriage complete; ready for an agent to pick up

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions