Files
claudetools/.claude/commands/wiki-lint.md
Mike Swanson d9ab515463 feat: add /wiki-compile skill + Syncro live-check in /wiki-lint
/wiki-compile: new skill that seeds or refreshes wiki client articles
from session logs and live Syncro PSA data.

- Three modes: seed (new article), refresh (surgical update), full (--full flag)
- Syncro enrichment for client targets: customer profile, contacts,
  open tickets, recent invoices, asset count
- Ambiguous customer search: pause and ask user to pick
- Customer not found: graceful warn + continue with session logs only
- Syncro is authoritative for all billing fields (hours, rate, contract type)
- Refresh mode: surgical edits only (hours, active tickets, frontmatter)
- Seed/full: Ollama qwen3:14b synthesis; Claude-direct fallback
- Asset count in Profile only — no asset detail tables in wiki
- Commits and pushes after write

/wiki-lint: add Step 6 — Syncro Live-Check
- Pulls live prepay_hours for every client article with a Syncro customer ID
- Auto-fixes stale hours in place; commits fixes in one batch
- Flags articles with open tickets and stale compiled date for review
- Adds Syncro section to lint report output

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 11:45:44 -07:00

7.4 KiB

Health-check the wiki for missing articles, stale content, broken backlinks, and cross-reference gaps.

Run this after any session where new session logs were created, or when starting a new session and the wiki may be out of date. Also run before any /wiki-compile all pass.


Step 1 — Missing Articles (Primary Check)

Scan for clients and projects that have session logs but no wiki article.

