Skip to content

Developer Productivity Dashboard — V1 Build-Out Playbook

Developer Productivity Dashboard — V1 Build-Out Playbook

STATUS: COMPLETE (as of 2026-07-23). T0/T1/T2 shipped and merged to dev. T3 and T5 were relocated to docs/playbooks/v2-team-velocity-playbook.md (owner: Fatima) — see that file for their live status. T4 (commit-trailer attribution) was deleted outright — the trailer convention was judged not the best solution for AI-attribution and will not be built; its work-item file was removed. New work (UI responsiveness, BOLDVelocity branding, Next.js/Vue migration) lives in docs/playbooks/v3-platform-modernization-playbook.md (owner: Sultan) and must land on dev before v2’s remaining tasks resume. This file is kept as the historical record for T0–T2; do not add new tasks here.

File: docs/playbooks/v1-dev-productivity-dashboard-playbook.md Base branch: dev (integration branch — main stays protected/production; PRs target dev) Branch naming: feature/<ado-task-id>-<slug>-v1-pr<n> (e.g. feature/112270-azure-devops-connector-v1-pr1) — PR-0 is the exception, committed directly to dev with no feature branch (see PR 0). Plan date: July 2026 Source spec: uploads/AlphaBOLD_Dev_Productivity_Dashboard_Design.docx (extracted to scratch/extracted_text.txt), Sections 5–9


How to Use This Document

Single source of truth for turning the current repo — a design-canvas mockup (Developer Productivity Dashboard.dc.html + mockData.js) of the chosen “Editorial Soft” dashboard design — into the real system described in the design doc’s Section 5 (Recommended Architecture) and Section 8 (Implementation Roadmap): connectors → metrics store → served dashboard → optional AI Assistant. Each PR has a verbatim prompt block — copy the fenced block, paste into a fresh Claude Code session, let it execute.

Task order is T0 → T1 → T2 → T3 → T4 → T5, matching the roadmap’s phase order (Section 8). PR numbers now match task numbers 1:1 (PR-0 = T0 … PR-5 = T5). Each phase’s PR(s) branch from the previous phase’s merged work — this is a straight stack, not a fan-out, because each phase’s connector/API is additive on top of the last (Section 6.3: “Build in phases, not all at once”).

Reference inside Claude Code:

@docs/playbooks/v1-dev-productivity-dashboard-playbook.md read section "PR 1" and execute the prompt verbatim

0. Prerequisite — Baseline Commit

This directory is currently untracked in its git repo (~/Projects, branch main) — the mockup files (Developer Productivity Dashboard.dc.html, mockData.js, support.js, assets/, CLAUDE.md, USAGE.md) have never been committed. Before any PR branches, commit the existing prototype to main as-is (it is the visual spec PR-0 works from — do not modify it as part of this commit). No PR in this playbook should be the one that first introduces these files.

Then cut dev from main. PR-0 (T0) is committed directly to dev — no feature branch, no PR review — since it’s the bootstrap step that establishes dev’s initial working state (shell extraction + graphify knowledge graph). Every PR from PR-1 onward branches from dev or a prior PR’s branch, and goes through the normal feature-branch + PR review flow back into dev. main stays the protected production branch; promoting devmain for a release is a separate, later decision outside this playbook’s scope.


1. Executive Summary

#ItemStatus / GapRoadmap phase
T0The dashboard design exists only as a stakeholder-review canvas (.dc.html, CDN-loaded React/Babel via support.js, not shippable)No production dashboard shell exists yet; mock data is hardcoded in-repo with no served APIPhase 1 (shell) — DONE, merged to dev
T1No connector layerNo code pulls Git/Azure DevOps activity; mockData.js fabricates commits/PRs/velocity instead of reading real dataPhase 1 (connector) — DONE, merged to dev
T2No metrics store or read APIDashboard reads mockData.js directly in-browser; nothing persists or pre-aggregatesPhase 1 (store + API) — DONE, merged to dev
T3No AI-tool usage dataCopilot Metrics API, Copilot Studio, and Claude Code Admin API are not integrated; tool-adoption sparkline has no real backing dataPhase 2 — relocated to v2-team-velocity-playbook.md, on hold (blocked on IT secret-key provisioning for Copilot/Copilot Studio/Claude Code Admin API credentials)
T4No AI-attribution layerDELETED. Commit-trailer attribution (Assisted-By: copilot/claude-code) judged not the best solution; no replacement scoped yet.Phase 3
T5No natural-language query layerNo AI Assistant/chatbot exists over the metrics store; design doc’s optional Claude Code Skill (Appendix A) is superseded by an assistant integration per this playbook’s latest revisionPhase 4 — relocated to v2-team-velocity-playbook.md

