How every AI-assisted action becomes a measurable metric — from git commit to executive dashboard
7 data sources feed into EventBridge, processed by Lambda, triple-written to DynamoDB (events + metadata) and CloudWatch (time-series). Dashboards read from CloudWatch (real-time) and DynamoDB (historical queries). 8 event types carry 6 AI-DORA metrics across every commit, PR, deploy, and eval gate.
Installed via bootstrapper/metric-hooks/install.sh. Fire automatically on every commit and merge.
| Hook | Trigger | Data Captured | Output |
|---|---|---|---|
| prepare-commit-msg | Before commit message editor | Detects AI tool via env vars, scans for Co-Authored-By, detects spec files in staged changes | Adds trailers: AI-Origin, AI-Tool, AI-Model, Spec-Ref |
| post-commit | After successful commit | SHA, author, files changed, lines added/removed, all trailers from message | JSON to .prism/metrics/ + async emit to EventBridge |
| post-merge | After merge or git pull | AI commits vs human commits on branch, lead time (first commit → merge), AI-to-merge ratio | JSON to .prism/metrics/ + async emit to EventBridge |
AI Tool Detection Logic: The prepare-commit-msg hook checks environment variables in this order: CLAUDE_CODE / CLAUDE_SESSION_ID → claude-code, KIRO_SESSION → kiro, Q_DEVELOPER_SESSION → q-developer. If none match, it scans the commit message for AI indicators. Default: AI-Origin: human.
The webhook handler at collector/github-webhook-handler/index.ts processes 5 event types with HMAC-SHA256 signature verification.
| GitHub Event | Event Type Emitted | Key Data Extracted |
|---|---|---|
| push | prism.d1.commit | Files changed per commit, AI trailers parsed from each commit message, aggregate AI ratio for the push |
| pull_request (merged) | prism.d1.pr | Lead time (created_at → merged_at), lines changed (additions + deletions), AI-to-merge ratio |
| deployment | prism.d1.deploy | Deployment frequency count (1 per event), deployment timestamp |
| deployment_status | prism.d1.deploy | Change failure rate: 1 if failure/error, 0 if success |
| check_run (eval-*) | prism.d1.eval | Eval gate pass/fail (checks for names starting with eval- or prism-eval-), duration |
Three workflows in bootstrapper/github-workflows/ emit structured events on specific triggers.
prism.d1.pr + prism.d1.deploy
prism.d1.assessment
prism.d1.agent.eval
The shell script at collector/ci-metadata-emitter/emit-metrics.sh runs inside GitHub Actions to emit deploy/PR events. It parses the git log from base ref to HEAD, counts commits by AI origin, calculates AI-to-merge ratio, and emits to EventBridge.
# Environment variables the emitter reads
PRISM_EVENT_TYPE=deploy|pr PRISM_TEAM_ID=team-alpha
PRISM_EVENT_BUS=prism-d1-metrics PRISM_REPO=owner/repo
PRISM_BASE_REF=origin/main PRISM_SHA=abc123
PRISM_PR_CREATED_AT=2026-04-20T10:00:00Z # for lead time calc
Every event follows this structure on EventBridge:
{
"source": "prism.d1.velocity",
"detail-type": "prism.d1.commit | .pr | .deploy | .eval | .incident | .assessment | .agent | .agent.eval",
"detail": {
"team_id": "team-alpha",
"repo": "owner/repo-name",
"timestamp": "2026-04-22T14:30:00Z",
"prism_level": 3,
"metric": {
"name": "commit.files_changed", // primary metric name
"value": 5, // numeric value
"unit": "files" // count | percent | seconds | hours | files | lines
},
"ai_context": {
"tool": "claude-code", // claude-code | kiro | q-developer | none
"model": "claude-sonnet-4", // model identifier
"session_id": "sess_abc123", // optional session ID
"origin": "ai-assisted" // ai-assisted | ai-generated | human
},
"dora": {
"deployment_frequency": 1, // count per event
"lead_time_seconds": 3600, // PR created → merged
"change_failure_rate": 0.0, // 0 or 1 per event, averaged over time
"mttr_seconds": null // incident → resolution
},
"ai_dora": {
"ai_acceptance_rate": 0.85, // approved reviews / total reviews
"ai_to_merge_ratio": 0.70, // AI commits / total commits
"spec_to_code_hours": 1.8, // spec approved → code ready
"post_merge_defect_rate": 0.014, // defects per AI-assisted merge
"eval_gate_pass_rate": 1.0, // 1 if pass, 0 if fail
"ai_test_coverage_delta": 0.123 // coverage change from AI tests
}
}
}
The Lambda processor (infra/lib/lambda/metrics-processor.ts) does a triple-write for every event:
| Field | Value | Purpose |
|---|---|---|
| Table | prism-d1-events | Immutable event log |
| Partition Key | {team_id}#{repo} | Team+repo scoping |
| Sort Key | {timestamp} ISO 8601 | Time-ordered within partition |
| GSI | by-detail-type (PK: detail_type, SK: timestamp) | Query by event type across teams |
| TTL | 365 days | Auto-expire old events |
| Data | Full event detail (JSON stringified) | Complete audit trail |
| Field | Value | Purpose |
|---|---|---|
| Table | prism-team-metadata | Latest snapshot per team/repo |
| Key | team_id + repo | Fast lookup for current state |
| Updated | Every event overwrites latest values | Always-current DORA + AI-DORA numbers |
| TTL | None | Persists until team is removed |
Published to namespace PRISM/D1/Velocity with dimensions:
| Dimension | Source | Required |
|---|---|---|
| TeamId | detail.team_id | Yes |
| Repository | detail.repo | Yes |
| AIOrigin | detail.ai_context.origin | Optional — enables filtering by ai-generated / ai-assisted / human |
| AgentName | detail.agent.name | Optional — for agent metrics only |
Dimensionless publishing: Every metric is also published without dimensions, enabling aggregate queries across all teams and repos in a single dashboard widget.
| Dashboard | Data Source | Refresh | Audience |
|---|---|---|---|
| CloudWatch Team Velocity | CloudWatch metrics (PRISM/D1/Velocity) | Real-time | Engineering teams, tech leads |
| CloudWatch Executive Readout | CloudWatch metrics (PRISM/D1/Velocity) | Real-time | CTOs, VPEs, directors |
| QuickSight AI-DORA Analysis | Timestream (fed from CloudWatch) | Near real-time | Engineering leaders |
| QuickSight PRISM Level Tracker | Timestream + DynamoDB metadata | Near real-time | Executive review |
| API: GET /metrics/{team_id} | DynamoDB events table | On-demand | Custom integrations |
| Alarm | Metric | Threshold | Period |
|---|---|---|---|
| AI Acceptance Rate Low | AIAcceptanceRate | < 20% | 6 hours |
| Eval Gate Pass Rate Low | EvalGatePassRate | < 70% | 6 hours |
| Change Failure Rate High | ChangeFailureRate | > 20% | 6 hours |
| Agent Success Rate Low | AgentSuccessRate | < 80% | 1 hour |
Claude Code, Kiro, and Q Developer token consumption is NOT tracked today. The pipeline captures which tool was used and what it produced (commits, PRs), but not how many tokens it consumed or what it cost. Agent token usage (AgentTokensUsed) is tracked for Strands agents, but not for interactive developer tool sessions.
| Dimension | Today | Missing |
|---|---|---|
| Tool identity | Tracked via env var detection | — |
| Model used | Tracked via AI-Model trailer | — |
| Code output | Tracked lines/files per commit | — |
| Token consumption | Not tracked | Input tokens, output tokens, total tokens per session/commit |
| Session duration | Not tracked | How long each Claude Code / Kiro session lasted |
| Cost per session | Not tracked | Dollar cost of each AI interaction |
| Cost per commit | Not tracked | Correlation of token cost to code output |
| Cost per PR/feature | Not tracked | Aggregate cost across a feature's lifecycle |
| Developer-level cost | Not tracked | Per-developer AI consumption patterns |
| License spend | Not tracked | Monthly tool subscription costs |
~/.claude/ local storage.See the Token & Cost Intelligence phase in the Community Roadmap for the full implementation plan.
Bedrock InvokeModel API calls
|
v
CloudTrail (logs every call with input_tokens, output_tokens, model_id)
|
v
EventBridge Rule (matches bedrock.amazonaws.com InvokeModel events)
|
v
Lambda: token-cost-processor
- Extract: model_id, input_tokens, output_tokens, timestamp, IAM user/role
- Look up cost: model pricing table (DynamoDB)
- Correlate: timestamp proximity to commits (within 5-min window)
- Correlate: IAM role → developer identity
- Aggregate: per-session, per-commit, per-PR, per-feature
|
v
CloudWatch: PRISM/D1/Velocity namespace
- BedrockTokensInput (by TeamId, Developer, Model)
- BedrockTokensOutput (by TeamId, Developer, Model)
- BedrockCostUSD (by TeamId, Developer, Model)
- CostPerCommit (by TeamId, AITool)
- CostPerPR (by TeamId)
|
v
Dashboards: Token usage trends, cost overlays, ROI calculation
| Component | Location | Purpose |
|---|---|---|
| Git hooks | bootstrapper/metric-hooks/ | Local commit metadata capture + AI tool detection |
| GitHub webhook handler | collector/github-webhook-handler/index.ts | Process push, PR, deploy, check_run events |
| CI metric emitter | collector/ci-metadata-emitter/emit-metrics.sh | Shell script for GitHub Actions metric emission |
| Commit analyzer | collector/git-hooks/prism-commit-analyzer.ts | Standalone commit analysis tool |
| Metrics processor Lambda | infra/lib/lambda/metrics-processor.ts | EventBridge → DynamoDB + CloudWatch triple-write |
| API handler Lambda | infra/lib/lambda/api-handler.ts | REST API for ingestion + queries |
| Metrics pipeline stack | infra/lib/metrics-pipeline-stack.ts | EventBridge bus + DynamoDB tables + Lambda |
| API stack | infra/lib/api-stack.ts | API Gateway + Lambda + usage plans |
| Dashboard stack | infra/lib/dashboard-stack.ts | CloudWatch dashboards + alarms |
| AI metrics workflow | bootstrapper/github-workflows/prism-ai-metrics.yml | PR merge → AI-DORA event emission |
| DORA weekly workflow | bootstrapper/github-workflows/prism-dora-weekly.yml | Weekly DORA + AI adoption assessment |
| Agent eval workflow | bootstrapper/github-workflows/prism-agent-eval.yml | Agent quality gate on PRs |
| Workshop module | workshop/04-instrumenting-ai-metrics/ | Hands-on exercises for metric instrumentation |