Change provenance and risk routing
PLChange provenance and risk routing is the policy that sets review depth, approvals, and release controls for each pull request from what the change touches: sensitive systems, data classes, public contracts, test and CI files, and reversibility, recorded in the evidence bundle. Authorship is recorded too, but only for measurement and audit, never as the routing signal.
Your organization added an ai-generated label six months ago and made it require two reviewers. Engineers stopped ticking the box within a month, because the label meant waiting a day. Last week a one-line human edit to the webhook signature check merged with a single approval, and it was the change that broke production. The label measured the wrong thing and routed the wrong way.
This page is for the CTO or VP Engineering who answers scorecard question Q11 and the tech leads who enforce the result. It does not define the manifest: the fields, the pull request template and the CI checker live on the evidence bundle, the site’s one change-manifest schema. This page decides what those fields route to, how provenance is kept without becoming a gate, and how you prove the routing works.
Q11 · Quality gates Max-score evidence: intent, affected-system, data and reversibility metadata route evidence and named approvals; authorship is retained for measurement.
What a provenance and routing policy gives you
Section titled “What a provenance and routing policy gives you”- A field-to-control table that turns each evidence-bundle field into a required check, a named approver or a release control.
- Three policy classes the starter bundle policy does not have (personal data, public contract and agent configuration) with their
CODEOWNERSlines. - A one-page
change-routing-policy.mdtemplate to adopt as-is. - A fixture test that proves a personal-data change cannot route as
standard. - Two metric definitions that use provenance for measurement: routing escape rate and provenance coverage.
- Three copy-paste prompts: audit last month’s routing, draft the policy globs, and review an incident’s routing.
Why is “AI-authored” a poor routing signal?
Section titled “Why is “AI-authored” a poor routing signal?”Authorship routes wrong in both directions. Extra review for every AI-assisted change floods the queue with trivial changes and gives engineers a reason to leave the label off. Light review for “human” code leaves a blind spot exactly where the webhook change above sat. Neither outcome depends on what the change does.
The risk of a change comes from its blast radius, the sensitivity of the data it reaches, whether anything outside the repository depends on it, whether it weakens the checks that judge every other change, and how hard it is to undo. All five are visible in the diff and the evidence bundle. The model name and the share of generated lines are not.
Provenance still earns its keep, for three jobs that are not routing:
- Measurement. The canonical AI metrics split every impact metric into agent-assisted and other changes, which needs a reliable marker on each merged pull request.
- Incident analysis. When a change fails, the session, prompt and task behind it explain how the defect got in, which tells you which evidence the risk class should have demanded.
- Audit. Regulated teams must show who accepted the intent, who approved the merge and who released the change. The bundle’s
human_owneranswers the first; the pull request history on your platform (GitHub, GitLab) records the other two.
Which evidence-bundle fields route a change?
Section titled “Which evidence-bundle fields route a change?”Route on the fields the checker recomputes or verifies from the diff, and treat the rest as claims to audit. The declared risk class can only raise the floor the diff sets, as the bundle’s rules explain.
| Bundle field | What it signals | Control it triggers | Enforced by |
|---|---|---|---|
spec.link or spec.delta missing, or the link does not resolve | Nobody stated the intended behavior, so no check can prove it | Block the merge until the author links the spec and lists the behavior delta | The required evidence status check |
risk.touches: auth, money, schema, migrations | A mistake is expensive and slow to detect | A named code owner reads the code as well as the bundle | CODEOWNERS plus required code-owner review |
risk.touches: infra | Deployment or CI behavior changes | Class at least standard: one reviewer reads the bundle and the review agent’s findings | Checker floor (min_risk: standard) plus CODEOWNERS on .github/workflows/ |
risk.touches: personal_data (added below) | Customer data can leak or be corrupted | Privacy or security owner approves; tests use synthetic data only | CODEOWNERS on the data-handling paths |
risk.touches: public_contract (added below) | Consumers outside the repository break | Compatibility or contract tests in checks, consumer team approves | CODEOWNERS plus a required contract-test job |
risk.touches: agent_config (added below) | Every later agent run behaves differently, including the review agents | Platform owner approves | CODEOWNERS |
risk.oracle_changes with direction: looser | What “green” means changes for every other change | Class high; the test’s code owner reads the change | Checker floor plus CODEOWNERS on test paths |
risk.rollback names a migration, data rewrite or external side effect | The change cannot be undone by a revert | Dry run, backup check, staged rollout, production approval | Deployment environment with required reviewers |
acceptance result not pass, empty checks, missing runtime or evals where required | The claim is unproven | Block the merge, whoever the author is | The required evidence status check |
provenance.* | Who and what produced the change | No routing effect; stored for metrics and audit | Checker requires agent, model and human_owner |
The last row is the Q11 rule in one line. Every other row applies identically to human-only, AI-assisted and agent-produced changes.
How do the site’s risk vocabularies line up?
Section titled “How do the site’s risk vocabularies line up?”Three pages use three scales for the same idea. This crosswalk keeps a policy that references all three consistent:
| Evidence bundle class | Review lane | Governance tier | Release control |
|---|---|---|---|
low | 0 · Low risk | 1 · Reversible local | Normal deploy |
standard | 1 · Standard | 1 · Reversible local | Canary or flag where available |
high | 2 · Sensitive | 1, or 2 when the change needs a staging rehearsal | Staged rollout, then production approval |
high with an irreversible rollback | 2 · Sensitive | 3 · Production or regulated | Named owner approves the protected production job |
How do you route pull requests on the evidence bundle?
Section titled “How do you route pull requests on the evidence bundle?”The routing policy sits on top of the bundle gate, so install that first. Each step below adds one control, and none of them reads the author.
-
Install the evidence bundle gate. Add the template, policy, checker, workflow and
CODEOWNERSfrom the evidence bundle page, merge them, then make theevidencecheck required. Everything below extends.github/evidence-policy.ymlandCODEOWNERS. -
Add the classes Q11 names that the starter policy omits. The starter covers auth, money, schema, migrations and infrastructure. Personal data, public contracts and agent configuration need their own classes. Add them under
sensitive:and adjust the globs to your repository:# .github/evidence-policy.yml: append under the existing sensitive: keypersonal_data: { globs: ['**/customers/**', '**/*pii*', '**/exports/**'], min_risk: high }public_contract: { globs: ['packages/sdk/**', '**/public-api/**'], min_risk: high }agent_config: { globs: ['**/CLAUDE.md', '**/AGENTS.md', '.claude/**', '.codex/**', '.cursor/**', '.mcp.json'], min_risk: high }The checker iterates over every entry under
sensitive:, so the new classes need no code change: a diff that matches them fails unlessrisk.touchesnames them andrisk.classishigh. Give each glob a non-agent owner in the same pull request:# .github/CODEOWNERS: insert above the oracle globs (**/*.test.* and below)**/customers/** @acme/privacy**/*pii* @acme/privacy**/exports/** @acme/privacypackages/sdk/** @acme/api-owners**/public-api/** @acme/api-owners**/CLAUDE.md @acme/platform**/AGENTS.md @acme/platform.claude/ @acme/platform.codex/ @acme/platform.cursor/ @acme/platform.mcp.json @acme/platformCODEOWNERS applies the last matching line. Appended below the bundle page’s oracle globs,
**/customers/**would takesrc/customers/export.test.tsaway from@acme/platformand weaken the looser-oracle control, so insert these lines above the oracle globs. Listing two teams on one line does not require both: an approval from either team satisfies it.Path globs find data handling only where the code is organized by it. A query that joins customer email into an analytics table can live anywhere. That is why the bundle lets the author add a class to
risk.touchesbeyond what the globs detect, and why the routing audit prompt below looks for exactly this gap. -
Write the routing decisions down once. The checker and
CODEOWNERSenforce the routes; the policy file records why, who owns each class and who may grant an exception. Store it next to the review policy:change-routing-policy.md # Change routing policy (version 1.0, owner: VP Engineering)## 1. SignalReview depth, approvals and release controls follow the evidence bundle(.github/evidence-policy.yml): sensitive classes touched, oracle changes,rollback, and completeness of evidence. The class computed from the diffis the floor; a person may raise it, nobody may lower it.## 2. AuthorshipProvenance (human, AI-assisted, agent; tool, model, session) is recordedon every change, including human-only ones (agent: none, model: none).It is never an input to routing, approval or release. It is used for themetrics in section 5 and for incident review.## 3. Routes- low: one reviewer reads the bundle.- standard: one reviewer reads the bundle, the oracle changes and anyunrequested behavior; a review agent's findings are attached.- high: the code owner of every touched class reads the code.- irreversible rollback: dry run, backup check, staged rollout, and anamed approver on the production environment.- incomplete evidence: blocked, regardless of author or class.## 4. ExceptionsOnly the owner of a class may waive its control, in writing on the pullrequest, with an expiry date. The platform team reviews open exceptionsmonthly.## 5. MeasurementMonthly: routing escape rate, provenance coverage, share of pullrequests routed high, and the agent-cohort metrics from the metricsframework. A class whose escape rate rises gets stronger evidencerequirements, not an authorship rule. -
Put the release controls where no label can skip them. Routing that ends at merge leaves the riskiest part, production, to memory. Give the production deployment environment required reviewers, and have the deploy workflow read the class from the
evidencecheck output, not from a label a person can edit. The mechanics are on the production approval gate and progressive delivery. -
Record provenance on every change. Human-only pull requests fill the bundle’s
provenancewithagent: noneandmodel: none, so the field is present on every merged change and the cohort split in your metrics has no unknowns. The tabs below show where each tool can supply provenance automatically. -
Prove the new classes route. Reuse the bundle page’s fixture method:
EVIDENCE_CHANGED_FILESreplacesgit diff, so a fixture needs a fake event and a path list. Take a copy of the template bundle declared asstandard, with the cited spec and test files present in the branch:Terminal window # Terminal, repository rootGITHUB_EVENT_PATH=fixtures/ev-standard.json \EVIDENCE_CHANGED_FILES='src/customers/export.ts' \node scripts/check-evidence.mjs .github/evidence-policy.ymlThe run must exit 1 and report both
diff touches personal_data (src/customers/export.ts) but risk.touches omits itandrisk.class is standard, but the diff requires at least high. Add one such fixture per new class, plus one that touches.github/evidence-policy.ymlitself, and run them in your normal test job.
Where does provenance come from in Claude Code, Codex and Cursor?
Section titled “Where does provenance come from in Claude Code, Codex and Cursor?”The bundle’s provenance block works identically in all three tools: the agent fills it from the bundle prompt on the evidence bundle page. What differs is the automatic record you can compare it against. For every tool, Entire CLI (v0.11.3, 2026-09-25) links each commit to the agent session that produced it through an Entire-Checkpoint: trailer.
Install Entire CLI once per machine with brew install --cask entireio/tap/entire (macOS and Linux) or curl -fsSL https://entire.io/install.sh | bash. It is a Go binary; the npm package entire is an unrelated project.
On Team and Enterprise plans with the Claude GitHub app installed and GitHub analytics turned on, Claude Code’s contribution analytics labels credited merged pull requests claude-code-assisted. Attribution matches sessions from 21 days before to 2 days after the merge, and code rewritten by more than 20% is not credited. Contribution metrics are unavailable under Zero Data Retention; use the bundle field and Entire trailers there.
# Terminal, repository root: per-commit session provenanceentire enable --agent claude-codeIn GitHub search, is:pr is:merged label:claude-code-assisted lists the credited pull requests, which is the sample for the provenance coverage metric below.
codex exec -o pr-body.md writes the agent’s final message, including the bundle, to the pull request body; the evidence bundle page has the full command. Add session provenance per commit:
# Terminal, repository rootentire enable --agent codexFor Codex, the bundle’s provenance block and the Entire trailers are the attribution sources this page relies on; compare them through the provenance coverage metric below.
Put the bundle instruction in a project rule so agents fill provenance on pull requests they open, and add session provenance per commit:
# Terminal, repository rootentire enable --agent cursorCursor’s PR Routing & Approval “assigns reviewers based on code ownership and commit history, and can approve low-risk PRs when your criteria are met” (cursor.com, checked 2026-08-28). Write those criteria to match the low route only, never standard or high. See Rollouts and PR Routing & Approval.
Entire stores session transcripts in your git repository. On a public repository, send checkpoints to a private one with entire enable --checkpoint-remote github:your-org/checkpoints, and review its redaction limits before you enable it team-wide.
How do you measure routing without routing on authorship?
Section titled “How do you measure routing without routing on authorship?”Use the canonical definitions for the agent-cohort metrics (agent cohort change fail rate, 14-day follow-up fix rate, escaped defects). Two further definitions measure the routing policy itself:
| Metric | Definition | What a bad trend means |
|---|---|---|
| Routing escape rate | Incidents and reverts whose post-incident review assigns a higher class than the pull request was routed at ÷ all incidents and reverts traced to a change, per quarter | A class is missing or a glob has drifted. Fix the policy, then add a fixture. |
| Provenance coverage | Merged pull requests whose bundle provenance.agent agrees with the automatic record (analytics label or Entire trailer) ÷ merged pull requests with an automatic record, per month | People or agents are hiding or guessing provenance, so the cohort metrics are unreliable. |
Also watch the share of pull requests routed high. When it climbs toward most of the queue, the globs cover too much and reviewers are back to reading every diff.
If the agent cohort fails more often than the other cohort within the same class, tighten the evidence that class requires for every change, for example a mutation score on changed files. Adding an authorship rule instead returns you to the label nobody ticks.
Copy-paste prompts for provenance and routing
Section titled “Copy-paste prompts for provenance and routing”How does each Q11 answer move to the next?
Section titled “How does each Q11 answer move to the next?”| Q11 answer | What it looks like | Next step on this page |
|---|---|---|
| No provenance or risk routing | Every pull request gets the same review | Step 1: install the evidence bundle gate |
| Manual AI marker or reviewer convention | An ai-generated checkbox, extra review by habit | Steps 1 and 5: record provenance on every change, stop routing on it |
| Machine-readable provenance plus path-based risk labels | Bundle and risk:* labels, starter classes only | Steps 2 to 4: add data, contract and agent-config classes; tie release controls to the class |
| Intent, system, data and reversibility route evidence and named approvals; authorship kept for measurement | This page in place, with fixtures and the two metrics | Keep the routing escape rate falling; review exceptions monthly |
What breaks when you route on the manifest?
Section titled “What breaks when you route on the manifest?”The routing reads a label people can edit. Anyone with triage access can change risk:standard to risk:low. Recovery: route merge approvals through CODEOWNERS paths and release controls through the evidence check’s output, and treat the label as display only.
A data-handling change matches no glob. Customer data flows through a module named sync/, so the change routes standard. Recovery: run the routing audit prompt monthly, add the missing glob with an owner, and add a fixture so the next rename fails a test.
Everything becomes high. Broad globs send most of the queue to code owners, who then approve without reading. Recovery: narrow each class to code where a mistake is expensive and slow to detect, and watch the share routed high monthly.
Provenance disappears once it stops mattering for review. With no routing consequence, people skip the field. Recovery: the checker already requires agent, model and human_owner; compare them with the automatic record through the provenance coverage metric.
An AI reviewer or approval bot satisfies a high route. Recovery: code owners for high classes are human teams, and no bot account belongs to them. Machine approval is allowed only on low, as the review automation policy states.
Session transcripts leak. Entire writes prompts and transcripts into git, and its secret redaction is best-effort. Recovery: use a private checkpoint remote, remove the affected checkpoints and rotate any exposed credential.
Where to go next with change routing
Section titled “Where to go next with change routing”Frequently asked questions
Should pull requests be routed to stricter review based on whether an AI agent wrote the code?
No, pull requests must be routed by what the change touches (sensitive paths, data classes, public contracts, CI/test files, and reversibility) recorded in the evidence bundle, while AI authorship is tracked only for measurement and audit.
Why does routing pull requests by AI authorship fail as a quality gate?
Routing by self-reported AI labels incentivizes developers to under-report agent usage and ignores high-risk human edits, whereas path- and impact-based routing enforces the right controls on every change.