claude-handoff
MAmattpocock/skills288k近 7 天新增 10,178 个 star
Read-only vault health diagnostic. Generates a report without modifying any files. Checks: graphify-out integrity, setup verification, orphan entities, dangling content, old content (>15 days). Safe to run at any frequency. Use when: "bedrock healthcheck", "bedrock-healthcheck", "vault health", "check vault", "vault status", "/bedrock:healthcheck".
Entity definitions and templates are in the plugin directory, not the vault root. Use the "Base directory for this skill" provided at invocation to resolve paths:
<base_dir>/../../entities/<base_dir>/../../templates/{type}/_template.md<base_dir>/../../CLAUDE.md (already injected automatically into context)Where <base_dir> is the path provided in "Base directory for this skill".
Resolve which vault to diagnose. This skill can be invoked from any directory.
Step 1 — Parse --vault flag:
Check if the input arguments include --vault <name>. If found, extract the vault name.
Step 2 — Resolve vault path:
If --vault <name> was provided:
Read the vault registry at <base_dir>/../../vaults.json. Find the entry matching the name.
If not found: error — "Vault <name> is not registered. Run /bedrock:vaults to see available vaults."
If found: set VAULT_PATH to the entry's path value.
If no --vault flag — CWD detection:
Read <base_dir>/../../vaults.json. Check if the current working directory is inside any registered vault path
(CWD starts with a registered vault's absolute path). If multiple match, use the longest path (most specific).
If found: set VAULT_PATH to the matching vault's path.
If CWD detection fails — default vault:
From the registry, find the vault with "default": true.
If found: set VAULT_PATH to the default vault's path.
If no resolution:
Error — "No vault resolved. Available vaults:" followed by the registry listing.
"Use --vault <name> to specify, or run /bedrock:setup to register a vault."
Step 3 — Validate vault path:
test -d "<VAULT_PATH>" && echo "exists" || echo "missing"
If missing: error — "Vault path <VAULT_PATH> does not exist on disk. Run /bedrock:setup to re-register."
Step 4 — Read vault config:
cat <VAULT_PATH>/.bedrock/config.json 2>/dev/null
Extract language and other relevant fields for use in later phases.
From this point forward, ALL vault file operations use <VAULT_PATH> as the root.
<VAULT_PATH>/actors/, <VAULT_PATH>/people/, etc.<VAULT_PATH>/graphify-out/This skill produces a diagnostic report of vault health without modifying any files. It scans the vault once, runs 5 checks against the scan data, and prints the results.
You are a read-only agent. You do NOT write files, commit, push, invoke other skills, or spawn subagents. Your only output is the diagnostic report printed to the terminal.
| # | Check | What it verifies |
|---|---|---|
| 1 | graphify-out | Graph.json exists, is valid, is fresh |
| 2 | Setup | Directories, templates, entity definitions, plugin manifest |
| 3 | Orphan entities | Entities with zero inbound wikilinks |
| 4 | Dangling content | Entities fully disconnected (no inbound, no outbound, no relations) |
| 5 | Old content | Entities with updated_at older than 15 days |
Each check reports one of:
Read all entity files once and store the data for use across all 5 checks.
For each entity directory (<VAULT_PATH>/actors/, <VAULT_PATH>/people/, <VAULT_PATH>/teams/, <VAULT_PATH>/concepts/, <VAULT_PATH>/topics/, <VAULT_PATH>/discussions/, <VAULT_PATH>/projects/, <VAULT_PATH>/fleeting/):
.md files using Glob, excluding _template.md and _template_node.md
<VAULT_PATH>/actors/*.md (flat) and <VAULT_PATH>/actors/*/*.md (folder)<VAULT_PATH>/actors/*/nodes/*.mdFor each entity file found in 1.1:
typename (or derive from filename)aliases (array)updated_at (date string)actors, people, teams, related_to, etc.)[[target]] (regex: \[\[([^\]]+)\]\])outbound_wikilinks: union of all wikilinks from body + frontmatter arrayshas_frontmatter_relations: true if any frontmatter array field contains at least one wikilink valueentity_slug: the filename without extension (used as the canonical identifier)Output: vault_entities map: entity_slug → {type, name, aliases[], updated_at, outbound_wikilinks[], has_frontmatter_relations, file_path}
Also collect: all_entity_slugs — set of all entity slugs in the vault (for resolving wikilinks).
Check if directory <VAULT_PATH>/graphify-out/ exists:
ls -d <VAULT_PATH>/graphify-out/ 2>/dev/null && echo "EXISTS" || echo "MISSING"
If MISSING:
/bedrock:teach on an actor repository to generate."If EXISTS, check <VAULT_PATH>/graphify-out/graph.json:
test -f <VAULT_PATH>/graphify-out/graph.json && echo "EXISTS" || echo "MISSING"
If graph.json MISSING:
/bedrock:teach to generate."If graph.json EXISTS, validate and extract stats:
python3 -c "
import json, os, time
from pathlib import Path
g = json.loads(Path('<VAULT_PATH>/graphify-out/graph.json').read_text())
nodes = g.get('nodes', [])
code_nodes = [n for n in nodes if n.get('file_type') == 'code']
mtime = os.path.getmtime('<VAULT_PATH>/graphify-out/graph.json')
mod_date = time.strftime('%Y-%m-%d', time.localtime(mtime))
days_old = (time.time() - mtime) / 86400
print(f'total_nodes={len(nodes)}')
print(f'code_nodes={len(code_nodes)}')
print(f'mod_date={mod_date}')
print(f'days_old={int(days_old)}')
print(f'stale={\"yes\" if days_old > 30 else \"no\"}')
" 2>/dev/null || echo "INVALID_JSON"
If INVALID_JSON:
If valid:
/bedrock:teach or /bedrock:sync to update."Store: graphify_status, graphify_details, graphify_node_count
Verify the vault structure and plugin dependencies.
Check that each expected directory exists:
<VAULT_PATH>/actors/, <VAULT_PATH>/people/, <VAULT_PATH>/teams/, <VAULT_PATH>/concepts/, <VAULT_PATH>/topics/, <VAULT_PATH>/discussions/, <VAULT_PATH>/projects/, <VAULT_PATH>/fleeting/For each directory, check if _template.md exists inside it.
Record: list of missing directories, list of directories missing templates.
Check that entity definitions exist in the plugin directory:
<base_dir>/../../entities/
Expected files: actor.md, person.md, team.md, concept.md, topic.md, discussion.md, project.md, fleeting.md
Record: list of missing entity definitions.
Check that .claude-plugin/plugin.json exists and is valid JSON:
python3 -c "import json; json.loads(open('.claude-plugin/plugin.json').read()); print('VALID')" 2>/dev/null || echo "INVALID"
Record: manifest status.
Store: setup_status, setup_details, setup_issue_count
For each entity in vault_entities:
[[entity_slug]]
vault_entities have this entity's slug in their outbound_wikilinksaliases, check if any alias (converted to slug format) appears in other entities' outbound wikilinksExclude from orphan check:
_template.md)Store: orphan_entities[] — list of {entity_slug, type}
Aggregate: orphan_count_by_type — map type → count
Result:
From the orphan list (Check 3), further filter for entities that are fully disconnected:
An entity is dangling if ALL three conditions are true:
outbound_wikilinks is empty)has_frontmatter_relations is false)Store: dangling_entities[] — list of {entity_slug, type}
Result:
For each entity in vault_entities:
updated_at from the entity dataupdated_at is missing or cannot be parsed: skip (do not flag — missing metadata is a setup issue, not a staleness issue)current_date - updated_atStore: old_entities[] — list of {entity_slug, type, updated_at, age_days}, sorted by age_days descending (oldest first)
Aggregate: old_count_by_type — map type → count
Result:
Print the full report to the terminal.
## /bedrock:healthcheck — Report
| Check | Status | Count | Details |
|---|---|---|---|
| graphify-out | {graphify_status} | {node_count} nodes | {graphify_details} |
| Setup | {setup_status} | {setup_issue_count} issues | {setup_details} |
| Orphan entities | {orphan_status} | {orphan_count} orphans | {orphan_details} |
| Dangling content | {dangling_status} | {dangling_count} dangling | {dangling_details} |
| Old content (>15d) | {old_status} | {old_count} stale | {old_details} |
### Orphan Entities
| # | Entity | Type |
|---|---|---|
| 1 | [[entity-slug]] | actor |
| 2 | [[entity-slug]] | person |
| ... | ... | ... |
**By type:** actors: N, people: N, teams: N, ...
### Dangling Content (fully disconnected)
| # | Entity | Type |
|---|---|---|
| 1 | [[entity-slug]] | fleeting |
| ... | ... | ... |
### Old Content (>15 days without update)
| # | Entity | Type | Last updated | Age |
|---|---|---|---|---|
| 1 | [[entity-slug]] | actor | 2026-03-01 | 45 days |
| 2 | [[entity-slug]] | topic | 2026-03-15 | 31 days |
| ... | ... | ... | ... | ... |
**By type:** actors: N, topics: N, ...
Based on findings, append actionable suggestions:
/bedrock:compress to detect and fix alignment issues (broken backlinks, missing entities)."/bedrock:teach on an actor repository to generate or update the graph."/bedrock:setup to initialize missing directories or templates."| Situation | Action |
|---|---|
| Empty vault (no entity files) | Report all checks as OK with 0 counts. "Vault is empty — no entities found." |
| Entity file cannot be read | Skip entity, do not fail the check. Note in report: "N entities skipped due to read errors." |
| Frontmatter cannot be parsed | Skip entity for frontmatter-dependent checks (updated_at, relations). Count as readable for wikilink checks. |
| graphify-out/graph.json is not valid JSON | Report as WARN for Check 1. Continue with other checks. |
| Plugin directory not accessible | Report as WARN for Check 2. Continue with other checks. |
No updated_at field in entity | Skip for Check 5 (old content). Do not flag as old. |
| Rule | Detail |
|---|---|
| Read-only | NEVER use Write, Edit, Skill, or Agent tools. This skill only reads and reports. |
| No git operations | NEVER run git add, commit, push, pull, or any mutating git command. |
| No skill invocations | NEVER invoke /bedrock:compress, /bedrock:teach, /bedrock:preserve, or any other skill. Suggest them in text only. |
| Terminal output only | The report is printed to the terminal. No files are created or modified. |
| Single-pass scan | Phase 1 scans once. All 5 checks in Phase 2 use the same scan data. |
| Exclude templates | Always exclude _template.md and _template_node.md from entity counts and checks. |
| 15-day threshold | Old content is defined as updated_at > 15 days from current date. Hardcoded. |
| 30-day threshold | Stale graph is defined as graph.json modification date > 30 days. Hardcoded. |
| Bare wikilinks | Parse wikilinks as [[name]] only. Never path-qualified ([[dir/name]]). |
| Sensitive data | NEVER include credentials, tokens, passwords, PANs, CVVs in the report. |
| Vault resolution first | Resolve VAULT_PATH before any file operation — never assume CWD is the vault |
All entity paths use <VAULT_PATH>/ prefix | <VAULT_PATH>/actors/, not actors/ |
MAmattpocock/skills288k近 7 天新增 10,178 个 star
AFaffaan-m/ECC278k近 7 天新增 4,046 个 star
AFaffaan-m/ECC278k近 7 天新增 4,046 个 star
AFaffaan-m/ECC278k近 7 天新增 4,046 个 star
DIDietrichGebert/ponytail162k近 7 天新增 5,405 个 star