.agents/skills/deep-review/references/dimensions/release-risk.md
The last gate before shipping. Every other dimension asks "is this code correct?" — this one asks "if we merge and deploy this today and it turns out wrong, how bad is the recovery?" A change can be flawless and still be a bad thing to ship in one piece.
Seven risk classes, each with its own irreversibility profile:
Findings here are release decisions, not just defects: alongside fix_options, propose the de-risking move (split the PR, ship behind a flag, land the migration in a separate earlier PR, backfill in a separate job, stage the rollout).
Much of this dimension's subject matter is not visible in the diff — the shape of rows already in production, whether an env var is set in each deploy target, what is sitting in the queue right now. Do not force those into findings; asserting facts you cannot read is exactly the hallucination the verify pass exists to catch.
issues entry): you can point at the diff and argue the consequence. Use this whenever the evidence is in the code.release_checks array): an objective pre-deploy confirmation item — "this change depends on X; confirm X before deploying". No severity, no verification, straight to the report as a checklist for the human. Use when the answer lives in production state or in a system outside the repo.A release check is not a downgraded finding. If the code itself is wrong, it is a finding. If the code is fine but shipping it safely depends on something you cannot see, it is a check.
Persisted state
git revert cannot undo — so it always gets read, in full. But reading it is not reporting it: an additive, reversible migration (nullable column, new table, concurrent index) with no ordering hazard produces no output at all — not a finding, and not a release check either, because there is nothing for a human to confirm. It earns a finding through one of the specific hazards below, or a release check when shipping it safely depends on production state you cannot read (row counts, existing data shape, whether a backfill already ran)DROP COLUMN / DROP TABLE / RENAME, narrowing ALTER COLUMN TYPE, removing an enum value — old data is gone or unreadable once appliedUPDATE / DELETE over existing rows) with no dry-run count, no backup path, and no way to reconstruct the old valuesNOT NULL, UNIQUE, CHECK, new FK) — these fail at deploy time on dirty production data that dev fixtures never containedON DELETE CASCADE on a new FK: a single row deletion now silently removes rows in other tablesjsonb columns: keys added/renamed inside the column, or a value's type changedlocalStorage, IndexedDB, persisted store state. Worst case of all — the data lives on the user's machine, you cannot migrate it, and on desktop you cannot even force the client to updateDev-cycle drift
This class only exists because features get reworked. When a requirement went through several design iterations before landing, the branch accumulates two kinds of residue — one in the committed migrations, one in the developer's local database — and only the first is visible in the diff. Both are worth checking precisely on the PRs that feel most finished.
ADD COLUMN then DROP COLUMN, a table created then renamed, a backfill for rows that only exist on someone's laptop, a DROP ... IF EXISTS guarding an object that never shipped. Recommend squashing into the final shape — the churn is not free: every extra statement is another lock, another failure point, and a false record of the schema's historyIF EXISTS on an object the migration itself just created, a delete-then-recreate to avoid a local conflict, a data fix-up for a shape only local iterations produced) should not ship. They are dead weight in production and they hide the real preconditionrelease_checks as "verify against a freshly migrated database"Deploy-moment state
git revert cannot recall a message already in flight — check that the consumer accepts the old payload for at least one deploy cycle, or that the change is drain-and-deployPrompt surface
A prompt edit is a one-line diff that changes the product's behavior for every user, and it is the change class with the weakest safety net in the entire repo: no type checks it, no unit test fails on it, and code review reads it as prose rather than as the control logic it actually is. Treat any diff touching a system role, tool description, parameter description, or context-assembly template as a behavior change of the same weight as editing a core function — a reviewer nodding at "the wording reads better" is not review.
Where they live: packages/prompts/src/prompts/** (systemRole, tools, planning, memory, and the rest), each builtin tool's manifest.ts + systemRole.ts under packages/builtin-tool-*/, and the assembly/injection order in packages/context-engine/.
git log -S on the removed sentence before accepting a deletion as harmlesssecurity finding; the release angle is that it reaches production instantly with no gateobservability, but flag here that it ships with no gradual rolloutRollback granularity (feature flags)
The question is not "is a flag nice to have" — it is what does undoing this cost, and can that cost be lowered. Reverting a PR means a revert commit, a rebuild, a redeploy, and it takes everything else in that PR with it. Turning a flag off is seconds and surgical, and this repo can flip flags at runtime through edge config without a deploy at all (packages/app-config/src/featureFlags/, packages/edge-config/).
Recommend gating when all of these hold:
Also recommend one when the rollout should be staged (small cohort first, watch a metric, then widen) — that is a capability a revert cannot give you at all.
Do not recommend a flag when:
When you do recommend one, state the removal condition in the same breath: what observation makes it safe to delete the flag and the old path.
Shared surface and high-frequency UI
Two different multipliers, same class. A base component's reach is its call-site count; a high-frequency screen's reach is the number of users who hit it every day. The second one has no import graph to measure it, which is why it gets skipped.
High-frequency surfaces — the entry screen after auth, the main chat/work surface, the global navigation and sidebar, the command palette, the composer/input, anything on the path a user walks within seconds of opening the product:
ux; whether shipping it all at once is wise belongs hereShared surfaces — measured by call sites:
src/components/, anything exported from a packages/* public entry, shared hooks/utils/contexts, and design-system wrappers — treat these as base surfaces regardless of how small the diff is.desktop/.mobile variants and other packagesif/switch on a specific caller, or logic that belongs to one consumer pushed down into the shared component — the next variant can only be another branchPR purity
.agents/skills/db-migrations/SKILL.md — rollout strategy, online index creation, backfills, what makes a migration safe.agents/skills/drizzle/SKILL.md — schema conventions, what generates a migration.agents/skills/upstash-workflow/SKILL.md — workflow/queue semantics, what a step change means for runs already in progress.agents/skills/pr/SKILL.md — stacked-PR workflow and layer ordering; the concrete mechanics for any split you recommend.agents/skills/react/SKILL.md — component layering, which surfaces count as shared.agents/skills/builtin-tool/SKILL.md — manifest/description conventions, how a tool's text reaches the model.agents/skills/agent-tracing/SKILL.md — pulling real transcripts, the only way to show a prompt change's before/afterjsonb column writes, cache set calls with object payloads, and client-persistence writes, and compare each written shape against what its reader accepts.release_checks item to replay the migrations on a fresh database before deploying.process.env, env schema files, flag lookups) and check whether the diff also adds it to the example/schema files — an env var read but never declared is a release check at minimum. Finally, trace new bulk write paths for outbound senders (mail, notification, payment, webhook).git log -S '<removed phrase>' to recover why they were added. For a tool/parameter description, name the tool and the direction of the selection-rate change. Then check the PR for any evidence of validation (eval, transcript, staged rollout); none of the three on a user-facing prompt is itself the finding.rg -l "from '.*<Component>'" or the package's import graph) and state the number in the finding — blast radius is the evidence. Then diff the props/behavior contract, not just the implementation.release_checks, phrased as something a human can confirm in one action. Never guess it into a finding.This dimension is the easiest one to turn into a rubber stamp that blocks every PR touching the database. Hold the line:
Purity findings cap at p1 and are normally blocks_release: false — a split is a process improvement, not a shipping blocker, unless the bundled part is itself a p0 risk.
Prompt findings sit at p1 by default. p0 only when the edit removes a safety/refusal constraint or breaks a contract another system parses (a tool schema, a structured-output format) — "the model may behave differently" is p1 at most, because it is recoverable by a redeploy even though the outputs it already produced are not.
likelihood here means how likely the risk materializes, not how often the code runs. A migration executes exactly once with certainty, but whether it damages anything depends on the production data: high when the hazard depends on data that certainly exists (any populated table), medium when it depends on data shapes we plausibly have, low when it needs a state the product has probably never produced.
performance dimension. Report the data-safety and reversibility angle here and do not restate the locking analysis.code-style and observability. This dimension asks only what happens to users on the next request and how it is taken back.IF NOT EXISTS / IF EXISTS) on objects the migration did not create — those are the repo's convention and belong to performance's idempotency rule, not here. Only guards protecting against a state that exists solely on a developer's machine are a finding.ux. This dimension judges only how far and how fast a bad outcome would spread, and what it costs to pull back.reuse-architecture. This dimension only judges the blast radius of changing it.workflow. Purity is about the diff's internal composition, not its paperwork.