Makes an architectural / project / scope decision using a 5-part model
INSTEAD of asking the user. Structure: π― Decision / Why / π‘ Security /
π Scalability / Alternatives / Plain-language analogy.
1 question = 1 atomic artifact.
Use when: the agent is about to ask an architectural / scope question;
"/decision-first", "decide it yourself", "apply the decision model"
Installs into .claude/skills of the current project.
Are you the author of Decision First?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/bearded-illirian-decision-first)
---
name: decision-first
description: |
Makes an architectural / project / scope decision using a 5-part model
INSTEAD of asking the user. Structure: π― Decision / Why / π‘ Security /
π Scalability / Alternatives / Plain-language analogy.
1 question = 1 atomic artifact.
Use when: the agent is about to ask an architectural / scope question;
"/decision-first", "decide it yourself", "apply the decision model"
---
# Decision-First Protocol
Makes a decision **on behalf of** the user via a 5-section model with full reasoning and alternatives. Invoked whenever the agent is about to ask an architectural / project / scope question β instead of asking, the skill is called.
**Core idea:** the user prefers autonomous decisions with transparent reasoning over back-and-forth Q&A. A decision can be contested post-hoc (round 2) β cheaper than a synchronous pause-and-ask.
**When to call:** exists **2+ reasonable alternatives** and a justified selection is required. If one option is obviously correct β do not call, just act.
## Input
An ambiguous architectural, scope, or design question the agent is about to ask the user.
## Output
`decision-{NN}.md` capturing the choice via a 5-part model (π― Decision / Why / π‘ Safety / π Scalability / Alternatives / In plain language).
## Hands off to
Returns control to the calling skill (typically `arch-first`, `plan-first`, or `library-first`).
---
## Step 0 β Task context
Ensure `{log_dir}` and `{slug}` are known. Otherwise resolve from the latest task log folder.
---
## Step 1 β Identify decision(s)
**Auto-mode** β pick the last unresolved question from the current conversation. If related questions cluster (e.g. "flatten + format" = 2 decisions) β handle all in one invocation, one artifact per decision.
**Manual mode** (`/decision-first`) β either process the questions the user described, or ask "which questions?".
**Cutoff:** obvious choice β skip the skill, just act.
---
## Step 2 β Apply the 5-section model
Per decision:
```markdown
# D{N} β {short title}
π― **Decision:** {chosen option in one sentence}
**Why this option:**
- {specific reason 1}
- {specific reason 2}
**π‘ Security:** {security analysis. If N/A β explicit `not applicable`}
**π Scalability:** {scaling impact. If N/A β explicit `not applicable`}
| Alternative | Why rejected |
|---|---|
| {option 1} | {concrete drawback} |
| {option 2} | {concrete drawback} |
**Plain-language analogy:** {real-world analogy without technical jargon}
```
Rules:
- π― Decision β one sentence, no "possibly X"
- Why β 2 to 5 concrete reasons
- π‘ Security + π Scalability β always present (even if `not applicable` with rationale)
- At least 2 real alternatives (no straw men)
- Analogy β from real life (warehouse / shop / kitchen)
---
## Step 3 β Numbering
Per-task auto-numbering scoped to `{log_dir}`:
```bash
NEXT_NN=$(( $(ls "{log_dir}"/decision-*.md 2>/dev/null | wc -l) + 1 ))
```
Format `decision-{NN}.md` (zero-padded). Retry β `decision-{NN}.R2.md`.
---
## Step 4 β Write and register
Each decision = one file `{log_dir}/decision-{NN}.md`. Add a row to `task.md` `## Task files` section + a link block at the end.
Register in `task_artifacts` (one row per decision):
```bash
sqlite3 {routing_db} \
"INSERT INTO task_artifacts
(task_id, block_num, round_num, artifact_type, file_name, file_path, created_by, created_at)
VALUES ('{slug}', {block_num or NULL}, 1, 'decision', 'decision-{NN}.md',
'{log_dir}/decision-{NN}.md', 'decision-first', '{date}');"
```
---
## Step 5 β Output summary
Group decisions inline in chat:
```
β Decision-first β N decisions taken:
[D{NN}] π― {chosen} β {1-line reasoning}
[D{NN+1}] π― {chosen} β {1-line reasoning}
```
After output β **continue working**. Do not wait for approval (user objects β "rewrite D{NN}" triggers round 2).
---
## Principles
1. **Do not ask** β call the skill instead of asking the user
2. **All 5 sections mandatory** β even `not applicable` must be explicit
3. **Real alternatives only** β no straw men
4. **Analogy mandatory** β makes the decision accessible to non-technical stakeholders
5. **1 question = 1 artifact** β for analytics and typing
6. **Flag unknowns** β insufficient data β mark as `β οΈ requires validation`
---
## Anti-patterns
### β Asking a question instead of the skill
2+ alternatives + no clear winner β call the skill. Do not ask.
### β Skipping Security or Scalability
UI/cosmetic doesn't excuse silence. Write `not applicable` with a reason.
### β Straw-man alternatives
Alternatives must be viable choices in the same value system.
### β Silent choice under insufficient data
Explicitly flag `β οΈ requires validation` β do not hide the uncertainty.
### β Bundling multiple decisions in one file
1 question = 1 file = 1 row in task_artifacts. Group visually in chat only.
### β Inlining instead of `Skill()`
Always via the Skill tool β otherwise version drift + no artifact registration.
---
## Example β reference decision (public form)
```markdown
# D1 β `producer_id` in draft: denormalize or JOIN?
π― **Decision:** denormalize β copy `producer_id` from source into draft at INSERT.
**Why this option:**
- Analytics queries filter by producer often. JOIN on millions of rows is slow.
- INTEGER (4 bytes) β cheap in storage.
- Source is immutable after processing β single source of truth preserved.
**π‘ Security:** validated by the catalog FK trigger at INSERT β no forgery. Deactivating the producer blocks new INSERTs, keeps old audit trail.
**π Scalability:** 1M rows β SELECT without JOIN = O(log n) with an index. With JOIN β double scan. On 10M rows β seconds vs milliseconds.
| Alternative | Why rejected |
|---|---|
| JOIN on every analytics | Degrades on large volumes |
| Materialized view | SQLite has no MV. VIEW = same JOIN under the hood |
| Periodic refresh job | Sync complexity. Denormalization at INSERT is simpler |
**Plain-language analogy:** imagine an archive of invoices. Storing only supplier id β building a report by supplier is slow (JOIN with registry). Storing a small copy of the supplier label right next to the invoice β report is instant. Registry updates don't affect the archive because the archive is history, not the present.
```
---
## Related skills
- **plan-first** β plans execution steps (after decisions are made)
- **note-first** β saves a free-form note (after user request)
- **arch-first** β multi-block architectural tasks (invokes decision-first at forks)