---
type: skill
name: resolver-query
description: Read Meta/RESOLVER.md, parse rules and statuses, and answer a natural-language question by surfacing the matching rule(s). Trigger /resolver-query <natural-language-question>. Use when an operator wants to look up which rule applies to a query without reading the full RESOLVER.md by hand. Do NOT use for writing rules (that is synth-pr-to-sop or synth-thread-to-sop) or for rebuilding RESOLVER.md (that is resolver-build.py).
argument-hint: "<natural-language-question> [--vault-root PATH] [--limit N]"
tool_access:
  - Read
  - Grep
policy_constraints:
  - rule: Never write to RESOLVER.md from this skill.
    exception_handling: abort and surface to caller
  - rule: Never call an external LLM API; the host Claude session does the natural-language matching.
    exception_handling: abort and surface to caller
  - rule: Read-only on the vault. No Edit, no Write.
    exception_handling: abort and surface to caller
required_inputs:
  - name: question
    type: string
    required: true
    description: The natural-language query the operator wants to route to a rule.
  - name: vault_root
    type: string
    required: false
    description: Vault root. Defaults to current working directory.
  - name: limit
    type: integer
    required: false
    description: Max number of ranked candidates to return. Default 5.
output_shape:
  summary: string
  matched_rules: array
confidence: 0.7
freshness_days: 90
last_verified: "2026-04-30"
source_count: 1
---

# /resolver-query

Look up which rule in `Meta/RESOLVER.md` applies to a natural-language question. The skill itself does NOT call an LLM. It reads RESOLVER.md, parses every rule row, and returns either a decisive match, a ranked candidate list, or "no rule matches." The host Claude session does the natural-language understanding on top of the structured output.

## When to run

- An operator wonders which rule governs a recurring question (pricing, deploy, refund, hiring exception).
- A new teammate wants to find the policy for a scenario without reading the full resolver index.
- Any time the resolver layer should answer a query and the operator wants the structured candidate set in one call.

## How it works

1. The skill reads `Meta/RESOLVER.md` from the vault root.
2. It parses the YAML frontmatter for the build timestamp and counts.
3. It parses every row of the `## Rules` table into a structured record.
4. It runs a deterministic match against the question:
   a. Tokenize the question (lowercase, drop stopwords, keep stems).
   b. For each rule, score by token overlap against `rule_id`, source path, skill link, and source-file H1/topic when available.
   c. If exactly one rule scores >= the decisive threshold, return that rule directly.
   d. Otherwise return up to `--limit` rules ranked by score.
   e. If no rule scores above zero, return `no rule matches this query`.
5. The host session then reads the structured output and frames the answer to the operator.

## Step 1: Run the skill

```bash
python3 skills/resolver-query/query.py "How do we handle pricing exceptions?" \
    --vault-root <vault>
```

Output is a JSON document on stdout with shape:

```json
{
  "question": "...",
  "vault_root": "...",
  "resolver_built_at": "...",
  "rule_count": 17,
  "match_kind": "decisive | ranked | none",
  "matched_rules": [
    {
      "rule_id": "...",
      "type": "decision | workflow | exception | fact",
      "status": "active | stale | superseded | under-review | unknown",
      "last_verified": "...",
      "source_path": "...",
      "skill_link": "...",
      "score": 0.0
    }
  ],
  "summary": "..."
}
```

## Step 2: Read the matched rule

If the match kind is `decisive`, the host session opens the rule's source file (`source_path`). If `ranked`, the host session presents the top candidates to the operator and lets them pick. If `none`, the host session tells the operator no rule applies and offers to draft one (which would route to `synth-thread-to-sop` or `synth-pr-to-sop`).

## Rules

- The skill is read-only. It NEVER writes to `RESOLVER.md` or any source file.
- The skill makes no external network calls. No LLM API is invoked from inside `query.py`.
- The matching algorithm is deterministic and stdlib-only. The host Claude session is the natural-language layer on top.
- When `match_kind == none`, the skill returns the empty `matched_rules` list and the host session tells the operator no rule matches; it does not invent one.

## Boundary

- Adjacent skills:
  - `/synth-pr-to-sop` and `/synth-thread-to-sop` write new rules.
  - `scripts/resolver-build.py` rebuilds `RESOLVER.md`.
  - `scripts/resolver-conflict-report.py` surfaces conflicts in JSON.
  - `scripts/resolver-branch-merge-prompt.py` drafts merge prompts.
- This skill READS the rendered index. It does not refresh, edit, or rewrite it.