Initial AI-tools integration scope: V1 (T3/T4) integrates exactly three AI tools — GitHub Copilot, Copilot Studio, and Claude Code. Cursor is not part of this initial integration (no usage connector, no commit-trailer value, no export ingestion); revisit as a P2 addition if adoption data shows real Cursor usage worth tracking.

PR Strategy — DONE: PR-0 through PR-2 (T0–T2), merged to dev. PR-3/PR-5 relocated, PR-4 deleted.

  • PR-0 carries T0: extract the chosen “Editorial Soft” design out of the .dc.html canvas format into a plain dependency-free static page, still fed by mockData.js (unchanged data contract), plus a graphify knowledge-graph pass over the repo. Committed directly to dev — no feature branch, no PR review — since this establishes dev’s initial working state. DONE.
  • PR-1 carries T1: the Azure DevOps connector (Section 5.1) — a scheduled, code-only script, no LLM calls. Branches from dev. DONE.
  • PR-2 carries T2: the metrics store (Section 5.2, SQLite for the pilot) and thin read API (Section 5.3), and switches the dashboard shell from mockData.js to real API calls behind the same data shape, so PR-0’s UI code needs no rewrite. Branches from PR-1. DONE — PR-1/PR-2 merged to dev together as the Phase 1 checkpoint.
  • PR-3 (T3) and PR-5 (T5): relocated to docs/playbooks/v2-team-velocity-playbook.md (owner: Fatima). See “PR 3”/“PR 5” pointer sections below.
  • PR-4 (T4): deleted — see “PR 4” pointer section below.

Merge Sequencing

  1. PR-0 (T0) → committed directly to dev. DONE.
  2. PR-1 (T1)DONE.
  3. PR-2 (T2)DONE — PR-1 + PR-2 merged to dev together as the Phase 1 MVP milestone.
  4. PR-3 (T3), PR-4 (T4), PR-5 (T5): see relocated/deleted pointer sections below — no further merge sequencing tracked in this file.

Model Guidance

PRTaskRecommended ModelEffortReason
PR-0T0 (design shell extraction + graphify)Sonnet 5mediumMechanical port of the canvas’s markup/CSS out of .dc.html binding syntax into plain JS, but needs care not to lose interaction behavior (filters, sort); plus a graphify pass
PR-1T1 (Azure DevOps connector)Sonnet 5mediumNew scheduled script + Azure DevOps Git REST API calls + normalization to Section 3’s metric definitions
PR-2T2 (metrics store + API)Sonnet 5medium-highNew schema, ingest-time aggregation, thin API layer, and swapping the dashboard’s data source without changing its rendering code

Model Guidance for T3/T5 now lives in v2-team-velocity-playbook.md. T4 is deleted — no guidance needed.


2. PR Plan

PRBranchItemsBranches fromEst.Status
PR-0(none — direct commit)T0dev (bootstrap)1–2 daysDONE
PR-1feature/112270-azure-devops-connector-v1-pr1T1dev3–4 daysDONE
PR-2feature/112271-metrics-store-thin-api-v1-pr2T2feature/112270-azure-devops-connector-v1-pr13–4 daysDONE
PR-3(relocated)T3see v2-team-velocity-playbook.md
PR-4(deleted)T4deleted 2026-07-23
PR-5(relocated)T5see v2-team-velocity-playbook.md

ADO task IDs: T0=112269, T1=112270, T2=112271, T3=112272, T4=112273 (work item deleted), T5=112274 (see work-items/).


3. Files Touched

File / pathPR
public/index.html, public/dashboard.js, public/dashboard.css (new)PR-0 (T0)
graphify-out/ (new — knowledge graph generated by the graphify skill)PR-0 (T0)
Developer Productivity Dashboard.dc.html, support.jsUnchanged — stay as the stakeholder-review canvas; not deleted
mockData.jsPR-0 (T0, consumed as-is), PR-2 (T2, superseded as the live data source — kept only as an offline fixture for local dev)
connectors/ado_connector.py (new)PR-1 (T1)
store/schema.sql, store/db.py (new)PR-2 (T2)
api/server.py (new — thin read API, Section 5.3)PR-2 (T2)

