project-board-enforcement
MANDATORY for all work - the project board is THE source of truth. This skill provides verification functions and gates that other skills MUST call. No work proceeds without project board compliance.
What this skill does
# Project Board Enforcement
## Overview
The GitHub Project board is THE source of truth for all work state. Not labels. Not comments. Not memory. The project board.
**Core principle:** If it's not in the project board with correct fields, it doesn't exist.
**This skill is called by other skills at gate points. It is not invoked directly.**
## API Optimization Requirement
**CRITICAL:** All read operations MUST use cached data from `github-api-cache`.
The following environment variables MUST be set before using this skill:
- `GH_CACHE_ITEMS` - Cached project items JSON
- `GH_CACHE_FIELDS` - Cached project fields JSON
- `GH_PROJECT_ID` - Project node ID
- `GH_STATUS_FIELD_ID` - Status field ID
- `GH_STATUS_*_ID` - Status option IDs
If these are not set, invoke `session-start` first to initialize the cache.
## The Rule
**Every issue, epic, and initiative MUST be in the project board BEFORE work begins.**
This is not optional. This is not a suggestion. This is a hard gate.
## Required Environment
```bash
# These MUST be set. Work cannot proceed without them.
echo $GITHUB_PROJECT # Full URL: https://github.com/users/USER/projects/N
echo $GITHUB_PROJECT_NUM # Just the number: N
echo $GH_PROJECT_OWNER # Owner: @me or org name
```
If any are missing, stop and configure them before proceeding.
## Project Field Requirements
### Mandatory Fields
Every project MUST have these fields configured:
| Field | Type | Required Values |
|-------|------|-----------------|
| Status | Single select | Backlog, Ready, In Progress, In Review, Done, Blocked |
| Type | Single select | Feature, Bug, Chore, Research, Spike, Epic, Initiative |
| Priority | Single select | Critical, High, Medium, Low |
### Recommended Fields
| Field | Type | Purpose |
|-------|------|---------|
| Verification | Single select | Not Verified, Failing, Partial, Passing |
| Criteria Met | Number | Count of completed acceptance criteria |
| Criteria Total | Number | Total acceptance criteria |
| Last Verified | Date | When verification last ran |
| Epic | Text | Parent epic issue number |
| Initiative | Text | Parent initiative issue number |
## Verification Functions
**All read operations use cached data (0 API calls). Only writes require API calls.**
### Verify Issue in Project
**GATE FUNCTION** - Called before any work begins. **0 API calls (uses cache).**
```bash
verify_issue_in_project() {
local issue=$1
# Get project item ID FROM CACHE (0 API calls)
ITEM_ID=$(echo "$GH_CACHE_ITEMS" | jq -r ".items[] | select(.content.number == $issue) | .id")
if [ -z "$ITEM_ID" ] || [ "$ITEM_ID" = "null" ]; then
echo "BLOCKED: Issue #$issue is not in the project board."
echo ""
echo "Add it with:"
echo " gh project item-add $GITHUB_PROJECT_NUM --owner $GH_PROJECT_OWNER --url \$(gh issue view $issue --json url -q .url)"
return 1
fi
echo "$ITEM_ID"
return 0
}
```
### Verify Status Field Set
**GATE FUNCTION** - Called before work proceeds past issue check. **0 API calls (uses cache).**
```bash
verify_status_set() {
local issue=$1
local item_id=$2
# Get current status FROM CACHE (0 API calls)
STATUS=$(echo "$GH_CACHE_ITEMS" | jq -r ".items[] | select(.id == \"$item_id\") | .status.name")
if [ -z "$STATUS" ] || [ "$STATUS" = "null" ]; then
echo "BLOCKED: Issue #$issue has no Status set in project board."
echo ""
echo "Set status before proceeding."
return 1
fi
echo "$STATUS"
return 0
}
```
### Add Issue to Project
**Called by issue-prerequisite after issue creation. 1 API call + cache refresh.**
```bash
add_issue_to_project() {
local issue_url=$1
# Add to project (1 API call - unavoidable write)
gh project item-add "$GITHUB_PROJECT_NUM" --owner "$GH_PROJECT_OWNER" --url "$issue_url"
if [ $? -ne 0 ]; then
echo "ERROR: Failed to add issue to project."
return 1
fi
# Refresh cache after adding (1 API call)
export GH_CACHE_ITEMS=$(gh project item-list "$GITHUB_PROJECT_NUM" --owner "$GH_PROJECT_OWNER" --format json)
# Get the item ID from refreshed cache
local issue_num=$(echo "$issue_url" | grep -oE '[0-9]+$')
ITEM_ID=$(echo "$GH_CACHE_ITEMS" | jq -r ".items[] | select(.content.number == $issue_num) | .id")
echo "$ITEM_ID"
return 0
}
```
### Set Project Status
**Called at every status transition. 1 API call (uses cached IDs).**
```bash
set_project_status() {
local item_id=$1
local new_status=$2 # Backlog, Ready, In Progress, In Review, Done, Blocked
# Use cached IDs (0 API calls for lookups)
# GH_PROJECT_ID, GH_STATUS_FIELD_ID set by session-start
# Get option ID from cache
local option_id
case "$new_status" in
"Backlog") option_id="$GH_STATUS_BACKLOG_ID" ;;
"Ready") option_id="$GH_STATUS_READY_ID" ;;
"In Progress") option_id="$GH_STATUS_IN_PROGRESS_ID" ;;
"In Review") option_id="$GH_STATUS_IN_REVIEW_ID" ;;
"Done") option_id="$GH_STATUS_DONE_ID" ;;
"Blocked") option_id="$GH_STATUS_BLOCKED_ID" ;;
*)
# Fallback: look up from cached fields (0 API calls)
option_id=$(echo "$GH_CACHE_FIELDS" | jq -r ".fields[] | select(.name == \"Status\") | .options[] | select(.name == \"$new_status\") | .id")
;;
esac
if [ -z "$option_id" ] || [ "$option_id" = "null" ]; then
echo "ERROR: Status '$new_status' not found in project."
return 1
fi
# Single API call to update status
gh project item-edit --project-id "$GH_PROJECT_ID" --id "$item_id" \
--field-id "$GH_STATUS_FIELD_ID" --single-select-option-id "$option_id"
return $?
}
```
### Set Project Type
**Called when creating issues. 1 API call (uses cached IDs).**
```bash
set_project_type() {
local item_id=$1
local type=$2 # Feature, Bug, Chore, Research, Spike, Epic, Initiative
# Get type field ID and option from cache (0 API calls)
local type_field_id=$(echo "$GH_CACHE_FIELDS" | jq -r '.fields[] | select(.name == "Type") | .id')
local option_id=$(echo "$GH_CACHE_FIELDS" | jq -r ".fields[] | select(.name == \"Type\") | .options[] | select(.name == \"$type\") | .id")
if [ -z "$option_id" ] || [ "$option_id" = "null" ]; then
echo "ERROR: Type '$type' not found in project."
return 1
fi
# Single API call to update type
gh project item-edit --project-id "$GH_PROJECT_ID" --id "$item_id" \
--field-id "$type_field_id" --single-select-option-id "$option_id"
}
```
## State Queries via Project Board
**All queries use cached data. 0 API calls.**
### Get Issues by Status
**USE THIS instead of label queries. 0 API calls (uses cache).**
```bash
get_issues_by_status() {
local status=$1 # Ready, In Progress, etc.
# Use cached data (0 API calls)
echo "$GH_CACHE_ITEMS" | jq -r ".items[] | select(.status.name == \"$status\") | .content.number"
}
# Examples:
# get_issues_by_status "Ready"
# get_issues_by_status "In Progress"
# get_issues_by_status "Blocked"
```
### Get Issues by Type
**0 API calls (uses cache).**
```bash
get_issues_by_type() {
local type=$1 # Epic, Feature, etc.
echo "$GH_CACHE_ITEMS" | jq -r ".items[] | select(.type.name == \"$type\") | .content.number"
}
```
### Get Epic Children
**0 API calls (uses cache).**
```bash
get_epic_children() {
local epic_num=$1
echo "$GH_CACHE_ITEMS" | jq -r ".items[] | select(.epic == \"#$epic_num\") | .content.number"
}
```
### Count by Status
**0 API calls (uses cache).**
```bash
count_by_status() {
local status=$1
echo "$GH_CACHE_ITEMS" | jq "[.items[] | select(.status.name == \"$status\")] | length"
}
```
## Gate Points
These are the points in workflows where project board verification is MANDATORY:
| Workflow Point | Gate | Skill |
|----------------|------|-------|
| Before any work | Issue in project | issue-driven-development Step 1 |
| After issue creation | Add to project, set fields | issue-prerequisite |
| Starting work | Status → In Progress | issue-driven-development Step 6 |
| Creating branch | Verify project membRelated in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.