# List all client slugs that have session-logs but no wiki article
cd D:/claudetools
for dir in clients/*/session-logs; do
  slug=$(echo "$dir" | sed 's|clients/||;s|/session-logs||')
  wiki="wiki/clients/$slug.md"
  if [ ! -f "$wiki" ]; then
    count=$(ls "$dir"/*.md 2>/dev/null | wc -l)
    echo "MISSING: $wiki  ($count session logs)"
  fi
done
# List all project slugs that have session-logs but no wiki article
for dir in projects/*/session-logs; do
  slug=$(echo "$dir" | sed 's|projects/||;s|/session-logs||')
  wiki="wiki/projects/$slug.md"
  if [ ! -f "$wiki" ]; then
    count=$(ls "$dir"/*.md 2>/dev/null | wc -l)
    echo "MISSING: $wiki  ($count session logs)"
  fi
done

Report each missing article as:

[MISSING] wiki/clients/<slug>.md — <N> session logs, oldest: <YYYY-MM-DD>

Suggest: Run /wiki-compile client:<slug> to seed.


Step 2 — Stale Articles

Check last_compiled date in all wiki article frontmatter. Flag any article where:

  • last_compiled is more than 90 days ago AND there are session logs newer than last_compiled
  • Report as [STALE] with days since compile and count of new logs

Use grep -r "last_compiled:" wiki/ to collect dates, then compare against session log mtimes.


Scan all [[link]] references in wiki articles. For each [[slug]], check:

  • Does wiki/clients/<slug>.md exist? Or wiki/projects/<slug>.md? Or wiki/systems/<slug>.md?
  • If none match → flag as [BROKEN_LINK]
grep -rh '\[\[' wiki/ | grep -o '\[\[[^]]*\]\]' | sed 's/\[\[//;s/\]\]//' | sort -u

For each slug found, normalize before checking:

  1. Strip leading wiki/ prefix if present → flag as [BAD_FORMAT] (seeding agents sometimes write wrong format)
  2. Strip trailing .md extension if present → also flag as [BAD_FORMAT]
  3. Check existence: wiki/<slug>.md, wiki/clients/<slug>.md, wiki/projects/<slug>.md, wiki/systems/<slug>.md, wiki/patterns/<slug>.md
  4. If no file found after normalization → flag as [BROKEN_LINK]

Note: [[systems/neptune]] will always show as broken until neptune is seeded — that's expected.


Step 4 — Index Gaps

Read wiki/index.md. For every .md file in wiki/clients/, wiki/projects/, wiki/systems/:

  • Is it listed in wiki/index.md? If not → flag as [NOT_INDEXED]

Conversely, for every row in wiki/index.md:

  • Does the linked file actually exist? If not → flag as [DEAD_INDEX_ENTRY]

Step 5 — Compilation Queue Cleanup

Read the ## Compilation Queue section in wiki/index.md. For each entry:

  • Does the corresponding wiki/<type>/<slug>.md file now exist? If yes → flag the queue entry as stale, suggest removing it.

Step 6 — Syncro Live-Check (Client Articles, Auto-Fix)

For every client wiki article that contains a Syncro customer ID line, pull live billing data from Syncro and auto-fix stale values in place. This step runs silently — no user confirmation needed. Fixes are committed at the end.

Setup

BASE="https://computerguru.syncromsp.com/api/v1"
USER_ID=$(jq -r '.user // empty' "$CLAUDETOOLS_ROOT/.claude/identity.json")
case "$USER_ID" in
  mike)   API_KEY="T259810e5c9917386b-52c2aeea7cdb5ff41c6685a73cebbeb3" ;;
  howard) API_KEY="Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" ;;
  *)      echo "[SYNCRO] No API key for user '$USER_ID' — skipping Step 6" ; exit 0 ;;
esac

For Each Client Article

for ARTICLE in wiki/clients/*.md; do
  SLUG=$(basename "$ARTICLE" .md)

  # Extract Syncro customer ID — skip if not documented
  CUST_ID=$(grep -oP '(?<=\*\*Syncro customer ID:\*\* )\d+' "$ARTICLE" 2>/dev/null)
  [ -z "$CUST_ID" ] && continue

  # Pull live customer data
  CUST=$(curl -s "$BASE/customers/${CUST_ID}?api_key=$API_KEY" | jq '.customer')
  [ -z "$CUST" ] && echo "[SYNCRO][WARNING] $SLUG — API returned empty for customer $CUST_ID" && continue

  LIVE_HOURS=$(echo "$CUST" | jq -r '.prepay_hours // "0"')
  TODAY=$(date +%Y-%m-%d)

  # --- Fix 1: Hours remaining ---
  # Extract current wiki value (match pattern: "X.X hrs as of")
  WIKI_HOURS=$(grep -oP '[\d.]+ hrs as of' "$ARTICLE" | grep -oP '[\d.]+' | head -1)

  if [ -n "$WIKI_HOURS" ] && [ "$WIKI_HOURS" != "$LIVE_HOURS" ]; then
    # Replace the Hours remaining line with live value
    sed -i "s/\*\*Hours remaining[^:]*:\*\*[^\n]*/\*\*Hours remaining (if prepaid):\*\* ${LIVE_HOURS} hrs as of ${TODAY} (Syncro live)/" "$ARTICLE"
    echo "[SYNCRO][FIXED] $SLUG — hours: wiki=${WIKI_HOURS} → Syncro=${LIVE_HOURS}"
    SYNCRO_FIXES+=("$SLUG: hours ${WIKI_HOURS}${LIVE_HOURS}")
  fi

  # --- Check 2: Open ticket count (flag only, no auto-fix) ---
  OPEN_COUNT=$(curl -s "$BASE/tickets?customer_id=${CUST_ID}&status=New,In+Progress,Scheduled,Waiting+on+Customer&per_page=1&api_key=$API_KEY" | jq '.meta.total_count // (.tickets | length)')
  # Flag if article was compiled > 7 days ago and open ticket count changed
  COMPILED=$(grep -oP '(?<=last_compiled: )[\d-]+' "$ARTICLE")
  COMPILED_AGE=$(( ( $(date +%s) - $(date -d "$COMPILED" +%s 2>/dev/null || echo 0) ) / 86400 ))
  if [ "$COMPILED_AGE" -gt 7 ] && [ "$OPEN_COUNT" -gt 0 ]; then
    SYNCRO_TICKET_FLAGS+=("[TICKETS_CHECK] $SLUG$OPEN_COUNT open ticket(s) in Syncro; article compiled ${COMPILED_AGE}d ago")
  fi
done

Commit Fixes (if any)

if [ ${#SYNCRO_FIXES[@]} -gt 0 ]; then
  cd "$CLAUDETOOLS_ROOT"
  git add wiki/clients/*.md
  git commit -m "wiki-lint: Syncro live-check auto-fix (${#SYNCRO_FIXES[@]} article(s))"
  git push origin main
fi

Add to Lint Report

Append to the report output:

### Syncro Live-Check (N auto-fixed, M flagged)
[SYNCRO][FIXED] cascades-tucson — hours: 37.5 → 31.0 (Syncro live as of YYYY-MM-DD)
[TICKETS_CHECK] valleywide — 2 open ticket(s) in Syncro; article compiled 14d ago

If API key is missing or Syncro is unreachable, emit [SYNCRO] Skipped (API unavailable) and continue.


Output Format

Emit a clean lint report:

## Wiki Lint Report — YYYY-MM-DD

### Missing Articles (N)
[MISSING] wiki/clients/evs.md — 1 session log (2026-04-17)
...

### Stale Articles (N)
[STALE] wiki/clients/cascades-tucson.md — compiled 2026-05-24, 3 new logs since
...

### Broken Backlinks (N)
[BROKEN_LINK] wiki/clients/kittle.md → [[gururmm]] (no file found)
...

### Index Gaps (N)
[NOT_INDEXED] wiki/clients/new-client.md — not listed in index.md
...

### Compilation Queue — Stale Entries (N)
[QUEUE_STALE] client:birthbiologic — wiki/clients/birth-biologic.md exists; remove from queue
...

### Syncro Live-Check (N auto-fixed, M flagged)
[SYNCRO][FIXED] cascades-tucson — hours: 37.5 → 31.0 (Syncro live)
[TICKETS_CHECK] valleywide — 2 open ticket(s); article compiled 14d ago
...

### Summary
- N missing articles → run /wiki-compile for each
- N stale articles → run /wiki-compile to refresh
- N broken links → fix manually or after recompile
- N index gaps → update wiki/index.md
- N Syncro hours auto-fixed, M ticket flags for review

After the report, ask: "Run /wiki-compile for any of the missing articles now?"