Skip to content
Back to skills

Diagnose Refusal

ASecurity

'Use when a coding-agent session refused, blocked, filtered, or returned HTTP 403/401/429 instead of

  • 2 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added September 19, 2026
ai-agentspythongoshellbashrailsdebugginggitapibackendsecurity

Works with

  • cursor
  • api
  • mcp

Security analysis

A100/100

Pro scans all 8 files and shows the line behind each finding

Scanned October 4, 2026

npx -y skills add Tamircohen28/tamirs-superpowers --skill diagnose-refusal --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Diagnose Refusal?

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

Security grade badge for Diagnose Refusal
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tamircohen28-diagnose-refusal/badge)](https://www.skillsdirectory.com/skills/tamircohen28-diagnose-refusal)

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
---
name: diagnose-refusal
description: 'Use when a coding-agent session refused, blocked, filtered, or returned HTTP 403/401/429 instead of
  doing the asked work, and the user needs to know WHICH LAYER refused — harness policy, project
  instructions, LiteLLM guardrail/routing, upstream provider filter, model refusal, tool permission,
  or context contamination. Triggers: ''diagnose refusal'', ''/diagnose-refusal'', ''why did it
  refuse'', ''where did the refusal come from'', ''GLM refused'', ''LiteLLM blocked'', ''provider
  filter'', ''model refused'', ''HTTP 403 from the model'', ''safety refusal'', ''cannot tell if this
  is the model or the proxy''.'
when_to_use: 'Phrases: ''diagnose refusal — GLM through LiteLLM started blocking'', ''which layer killed it:
  harness, proxy, or model?'', ''write a diagnostic bundle''. Not for ordinary stack-trace bugs — that
  is targeted-debug.'
argument-hint: '[notes about the refusal — model name, proxy, skill that triggered it]'
arguments: []
disable-model-invocation: false
user-invocable: true
allowed-tools:
- Read
- Grep
- Glob
disallowed-tools: []
effort: medium
context: ''
agent: ''
hooks: {}
paths: []
shell: bash
metadata:
  tamirs:
    visibility: public
    category: debugging
    role: debugger
    validation-tier: 1
    updated-date: '2026-09-10'
    capabilities:
      required:
        - skills
        - shell
      optional:
        - git
        - mcp
    tags:
      - debugging
      - refusal
      - litellm
      - provider
      - guardrail
      - diagnostics
      - routing
  capability: refusal-diagnostics
  updated-date: '2026-09-10'
---

# Diagnose Refusal

**Diagnostics only.** Isolate *where* a refusal originated in the request path. Do not
retry, reinterpret, weaken, jailbreak, or continue the refused task.

## Hard invariants

1. Do **not** retry the refused operation.
2. Do **not** bypass, weaken, reinterpret, jailbreak, or circumvent any safety policy.
3. Do **not** continue the task that triggered the refusal.
4. Do **not** invent invisible instructions — write `Not visible from this session.`
5. Do **not** expose hidden reasoning or private chain-of-thought.
6. Do **not** copy credential files (`.env`, `.env.*`, `credentials.json`, `*.pem`, `*.key`).
7. Do **not** modify application source or configuration.
8. Redact secrets: replace API keys, tokens, cookies, passwords, Authorization headers,
   and private keys with `***REDACTED***`. For env vars, record **names and SET/UNSET
   only** — never values.

If the current model is itself refusing, this skill still does not ask it to continue —
it switches the job entirely to benign inspection of config, routing, and the refusal text.

## Why this skill exists

A refusal sentence alone is almost useless. The same surface text can come from the
harness, a project skill, a LiteLLM guardrail, a mis-route, an upstream provider filter,
or the model. Differential diagnosis needs a sanitized bundle and a reconstructed path.

## Bundle layout (v2)

Create or replace under the repo root (or cwd if not a git repo):

```text
.refusal-debug/
├── report.md          # full diagnosis (sections 1–9)
├── request.json       # sanitized request metadata if available; else {"status":"unavailable"}
├── response.json      # sanitized response/error metadata if available; else {"status":"unavailable"}
├── routing.md         # HARNESS → LITELLM → PROVIDER → MODEL
├── environment.md     # safe env / tool versions
└── manifest.txt       # list of files created
```

Initialize with the bundled script, then fill the files:

```bash
bash skills/debugging/diagnose-refusal/scripts/init-bundle.sh
bash skills/debugging/diagnose-refusal/scripts/collect-environment.sh > .refusal-debug/environment.md
```

Resolve the skill directory from whatever path the harness loaded (plugin root,
checkout, or symlink). Prefer `git rev-parse --show-toplevel` then
`skills/debugging/diagnose-refusal/scripts/…`.

After writing any file that may contain pasted error bodies, run:

```bash
python3 skills/debugging/diagnose-refusal/scripts/redact-secrets.py .refusal-debug/report.md
python3 skills/debugging/diagnose-refusal/scripts/redact-secrets.py .refusal-debug/request.json
python3 skills/debugging/diagnose-refusal/scripts/redact-secrets.py .refusal-debug/response.json
```

Classification taxonomy: [references/refusal-classes.md](references/refusal-classes.md).
Report skeleton: [references/report-template.md](references/report-template.md).

## Workflow

Copy and track:

```text
Diagnose-refusal progress:
- [ ] 0. Init bundle + hard-invariant stance
- [ ] 1. Incident capture
- [ ] 2. Conversation state
- [ ] 3. Active repository instructions
- [ ] 4. LiteLLM / proxy path
- [ ] 5. Environment (script)
- [ ] 6. Refusal classification
- [ ] 7. Request-path reconstruction → routing.md
- [ ] 8. Comparison tests (propose only — do not execute refused task)
- [ ] 9. Final assessment (top of report.md)
- [ ] 10. Bundle manifest + completion reply
```

### 0. Init

```bash
bash skills/debugging/diagnose-refusal/scripts/init-bundle.sh
```

Incorporate any user notes from `$ARGUMENTS` / the slash-command argument into section 1.

### 1. Incident → `report.md`

Record:

- current date/time (UTC)
- active model name if visible
- provider/backend if visible
- agent/harness name and version if available
- the user's immediately preceding request that resulted in refusal
- the complete refusal response (redacted)
- whether the refusal appeared before or after any tool call
- whether an HTTP/API error was visible
- status / error / request IDs if available

Populate `request.json` / `response.json` when structured metadata exists (status code,
request id, model id, error type). Otherwise write `{"status":"unavailable","reason":"…"}`.

### 2. Conversation state

Summarize the relevant conversation immediately before the refusal. Include the exact
relevant user message where possible.

Identify relevant:

- system/project instructions visible to you
- `AGENTS.md` / `CLAUDE.md` instructions
- activated skills
- slash commands
- MCP tools
- tool permissions
- model overrides
- agent overrides

### 3. Active repository instructions

Look for and inspect, if they exist:

- `AGENTS.md`, `CLAUDE.md`
- `.claude/`, `.opencode/`, `.agents/`, `.cursor/`
- `skills/`, `SKILL.md`
- `MANTIS.md`, `mantis/`
- `opencode.json`, `opencode.jsonc`
- `litellm_config.yaml`, `config.yaml`, `config.yaml.example`

Record only configuration relevant to models, providers, routing, system prompts,
security rules, guardrails, moderation, permissions, skills, callbacks, fallbacks.
**REDACT secrets.**

### 4. LiteLLM / proxy

Determine whether LiteLLM (or another proxy) appears in the request path.

If yes, inspect accessible local configuration for:

- `model_list` / `model_name` / `litellm_params.model`
- `api_base` / `custom_llm_provider`
- `router_settings` / `fallbacks` / `context_window_fallbacks`
- `callbacks` / `guardrails` / moderation configuration

Write the probable route into `routing.md`:

```text
HARNESS → LITELLM → PROVIDER → MODEL
```

Mark each layer `CONFIRMED` / `INFERRED` / `UNKNOWN`. Do not make network requests
merely to discover secrets or credentials.

### 5. Environment

```bash
bash skills/debugging/diagnose-refusal/scripts/collect-environment.sh > .refusal-debug/environment.md
```

The script records tool versions and **env var names** (SET/UNSET) for LiteLLM / GLM /
ZAI / OpenRouter / Anthropic / OpenAI / MODEL / PROVIDER / API_BASE families only.

### 6. Refusal classification

Classify into one or more classes from
[references/refusal-classes.md](references/refusal-classes.md)
(`HARNESS_POLICY` … `UNKNOWN`). For every selected class:

```text
Evidence:
Confidence: LOW | MEDIUM | HIGH
```

Do not claim HIGH without direct evidence.

### 7. Request-path reconstruction

In both `report.md` and `routing.md`, produce:

```text
User
 ↓
Slash command / skill
 ↓
Agent/harness
 ↓
Project/system instructions
 ↓
LiteLLM (or other proxy)
 ↓
Selected provider
 ↓
Model
```

Annotate where the refusal most likely originated.

### 8. Comparison tests (propose only)

Do **NOT** execute the original refused task.

Propose the minimum safe diagnostic comparison tests:

| Test | Purpose |
|------|---------|
| A | Same harmless prompt through current harness |
| B | Same harmless prompt directly through LiteLLM / proxy |
| C | Same harmless prompt directly through the underlying provider (legitimate configured endpoint only) |
| D | A clearly authorized benign code-security review against a local toy fixture |

Goal: differential diagnosis, not bypassing safeguards.

### 9. Final assessment

Put this block at the **top** of `report.md`:

```text
Most likely refusal layer: <CLASS>
Confidence: <LOW|MEDIUM|HIGH>
Primary evidence: <one or two lines>
Second-most likely layer: <CLASS or none>
Missing evidence needed: <bullet list>
```

Then list concrete next debugging actions.

### 10. Manifest and completion reply

```bash
# refresh file list
find .refusal-debug -type f | sort > .refusal-debug/manifest.txt
python3 skills/debugging/diagnose-refusal/scripts/redact-secrets.py --all .refusal-debug
```

Respond **only** with:

```text
Diagnostic bundle created at .refusal-debug/

Most likely refusal layer: <layer>
Confidence: <LOW|MEDIUM|HIGH>

Upload .refusal-debug/report.md here for deeper analysis.
```

## Degrades

| Missing capability | Behavior |
|--------------------|----------|
| `git` unavailable | Use cwd as root; say so in `environment.md` |
| No LiteLLM config on disk | Mark LiteLLM `UNKNOWN`; still classify from HTTP/error evidence |
| No structured request/response | Write `unavailable` JSON stubs; continue |
| MCP absent | Skip MCP inventory; note `Not visible from this session.` |

## Anti-patterns

- Asking the stuck model "are you sure you can't continue?"
- Re-issuing the refused prompt under a "for educational purposes" wrapper
- Copying `.env` into the bundle
- Claiming HIGH confidence from vibe alone
- Silent retries of the refused tool call

Files in this skill

  • SKILL.md10.7 KB
  • evals/evals.json3.8 KB
  • evals/trigger-evals.json1.4 KB
  • references/refusal-classes.md2.2 KB
  • references/report-template.md1.7 KB
  • scripts/collect-environment.sh3.7 KB
  • scripts/init-bundle.sh2.6 KB
  • scripts/redact-secrets.py3.7 KB

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.