Skip to content
Back to skills

Kb Lint

ASecurity

Health check for the workhub vault knowledge base. Detects orphan documents, broken links, index drift, tag issues, and stale content across projects/knowledge/archive. Run periodically or as part of weekly review.

  • 3 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 3, 2026
developmentbashnode

Works with

  • cli

Security analysis

A100/100

Scanned September 30, 2026

npx -y skills add atman-33/workhub --skill kb-lint --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Kb Lint?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Kb Lint
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/atman-33-kb-lint/badge)](https://www.skillsdirectory.com/skills/atman-33-kb-lint)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: kb-lint
description: Health check for the workhub vault knowledge base. Detects orphan documents, broken links, index drift, tag issues, and stale content across projects/knowledge/archive. Run periodically or as part of weekly review.
argument-hint: "[--fix] [--zone <name>]"
---

# KB Lint — Knowledge Base Health Check

Audit the workhub vault for structural issues, inconsistencies, and
maintenance opportunities. Covers the note zones (`inbox/`, `projects/`,
`knowledge/`, `archive/`), the memory note types under `memory/notes/`, plus a
size check on `memory/identity/decision-policy.md` —
the task board (`tasks/`) is app-managed and only gets link checks.

## Usage

```
/kb-lint                       # Full report (read-only)
/kb-lint --fix                 # Auto-fix safe issues
/kb-lint --zone knowledge      # Lint only one zone
```

## Checks

### 1. Index Drift
Compare `_index.md` contents (`projects/_index.md`, `knowledge/_index.md`,
`archive/_index.md`) against actual files on disk.

| Issue | Meaning |
|-------|---------|
| MISSING | Listed in index but file/folder not found |
| UNLISTED | File/folder exists but not in index |
| STALE_INDEX | `updated` date > 7 days older than newest change in the zone |

**Auto-fix:** Add unlisted entries, remove missing entries, update dates.

### 2. Orphan Documents
Files in `projects/`, `knowledge/`, or `archive/` that have:
- No incoming `[[wikilinks]]` from other files
- No entry in any `_index.md`
- No tags

Exclude from check: `journal/**`, `inbox/**`, `tasks/**`, `templates/**`,
`_ai/**`, `_index.md`, `home.md`, `AGENTS.md`, `CLAUDE.md`.

**Report:** List orphans with suggested action (link, tag, or archive).

### 3. Tag Consistency

| Issue | Rule |
|-------|------|
| MISSING_PROJECT_TAG | File in `projects/x/` lacks `#proj/x` |
| BAD_TAG_FORMAT | Spaces or unexpected casing in tag |
| CROSS_REF_TAG | `#proj/x` tag on file outside `projects/` — note as intentional cross-reference |

**Auto-fix:** Add missing `#proj/` tags to frontmatter.

### 4. Broken Links
For each `[[wikilink]]` found in vault documents:
- Verify target file exists
- Report `BROKEN_LINK` if not found

With obsidian CLI: `obsidian links broken`
Without CLI: Grep for `\[\[.*?\]\]`, resolve each target.

### 5. Frontmatter Quality
Check documents in note zones for required fields:

| Field | Required? |
|-------|-----------|
| `title` | Yes |
| `created` | Yes |
| `tags` | Recommended |
| `type` | Recommended |

Task files (`tasks/`) follow the task schema instead — do not flag them here.

**Report:** Count of documents missing each field, list worst offenders.

### 6. Stale Content

| Issue | Condition |
|-------|-----------|
| POSSIBLY_STALE | Project note not modified >30 days while the project is active |
| SHOULD_ARCHIVE | `projects/NNNN-<name>/` whose project is finished but still outside `archive/` |
| MISPLACED | Actively edited material found in `archive/` |
| INBOX_PILEUP | `inbox/` holds items older than 14 days → suggest `/kb-ingest` |

### 7. Decision policy size

`memory/identity/decision-policy.md` is read in full every time an agent is about to
ask the owner something, and by the `secretary` subagent on every question it
gates. It holds the axes of a decision; the individual calls belong in
`memory/notes/`, which is reached by search (`cli.mjs notes`), never read whole.

The limits are measured by the `memory` plugin, not here, so the two cannot
drift apart:

```bash
node "<memory plugin>/engine/cli.mjs" doctor
```

Report its `cap:` lines — `policy entries` (more than 50 across every
section), `policy entry P-NN` (an entry over 3 lines), `policy ids` (an entry
with no `P-NN`, or one used twice) and `policy cases` (individual cases written
into the policy). The policy is not held to the 120-line limit of the other
`identity/` notes. Where that plugin is not installed, skip this section and say
so — do not re-implement the limits here.

**Report:** name the offending entries and suggest what to do — merge two
entries into the axis they share, drop one that a later entry subsumes, or move
a case down to `memory/notes/`. Never auto-fix: deciding
which rule survives is the owner's call.

`memory/notes/` has no size limit and is not checked here.

### 8. Memory note types

Only when the vault has a `memory/` folder. Notes there declare a `type:` and
are read back structurally — a session briefing asks for open decisions, not
for notes that look relevant — so a note with no type, or one missing the
fields its type is read by, is invisible rather than merely untidy.

The check is the `memory` plugin's own validator, so the two cannot disagree:

```bash
node "<memory plugin>/engine/cli.mjs" validate memory/notes/*.md
```

Where that plugin is not installed, skip this section and say so — do not
re-implement the rules here.

| Issue | Condition |
|-------|-----------|
| MEMORY_UNTYPED | A note under `memory/` with no `type:` |
| MEMORY_FIELDS | A typed note missing a field its type is required to carry |

**Report:** list the findings verbatim; the validator already explains each one
and why it matters. **Never auto-fix, and never treat this as a failure** —
validation warns by design. A memory whose writes can be rejected stops being
written to, and an empty memory is worse than an untidy one.

`memory/identity/` is exempt: those notes are read in full, never searched.

## Output Format

```markdown
# KB Lint Report — {date}

## Summary
- Passed: N checks
- Warnings: N items
- Errors: N items

## Details
### Index Drift
...
### Orphan Documents
...
### Tag Issues
...
### Broken Links
...
### Frontmatter Quality
...
### Stale Content
...
### Decision Policy Size
...

## Recommended Actions
1. {highest priority}
2. ...
```

## Severity

| Level | Examples | Auto-fixable |
|-------|----------|-------------|
| Error | Broken links, missing files | Some |
| Warning | Missing tags, orphans, stale content, policy over limit | Most (never the policy) |
| Info | Optimization suggestions, inbox pileup | No |

## Log Entry

Append to `_ai/logs/kb-log.md`:
```
[date] lint | passed N | warnings N | errors N | fixed N
```

## Arguments

| Argument | Effect |
|----------|--------|
| `--fix` | Auto-fix safe issues (index drift, tag addition) |
| `--zone <name>` | Limit to one zone: projects, knowledge, or archive |

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.