T3/T5 file lists (connectors, assistant/, chat widget) now live in v2-team-velocity-playbook.md. T4’s planned files (hooks/commit-trailer/) were never built — task deleted.


4. Hard Rules

  1. Metric definitions come only from Section 3 of the design doc (scratch/extracted_text.txt lines 38–64) — commit count, PR throughput, AI-assisted %, churn, velocity, cycle time, tool adoption. Connectors normalize to these definitions; never invent a new metric or redefine an existing one to fit a data source’s native shape (Section 9 risk: “Metric definitions drift across tools”).
  2. No connector, store, or API layer makes an LLM call. Section 5.1 is explicit: “No LLM calls happen in this layer — it is pure, deterministic ETL.” The only phase allowed to call an LLM is PR-5’s AI Assistant, and only on-demand, per user question.
  3. “AI-assisted %” must ship as a blended, labeled metric (tool-reported layer + commit-attribution layer, Section 4) — never present it as a single precise number implying per-commit certainty the data doesn’t support.
  4. Do not build the AI-attribution commit-trailer convention (PR-4) as an org-wide rollout. Moot — PR-4/T4 deleted 2026-07-23 (commit-trailer attribution judged not the best solution). Kept here as historical context only; no replacement attribution approach is scoped yet.
  5. Each connector is isolated and independently versioned (Section 9: “Keep each connector isolated and versioned so one vendor’s API change doesn’t break the whole pipeline”) — a Copilot API schema change must not require touching ado_connector.py, copilot_studio_connector.py, or claude_code_connector.py, and vice versa.
  6. Store aggregated results, not raw API payloads (Section 6.4). Raw connector responses may be cached transiently for debugging but are not the persisted store schema.
  7. If PR-5’s AI Assistant is built, keep the system prompt schema-grounded and minimal (Section 6.2’s spirit) — tool definitions + a short instruction to call a tool and summarize, nothing more. Detailed schema/edge-case docs go in a separate reference file the assistant only pulls in when a question needs it, not inlined into the system prompt.
  8. UI framing must keep individual metrics contextualized against team/sprint averages (Section 2, Section 7.2, Section 9) — never ship a raw per-person leaderboard sort with no team baseline shown alongside.
  9. Co-authored-by: Claude trailer forbidden on commits. Use the commit-msg skill.
  10. All repos hosted on Azure DevOps (ADO), not GitHub — connectors (PR-1 onward) target the ADO Git REST API. See PR 1’s “Data Source” subsection for exact endpoints/auth.
  11. Branch names follow feature/<ado-task-id>-<slug>-v1-pr<n> (§2 table) — PR-0 is the sole exception, committed directly to dev with no feature branch.
  12. No automatic git actions. Never stage, commit, or push without explicit user approval — once implementation is complete and all tests/checks pass, stop and confirm with the user first. On approval: stage all files, commit (via commit-msg skill), push. No PR is opened as part of this workflow.

5. Out of Scope

  • Real-time/live-polling refresh — Section 5.2 is explicit that aggregation happens once, on ingest, not on every dashboard view. Scheduled (hourly cron / Azure Pipelines schedule) refresh only.
  • A fully custom analytics UI framework — Section 7 doc already specifies the exact layout (top bar, KPI row, main row, team table, secondary row); PR-0 is a port of that spec, not a redesign.
  • Cursor integration of any kind (usage connector, commit-trailer value, export ingestion) — initial AI-tools scope is GitHub Copilot, Copilot Studio, and Claude Code only (see Executive Summary). Also no stable public Cursor API exists today (Section 4, Section 9) even if it were in scope. Revisit as a P2 addition.
  • Running the whole dashboard through the AI Assistant — Section 5.4 explicitly rules this out (“a conversational layer on top of the dashboard, not the dashboard’s engine”); the assistant in PR-5 is additive, not a replacement rendering path.
  • GraphRAG or a vector-embedding index for PR-5’s MVP — the metrics store is small, structured, and already has an aggregation API (Section 5.3); a schema-grounded tool-calling assistant answers correctly without a new retrieval index. Revisit only under the P2 conditions in PR-5’s “RAG Strategy” subsection.
  • Individual performance-review scoring, alerts, or ranking features — Section 2’s explicit non-goal (“not as an individual performance-review score”).

6. Per-Session Contract

