/bedrock:healthcheck — Vault Health Report

SkillFiles & storage

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".

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the /bedrock:healthcheck — Vault Health Report skill

What this skill tells your AI

The instructions your AI receives, as published by iurykrieger/claude-bedrock in skills/healthcheck/SKILL.md and read by ahel’s review.

Plugin Paths

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:

  • Entity definitions: <base_dir>/../../entities/
  • Templates: <base_dir>/../../templates/{type}/_template.md
  • Plugin CLAUDE.md: <base_dir>/../../CLAUDE.md (already injected automatically into context)

Where <base_dir> is the path provided in "Base directory for this skill".


Vault Resolution

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:

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  • Entity directories: <VAULT_PATH>/actors/, <VAULT_PATH>/people/, etc.
  • Graphify output: <VAULT_PATH>/graphify-out/

Overview

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.

Five health checks

#CheckWhat it verifies
1graphify-outGraph.json exists, is valid, is fresh
2SetupDirectories, templates, entity definitions, plugin manifest
3Orphan entitiesEntities with zero inbound wikilinks
4Dangling contentEntities fully disconnected (no inbound, no outbound, no relations)
5Old contentEntities with updated_at older than 15 days

Status values

Each check reports one of:

  • OK — no issues found
  • WARN — issues found (with details)
  • MISSING — prerequisite not met (e.g., graphify-out absent)

Phase 1 — Scan the Vault

Read all entity files once and store the data for use across all 5 checks.

