Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions .github/objective-mapping.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
{
"_comment": "Objective mapping for GitHub labels -> numeric values. This repo now favors root initiative/campaign labels first, with process/component labels kept as lower-value fallbacks.",
"label_to_value": {
"critical": 100,
"p0": 100,
"z_campaign_security-alert-burndown": 95,
"agentic-campaign": 90,
"security": 85,
"automation": 35,
"observability": 70,
"testing": 65,
"test": 65,
"copilot-opt": 60,
"bug": 60,
"security-fix": 60,
"reliability": 55,
"safe-outputs": 55,
"high-priority": 50,
"tool-improvement": 50,
"workflow-optimization": 50,
"improvement": 45,
"workflow": 45,
"mcp": 45,
"cli": 40,
"actions": 40,
"engine": 40,
"automated-analysis": 35,
"dx": 35,
"developer-experience": 35,
"quick-win": 35,
"performance": 30,
"optimization": 30,
"lint-monster": 25,
"maintenance": 25,
"refactoring": 25,
"code-quality": 25,
"automated-fix": 25,
"telemetry": 20,
"enhancement": 20,
"documentation": 10,
"dependencies": 10,
"experiment": 5,
"question": 0,
"good first issue": 0,
"ai-generated": 0,
"ai-inspected": 0
},
"multi_label_logic": "max",
"priority_labels": [
"critical",
"p0",
"z_campaign_security-alert-burndown",
"agentic-campaign",
"security",
"observability",
"testing",
"test",
"safe-outputs",
"tool-improvement",
"workflow-optimization",
"copilot-opt",
"security-fix",
"reliability",
"bug",
"high-priority",
"automation"
]
}
48 changes: 33 additions & 15 deletions .github/workflows/objective-impact-report.lock.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

92 changes: 59 additions & 33 deletions .github/workflows/objective-impact-report.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ on:
permissions:
issues: read
safe-outputs:
close-issue:
required-title-prefix: "Impact Efficiency Report - "
target: "*"
max: 1
create-issue:
title-prefix: "Impact Efficiency Report - "
max: 1
---

Expand All @@ -21,7 +26,7 @@ Use this model:
```text
Outcome = recorded work item produced by a GitHub Agentic Workflow run
Objective = issue/epic/work item linked to the outcome
Objective Value = value from planning metadata (priority, severity, milestone, project)
Objective Value = numeric value from the repository objective-mapping configuration applied to traced root labels
Outcome Indicator = 1 for accepted/delivered outcomes, 0 otherwise
Outcome Value = Outcome Indicator × Objective Value
Impact Efficiency = Σ Outcome Value / AI Credits
Expand All @@ -30,14 +35,27 @@ Impact Efficiency = Σ Outcome Value / AI Credits
Treat an outcome as one recorded result item produced by a GitHub Agentic Workflow run (for example, a PR change, completed fix, or report action), which may later be accepted or not accepted.
Use workflow run outputs/artifacts and linked GitHub objects (issues, PRs, comments, discussions) as the outcome source of truth.
Treat AI Credits as total model-credit cost consumed by the workflow runs that produced the analyzed outcomes.
Retrieve AI Credits from workflow-run usage/billing data available to the run context, and use the same time window as outcomes.
When available, use deterministic precomputed run data that already includes each run's `aic` field.
Prefer existing gh-aw outputs that already surface `aic`, such as pre-downloaded `gh aw logs --json` data or audit/log artifacts derived from the same run summaries.
Only fall back to MCP or other live retrieval if deterministic precomputed AIC inputs are unavailable.
Use the same time window for AIC as for outcomes.

Do not perform workflow attribution.
Outcomes deliver value.
Objectives provide context and importance.
AI Credits provide cost.
Do not use an LLM judge.

## AIC Source of Truth

Resolve AI Credits in this order:

1. Deterministic precomputed `gh aw logs --json` style workflow-run data with per-run `aic`
2. Pre-downloaded audit/log artifacts that already expose run-level `aic`
3. MCP or other live retrieval only as a documented fallback

If a run's `aic` field is missing or null, treat it as `0` and count it as missing-cost data in the report.

## Scope

Analyze workflow outcomes and linked objectives from the last 180 days.
Expand All @@ -46,46 +64,39 @@ Analyze workflow outcomes and linked objectives from the last 180 days.

For each outcome, find the associated objective first, then compute `Objective Value`.

Use the first matching priority or severity signal from objective labels or fields as the base value:
Use the repository objective mapping as the source of truth:

```text
P0 / urgent / critical = 100
P1 / high = 50
P2 / medium = 20
P3 / low = 5
unknown = 1
.github/objective-mapping.json
or OBJECTIVE_MAPPING_JSON when explicitly provided
```

Recognize common label forms case-insensitively:
Treat labels on the traced root object as the input to the mapping.
The mapping is label-based and already defines both value and multi-label behavior.

```text
P0, priority:P0, priority/P0, severity:critical, critical, urgent
P1, priority:P1, priority/P1, severity:high, high
P2, priority:P2, priority/P2, severity:medium, medium
P3, priority:P3, priority/P3, severity:low, low
Objective Value = mapping.ComputeObjectiveValue(root_labels)
Objective Labels = mapping.GetObjectiveLabels(root_labels)
```

Then apply planning context adjustments:
Do not invent fallback scoring rules such as milestone bonuses, project bonuses, or priority-to-points heuristics when the mapping file is present.

```text
Objective is assigned to a milestone = +10
Objective is assigned to a project = +10
Examples of mapped labels in this repository include campaign, security, observability, testing, automation, and other configured objective labels.
```

Cap `Objective Value` at 120 (`100 + 10 + 10` maximum from base plus planning adjustments).

The cap prevents a small number of heavily tagged objectives from dominating the metric.

All other labels are classification only.
If a traced root object has no labels that exist in the mapping, mark the outcome as `unmapped`.

## Outcome association rules

For each workflow outcome, associate one objective using this order:
For each workflow outcome, follow the implemented root-tracing behavior:

1. Explicit linked issue or work item reference in the outcome.
2. Issue linked through the related pull request.
3. Parent issue/epic if explicitly linked.
4. If no objective can be found, mark as `unmapped`, exclude it from `Σ Outcome Value`, and report it separately.
1. For pull-request outcomes, trace the PR to its linked closing issue and use that root issue's labels.
2. If PR root tracing fails, or for direct issue outcomes, use labels on the issue itself.
3. Record the traced root URL when one is found so the report preserves an audit trail.
4. If no mapped objective labels can be found, mark the outcome as `unmapped`, exclude it from `Σ Outcome Value`, and report it separately.

Prefer precomputed outcome evaluation data when available. Do not re-derive a different mapping model inside the report.

## Computation

Expand All @@ -105,13 +116,26 @@ Then compute:
```text
Accepted Outcome Count = count(outcomes where Outcome Indicator = 1)
Total Outcome Value = sum(Outcome Value)
AI Credits = sum(run.aic across analyzed runs)
Impact Efficiency = Total Outcome Value / AI Credits (value units per AI Credit; undefined when AI Credits = 0)
```

If AI Credits is missing or zero, report that Impact Efficiency is not computable and explain whether credits data was unavailable or no credits were consumed in the analysis window.
If only some runs are missing `aic`, still compute the metric from the available values and explicitly report how many runs had missing cost data.

## Report

Before creating the new report, search for an existing open issue titled:

```text
Impact Efficiency Report - YYYY-MM-DD
```

If one already exists for today:

1. Close that issue first with a brief comment explaining that it is being replaced by a freshly generated report for the same day.
2. Then create the new report issue.

Create one issue titled:

```text
Expand All @@ -137,8 +161,8 @@ The report must include:

### Top objectives by delivered value

| Objective | Priority/Severity | Milestone | Project | Delivered Outcome Value |
|---|---|---|---|---:|
| Objective Label | Delivered Outcome Value | Attempted Outcome Value | Delivered Outcomes | Efficiency |
|---|---:|---:|---:|---:|

### Unmapped outcomes

Expand All @@ -159,12 +183,14 @@ Explain which one better reflects meaningful delivered value relative to cost.
Mention missing or weak links in:

- outcome-to-objective association
- priority/severity metadata
- milestone/project metadata
- root tracing and linked-object coverage
- label mapping coverage in `.github/objective-mapping.json`
- AI Credits availability

## Safe output
State whether AI Credits came from deterministic precomputed data or from a live fallback path.

Use only `create-issue`.
If AI Credits are unavailable, still produce the delivered-value analysis and clearly state that the cost-normalized Impact Efficiency metric could not be computed.

## Safe output

If a report for today already exists, do nothing.
Use only `close-issue` and `create-issue`.
1 change: 1 addition & 0 deletions pkg/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ All diagnostic output MUST go to `stderr` using `console` formatting helpers. St
| `gh aw trial` | `NewTrialCommand` | Run trial workflow executions |
| `gh aw deploy` | `NewDeployCommand` | Deploy agentic workflows to a target repository using a pull request |
| `gh aw outcomes` | `NewOutcomesCommand` | Check what happened to a workflow run's safe outputs |
| `gh aw outcomes history` | `NewOutcomesHistorySubcommand` | Score recent closed issues and merged PRs against the objective mapping |
| _No `gh aw deps` command_ | `deps_*.go` (internal utilities) | Dependency reporting/advisory helpers used by other commands |
| `gh aw version` | `versionCmd` (main.go) | Show version information |
| `gh aw completion` | `NewCompletionCommand` | Generate shell completion scripts |
Expand Down
6 changes: 4 additions & 2 deletions pkg/cli/audit_report.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"time"

"github.com/github/gh-aw/pkg/constants"
"github.com/github/gh-aw/pkg/github"
"github.com/github/gh-aw/pkg/logger"
"github.com/github/gh-aw/pkg/sliceutil"
"github.com/github/gh-aw/pkg/timeutil"
Expand Down Expand Up @@ -431,9 +432,10 @@ func buildAuditData(processedRun ProcessedRun, metrics LogMetrics, mcpToolUsage

// Evaluate outcomes for created items if any exist
if len(createdItems) > 0 {
outcomeReports := EvaluateOutcomes(createdItems, "")
mapping := github.LoadObjectiveMappingFromConfig()
outcomeReports := EvaluateOutcomes(createdItems, "", mapping)
auditData.Outcomes = outcomeReports
outcomeSummary := ComputeOutcomeSummary(outcomeReports)
outcomeSummary := ComputeOutcomeSummary(outcomeReports, mapping)
auditData.OutcomeSummary = &outcomeSummary
}

Expand Down
Loading
Loading