Every session:

  1. Branch from prior PR’s branch (per §2 table) — except PR-0, which works directly on dev.
  2. Scoped changes only — no opportunistic cleanup of Developer Productivity Dashboard.dc.html (it stays as the stakeholder-review artifact, untouched by these PRs).
  3. Add a runnable check for any new non-trivial logic (connector normalization, aggregation, API route) — a small pytest test file for Python, or an assert-based self-check script; no test framework scaffolding beyond what the PR’s own code needs.
  4. All checks green before commit (pytest for Python pieces once introduced in PR-1; plain node --check / manual load via a local static server for PR-0’s JS).
  5. Once all checks are green, stop and confirm with the user before any git action — do not stage, commit, or push without explicit approval (see Hard Rule 12).
  6. On approval: git add -A, commit-msg skill for the message (no Claude co-author trailer), git push -u origin <branch> (PR-0 pushes directly to dev: git push origin dev).
  7. No PR is opened — push is the last step. This contract applied to T0–T2 only; T3/T5 now follow v2-team-velocity-playbook.md’s contract, T4 is deleted.

PR 0 — Extract a shippable dashboard shell from the design canvas + graphify integration (T0)

Merge model: direct commit to dev — no feature branch, no PR review (bootstrap step) ADO task: 112269 Model: Sonnet 5 Effort: medium

Problem

Developer Productivity Dashboard.dc.html is a design-review tool artifact, not production code: it depends on support.js pulling React/ReactDOM/Babel from unpkg.com at runtime, and uses a proprietary <x-dc>/{{ }}/sc-if template-binding syntax meant for a design canvas editor. Section 5.3 calls for “a static/served web page (React or plain HTML/JS)”; per Ponytail’s ladder (rung 4/6: native platform features over dependencies, shortest working code), a plain dependency-free static page is the right size for a dashboard whose only interactivity is filter dropdowns, sort-on-click columns, and chart rendering already fully specified by the mockup’s markup — no React/build toolchain needed.

Because this is the first work to land on dev, it is committed directly to dev rather than through a feature branch + PR — there is no prior dev state to protect with a review gate yet. PR-1 onward branch from this baseline and go through the normal PR flow.

Required change

  1. Create public/index.html + public/dashboard.js + public/dashboard.css: the canvas’s “Editorial Soft” markup, colors, and layout (top bar, KPI row, velocity + composition charts, team table, secondary row — Section 7.1), translated from the canvas’s {{ dash.field }} bindings into plain DOM updates driven by a small state object (project filter, tool filter, date-range key, sort key/dir) — same shape as the existing buildDash() logic in the .dc.html script block.
  2. Keep consuming mockData.js’s generateDataset() / aggregate() unchanged — this PR is shell-only; PR-2 is what swaps the data source to the real API. Import it as a plain ES module the same way the canvas script does (import('./mockData.js')).
  3. Leave Developer Productivity Dashboard.dc.html and support.js in place, untouched — they remain the stakeholder-review artifact, independent of the production shell.
  4. Update USAGE.md with how to run the new public/ shell alongside the existing canvas instructions (both need a static HTTP server per the existing CORS note).
  5. Run the graphify Claude Code skill/plugin against the repo once the shell lands, to generate graphify-out/ — a persistent knowledge graph of the codebase (files, components, data-shape relationships between mockData.js, the canvas, and the new public/ shell). Commit graphify-out/ alongside the shell so PR-1 onward (and any future session) can query codebase relationships via graphify instead of re-deriving them from scratch each session.

Prompt — paste verbatim into Claude Code

