Skip to content
Back to skills

Refine Prompt

ASecurity

Reconstruct a free-form prompt into actionable AC + assumptions + confidence band before the engine plans — '/work \"…\"', 'baue X', 'ist der Prompt klar genug für die Engine?'.

  • 10 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added June 5, 2026
ai-agentspythongophpnextjsapibackend

Works with

  • cursor
  • cli
  • api

Security analysis

A100/100

Scanned June 5, 2026

npx -y skills add event4u-app/agent-config --skill refine-prompt --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Refine Prompt?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Refine Prompt
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/event4u-app-refine-prompt/badge)](https://www.skillsdirectory.com/skills/event4u-app-refine-prompt)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
model_tier: inherit
name: "refine-prompt"
description: "Reconstruct a free-form prompt into actionable AC + assumptions + confidence band before the engine plans — '/work \"…\"', 'baue X', 'ist der Prompt klar genug für die Engine?'."
personas:
  - developer
  - senior-engineer
  - ai-agent
domain: product
execution:
  type: assisted
  handler: internal
  allowed_tools: []
workspaces:
  - agent-config-maintainer
packs:
  - meta
---

# Refine Prompt

> Move a free-form prompt from "raw text" to "engine-ready" in one run.
> Produces reconstructed acceptance criteria, explicit assumptions,
> and a confidence band that decides whether the engine proceeds
> silently, halts for confirmation, or refuses to plan.
>
> Sibling of [`refine-ticket`](../refine-ticket/SKILL.md) — same
> reconstruction-of-intent pattern, different input shape. Tickets
> arrive structured (id, title, AC); prompts arrive as one string.

## When to use

- The user invokes `/work "<prompt>"` or pastes a free-form request.
- The dispatcher hits `input.kind="prompt"` in the `refine` step.
- A prompt looks ambiguous, broad, or scope-undefined and the user
  asks "ist das klar genug, um loszulegen?".
- Before any plan/apply step on prompt-driven work — never after.

## When NOT to use (near-misses)

| Phrasing | Route to |
|---|---|
| "refine this ticket" | [`refine-ticket`](../refine-ticket/SKILL.md) |
| "estimate this prompt" | not supported — score then estimate downstream |
| "plan this feature" | `/feature-plan` (downstream) |
| "is this a duplicate?" | `validate-feature-fit` (sub-skill, post-refine) |

`refine-prompt` is the *first* gate on prompt-driven flow. It does not
plan, does not implement, does not write back anywhere.

## Input

Exactly one path: a non-empty raw string carried in
`state.input.data.raw` (built by [`work_engine.resolvers.prompt`](../../templates/scripts/work_engine/resolvers/prompt.py)).
No branch detection, no URL parsing, no clipboard fallback — the
calling command (`/work`) owns prompt capture; this skill only refines.

If `raw` is missing, empty, or whitespace-only the resolver already
raised `PromptResolverError`. The skill never receives that input.

## Modes and bypass

The skill honours `prompt_optimization.inbound` (or
`prompt_optimization.default` when no inbound override is set) from
`.agent-project-settings.yml` / `.agent-settings.yml`. Three modes:

| Mode | Behaviour |
|---|---|
| `off` | The skill is a no-op. The dispatcher writes `confidence={"band":"high","score":1.0}` directly and the engine proceeds with the literal prompt. No assumption inference, no clarifying questions. |
| `mini` | Stack-aware light shaping. Steps 1-2 run; step 3 only emits `assumes:` lines for *implicit stack constraints* (framework, package manager) detected from config files. Steps 4-5 produce 3 AC bullets max. Low-band halts ask at most one question; medium-band halts are auto-confirmed silently. |
| `max` *(default)* | Full procedure — every step 1–6 runs. Medium-band halts surface the assumption list verbatim; low-band halts ask one clarifying question. This is the existing behaviour. |

**Bypass prefix.** If the raw prompt starts with the configured
`prompt_optimization.bypass_prefix` (default `/raw`), the skill
becomes a no-op regardless of mode. The dispatcher strips the
prefix, passes the remainder through verbatim, and records
`bypass:true` in the envelope so downstream surfaces (delivery
report, `--no-prose-synthesis`) can attribute the skip.

```
/raw migrate auth.service.ts to use jose, keep the API shape
```

`/raw` is reserved at the prompt boundary only — it has no meaning
mid-prompt and is not stripped when it appears inside the body.

### Stack-config read (mini / max only)

When the mode is `mini` or `max`, step 3 may read these config files
(read-only, scope-locked) to enrich the `assumes:` block:

- `package.json` — JS / TS framework detection (Next.js App vs Pages,
  Remix, SvelteKit, Astro, Expo, …)
- `composer.json` — PHP framework detection (Laravel, Symfony,
  framework-less)
- `pyproject.toml` / `requirements.txt` — Python framework detection
- `CLAUDE.md` / `AGENTS.md` — project-declared stack hints
- `.cursorrules` — project-declared stack hints
- `tsconfig.json` — TS path-alias / module-resolution hints

The skill MUST NOT read source files, `.env*`, secrets, or user
data. Detection lands as a single `assumes: stack=<framework>@<version>`
line; the medium-band halt is the user's chance to flip it.

## Procedure

### 1. Read and analyze the prompt

Examine the raw text top to bottom *before* changing anything in
state. Identify the *single* desired outcome in one sentence —
verb + object + observable result. If the prompt names two
unrelated outcomes (e.g. "fix login AND refactor the dashboard"),
record both but flag scope-overload in step 5; the score will
land in `medium` or `low`.

This is an analysis pass, not an execution pass. The skill does
not modify the prompt, infer code changes, or call any tool — it
investigates the input and produces a structured envelope the
dispatcher reads.

### 2. Enumerate explicit constraints

Pull every concrete signal from the prompt verbatim:

- **Files / modules** named in the text (`UserController`,
  `auth.service.ts`, `migrations/2024_…`).
- **Behaviour anchors** — endpoints, routes, commands, fixtures.
- **Hard rules** — "must not break X", "without changing the API",
  "keep backwards compat".

Constraints come from the prompt only. Inferred constraints belong in
step 3 (assumptions), never here.

### 3. Infer reasonable assumptions

Anything the prompt implies but does not state. Examples:

- "fix the login bug" → assumes the bug is in the existing `auth/`
  module (no new auth provider).
- "add caching" → assumes the project's primary cache driver
  (per `.agent-settings.yml` / `config/cache.php`).
- "speed up the export" → assumes "faster" means runtime, not memory.

Each assumption is a single line, prefixed with `assumes:`. The
medium-band halt surfaces them verbatim — no rewording, no
explanations.

### 4. Generate the AC list

Three to seven bullet points. Each bullet is observable and
testable in the project's existing test surface (Pest / Jest /
pytest / etc.). Avoid:

- "works correctly" / "is fast" / "looks better" (untestable)
- "no regressions" (the test suite already covers that)
- "follows best practices" (not an AC)

Anchor each bullet to a constraint from step 2 or an assumption from
step 3 — never both implicit.

### 5. Score confidence

Delegate to [`scripts.work_engine.scoring.confidence`](../../templates/scripts/work_engine/scoring/confidence.py):

```python
from work_engine.scoring.confidence import score
result = score(raw=prompt_raw, ac=reconstructed_ac, assumptions=assumptions)
# result.band ∈ {"high", "medium", "low"}
# result.score ∈ [0.0, 1.0]
# result.dimensions: dict[str, int]   # 0–2 per dimension
# result.reasons: list[str]            # human-readable rationale
```

The rubric (5 dimensions × 0–2, sum / 10) and band thresholds
(`high ≥ 0.8`, `medium 0.5–0.79`, `low < 0.5`) are owned by
`confidence.py`. Do not re-derive them in prose.

### 6. Self-review (3-scan checklist)

Before emitting the envelope, run these three scans. Each is a fast pass; failure blocks emission.

1. **Spec coverage** — every concrete signal from step 2 (constraints) and step 3 (assumptions) is reflected somewhere in the AC list. Walk the constraint list top-to-bottom; each must anchor at least one AC bullet or appear in the *Assumptions* block.
2. **Placeholder / TODO scan** — the rendered envelope contains no `<placeholder>`, `TODO`, `FIXME`, `tbd`, `???`, `XXX` strings. The literal angle-bracket placeholders in the template (`<one sentence …>`, `<bullet>`) must be replaced with concrete text before emission.
3. **Type / shape consistency** — every named file, module, route, or command in the AC matches the project's existing conventions. If the prompt names `auth.service.ts` but the codebase uses `AuthService.php`, surface the mismatch in *Assumptions* rather than adopting the prompt's spelling.

Source: adapted from `obra/superpowers` `writing-plans/SKILL.md` § Self-Review (v5.1.0).

## Band-action mapping

The `refine` dispatcher step in `directives/backend/refine.py` reads
the score and returns one of three outcomes — the skill does not
decide the action, only produces the inputs.

