harness: add Definition-of-Done skill routing (auto-gate work with matching check-skills)

Skill-first rule now has two halves: route the request to a doing-skill,
then gate the result with the matching check-skill before 'done' --
inferred from the request, not user-named. Adds .claude/SKILL_ROUTING.md
(on-demand request->doing-skill->check-skill map). Enforcement tier A+B
(CORE rule + map; Stop-hook backstop deferred). Calibrate to stakes,
Ollama Tier-0 for cheap passes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-26 11:57:44 -07:00
parent 5bace24371
commit ca37a606c6
4 changed files with 91 additions and 1 deletions

View File

@@ -42,6 +42,16 @@ production, data-loss. Detail: EXTENDED + `.claude/OLLAMA.md`.
the memory rules (e.g. [[feedback_syncro_billing]]) describe what the SKILL does, not a license the memory rules (e.g. [[feedback_syncro_billing]]) describe what the SKILL does, not a license
to free-hand it. Reach for raw API ONLY when no skill fits or the skill genuinely cannot do it to free-hand it. Reach for raw API ONLY when no skill fits or the skill genuinely cannot do it
— and say so explicitly when you do. Mistakes here go to `errorlog.md` (`--correction`). — and say so explicitly when you do. Mistakes here go to `errorlog.md` (`--correction`).
- **Definition of Done — route the REQUEST to a doing-skill, then GATE the result with the
matching check-skill(s) before calling work done — automatically, without being asked.**
You map the request to skills from the conversation + expected end result; the user should not
have to name skill A/B/C. Standing gates (run the check-skill BEFORE declaring done): code edits
`/code-review` + `/simplify` (+ `/security-review` if it touches auth/creds/security); anything
outbound/client-facing → `impeccable` / `stop-slop`; Syncro/vendor work → its skill's own
preview+verify gate; wiki/memory writes → their lint (`wiki-lint`/`memory-dream`). **Calibrate to
stakes** (a typo fix doesn't need a full review) and **use Ollama Tier-0** for the cheap
classify/prose passes so this stays low-token. The full request→doing-skill→check-skill map is
`.claude/SKILL_ROUTING.md` — read it on demand when a request maps to a skill or work nears done.
- **Credentials — capture, vault, document (ALWAYS).** ANY credential that surfaces in a - **Credentials — capture, vault, document (ALWAYS).** ANY credential that surfaces in a
session — one the user pastes, one you create/rotate, one you discover in a log/config — you session — one the user pastes, one you create/rotate, one you discover in a log/config — you
MUST immediately store it in the SOPS vault **via the `vault` skill** (the canonical path — MUST immediately store it in the SOPS vault **via the `vault` skill** (the canonical path —

78
.claude/SKILL_ROUTING.md Normal file
View File

@@ -0,0 +1,78 @@
# Skill Routing Map
> On-demand reference for the CORE **Skill-first** + **Definition of Done** rules
> (`.claude/CLAUDE.md`). Read this when a request maps to a skill, or when work nears "done"
> and needs its check-skill. You infer the right skills from the request + expected end result —
> the user should NOT have to name them. **Calibrate to stakes** (a typo fix needs no full review)
> and **use Ollama Tier-0** for the cheap classify/prose passes so this stays low-token.
## How to use this (every substantive request)
1. **Route the action** → pick the *doing-skill* for what's being asked (tables below).
2. **Do the work** through that skill (not hand-rolled API).
3. **Gate the result** → before saying "done," run the *check-skill(s)* matching the work-type.
4. Only declare done after the gate passes. If you skip a gate for stakes reasons, say so.
---
## Doing-skills (request → the skill that DOES it)
| Request signal | Skill |
|---|---|
| Ticketing, billing, invoicing, customers, scheduling, appointments | `/syncro` (after-hours/emergency billing → `/syncro-emergency-billing`). Autotask ONLY on an explicit "in Autotask" request. |
| Any credential — read/store/rotate a secret, API key, password, token, SSH key | `vault` |
| Run a command / investigate / script on an RMM agent | `/rmm` (find the host first with `rmm-search`) |
| M365 investigation/remediation, breach check, mailbox/inbox-rule/forwarding audit, tenant sweep | `remediation-tool` |
| Onboard a new M365 tenant to the remediation app suite | `onboard365` |
| Backblaze / B2 storage, buckets, backup storage cost | `b2` |
| Bitdefender / GravityZone AV — endpoints, sweeps, policies, quarantine, EDR | `bitdefender` |
| Datto EDR / Datto AV — detections, isolate, scan, agent deploy | `datto-edr` |
| VoIP — PacketDial / OITVOIP / NetSapiens domains, users, DIDs, queues, CDRs | `packetdial` |
| Email security — Mailprotector/CloudFilter held/quarantined mail, allow/block rules | `mailprotector` |
| ScreenConnect / CW Control sessions, access installer, backstage command | `screenconnect` |
| Synology NAS | `synology` |
| Yealink phone device management | `yealink-ymcs` |
| UniFi WiFi tuning / RF / channel analysis | `unifi-wifi` |
| Map/repoint a Windows network drive on a remote endpoint | `drive-map` |
| Send someone a Discord DM / copy-paste-friendly link or command | `discord-dm` |
| Inter-session messaging, fleet todos, resource locks, coord status | `coord` |
| Git / Gitea / submodules / sync health | `gitea` (or `/sync`, `/scc`, `/save` for session ops) |
| Build/verify GuruRMM agent/server/dashboard, pre-merge check | `gururmm-build` |
| Capture an RMM feature idea | `/feature-request`; GuruConnect feature → `gc-feature-request` |
| Compile session logs/Syncro into wiki | `/wiki-compile` |
| Create a new skill or slash command | `skill-creator` |
| Independent 2nd opinion / adversarial verify | `grok` (xAI) or `agy` (Gemini) |
| Image/video gen, live web/X search past cutoff | `grok` |
| Deep multi-source researched report | `deep-research` |
> Not listed? If no skill fits, do it directly — and say so. New recurring need → `skill-creator`.
---
## Check-skills (work-type → the gate run BEFORE "done")
**Code changes** (any edit to source):
- `/code-review` — correctness/bugs. `/simplify` — reuse/cleanup. Scale to stakes.
- `/security-review` — REQUIRED when the change touches auth, credentials, security, or production risk.
- `test-driven-development` — when implementing a feature/bugfix (test first). `/verify` or `run` — confirm real behavior, not just tests.
- `rust-skills` — Rust. `inject-standards` — apply project coding standards. `human-flow`/`impeccable` — interactive UI.
- GuruRMM specifically: `gururmm-build` verify before merge-to-main (merge IS the deploy).
**Outbound / client-facing** (anything sent to a client or vendor — Syncro comment, email, DM, doc):
- `impeccable` — polish + correctness before it leaves (standing rule). `stop-slop` — strip AI-slop tone.
- Internal-only drafts are exempt.
**Syncro / vendor actions**:
- The skill's own **preview + explicit-confirm gate** is the check — show the full payload, wait for yes, then post. Never post-then-report. (Syncro: no API edit/delete after the fact.)
**Docs / wiki / memory writes**:
- Wiki articles → `wiki-lint`. Memory store edits → `memory-dream` checks (index/backlinks/dupes).
---
## Stakes calibration (don't burn tokens)
- Trivial/mechanical (typo, comment, rename, one-line doc) → skip the heavy review; a quick self-check is enough. Say you skipped and why.
- Normal change → the standard gate above.
- Security / auth / credential / migration / production / data-loss / outbound-to-client → full gate, bump model one tier, never skip.
- Push the cheap parts (classify which skills apply, prose/tone passes) to **Ollama Tier-0**; reserve inherited/opus for the actual judgment.
See also: `.claude/CLAUDE_EXTENDED.md` (full workflow detail), memories `[[feedback_skill_first_routing]]`, `[[feedback_impeccable_on_outbound]]`, `[[feedback_syncro_preview_mandatory]]`, `[[feedback_calibrate_effort_to_stakes]]`.

View File

@@ -110,7 +110,7 @@
- [Don't present inferred topology as fact](feedback_no_inferred_topology_as_fact.md) — Private-IP overlap (172.16.x on both sides) is NOT proof of a site-to-site link; I fabricated a VWP<->office VPN. State observations vs inferences; a failed reachability test disproves a link, don't explain it away; test "can reach RMM" against the EXTERNAL endpoint, not internal 172.16.3.30. - [Don't present inferred topology as fact](feedback_no_inferred_topology_as_fact.md) — Private-IP overlap (172.16.x on both sides) is NOT proof of a site-to-site link; I fabricated a VWP<->office VPN. State observations vs inferences; a failed reachability test disproves a link, don't explain it away; test "can reach RMM" against the EXTERNAL endpoint, not internal 172.16.3.30.
### Syncro ### Syncro
- [Skill-first routing — use the skill, never hand-roll the API](feedback_skill_first_routing.md) — If an installed skill covers the task, INVOKE IT. Syncro billing/invoicing ALWAYS runs through `/syncro` (or `/syncro-emergency-billing`), never ad-hoc curl — free-handing payloads is what makes Winter fix malformed tickets. Now a CORE rule. Generalizes to vault/rmm/remediation-tool/etc. - [Skill-first routing + Definition of Done](feedback_skill_first_routing.md) — If a skill covers the task, INVOKE IT (Syncro billing ALWAYS via `/syncro`, never ad-hoc curl), AND gate the result with the matching check-skill before "done" (code→/code-review+/simplify+/security-review; outbound→impeccable/stop-slop; wiki/memory→wiki-lint/memory-dream) — inferred from the request, not user-named. CORE rule; full map in `.claude/SKILL_ROUTING.md`; calibrate to stakes, Ollama Tier-0 for cheap passes.
- [Syncro API plumbing](feedback_syncro_api.md) — Content-Type required on all POST/PUT; NO idempotency anywhere — always GET before retrying; response wrappers (`.ticket.id`, `.comment.id`); add_line_item shape (internal ID, flat response, required fields); HTML uses `<br>` not `<ul>/<li>`; timer_entry response is FLAT but SUPERSEDED (use add_line_item). - [Syncro API plumbing](feedback_syncro_api.md) — Content-Type required on all POST/PUT; NO idempotency anywhere — always GET before retrying; response wrappers (`.ticket.id`, `.comment.id`); add_line_item shape (internal ID, flat response, required fields); HTML uses `<br>` not `<ul>/<li>`; timer_entry response is FLAT but SUPERSEDED (use add_line_item).
- [Syncro billing rules](feedback_syncro_billing.md) — Bill with `add_line_item` directly (not timers); fetch rates LIVE; never invent labor names (real product names only); match labor type to delivery channel (never "Prepaid project labor"); labor `taxable:false` (AZ); warranty `1049360` (never patch price); emergency `26184` ×1.5 once, branch by `prepay_hours`; corrections preserve original tech's user_id; estimate hardware `32252`. - [Syncro billing rules](feedback_syncro_billing.md) — Bill with `add_line_item` directly (not timers); fetch rates LIVE; never invent labor names (real product names only); match labor type to delivery channel (never "Prepaid project labor"); labor `taxable:false` (AZ); warranty `1049360` (never patch price); emergency `26184` ×1.5 once, branch by `prepay_hours`; corrections preserve original tech's user_id; estimate hardware `32252`.
- [Syncro workflow rules](feedback_syncro_workflow.md) — ALWAYS preview comments before posting (no exceptions); verify appointment day-of-week ("Saturday 2026-05-23") before creating; ASK who the appointment owner is; leave `contact_id` BLANK by default for ALL customers (ignore Syncro's contact-picker auto-default). - [Syncro workflow rules](feedback_syncro_workflow.md) — ALWAYS preview comments before posting (no exceptions); verify appointment day-of-week ("Saturday 2026-05-23") before creating; ASK who the appointment owner is; leave `contact_id` BLANK by default for ALL customers (ignore Syncro's contact-picker auto-default).

View File

@@ -7,6 +7,8 @@ metadata:
When a request maps to an installed skill or slash-command, **invoke that skill** rather than improvising raw `curl`/API calls. This is a hard rule, now in CORE `CLAUDE.md` ("Skill-first"). The canonical offender is **Syncro billing**: every invoice/line-item/ticket-billing request goes through the `/syncro` skill (or `/syncro-emergency-billing` for after-hours) — NOT ad-hoc API calls. When a request maps to an installed skill or slash-command, **invoke that skill** rather than improvising raw `curl`/API calls. This is a hard rule, now in CORE `CLAUDE.md` ("Skill-first"). The canonical offender is **Syncro billing**: every invoice/line-item/ticket-billing request goes through the `/syncro` skill (or `/syncro-emergency-billing` for after-hours) — NOT ad-hoc API calls.
**Two halves (CORE "Definition of Done"):** (1) route the REQUEST to a *doing-skill*, then (2) GATE the result with the matching *check-skill* BEFORE calling work done — automatically, inferred from the request + expected end result, WITHOUT the user naming skill A/B/C. Standing gates: code edits → `/code-review` + `/simplify` (+ `/security-review` if it touches auth/creds/security); outbound/client-facing → `impeccable`/`stop-slop`; Syncro/vendor → the skill's own preview+confirm gate; wiki/memory → `wiki-lint`/`memory-dream`. **Calibrate to stakes** (skip heavy review on a typo) and push cheap classify/prose passes to **Ollama Tier-0** to stay low-token. Full request→doing-skill→check-skill table: **`.claude/SKILL_ROUTING.md`** (read on demand). Decided with Mike 2026-06-26: enforcement tier "A+B" (CORE rule + on-demand map; deterministic Stop-hook backstop intentionally deferred until proven, to avoid friction).
**Why:** I default to "act directly" and, because I "know" the Syncro REST API, I reach for a hand-rolled `add_line_item` curl from memory. Free-handing the payload gets the structure wrong (attribution/`?api_key=` owner, `taxable:false`, line-item shape, priority/type format, blank contact, the preview gate), producing malformed tickets — and **Winter has to fix them** (already flagged on #32193/#32194 and others). The skill encodes all of that correctly and enforces the preview/confirm gate. The detailed billing rules in [[feedback_syncro_billing]] describe what the SKILL does when it bills; they are NOT a license to bypass the skill and do it by hand. **Why:** I default to "act directly" and, because I "know" the Syncro REST API, I reach for a hand-rolled `add_line_item` curl from memory. Free-handing the payload gets the structure wrong (attribution/`?api_key=` owner, `taxable:false`, line-item shape, priority/type format, blank contact, the preview gate), producing malformed tickets — and **Winter has to fix them** (already flagged on #32193/#32194 and others). The skill encodes all of that correctly and enforces the preview/confirm gate. The detailed billing rules in [[feedback_syncro_billing]] describe what the SKILL does when it bills; they are NOT a license to bypass the skill and do it by hand.
**How to apply:** **How to apply:**