You are implementing PR-0 of the Dev Productivity Dashboard build-out playbook
(docs/playbooks/v1-dev-productivity-dashboard-playbook.md).
Read the full PR-0 section before writing any code.
This is a direct commit to dev — no feature branch, no PR review. Work
directly on the dev branch (git checkout dev — cut it from main first if
it doesn't exist yet, per Section 0).
Scope — T0 ONLY. Create ONLY public/index.html, public/dashboard.js,
public/dashboard.css, and (STEP 4 below) graphify-out/. Do not modify
"Developer Productivity Dashboard.dc.html" or support.js — they stay as-is,
the stakeholder-review canvas. You may update USAGE.md to document the new
shell.
═══════════════════════════════════════
STEP 1 — Read the canvas
═══════════════════════════════════════
1. READ "Developer Productivity Dashboard.dc.html" in full, in particular
the "<script type=\"text/x-dc\" data-dc-script>" Component class at the
bottom of the file (buildDash(), toolColor(), renderVals()) — this is
the source of truth for what data each visual element binds to.
═══════════════════════════════════════
STEP 2 — Extract the shell
═══════════════════════════════════════
2. WRITE public/index.html: the canvas's HTML structure and inline
styles, with the {{ }} template bindings and sc-if/sc-for canvas
directives replaced by plain elements with IDs/classes dashboard.js can
target. Keep the AlphaBOLD visual language (warm off-white canvas,
near-black text, gold #E3AD21/#CB9328 accent, Manrope font) exactly as
in the source markup — this is a port, not a redesign.
3. WRITE public/dashboard.js: a plain ES module (no React, no JSX, no
build step) that:
- imports generateDataset and aggregate from ./mockData.js
- holds filter/sort state (project, tool, date range, sort key/dir) —
same fields as the canvas's state (projectFilter, toolFilter, etc.)
- re-renders the KPI row, velocity chart, composition chart, team table,
and repo/tool-adoption charts from aggregate()'s output whenever state
changes
- wires the project selector, date-range picker, tool filter pills, and
sortable column headers to update state and re-render
4. WRITE public/dashboard.css: extracted inline styles from the canvas's
markup, deduplicated into classes.
═══════════════════════════════════════
STEP 3 — Verify
═══════════════════════════════════════
5. Serve public/ with `python3 -m http.server` from that directory (or
equivalent) and load it in a browser. Confirm: KPI row populates,
velocity/composition charts render, team table sorts on column click,
project/tool/date filters update all widgets together (Section 7.2 —
shared filters, not per-widget).
6. Add a minimal assert-based self-check (e.g. public/dashboard.test.js
run via `node public/dashboard.test.js` or similar, no framework) that
imports aggregate() from mockData.js with a fixed filter set and asserts
the shape dashboard.js depends on (teamRows, kpis, repoBars, etc.) is
present — this guards the PR-0/PR-2 data-shape contract described in
the playbook.
7. Update USAGE.md: add a "Production shell (public/)" section alongside
the existing canvas-viewing instructions, noting it also requires an
HTTP server (same CORS reason as the canvas file) for mockData.js's
dynamic import.
═══════════════════════════════════════
STEP 4 — Graphify integration
═══════════════════════════════════════
8. Invoke the `graphify` skill/plugin against the full repo (canvas +
mockData.js + the new public/ shell) to build a persistent knowledge
graph of the codebase. Commit its output directory (`graphify-out/`) so
later PR sessions in this playbook can query file/component
relationships via graphify rather than re-deriving them from scratch.
Once implementation is complete and all tests pass, STOP. Do not stage,
commit, or push anything — confirm with the user first.
On user approval only:
1. git add -A (stage all files).
2. Commit via the commit-msg skill.
Suggested title: "feat: dpd PR-0 — extract shippable dashboard shell from design canvas + graphify integration (T0)"
Resolves: #112269
3. git push origin dev (direct commit — no PR to open, no feature branch).
No Co-authored-by: Claude trailer.

PR 1 — Azure DevOps connector (T1)

Branch: feature/112270-azure-devops-connector-v1-pr1 Branches from: dev Model: Sonnet 5 Effort: medium

Problem

No code pulls real commit/PR/cycle-time data. Section 6.3 (“Start with Git data only … to prove the dashboard shell and UI end-to-end”) and Section 5.1 (“Small scripts … run on a schedule … call the Git host’s … Admin APIs and drop normalized JSON/rows into a lightweight database … No LLM calls happen in this layer”) define this PR’s scope precisely: a deterministic, scheduled script, Git-host only, no AI-attribution guessing (that’s PR-3/PR-4). All repos are hosted on Azure DevOps (ADO) — this connector targets ADO’s Git REST API, not GitHub.

Data Source — Azure DevOps (ADO)

Verified via Microsoft Learn.

Git API (commits, PRs, repos)

PurposeEndpoint
Overviewhttps://learn.microsoft.com/rest/api/azure/devops/git/?view=azure-devops-rest-7.1
Commits — Get Commitshttps://learn.microsoft.com/rest/api/azure/devops/git/commits/get-commits?view=azure-devops-rest-7.1
Pull Requests — Get Pull Requestshttps://learn.microsoft.com/rest/api/azure/devops/git/pull-requests/get-pull-requests-by-project?view=azure-devops-rest-7.1
Repositories — Listhttps://learn.microsoft.com/rest/api/azure/devops/git/repositories/list?view=azure-devops-rest-7.1

Auth

PurposeEndpoint
Authentication guidance (PAT vs Entra ID vs service principal)https://learn.microsoft.com/azure/devops/integrate/get-started/authentication/authentication-guidance
Create/use PAThttps://learn.microsoft.com/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops
REST API request pattern + auth headerhttps://learn.microsoft.com/rest/api/azure/devops/?view=azure-devops-rest-7.2

Token (PAT or Entra ID) read from an environment variable, never hardcoded.

Required change

  1. connectors/ado_connector.py: calls the Azure DevOps Git REST API (Commits — Get Commits; Pull Requests — Get Pull Requests; Repositories — List, per the table above) for commits (to default/release branches), PRs (opened/reviewed/merged with cycle time), scoped to the org/project/repos the design doc’s mockup models (Atlas Platform, Beacon Analytics, Nimbus CRM, Foundry API, Lighthouse Mobile and their repos, per mockData.js’s PROJECTS/REPOS — real org/project/repo config replaces this fixture list before Phase 1 ships, but keep the same shape: project → repos → contributors).
  2. Normalize to Section 3’s exact definitions: commit count (merged-to-default/release only), PR throughput with cycle time (open→merge), churn (lines added+removed, supporting signal only — never surfaced as a target metric).
  3. No database yet (PR-2 adds the store) — this PR writes normalized rows to local JSON files under a connectors/output/ scratch path so PR-2 has a concrete shape to ingest, and so this PR is independently testable without the store existing.
  4. Runs via a script entrypoint suitable for cron or an Azure Pipelines schedule (Section 5.1) — no long-running process, no polling loop.
  5. Auth via a PAT (or Entra ID token) read from an environment variable (e.g. ADO_PAT), never hardcoded, sent as the standard ADO REST auth header (Basic, empty username + PAT as password, or a bearer Entra ID token) per the auth endpoints above.

Prompt — paste verbatim into Claude Code

You are implementing PR-1 of the Dev Productivity Dashboard build-out playbook
(docs/playbooks/v1-dev-productivity-dashboard-playbook.md).
Read the full PR-1 section (including its "Data Source — Azure DevOps (ADO)"
subsection), and Section 3 (Metrics Framework) and Section 5.1 of
scratch/extracted_text.txt, before writing any code.
Branch: feature/112270-azure-devops-connector-v1-pr1 from dev.
Scope — T1 ONLY. Create ONLY connectors/ado_connector.py and its test file
(tests/test_ado_connector.py). Do not touch public/ or mockData.js.
═══════════════════════════════════════
STEP 1 — Read the metric definitions
═══════════════════════════════════════
1. READ scratch/extracted_text.txt lines 38-64 (Section 3, Metrics
Framework table) and lines 65-85 (Section 4, Data Source Feasibility —
the Git-host row). These are the exact definitions to normalize to; do
not invent your own commit/PR/cycle-time semantics. The design doc's
Git host is Azure DevOps (ADO) for this org — use the ADO Git REST API
endpoints listed in PR-1's "Data Source" subsection above, not GitHub's.
═══════════════════════════════════════
STEP 2 — Build the connector
═══════════════════════════════════════
2. WRITE connectors/ado_connector.py:
- Accepts a list of {organization, project, repo_id, repo_name} configs
(start with a small hardcoded list matching mockData.js's PROJECTS/
REPOS shape — real org/project/repo config source is a follow-up, not
this PR's scope)
- For each repo, calls the Azure DevOps Git REST API for:
* Commits — Get Commits, merged to the default/release branch in a
given date range, grouped by contributor and day
* Pull Requests — Get Pull Requests, opened/reviewed/merged in that
range, with cycle time (opened_at → merged_at)
* lines added/removed per commit (churn — supporting signal only)
- Normalizes results into plain dicts matching Section 3's granularity
columns (repo, contributor, day/week/sprint as applicable)
- Is idempotent and safe to re-run (upsert semantics conceptually, even
though this PR writes to flat JSON not a DB yet)
- Writes output to connectors/output/ado_<date>.json (gitignore this
path — add connectors/output/ to .gitignore)
- No LLM calls anywhere in this file.
- ADO auth token (PAT or Entra ID) read from an environment variable
(e.g. ADO_PAT), never hardcoded — sent per the auth header pattern in
the REST API request docs linked in PR-1's "Data Source" subsection.
3. Add a script entrypoint (`if __name__ == "__main__":`) that can be
invoked directly for cron/Azure Pipelines scheduling, accepting a
--since/--until date range via argparse.
═══════════════════════════════════════
STEP 3 — Tests
═══════════════════════════════════════
4. WRITE tests/test_ado_connector.py: unit tests for the normalization
logic using mocked/fixture API responses (do not hit the real Azure
DevOps API in tests). Cover: commit grouping by contributor/day, PR
cycle-time calculation, churn is captured but not used as a target
metric anywhere in the output shape.
═══════════════════════════════════════
Verification
═══════════════════════════════════════
5. RUN pytest tests/ -v --tb=short. No failures.
Once implementation is complete and all tests pass, STOP. Do not stage,
commit, or push anything — confirm with the user first.
On user approval only:
1. git add -A (stage all files).
2. Commit via the commit-msg skill.
Suggested title: "feat: dpd PR-1 — Azure DevOps connector for commits, PRs, and cycle time (T1)"
Resolves: #112270
3. git push -u origin feature/112270-azure-devops-connector-v1-pr1. No PR to open.
No Co-authored-by: Claude trailer.

PR 2 — Metrics store + thin read API, dashboard goes live (T2)

Branch: feature/112271-metrics-store-thin-api-v1-pr2 Branches from: feature/112270-azure-devops-connector-v1-pr1 Model: Sonnet 5 Effort: medium-high

Problem

Nothing persists or pre-aggregates yet, and the dashboard shell built in PR-0 still reads mockData.js’s fabricated dataset in-browser. Section 5.2 (“pre-aggregated tables … Aggregation happens once, on ingest”) and Section 5.3 (“queries the metrics store directly through a thin API … costs nothing in AI tokens to view”) define the target: a database plus a small API, with aggregation done at ingest time, not on every page load.

Required change

  1. store/schema.sql: SQLite schema (Section 5.2: “Postgres, or even SQLite for a first pilot”) with pre-aggregated tables — daily commits per person, weekly velocity per team, AI-assisted % per repo (this last one stays 0/null until PR-4; do not fabricate it).
  2. store/db.py: ingest function that reads PR-1’s connector JSON output and writes/aggregates into the schema.
  3. api/server.py: a thin read API (pick the lightest option that satisfies “thin” — a single small HTTP server, no framework beyond what’s needed for a handful of GET routes) exposing the same filter shape the dashboard already uses (project, tool, date range) and returning data shaped like mockData.js’s aggregate() output, so public/dashboard.js only needs its fetch layer swapped, not its rendering logic.
  4. Update public/dashboard.js to call the API instead of importing mockData.js directly. Keep mockData.js in the repo as an offline/local-dev fixture (some way to run the shell without the store — e.g. an env flag or query param) rather than deleting it.

Prompt — paste verbatim into Claude Code

You are implementing PR-2 of the Dev Productivity Dashboard build-out playbook
(docs/playbooks/v1-dev-productivity-dashboard-playbook.md).
Read the full PR-2 section, and Section 5.2/5.3 of scratch/extracted_text.txt,
before writing any code. Read public/dashboard.js (from PR-0) in full first —
this PR must preserve its rendering logic, only swapping the data source.
Branch: feature/112271-metrics-store-thin-api-v1-pr2 from feature/112270-azure-devops-connector-v1-pr1.
Scope — T2 ONLY. Create store/schema.sql, store/db.py, api/server.py, and
their tests. Modify ONLY the data-fetching layer of public/dashboard.js
(not its rendering functions). Do not touch mockData.js's exports — it
stays as the offline fixture.
═══════════════════════════════════════
STEP 1 — Schema
═══════════════════════════════════════
1. WRITE store/schema.sql: SQLite tables for daily commits per
person/repo, weekly velocity per team/project, PR throughput with
cycle time, and an ai_assisted_pct table (repo, tool, period columns —
populate as 0/null for now, PR-4 fills it in). Match Section 3's
granularity columns exactly (repo, contributor, project, day/week/sprint).
═══════════════════════════════════════
STEP 2 — Ingest
═══════════════════════════════════════
2. WRITE store/db.py: a function that reads connectors/output/ado_*.json
(PR-1's output shape) and upserts into the schema — aggregation happens
here, at ingest time, not in the API layer (Section 5.2).
═══════════════════════════════════════
STEP 3 — Read API
═══════════════════════════════════════
3. WRITE api/server.py: GET routes that accept project/tool/date-range
filters and return JSON shaped like mockData.js's aggregate() return
value (teamRows, kpis, repoBars, velocityPoints, columns) — read
mockData.js's aggregate() function first to match its exact output
shape field-for-field, so public/dashboard.js's render functions don't
need to change.
═══════════════════════════════════════
STEP 4 — Wire the dashboard to the live API
═══════════════════════════════════════
4. In public/dashboard.js, replace the `import('./mockData.js')` +
in-browser aggregate() call with a fetch() to api/server.py's routes,
passing the same filter state. Keep a fallback/dev-mode path that still
uses mockData.js directly (e.g. gated by a `?mock=1` query param or
missing API reachability) so the shell remains runnable standalone per
USAGE.md's existing instructions.
═══════════════════════════════════════
STEP 5 — Tests
═══════════════════════════════════════
5. WRITE tests for store/db.py (ingest correctness against a fixture
connector JSON file) and api/server.py (route responses match the
expected aggregate() shape for a few filter combinations).
═══════════════════════════════════════
Verification
═══════════════════════════════════════
6. RUN pytest tests/ -v --tb=short. No failures.
7. Manually: run api/server.py, serve public/ over HTTP, load the
dashboard, confirm it renders from the live API (not mockData.js) with
data ingested from a sample connector JSON file.
Once implementation is complete and all tests pass, STOP. Do not stage,
commit, or push anything — confirm with the user first.
On user approval only:
1. git add -A (stage all files).
2. Commit via the commit-msg skill.
Suggested title: "feat: dpd PR-2 — metrics store, thin read API, dashboard wired to live data (T2)"
Resolves: #112271
3. git push -u origin feature/112271-metrics-store-thin-api-v1-pr2. No PR to open.
No Co-authored-by: Claude trailer.

PR 3 — Copilot, Copilot Studio, and Claude Code usage connectors (T3)

RELOCATED. Full spec, R&D, and prompt moved to docs/playbooks/v2-team-velocity-playbook.md (owner: Fatima) — on hold, blocked on IT provisioning the Copilot Metrics API / Copilot Studio Dataverse / Claude Code Admin API secret keys. See that file for current status and the verbatim prompt.


PR 4 — Commit-trailer attribution pilot (T4)

DELETED (2026-07-23). Commit-trailer attribution (Assisted-By: copilot/claude-code) was judged not the best approach for AI-attribution and will not be built. work-items/112273-commit-trailer-attribution.md was removed. No replacement is scoped yet — AI-assisted % stays tool-reported-layer-only (from T3) until a new attribution approach is decided.


PR 5 — AI Assistant/chatbot for ad-hoc querying (T5)

RELOCATED. Full spec, RAG strategy, and prompt moved to docs/playbooks/v2-team-velocity-playbook.md (owner: Fatima). See that file for current status and the verbatim prompt.


7. Verification Samples

After each phase merges, verify:

CheckpointVerify
Phase 1 (PR-0 direct-to-dev + PR-1/PR-2 merged)Dashboard loads over HTTP, renders from the real API (not mockData.js), filters/sort work end-to-end, ?mock=1 fallback still works offline
Any phaseEmpty/not-yet-connected sources show a “Connect Copilot Metrics API” / “Connect Copilot Studio” / “Connect Claude Code Admin API” state, per Section 7.2 — never a blank chart

PR-3/PR-4/PR-5 verification samples moved to v2-team-velocity-playbook.md (T4’s is removed — deleted task).


8. Rollback

  • PR-0 (T0, shell extraction + graphify): Since this is a direct commit to dev (no feature branch), roll back with a git revert of the PR-0 commit(s) directly on dev. Reverting removes public/ and graphify-out/; the .dc.html canvas remains the only artifact, no production shell exists. No data-layer impact since PR-0 has no backend.
  • PR-1 (T1, Azure DevOps connector): Revert connectors/ado_connector.py; PR-2’s store simply has no data to ingest yet (PR-2 can still merge independently if desired, just with an empty store).
  • PR-2 (T2, store + API): Revert store/, api/, and the public/dashboard.js fetch-layer change; the shell falls back to mockData.js via its existing dev-mode path.
  • PR-3/PR-5 (T3/T5): Rollback plans moved to v2-team-velocity-playbook.md.
  • PR-4 (T4): N/A — task deleted before implementation; nothing to roll back.