1.1 Enumerate entity files

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/):

  1. List all .md files using Glob, excluding _template.md and _template_node.md
    • For actors: include both <VAULT_PATH>/actors/*.md (flat) and <VAULT_PATH>/actors/*/*.md (folder)
    • Include code entities: <VAULT_PATH>/actors/*/nodes/*.md
  2. Record the directory and filename for each entity

1.2 Read entity data

For each entity file found in 1.1:

  1. Read the file
  2. Extract from frontmatter:
    • type
    • name (or derive from filename)
    • aliases (array)
    • updated_at (date string)
    • All frontmatter array fields that contain wikilinks (e.g., actors, people, teams, related_to, etc.)
  3. Extract from body:
    • All wikilinks [[target]] (regex: \[\[([^\]]+)\]\])
  4. Compute:
    • outbound_wikilinks: union of all wikilinks from body + frontmatter arrays
    • has_frontmatter_relations: true if any frontmatter array field contains at least one wikilink value
    • entity_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).


Phase 2 — Run Checks

2.1 Check 1 — graphify-out

  1. Check if directory <VAULT_PATH>/graphify-out/ exists:

    ls -d <VAULT_PATH>/graphify-out/ 2>/dev/null && echo "EXISTS" || echo "MISSING"
    
  2. If MISSING:

    • Status: MISSING
    • Details: "graphify-out/ directory not found. Run /bedrock:learn on an actor repository to generate."
    • Skip remaining sub-checks.
  3. If EXISTS, check <VAULT_PATH>/graphify-out/graph.json:

    test -f <VAULT_PATH>/graphify-out/graph.json && echo "EXISTS" || echo "MISSING"
    
  4. If graph.json MISSING:

    • Status: MISSING
    • Details: "graph.json not found in graphify-out/. Run /bedrock:learn to generate."
    • Skip remaining sub-checks.
  5. 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"
    
  6. If INVALID_JSON:

    • Status: WARN
    • Details: "graph.json exists but is not valid JSON."
  7. If valid:

    • If stale (>30 days): Status: WARN, Details: "Graph.json is stale (>30 days). Last updated: {mod_date}. Run /bedrock:learn or /bedrock:sync to update."
    • If fresh: Status: OK, Details: "{total_nodes} nodes ({code_nodes} code). Last updated: {mod_date}."

Store: graphify_status, graphify_details, graphify_node_count

2.2 Check 2 — Setup

Verify the vault structure and plugin dependencies.

2.2.1 Entity directories

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.

2.2.2 Entity definitions

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.

2.2.3 Plugin manifest

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.

2.2.4 Result
  • If everything present: Status: OK, Details: "All directories, templates, definitions, and manifest verified."
  • If issues found: Status: WARN, Details: list of missing items.

Store: setup_status, setup_details, setup_issue_count

2.3 Check 3 — Orphan entities

For each entity in vault_entities:

  1. Count inbound wikilinks: how many OTHER entities reference this entity via [[entity_slug]]
    • Search: count how many entities in vault_entities have this entity's slug in their outbound_wikilinks
    • Also check for alias matches: if entity has aliases, check if any alias (converted to slug format) appears in other entities' outbound wikilinks
  2. If inbound count = 0: mark as orphan

Exclude from orphan check:

  • Templates (_template.md)
  • The entity itself (self-links don't count)

Store: orphan_entities[] — list of {entity_slug, type} Aggregate: orphan_count_by_type — map type → count

Result:

  • If 0 orphans: Status: OK
  • If orphans found: Status: WARN, Details: count per type + entity names

2.4 Check 4 — Dangling content

From the orphan list (Check 3), further filter for entities that are fully disconnected:

An entity is dangling if ALL three conditions are true:

  1. No inbound wikilinks (already orphan from Check 3)
  2. No outbound wikilinks in the body (entity's outbound_wikilinks is empty)
  3. No frontmatter relations (entity's has_frontmatter_relations is false)

Store: dangling_entities[] — list of {entity_slug, type}

Result:

  • If 0 dangling: Status: OK
  • If dangling found: Status: WARN, Details: entity names

2.5 Check 5 — Old content

For each entity in vault_entities:

  1. Read updated_at from the entity data
  2. If updated_at is missing or cannot be parsed: skip (do not flag — missing metadata is a setup issue, not a staleness issue)
  3. Calculate age in days: current_date - updated_at
  4. If age > 15 days: mark as old

Store: 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:

  • If 0 old: Status: OK
  • If old found: Status: WARN, Details: count per type, oldest entity with age

Phase 3 — Generate Report

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 details (if WARN)

### Orphan Entities

| # | Entity | Type |
|---|---|---|
| 1 | [[entity-slug]] | actor |
| 2 | [[entity-slug]] | person |
| ... | ... | ... |

**By type:** actors: N, people: N, teams: N, ...

Dangling details (if WARN)

### Dangling Content (fully disconnected)

| # | Entity | Type |
|---|---|---|
| 1 | [[entity-slug]] | fleeting |
| ... | ... | ... |

Old content details (if WARN)

### 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, ...

Suggestions

Based on findings, append actionable suggestions:

  • If orphan or dangling count > 0: "Run /bedrock:compress to detect and fix alignment issues (broken backlinks, missing entities)."
  • If graphify-out is MISSING or stale: "Run /bedrock:learn on an actor repository to generate or update the graph."
  • If old count > 0: "Review {N} stale entities for relevance. Consider updating or archiving."
  • If setup has issues: "Run /bedrock:setup to initialize missing directories or templates."
  • If all checks are OK: "Vault is healthy. No action needed."

Error Handling

SituationAction
Empty vault (no entity files)Report all checks as OK with 0 counts. "Vault is empty — no entities found."
Entity file cannot be readSkip entity, do not fail the check. Note in report: "N entities skipped due to read errors."
Frontmatter cannot be parsedSkip entity for frontmatter-dependent checks (updated_at, relations). Count as readable for wikilink checks.
graphify-out/graph.json is not valid JSONReport as WARN for Check 1. Continue with other checks.
Plugin directory not accessibleReport as WARN for Check 2. Continue with other checks.
No updated_at field in entitySkip for Check 5 (old content). Do not flag as old.

Critical Rules

RuleDetail
Read-onlyNEVER use Write, Edit, Skill, or Agent tools. This skill only reads and reports.
No git operationsNEVER run git add, commit, push, pull, or any mutating git command.
No skill invocationsNEVER invoke /bedrock:compress, /bedrock:learn, /bedrock:preserve, or any other skill. Suggest them in text only.
Terminal output onlyThe report is printed to the terminal. No files are created or modified.
Single-pass scanPhase 1 scans once. All 5 checks in Phase 2 use the same scan data.
Exclude templatesAlways exclude _template.md and _template_node.md from entity counts and checks.
15-day thresholdOld content is defined as updated_at > 15 days from current date. Hardcoded.
30-day thresholdStale graph is defined as graph.json modification date > 30 days. Hardcoded.
Bare wikilinksParse wikilinks as [[name]] only. Never path-qualified ([[dir/name]]).
Sensitive dataNEVER include credentials, tokens, passwords, PANs, CVVs in the report.
Vault resolution firstResolve VAULT_PATH before any file operation — never assume CWD is the vault
All entity paths use <VAULT_PATH>/ prefix<VAULT_PATH>/actors/, not actors/

Signals

GitHub stars
99
Forks
8
Last commit
May 2026
Advanced
Catalog kind
skill
Gateway key
healthcheck-iurykrieger
Source
github.com/iurykrieger/claude-bedrock