Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsCommunityBlog
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

Back to skills

Vc Self Check

ASecurity

On-demand self-diagnostician orchestrator for the vc-fix plugin (Tier 2 of the client→vendor feedback loop). It SPAWNS the `self-check-diagnostician` subagent to read this session's telemetry jsonl + transcript + the skill-expectations oracle and return a validated finding STRUCT — the oracle, jsonl and transcript never enter the main conversation. The orchestrator then relays a SHORT summary (the exact fields that would be sent), and if ≥1 finding is BROKEN/DEGRADED asks ONE binary AskUserQu...

2 stars
0 votes
0 copies
0 views
Added 9/20/2026
ai-agentsgobashnodetestinggitapi

Works with

claude codecliapimcp

Security Analysis

A100/100

Scanned 9/20/2026

Install to Claude Code

$npx -y skills add VirtoCommerce/vc-mcp-testing-module --skill vc-self-check --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Vc Self Check?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Vc Self Check
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/virtocommerce-vc-self-check-vc-mcp-testing-module/badge)](https://www.skillsdirectory.com/skills/virtocommerce-vc-self-check-vc-mcp-testing-module)

More formats (shields.io, HTML) on the badges page.

Download Zip
Files
SKILL.md
---
name: vc-self-check
description: On-demand self-diagnostician orchestrator for the vc-fix plugin (Tier 2 of the client→vendor feedback loop). It SPAWNS the `self-check-diagnostician` subagent to read this session's telemetry jsonl + transcript + the skill-expectations oracle and return a validated finding STRUCT — the oracle, jsonl and transcript never enter the main conversation. The orchestrator then relays a SHORT summary (the exact fields that would be sent), and if ≥1 finding is BROKEN/DEGRADED asks ONE binary AskUserQuestion — file the issue(s) in Virto, yes/no — and on yes spawns the `self-check-deliverer` subagent to run the delivery. The one question is the ONLY operator interaction; a yes means 'publish whatever is appropriate, decide the form yourself' and the agent never asks again. It writes NO local report files (no DIAG-*.md/.json, no DELIVERY-*.md), never modifies the install, and never sends anything without an explicit yes (or a hand-set feedback.mode:auto). Plugin-wide (every vc-fix skill/command/agent), so NOT qa-prefixed. Runs from the end-of-turn tail-trigger (silent, no modal) when a span was flagged or a 👎 was recorded, or when the user runs /vc-self-check directly. Recursion/re-nag is prevented by the collector dropping vc-self-check + self-check-diagnostician spans + per-signature dedup + the selfCheckSeen guard.
argument-hint: "[latest | <session-id>] | deliver"
---

# /vc-self-check — vc-fix Self-Diagnostician (Tier 2) — ORCHESTRATION CONTRACT

This skill is an **orchestrator**. It does not analyse telemetry inline and it does not send inline.
It spawns the `self-check-diagnostician` subagent ([`agents/self-check-diagnostician.md`](../../agents/self-check-diagnostician.md)),
receives its validated finding struct, discloses it, asks the operator's one yes/no, and — on yes —
spawns the `self-check-deliverer` subagent ([`agents/self-check-deliverer.md`](../../agents/self-check-deliverer.md))
which drives [`deliver.mjs`](./deliver.mjs). The passive Tier-0 collector
([`hooks/session-telemetry.mjs`](../../hooks/session-telemetry.mjs)) records *what happened* as spans
and `type:"obs"` observations and assigns **no** severity; the subagent assigns it, judged against
the oracle ([`knowledge/diagnostics/skill-expectations.md`](../../knowledge/diagnostics/skill-expectations.md)).

**Why a subagent (PR #172 item 1).** Diagnosis reads the whole session jsonl, the transcript, and a
long oracle. Doing that inline floods the main conversation with material the operator never needs.
The subagent keeps all of it out of context and returns only a compact struct. It also cannot ask
questions — only the orchestrator can — so the "one question per turn" rule is structural, not a
convention.

**No local report artifacts (PR #172 item 2).** `DIAG-*.md`, `DIAG-*.json` and `DELIVERY-*.md` are
**gone** — none are written, none are read. The only persistence is a compact per-finding record in
the session's own `state.json` (`selfCheckFindings[]`), written by `deliver.mjs`, which is what stops
re-asking about a defect already declined and lets a failed send be retried.

---

## Hard invariants

- **Read-only w.r.t. the plugin install.** NEVER modify installed plugin files. The "proposed fix"
  is a written recommendation, not an applied edit.
- **Nothing leaves the machine without an explicit yes.** The diagnose flow makes no PR, no issue,
  no tracker write. `deliver.mjs` sends only on `--confirm` (the operator's yes) or the hand-set
  `feedback.mode: auto`. `feedback.mode: off` ⇒ no question, no send.
- **The subagent's output is not user-visible.** The orchestrator MUST restate it in chat — that
  restatement, showing the exact fields that would be sent, is the disclosure surface (it replaces
  the old "Show what would be sent" option).
- **The consent MUST be an actual `AskUserQuestion` TOOL CALL — never a prose "yes/no" typed into
  chat.** Emit the disclosure as text, then STOP and call the `AskUserQuestion` tool with a single
  binary question ("File the issue(s) in Virto?" → **Yes** / **No**). A question typed as plain prose
  (e.g. `File the issue(s) in Virto? (yes / no)`) does NOT count — it doesn't render the interactive
  form, is easy to miss, and does not gate delivery. If `AskUserQuestion` is unavailable (a headless /
  non-interactive run), do NOT fall back to a prose question: report the plan and stop (or rely on
  `feedback.mode: auto`). The disclosure text and the tool call are two separate steps.
- **The binary AskUserQuestion is the ONLY operator interaction in the delivery path, and a yes ends
  it.** After the operator says yes you MUST NOT ask again for ANY reason — the yes means *"publish
  whatever is appropriate, decide the form yourself"*. In particular, NEVER ask any of these (each is
  the agent's own deterministic decision, taken by the `self-check-deliverer`, not the operator's):
  - which route to take (new issue vs a comment on a deduped match) — see A3/Step 3;
  - whether to supplement an existing issue whose body lacks the evidence — YES, always (B1);
  - what to do when the boundary validator dropped a field — send what passed, note it in one clause
    of the result line (B3), never a question;
  - whether to keep or purge the session's telemetry — automatic (A4/Step 3), never a question.
- **The validator is the ONLY gateway (B3 — HARD PROHIBITION).** No agent, subagent, or skill may
  hand-author, edit, or "top up" an upstream issue/comment body to work around a validator denial.
  The only outbound bytes are the ones `deliver.mjs` composes from the closed-schema struct + the
  vendor-provenance channel. If content is still dropped after B1/B2, send what passed and note the
  omission — do not reach for `mcp__github__*` / `gh` / a raw body to add it back.
- **One info line + at most ONE question per turn.** The question, when asked, is the single binary
  *file the issue(s) in Virto — yes/no*. There is never a second question. No cleanup prompt (the
  24 h age-cap reclaims leftovers unprompted).
- **Never diagnose its own invocation.** The collector drops `vc-self-check` and
  `self-check-diagnostician` spans/observations; the subagent drops them again (belt and braces).
- **English only**; never print a secret.

---

## Flow

**The orchestrator has exactly four jobs (C2):** (1) spawn the diagnostician and receive its struct;
(2) relay the SHORT roll-up + disclosure and, if a routable finding exists, ask the ONE binary
question; (3) on yes, spawn the `self-check-deliverer` subagent with the struct; (4) print the
deliverer's one result line. It does NOT do dedup, route selection, body composition, the leak scan,
sending, or telemetry retention inline — those belong to `deliver.mjs`, driven by the deliverer, so
the dedup output and the issue/comment bodies never enter the main conversation.

### Step 1 — Spawn the diagnostician (do NOT analyse inline)

Immediately spawn the subagent with the **Task tool**, `subagent_type: "self-check-diagnostician"`.
Pass it: the session id (`latest` or the `<session-id>` arg) and `outputRoot`
(`VC_FIX_HOME || cwd`). Do not read the jsonl, the transcript, or the oracle yourself — that is the
whole point of the subagent.

It returns a JSON finding struct (schema v3): `{ sessionId, pluginVersion, nodeVersion, os,
feedback, sessionCount, findings[] }`. Each finding carries the enum verdict fields plus the v3
provenance fields (`pluginFile`/`pluginLine`/`codeExcerpt`/`offendingLiteral`/`apiShape`/
`proposedFix` + the vendor error identity). If it returns `findings: []` and no 👎, this was a clean
session — print the one clean info line (§Step 4) and stop.

### Step 2 — Relay the roll-up + disclosure (shown ONCE, before the question)

The subagent's output is invisible to the operator, so restate it — briefly, and **exactly once**.
Render the roll-up table + **exactly the fields that would be sent**, one finding per line, because
this is the only disclosure the operator gets before consenting. It is shown here, before the
question, and **never restated after delivery** (D2):

```
vc-fix self-check: 1 BROKEN, 1 DEGRADED (session <sid>, plugin 0.8.2)
• S1 qa-bug/ado_create_workitem (BROKEN) — HTTP_4XX at discover-tracker.mjs:232
    offending literal `$expand=all`; fix: drop $expand=Properties, request the valid enum member
    vendor: HTTP 400
• S2 qa-bug/admin_credential_handoff (DEGRADED) — permission_denied handoff gap
```

To compute the plan for disclosure, run `deliver.mjs` in its **dry** mode (it sends NOTHING) and read
only what you need — the dedup split and the normalized string fields — without dumping the plan JSON
into chat.

**Pass the struct via `--input <file>`, NEVER a `<json> | node …` pipe.** Write the validated struct
to a scratch file first, then run a plain command. The piped-stdin form is rejected by Claude Code's
auto-mode permission classifier **before the script runs** (a pipe feeding data into an interpreter
reads as arbitrary execution) and, being a pipeline, is not cleanly allowlistable — so a consented
delivery silently never happens in auto mode. A plain `node deliver.mjs --input <file>` is both
classifier-friendlier and narrowly allowlistable.

```bash
# write the struct to a scratch file (once), then run WITHOUT a pipe:
node "$pluginRoot/skills/vc-self-check/deliver.mjs" --input "<outputRoot>/.vc-fix/diagnostics/<sid>.deliver-input.json" --session <sid> --json
```

**Enumerate every possible OUTCOME the yes covers**, in this order — so the consent genuinely covers
what follows. Do NOT describe the plan as "one issue per finding"; that phrasing is what made the
real outcome (3 comments on 1 legacy issue) read as a deviation from consent:

1. one **new Issue** per genuinely new finding;
2. for an **already-reported** finding (an **open** dedup match), a **comment on the existing issue
   carrying the SAME evidence** the issue would — the `## Where` block, never a bare counter;
3. **dedup is OPEN-only (VCST-5582):** a defect whose only prior issue is **closed** is NOT a match —
   a closed issue is not proof the bug is gone, so a recurrence is filed as a **new** issue, not
   swallowed as "already fixed";
4. the session's **telemetry is purged** after a fully successful delivery (partial/failed keeps it).

State the dedup split verbatim from the dry plan's `summary`, e.g.
`1 already reported (#173 open), 2 new`. If a finding carries a
`vendorErrorMessage`, show the **normalized** value (the dry plan's `struct.findings[]` holds the
post-validation string) **verbatim** on its line — that is the §6b informed-consent disclosure; if
you cannot show it, it is not sent.

### Step 3 — The ONE question, then hand off to the deliverer (no more interaction)

Decide by `feedback.mode` (read from `project-profile.json`, default `ask`):

| mode | what the orchestrator does |
|---|---|
| **off** | No question, no send. Report the plan, note delivery is disabled, stop. |
| **auto** | No question — the operator consented at onboarding. Spawn the deliverer and print its line. |
| **ask** (default) | If ≥1 finding is BROKEN/DEGRADED and any has `plan: file` or `plan: comment`, call the **`AskUserQuestion` TOOL** (the interactive form — NOT a prose "yes/no" in chat; see Hard invariants) with ONE binary question: *"File these in the VirtoCommerce plugin repo?"* — **Yes** / **No**. There is no third option — Step 2 already showed what would be sent. |

- **Already offered this session?** If every finding's record in `state.json` is already `sent`/
  `declined` (the dry run wrote `pending` for anything new), stay silent — do not re-ask.
- **Yes** → **spawn the `self-check-deliverer` subagent** (Task tool,
  `subagent_type: "self-check-deliverer"`), passing it the finding struct, the `<sid>`, `outputRoot`,
  and the fact of the yes. It owns dedup, **deterministic route selection** (below), body
  composition, the leak scan, sending, and telemetry retention — and it asks nothing. Print its ONE
  result line (Step-4/D1). Do **not** run `--confirm` inline and do **not** re-ask anything, whatever
  the deliverer reports (a dropped field, a legacy-issue comment, a purge) — those are all covered by
  the yes (see the Hard-invariants forbidden-follow-ups list).
- **No** → nothing sent; `deliver` recorded `declined`, so it will not re-ask this session.

**Route selection is deterministic, decided by the deliverer, and never narrated before acting (A3):**

| dedup state | route |
|---|---|
| no OPEN match (incl. a closed prior issue) | file a new issue |
| open match | comment with full evidence (the `## Where` block) |

Dedup is **OPEN-only** — a closed prior issue is ignored, so a recurrence files a new issue.

**Telemetry retention is automatic and never asked (A4):** a fully successful delivery purges this
session (`<sid>.jsonl` + `<sid>.state.json`); a partial/failed one keeps it, and the deliverer says
so in one clause of the result line.

### Step 4 — The result line (post-delivery output is ONE line — D1)

Print the deliverer's single line verbatim: what was filed, what was commented (with links), and the
retention clause — **no tables, no restated roll-up** (Step 2 already showed it). Expand to a few
lines **only** when delivery PARTIALLY FAILED (which finding failed, and that its telemetry was kept
for retry). Example:

```
filed #212 (project-init/tracker_field_contract), +1 on #174 (qa-bug/ado_create_workitem, evidence attached); telemetry purged.
```

For a session with no delivery:

- Clean session (`findings: []`, no 👎): `vc-fix self-check: no plugin issues detected`.
- Observations recorded but none routed to a finding: the collector's own line already says
  `no blocking issues — N observation(s) recorded`; do not contradict it.

A turn emits ONE info line + at most ONE question. Never a second question, never a cleanup prompt.

---

## The deliver step (consent-gated) — contribute upstream

[`deliver.mjs`](./deliver.mjs) turns the finding struct (passed via **`--input <file>`**, never a
pipe — see the auto-mode note in Step 2) into GitHub Issues on `VirtoCommerce/vc-mcp-testing-module`.
On the interactive path the orchestrator does NOT run `--confirm` itself — after the one yes it spawns
the [`self-check-deliverer`](../../agents/self-check-deliverer.md) subagent, which writes the struct to
a scratch file and runs `deliver.mjs --input <file> --confirm` off the main thread (so dedup output +
issue/comment bodies never enter the conversation) and returns one line. `deliver.mjs` is still invoked
directly for the dry disclosure plan (Step 2) and as `/vc-self-check deliver`.

**The validator is the only gateway (B3).** Neither the orchestrator, the deliverer, nor any skill
may hand-author or edit an upstream body to route around a validator denial. The only outbound bytes
are what `deliver.mjs` composes from the closed-schema struct + the vendor-provenance channel
([`upstream-reduce.mjs`](./upstream-reduce.mjs)). If a field is still dropped after B1/B2, the
deliverer sends what passed and notes the omission in one clause of its result line — it never falls
back to `mcp__github__*` / `gh` / a raw body to add it back.

```
<struct.json  node deliver.mjs [--session <sid>] [--confirm] [--dry] [--as issue|local]
                               [--assert-nonempty] [--keep] [--json]
node deliver.mjs --batch  [--confirm] [--json]      # consolidate the state.json records
node deliver.mjs --purge  --session <sid> [--json]  # clear this session's telemetry
node deliver.mjs --backfill [--json]                # one-off: mark legacy bundled issues
```

- **Input is a struct on stdin**, not a report path. The old `--diag <path>` + markdown/regex
  recovery is gone (item 1): `deliver` re-derives nothing from prose.
- **`--assert-nonempty`** (implies `--dry`, no network) is the information-free-payload gate: exits
  **3** when a struct with a BROKEN/DEGRADED finding would carry nothing identifying (all `other` /
  `none` / `UNKNOWN` with no provenance).
- **`--batch`** consolidates the compact `selfCheckFindings[]` records still `pending` across all
  sessions' `state.json` into one delivery pass (thinner than an interactive run — the batch record
  carries no provenance). `--purge` clears a session's telemetry + records.

**One issue PER FINDING; dedup on `(skill, subject)` against OPEN issues only (VCST-5582).** A closed
prior issue is NOT a dedup match — a closed issue is not proof the defect is gone, so a recurrence
files a NEW issue instead of being swallowed as "already fixed". Defect
identity is exactly `(skill, subject)` (`findingKey`) — severity, verdict, outcome, errorCode and
counts are per-session judgements about the same bug and MUST NOT enter the key. That divergence is
why two sessions filed #173 and #174 for one `project-init/tracker_field_contract` defect
(`S2/UNKNOWN` vs `S1/HTTP_4XX`). Per finding:

- **Open match** → `+1 occurrence` comment (session count, plugin version, severity now) that
  **carries the same `## Where` evidence the issue body has** (location, code excerpt, offending
  literal, vendor identity, proposed fix) whenever the target issue does not already have it —
  matched on `WHERE_MARKER` + a content hash, so a legacy/evidence-less issue (#174) gets full detail
  on the FIRST comment and repeat occurrences stay a short counter (B1). If the new severity is
  higher, the comment says so and the issue title's verdict is upgraded.
- **No OPEN match** (no match at all, OR the only prior issue is CLOSED) → file it, embedding a
  searchable marker `<!-- vc-fix-finding: <skill>/<subject> -->`. A closed prior issue is ignored, so
  a recurrence surfaces as a fresh issue.
- **Legacy bridge:** #173/#174 are bundled issues with no per-finding marker, so the search ALSO
  matches `<skill>/<subject>` as text in the title/body (OPEN only) — else the first run refiles
  everything they contain. `--backfill` adds per-finding marker comments to open bundled issues.

**Two routes only** (`issue` / `local`), by the GitHub token's real rights via
`../project-init/probe-lib.mjs`. There is no PR route — a self-check contribution is a telemetry
report, not a code change; the old `pr`/`fork-pr` hand-offs sent nothing. `--as pr` is rejected. A
transient probe failure is retried once (`probeWithRetry`).

**Consent is `feedback.mode`** (`project-profile.json`, default `ask`) — `off` never sends, `ask`
means the orchestrator's per-finding yes/no, `auto` files directly. `/project-init` no longer asks
this at onboarding (item 4); it defaults to `ask` and is hand-editable.

**Containment (§2a) — vendor-provenance + boundary validation (item 5).** The outbound artifact is
built from a validated `UpstreamSignal` struct
([`upstream-reduce.mjs`](./upstream-reduce.mjs); spec
[`../../knowledge/diagnostics/upstream-schema.md`](../../knowledge/diagnostics/upstream-schema.md);
ADR [`../../knowledge/diagnostics/adr-upstream-default-deny.md`](../../knowledge/diagnostics/adr-upstream-default-deny.md)).
Every enum field is closed-vocabulary. Every STRING field either **proves vendor provenance** (a
`codeExcerpt`/`offendingLiteral` must be a verbatim substring of the cited plugin file, re-read by
`deliver` at send time) or passes a boundary validator that **denies — never coerces** — anything
carrying a URL host, an absolute path, an email, a token-shaped run, a GUID, a value read from the
client's `.env.*` / `project-profile.json`, or a work-item field outside `System.*` /
`Microsoft.VSTS.*`. Work-item STATE names, custom work-item TYPES, and repo/org/project names never
travel; counts do. A vendor error MESSAGE, if present, is normalized to placeholders, denied on any
surviving client value, and the orchestrator discloses it verbatim before the send. `findingStructSig`
deliberately excludes every v3 string, so a line-number shift cannot fork an already-filed issue.

**Lifecycle — log → analyze → contribute → delete.** On a confirmed send (or a dedup already
upstream) the processed session's telemetry (`<sid>.jsonl` + `<sid>.state.json`) is removed; `--keep`
retains. `local` (nothing sent) deletes nothing.

---

## Notes

- **Decision trail.** Every `finalize` writes a `decision` object on the jsonl. Review with
  `grep '"type":"finalize"' <outputRoot>/.vc-fix/diagnostics/<sid>.jsonl`.
- **The visible line — THREE states.** A finding/routing observation → run this skill + report;
  observations but none routing → `no blocking issues — N observation(s) recorded`; a genuinely
  empty record → `no plugin issues detected` (silence with `VC_FIX_DIAG_LINE=off`).
- Verdict/severity semantics + the (signal × expectation) table live in the oracle — cite them.
- A `LOW`-confidence diagnosis is fine — say so; better an honest "unclear, here's the evidence"
  than a confident wrong fix.

Attribution

VirtoCommerceVirtoCommerce
View sourceMore from VirtoCommerce →
SSkills DirectorySkills Directory

Your tool, in front of Claude Code builders.

3 founder slots · $299/mo · GSC-verified traffic · sponsors can never buy grades.

See placements

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 (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Your tool, in front of Claude Code builders.

3 founder slots · $299/mo · GSC-verified traffic · sponsors can never buy grades.

See placements

Related Skills

Caveman

Ultra-compressed communication mode. Cuts token usage ~75% by speaking like caveman while keeping full technical accuracy. Supports intensity levels: lite, full (default), ultra, wenyan-lite, wenyan-full, wenyan-ultra. Use when user says "caveman mode", "talk like caveman", "use caveman", "less tokens", "be brief", or invokes /caveman. Also auto-triggers when token efficiency is requested.

1023331 votes

Hyperplan

Adversarial multi-agent planning skill. Self-orchestrates 5 hostile category members (unspecified-low, unspecified-high, deep, ultrabrain, artistry) via team-mode for ruthless cross-critique debate, distills only the defensible insights, then MANDATORILY hands the distilled insight bundle to the `plan` agent for executable plan formalization. Use when planning needs maximum rigor and surfacing of weak assumptions, blind spots, and over-engineering. Triggers: 'hyperplan', 'hpp', '/hyperplan', ...

686011 votes

Mcp Code Execution

Routes multi-tool workflows through MCP servers for large datasets and pipelines. Use when Bash tool overhead is limiting throughput on data-heavy tasks.

3331 votes

catchup

Recovers prior coding-agent session context by running `catchup <agent> --since-compact`, which extracts a clean summary of a previous Codex, Claude Code, Antigravity, OpenCode, or Pi Agent session. Use when the user says "catch up", "what did the last session do", "get me up to speed", "I switched agents", or asks to recover/summarize a previous session before continuing. Do NOT use for the current conversation, git history, or any non-agent log.

611 votes

math-skill

A comprehensive mathematical reasoning skill for AI assistants — handles arithmetic to research-level problems with rigorous step-by-step reasoning, systematic verification, and transparent uncertainty handling

381 votes
View all in ai-agents →