| Band | Outcome | What the user sees |
|---|---|---|
| `high` | `SUCCESS` | Silent proceed; AC + assumptions land in the delivery report |
| `medium` | `PARTIAL` | Assumptions report halt: numbered list of `assumes:` lines + AC, user confirms or edits |
| `low` | `BLOCKED` | One clarifying question (per [`ask-when-uncertain`](../../rules/ask-when-uncertain.md) Iron Law) |

## Output format

The skill emits a structured envelope; the dispatcher renders it.
Required fields, in order:

1. **Goal** — single sentence, verb + object + observable result
2. **Acceptance criteria** — numbered list, 3–7 entries, each
   anchored to a step-2 constraint or a step-3 assumption
3. **Assumptions** — bullet list, each line prefixed `assumes:`
4. **Confidence** — band + score + per-dimension breakdown from
   `work_engine.scoring.confidence`

The shape below is the rendered surface for `medium` / `low`
halts; for `high` the same envelope lands in the delivery report
without a halt.

````markdown
## Reconstructed prompt

**Goal:** <one sentence, verb + object + observable result>

**Acceptance criteria:**
1. <bullet>
2. <bullet>
3. <bullet>

**Assumptions:**
- assumes: <line>
- assumes: <line>

**Confidence:** medium (0.62) — goal_clarity 2 · scope_boundary 1 · ac_evidence 2 · stack_data 1 · reversibility 0
````

For `low`, the question replaces the AC list:

```
> The prompt does not name <missing dimension>.
>
> 1. <option that resolves the gap>
> 2. <alternative resolution>
> 3. <skip / abandon>
```

## Gotchas

- The model invents AC that *sound* observable but aren't anchored
  in the prompt or a concrete file. Every AC must trace to a step-2
  constraint or a step-3 assumption — no free-floating bullets.
- Assumptions are not commitments. The medium-band halt is the
  user's chance to flip them; the skill never asserts an assumption
  as fact.
- The scorer is heuristic, not LLM-based. Token count is not a
  signal — a 200-word prompt can score `low` if the goal is vague,
  and a 20-word prompt can score `high` if scope is unambiguous.
- UI-shaped prompts ("redesign the dashboard", "make the form
  prettier") score `low` on `stack_data` until R3 lands the UI
  directive set; band-action is a pointer to R3, not a refusal.

## Do NOT

- Do NOT call this skill on `input.kind="ticket"` — that path runs
  through [`refine-ticket`](../refine-ticket/SKILL.md).
- Do NOT auto-confirm assumptions on the user's behalf in the
  medium-band halt. The halt is the contract.
- Do NOT stack multiple clarifying questions in the low-band halt.
  Iron Law: one question per turn.
- Do NOT mutate `state.input.data.raw`. The original prompt stays
  verbatim for replay; reconstructed output lands in
  `data.reconstructed_ac` and `data.assumptions`.
- Do NOT re-derive band thresholds in prose. They live in
  `confidence.py` and only there.
- Do NOT read source files, `.env*`, secrets, or arbitrary user
  files when stack-detecting in mini / max mode. The allowlist
  above (`package.json`, `composer.json`, `pyproject.toml`,
  `requirements.txt`, `CLAUDE.md`, `AGENTS.md`, `.cursorrules`,
  `tsconfig.json`) is exhaustive.
- Do NOT strip the `bypass_prefix` mid-prompt. The prefix is only
  recognised at the prompt boundary; matches inside the body stay
  literal.
- Do NOT silently rewrite the prompt in `max` mode without
  surfacing the assumption list on a medium-band halt. The diff
  is the contract.

## See also

- [`refine-ticket`](../refine-ticket/SKILL.md) — sibling for ticket-shaped input
- [`prompt-optimizer`](../prompt-optimizer/SKILL.md) — engine-outbound sibling; same `prompt_optimization` setting controls its mode
- [`work_engine.resolvers.prompt`](../../templates/scripts/work_engine/resolvers/prompt.py) — envelope builder
- [`work_engine.scoring.confidence`](../../templates/scripts/work_engine/scoring/confidence.py) — rubric + band thresholds
- [`ask-when-uncertain`](../../rules/ask-when-uncertain.md) — one-question-per-turn Iron Law
- [`artifact-drafting-protocol`](../../rules/artifact-drafting-protocol.md) — this skill was drafted under it
- AI Council session: `agents/runtime/council/responses/prompt-master-mini.json` (2026-05-17) — analysis behind the mini/max split and `/raw` bypass <!-- council-ref-allowed: ADR decision trace -->

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.