LLMSkillHub
mirroredCopied from Lifecycle-Innovations-Limited/claude-ops under MIT. Lifecycle-Innovations-Limited has not claimed this page, and is not affiliated with LLM SkillHub.

lifecycle-innovations-limited / vip

OPS on-demand: This skill should be used when the user asks to "vip list", "who is a VIP", "add someone…

0
SKILL.md
7.3 KB

/ops:vip — VIP List

Load ops-rules before acting. Public repo (no personal data). Outbound: one draft → one approval → one send. If AskUserQuestion / Workflow are missing, follow Rule 10 in ops-rules (Hermes: numbered options / two-turn Telegram card; delegate_task).

The priority layer over every inbox. VIPs are checked FIRST in any sweep,
answered first, drafted with extra care, and never buried in a bulk digest.

Scope (deliberately narrow)

This skill does four things and nothing else:

  1. Enforce the list — VIP senders rank ahead of everything else in every sweep.
  2. Require FULL context before answering or drafting for a VIP: the whole
    thread, every account on that channel, both directions, plus the ledger brief.

  3. Order triage output by tier.
  4. Suggest additions when the signals below appear.

It does not read histories for their own sake, does not draft unasked, and does
not open a second channel just because one record is open. A tier edit is
metadata only. Tagging someone is never an instruction to sweep their history.

Configuration

Nothing here is machine-specific. Every value resolves from userConfig, an env
var, or $HOME.

userConfig keyEnv overrideDefaultMeaning
vip_list_pathVIP_LIST_PATH$HOME/.claude-ops/state/vip-list.jsonTier data + why/register notes
vip_max_tierVIP_MAX_TIER2Highest tier treated as VIP
vip_suggest_enabled—trueEmit VIP candidate suggestions
vip_volume_days—30Window for the volume signal
vip_volume_min—12Two-way messages that trip volume
relations_cliRELATIONS_CLI$HOME/.claude-ops/relations/bin/relations-cliShared ledger CLI (see relations)
PREFS_PATH="${PREFS_PATH:-${CLAUDE_PLUGIN_DATA_DIR:-$HOME/.claude/plugins/data/ops-ops-marketplace}/preferences.json}"
read_pref() { [ -f "$PREFS_PATH" ] && python3 -c 'import json,sys;print(json.load(open(sys.argv[1])).get(sys.argv[2],"") or "")' "$PREFS_PATH" "$1" 2>/dev/null; }

VIP_LIST_PATH="${VIP_LIST_PATH:-$(read_pref vip_list_path)}"
VIP_LIST_PATH="${VIP_LIST_PATH:-$HOME/.claude-ops/state/vip-list.json}"
VIP_MAX_TIER="${VIP_MAX_TIER:-$(read_pref vip_max_tier)}"
VIP_MAX_TIER="${VIP_MAX_TIER:-2}"

# "No VIPs" and "the VIP list was never set up" are DIFFERENT answers and must
# never look the same. An unconfigured install that silently reports an empty
# list turns this skill into a no-op: every inbox sweep then treats the most
# important people as ordinary traffic and nobody finds out. Fail loud.
if [ ! -f "$VIP_LIST_PATH" ]; then
  echo "vip: no list at $VIP_LIST_PATH — set userConfig vip_list_path or VIP_LIST_PATH." >&2
  echo "vip: copy templates/vip-list.example.json there to start one." >&2
  exit 3
fi

The list file lives OUTSIDE the repo tree — it is the operator's identity and
must never be committed (ops-rules Rule 0). Shape:
templates/vip-list.example.json.

Tiers

TierMeaningHandling
1Inner circleNever let it sit. Checked first, answered first, never batched
2Key businessSame day. Ranked above general triage
3-5ReservedNot VIP by default (vip_max_tier = 2)

The ledger's importance_tier column is the source of truth for the tier value;
the JSON file carries the why and the register notes (language, tone, dates to
avoid). Both are read; the DB wins on conflict.

Operations

SubcommandWhat it does
list (default)Every person at or above vip_max_tier, grouped by tier
show <person>Tier, type, why, channel, register notes
set <person> --tier NAudited tier write via the ledger CLI, reason required
suggestRead-only candidate scan (see signals below); never writes
why <person>Which signal put a suggested candidate on the list
"$RELATIONS_CLI" vip-list --max-tier "$VIP_MAX_TIER"
"$RELATIONS_CLI" vip <person_id> --tier 1 --type personal --reason "<why>"

Tier writes go through the CLI, never raw SQL. The CLI owns
source_reference, the audit log, and the rollback path. A direct
UPDATE on the ledger DB — inline or wrapped in a script — leaves an
unauditable row and is forbidden even where no guard happens to fire.

Sweep order

Any inbox, chat, email, or ticket sweep runs in this order:

  1. Resolve the VIP set once (vip list), cache it for the sweep.
  2. Tier 1 senders, every channel, both directions, every account.
  3. Tier 2 senders, same.
  4. Everything else, normal triage.

A VIP with an unanswered inbound is always surfaced individually, with the
thread context, never as a line in a digest.

Suggesting additions

Suggest, never add silently. A tier change needs the owner's word, then the
audited CLI write. Three signals:

SignalTrigger
volumevip_volume_min+ two-way messages in vip_volume_days with someone off the list
frustrationThey say they are being ignored or chased ("still waiting", "any update")
chain-breakTheir last message is inbound and still unanswered

Two filters keep this honest, both learned from real false positives:

  • Anchor every keyword on both sides. A bare stem matches inside longer
    words (ping inside "tapping") and produces phantom frustration hits.

  • A thread ending on a sign-off is CLOSED, not broken. "Thanks!", "sounds
    good", an emoji, or any short ack with no question mark is not an open ask.
    Without this filter most chain-breaks are noise that buries the real ones.

Present at most 5 a week: who, which signal, the evidence line, and the exact
CLI command to apply it. Then ask plainly. On "no", do not raise that person
again.

Related skills

  • relations — the ledger, decision queue and draft path this list ranks
  • ops-inbox — the sweep that consumes the tier order
  • ops-comms — the send path, still gated by Rule 6 for every VIP
  • people — contact directory / identity resolution
  • ops-rules — Rule 0 (the list is operator data, never committed)