--- name: tradeoff description: > Score the options at a decision fork on four cost axes — reversibility, blast radius, cost-if-wrong, process cost — with a provenance grade on every cell so a guess never reads as a measurement. Report-only: no totals, no ranking arithmetic, no external-surface writes. when_to_use: > Triggers on "tradeoff", "trade-off", "트레이드오프", "트레이드 오프". Do NOT activate on "기존 결정의 부채 조회" (that is `debt`) or on "이슈 착수 가치 판정" (the Issue Review anchor's Judgement table owns that). verified-against-runtime: true runtime-verified-at: 2026-09-08 runtime-verified-note: "ugrep 7.8.4 (macOS 26.5.2, invoked as grep) — the Case 2 evidence block is a transcription of a live run: the sunset-field probe exits 1 over skills/ and 0 over hooks/." --- # Tradeoff ## Overview A decision fork produces two or more options, and the vocabulary for costing them already exists across this repo — `Scope-risk:` and `Confidence:` trailers, the `Blast Radius` clause, the SRP clause's "buys a review round, a merge ordering, a tracker entry, and a reviewer's context reload — each, every time". What is missing is a surface that puts them side by side at the moment of choosing. `Decision-Point Briefing` covers scope, risk and reversibility but fires only "when you stop to ask", so a fork the agent walks straight through is costed by nothing. This skill fills that gap and nothing else. It enumerates the options, scores each on four axes, and marks where every score came from. **Core principle:** a convention is not an option. When the lookup returns a precedent, that precedent is the answer and no table is built. ## When to Use - An implementation fork with two or more real candidates — a pair (hook vs skill, inline vs extracted) or a wider set (enforce in a hook / in a skill / in CI / in review only) - Deciding whether to act on a review finding, and whether it blocks Not for deciding whether a piece of work is worth starting — the Issue Review anchor's `Judgement` table (Need / Alternative / Urgency) owns that, and a second surface for it would only drift from the first. ## Process ### Step 1: Enumerate the options — three probes, then stop Take the options the user named, then run exactly these three probes. Three, then stop: this is the termination condition, not a search to be extended. 1. **Existing code** — does something already do this? `grep`, `Read`, a sibling implementation. 2. **Convention or precedent** — has a rule, a sibling skill, or a prior decision already settled this? Read `AGENTS.md`, `ETHOS.md`, the sibling `SKILL.md` files. 3. **Do nothing** — what happens if none of the options is taken? Add it to the option list; it is a real candidate, not a formality. **Probe 2 terminates the skill.** If it returns a precedent that covers the fork, print the precedent with its file and line, say which option it selects, and stop. Do not build a table. A rule is a trade-off the team already made, and re-scoring it here would be re-opening it — which `ETHOS.md` reserves to the team, not to the runtime. Reporting what the lookup returned is not re-opening it. ### Step 2: Score the four axes One ordinal value per cell — `low`, `moderate`, or `high`. Nothing else, and no numbers: a number invites addition, and an added column of self-authored values reads as a measurement. | Axis | The question | Where the vocabulary comes from | | ------ | -------------- | -------------------------------- | | Reversibility | If this is wrong, how expensive is undoing it? | "Irreversible or shared state — never proceed on your own" | | Blast radius | How far does a failure reach, including outside the system? | The `Blast Radius` clause; `Scope-risk:` trailer | | Cost-if-wrong | What is paid if the judgement turns out to be mistaken? | `Confidence:` trailer | | Process cost | Review rounds, merge ordering, reviewer context reload | The SRP clause | Score every option on every axis — one row per option, however many there are, with the do-nothing row always among them. **Do not narrow the set to a pair before scoring.** Dropping a candidate on the way to the table is a judgement made with no axis behind it, and it is invisible afterwards: the reader sees a two-row table and takes it for the whole fork. A candidate that does not survive belongs in the table with the cell that killed it, not outside it. The table's own cost is one row, so an option list is narrowed by its scores, never by anticipating them. `UNKNOWN` is for a cell you cannot call even directionally — not for a weak one. A cell you can call, but only from plausibility, still gets its value and is graded `assumed` in Step 3; that is what makes the weakness readable instead of hidden behind a blank. ### Step 3: Grade where each score came from Every cell carries one grade beside its value: | Grade | Means | Requirement | | ------- | ------- | ------------- | | `measured` | A command was run and its output decided this | Print the command beside the cell | | `estimated` | Inferred from a comparable case that was actually read | Name the case | | `assumed` | No basis beyond plausibility | Say so plainly | | `UNKNOWN` | Not callable even directionally | Leave the value empty | The grades exist to make the weak cells visible, not to make the table trustworthy. A table of `assumed` cells is a table of guesses that has been labelled honestly — it has not become evidence. ### Step 4: Report Print the table, then one line per option saying why it was chosen or dropped. - **No totals row.** No sum, no average, no weighted score, no ranking column. The axes are read side by side; they are not commensurable. - If the decision is worth keeping, propose a `Rejected: