Generate a portable stakeholder decision report for a CV deployment decision. TRIGGER when: user explicitly asks for a decision report, manager report, or stakeholder doc after a cost crossover has been computed; phrases: "write me a decision report", "generate a report for my manager", "I need a stakeholder doc", "produce the decision doc", "decision-report skill", "report for my team". SKIP when: no cost crossover exists yet — estimate-economics must run first and deliver a crossover number...
Scanned 9/6/2026
Install to Claude Code
npx -y skills add Borda/vision-delivery --skill decision-report --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Decision Report?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/borda-decision-report)More formats (shields.io, HTML) on the badges page.
---
name: decision-report
description: |
Generate a portable stakeholder decision report for a CV deployment decision.
TRIGGER when: user explicitly asks for a decision report, manager report, or stakeholder doc after a cost crossover has been computed; phrases: "write me a decision report", "generate a report for my manager", "I need a stakeholder doc", "produce the decision doc", "decision-report skill", "report for my team".
SKIP when: no cost crossover exists yet — estimate-economics must run first and deliver a crossover number; user is still in build work; user wants a one-paragraph summary (answer inline instead).
allowed-tools: Read, Write, Bash, Glob
---
<objective>
Emit a portable, decision-grade stakeholder report at `./decision-report-<YYYY-MM-DD>.md`.
Exit criterion: a Markdown file the user can hand to their manager. Every material number carries a source URL and `as_of` date. "Don't deploy / roll your own" is always a reachable recommendation — never omitted.
</objective>
<inputs>
Read these sources before writing. Do not ask for information the codebase already has.
| Section | Source |
| --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| PoC result + eval data (§4) | Packaged `scripts/baseline_map.py` output, or `.vision-delivery/ledger.jsonl` for session history; current Roboflow evidence delegated upstream |
| Frozen proof identity | Acceptance, baseline, handoff, ledger, and economics artifacts validated together with `../../resources/scripts/validate_proof_chain.py` |
| Economics + crossover (§6) | Absolute packaged `scripts/cost_model.py --streams <N> ...` output — run with the user's inputs; never hardcode figures |
| Options analysis (§5) | User-stated constraints + cost_model.py DIY vs managed outputs |
| Sensitivity (§6) | Re-run `cost_model.py` with `--streams` / `--uptime` inputs at ±20%; report delta |
| Eval threshold + model name | `.vision-delivery/eval-<session-id>.md` if present, else ask one targeted question |
Resolve the plugin root from this loaded `skills/decision-report/SKILL.md`, then run `<plugin-root>/scripts/cost_model.py` by absolute path with `--acceptance <frozen-acceptance.json>`. Never assume the user's project contains the helper. Use its output verbatim for all economic figures — no paraphrasing, no rounding beyond what the script reports. Before writing, run `<plugin-root>/resources/scripts/validate_proof_chain.py` without `--report` to obtain the terminal `chain_id`. A decision-grade report must reject `proof.status: unbound`, a failed/mismatched baseline, an invalid handoff, missing proof ledger actions, or a ledger/cost record that names a different digest. Rough unbound economics may be reported only as assumptions and cannot end in `go`.
</inputs>
\<output_structure>
Write `./decision-report-<YYYY-MM-DD>.md` with these ten sections in order:
**1. Header / metadata**
```
Owner: <name, if known>
Version: 1.0
Status: DRAFT
Date: <YYYY-MM-DD>
Decision: <one sentence stating exactly what is being decided>
Acceptance: <acceptance_id> / <acceptance_sha256>
Proof chain: <chain_id>
```
**2. Executive summary (≤1 page, written last)** Problem → recommendation → headline cost → value/ROI → top-3 risks → explicit ask (what you need from the reader). Written last; placed first.
**3. Problem and why now** Business problem + urgency. No urgency = acknowledge indefinite deferral is also a valid outcome.
**4. What was built and what it proves** PoC/MVP result measured against the user's own eval. Exact numbers — mAP, recall, count-MAE — on the user's own data. No softening.
**5. Options analysis (do-nothing mandatory)** ≥3 options:
- Option A: Managed deployment (Roboflow endpoint)
- Option B: Self-host / DIY
- Option C: Do nothing / defer
Honest pros/cons for each. Do not favour managed — the report must be able to recommend B or C.
**6. Economics — sourced, dated** One-time vs run-rate cost. Crossover point. Payback period.
Every material line must carry `[source: <URL>, as_of: <YYYY-MM-DD>]`. Lines without provenance are report failures.
Structure (copy from `cost_model.py` output — do not rewrite):
```
Self-host (<N> streams, <uptime>):
Cloud GPU (<instance>, spot): ~$X/mo [source: <URL>, as_of: <date>]
Engineer setup (<hours>h): ~$Y one-time
Ongoing ops (<hours>/wk): ~$Z/mo
Drift monitoring + retraining: ~$W/mo
Total run-rate: ~$<total>/mo + $<setup> one-time
Managed (<N> streams): ~$<managed>/mo [source: <URL>, as_of: <date>]
Crossover: <plain-English statement>
```
Sensitivities (±20% on each live-fetched rate — re-run cost_model.py to generate):
| Input varied | −20% | Base | +20% |
| --------------- | ---- | ---- | ---- |
| GPU spot rate | ... | ... | ... |
| Managed price | ... | ... | ... |
| Engineer hourly | ... | ... | ... |
**7. Risk analysis** Top risks by likelihood × impact. Mitigations. Residual risk after mitigation.
**8. Cost of inaction** Financial, operational, and reputational cost of not deploying. Value left on the table per month/quarter. Opportunity cost.
**9. Recommendation and next steps** State the recommendation plainly — one sentence. Execution path: who does what by when. What decision rights are needed. What is being approved.
**10. Appendix**
- Assumptions register (all inputs, with editable override values)
- Methodology (link to `scripts/cost_model.py`)
- Full `cost_model.py` output (paste verbatim)
- Raw eval data (mAP table or link to eval file)
- Frozen acceptance path/digest and validated handoff/evidence paths
- References (all source URLs)
\</output_structure>
\<honesty_rules>
- Do-nothing (Option C) and ≥1 DIY option (Option B) are mandatory. Never omit them.
- No material number without provenance (`[source: URL, as_of: date]` on every cost line).
- The report is a decision aid, not a sales deck. It must be able to recommend "don't deploy with us."
- If cost_model.py cannot reach a live pricing source, state the snapshot date and caveat explicitly: "Rates as of YYYY-MM-DD — live fetch failed; re-fetch recommended if older than 30 days."
- Sensitivities are mandatory in §6. Run cost_model.py with overrides — do not estimate them by hand.
\</honesty_rules>
<export>
After writing the Markdown file, append `decision_report_emitted` through `ledger_append.py`, then rerun `validate_proof_chain.py --report <report-path>`. Do not hand off a report unless that terminal validation passes. Then print once:
```
→ decision-report-<YYYY-MM-DD>.md
Export to docx (requires pandoc):
pandoc decision-report-<YYYY-MM-DD>.md -o report.docx
Markdown version is complete without pandoc.
```
Do not mention pandoc again after this one print.
</export>
\<ci_assertion>
`evals/decision-report/assert_contract.py` covers the report contract statically, and `evals/cost-model/assert_cost_model.py` covers the numeric engine. Before handing over an emitted report, verify:
1. Every line containing a dollar amount or "$/mo" matches `\[source: .*, as_of: \d{4}-\d{2}-\d{2}\]`
2. "Option C" or "Do nothing" or "defer" appears in the file
3. File exists and is non-empty
The structural check does not prove a generated report's numbers. Run the three checks against the actual emitted file and inspect its cited inputs.
\</ci_assertion>
<ledger>
Follow `../../resources/ledger-protocol.md`. Write one local record when the report file is created:
```json
{
"ts": "<ISO8601>",
"session": "<session-id>",
"skill": "decision-report",
"action": "decision_report_emitted",
"entity_id": "<workspace>/<project>",
"version": "0.4.0",
"event_id": "manual:<session-id>:decision_report_emitted:1",
"status": "success",
"source": "skill",
"acceptance_id": "<id/revision>",
"acceptance_sha256": "<sha256>",
"report_sha256": "<computed from the emitted report>",
"notes": "decision-report-<YYYY-MM-DD>.md; acceptance_sha256=<sha256>"
}
```
Append that record through the absolute packaged helper, never by writing JSONL directly:
```bash
python <plugin-root>/scripts/ledger_append.py \
--ledger <project-root>/.vision-delivery/ledger.jsonl \
--session <session-id> --skill decision-report \
--action decision_report_emitted --event-id manual:<session-id>:decision_report_emitted:1 \
--status success --acceptance <frozen-acceptance.json> \
--report <project-root>/decision-report-<YYYY-MM-DD>.md
```
</ledger>
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!