Skip to content
cccskills
FreePublished on GitHub

docs-lint

Run JellyRock's docs governance checks (broken markdown links, link anchors that match no heading, broken related-files frontmatter paths, stale tech-debt anchor references, journal-schema gates for progress.md and the decisions.md supersede chain, stale-doc detection) and surface a structured fix list grouped by category. Consumes the --json output of scripts/lint/docs-check.cjs and the human-readable output of scripts/lint/docs-stale.cjs. Use when a commit hits the docs-lint pre-push hook, before pushing a PR that touched docs/ or any CLAUDE.md, or when you want a one-shot pass over doc references.

The English summary is being prepared. Showing the original description.

jellyrock/jellyrock46 stars(GitHub 46 + cccskills 0)

Run score Not tested

See how to install

Files included (1)

  • SKILL.md8.7 KB

SKILL.md (original)

Review the instructions the agent will receive before you install.

/docs-lint: the docs governance gate, run by a script

Wraps JellyRock's doc validators with structured parsing and fixes proposed through Edit. Two layers:

  1. Reference integrity and journal schema: scripts/lint/docs-check.cjs, in --json mode. It catches broken related-files: frontmatter paths, broken inline markdown links, link anchors that match no heading (checked by GitHub's slug rule), stale tech-debt.md#anchor references, and two journal-schema gates (docs/progress.md frontmatter, the docs/decisions.md supersede chain). It scans docs/architecture/, docs/dev/, docs/user/, docs/adr/, the journals and every CLAUDE.md (the root one included, which links to AGENTS.md), but no directory whose name starts with a dot: check a link in .claude/ or .github/ by hand.
  2. Staleness: scripts/lint/docs-stale.cjs. An informational list of docs whose last-reviewed: is past the threshold (90 days by default). CI runs the blocking variant (docs-stale-blocking.cjs), which blocks only when a PR touches the territory of an architecture doc more than 120 days old without updating the doc.

Step 1: Run the validators

node scripts/lint/docs-check.cjs --json
npm run docs:stale --silent

docs-check.cjs --json writes a single-line JSON to stdout:

{
  "filesChecked": <n>,
  "errorsCount": 0,
  "errors": [
    {
      "category": "broken-related-file" | "broken-link" | "broken-anchor"
                | "stale-anchor" | "progress-frontmatter"
                | "decisions-supersede-chain",
      "file": "<repo-relative path>",
      "message": "<full diagnostic>",
      "target": "<the broken path or anchor>"
    }
  ]
}

Exit 0 means clean, 1 means errors found. docs:stale prints a readable list (<n> doc(s) tracked, <k> stale); pass its count to the user briefly.

Step 2: Categorize and propose fixes

For each error in the JSON, find the right fix. The category is a hint, not a rule: read the message before proposing.

broken-related-file

The related-files: frontmatter names a path that doesn't exist. Two cases:

  • The file moved and exists at a new path (git log --diff-filter=R over the last few months usually shows it). Fix: put the new path in related-files:. If the doc's shape or why still describes the file's role, the doc-maintenance rule applies: re-read it, and bump last-reviewed: only after that review.
  • The file was deleted. Fix: remove the line from related-files:. If the deletion changed the subsystem's shape (the doc now describes something that no longer exists), updating the doc body is a bigger fix: raise it with the user as a separate question.

broken-link

An inline [text](path) link points at a missing target. The same two cases as above. Fix: put in the new path, remove the link, or restore the target.

broken-anchor

A link's #fragment matches no heading or explicit <a id> in the target file. The usual cause is a renamed heading: dropping an em dash or a count from a heading changes its slug. Fix: point the link at the heading's new slug. If the link sits in a file that can't be edited (an ADR, or a journal, which changes only through /log and /done), keep the old slug alive with an explicit <a id="<old-slug>"></a> above the renamed heading. Find a heading's slug from the rendered page on GitHub, or by GitHub's rule: lowercase, drop punctuation, one hyphen per space.

stale-anchor

A tech-debt.md#<slug> citation names an entry that no longer exists in docs/architecture/tech-debt.md. Either the slug was renamed or the entry was removed because the work was done. Two cases:

  • The slug was renamed: search tech-debt.md for the new slug. Fix: put the new slug in the citation.
  • The entry was removed: no replacement exists. Fix: remove the citation, or rewrite the sentence without it. A removed entry's slug may be listed under "Recently removed", which is not a heading, so the link still breaks.

progress-frontmatter

docs/progress.md lacks a well-formed last-updated: field. This is a structural check only: the age of the date is not gated (it is a property of main, not of one PR). Fix: restore the field with today's date through /log running or /done running, not a hand edit. Those are the sanctioned ways to write this journal.

decisions-supersede-chain

A docs/decisions.md note breaks the supersede schema. The message names the note and the field. The cases, and what each means:

  • "still reads **status**: accepted; flip it to superseded": the supersede is a three-part edit and only part landed. Read the note first: if only part of the old decision was replaced, the fix is the partial pair (**partially-supersedes** and **partially-superseded-by**, each with a (scope) note, both notes staying accepted), not the flip. Flipping a partly replaced note to superseded passes the gate while making the record wrong, which is the failure this category exists to catch.
  • "records no **superseded-by**: pointer": the status flip landed but neither pointer did. Fix: name the successor's slug.
  • A one-sided pair or a dangling target: one side of the pair is missing, or it names a slug not in the file. Fix: add the mirror field, or correct the slug. Pointers resolve within decisions.md only: a note superseded by an ADR has no field for it, and that link is plain prose.
  • withdrawn involved: withdrawn is final (abandoned, not replaced). Fix: don't supersede a withdrawn note, and don't let one supersede anything. If the decision really was replaced, its status should have been superseded.
  • A duplicate slug or field: Fix: rename one slug (slugs are stable cross-reference keys), or drop the extra field line. A note supersedes at most one predecessor.

Make these fixes through /log decision where possible: it applies all three parts. A hand edit of this file is not the sanctioned path.

Stale docs (the docs:stale output)

Informational only: the doc's last-reviewed: is past the threshold. What to do depends on whether the current work touches the doc's related-files::

  • Touched and stale: for an architecture doc, CI's docs-stale-blocking.cjs blocks once it is past 120 days. Re-read the doc against the current code, then update it and bump last-reviewed:, or bump only the date if nothing in its shape or why changed.
  • Not touched and stale: leave it; CI won't block. Mention it as a doc to review soon.

Step 3: Apply the approved fixes

Walk the list with the user, one fix at a time or in groups (all broken-link errors in one file together). Apply each with Edit, and run the check again after each batch:

node scripts/lint/docs-check.cjs --json

Repeat until errorsCount is 0. Don't go beyond what the diagnostic names: if a broken-related-file shows a renamed file that the doc body still mentions, fix the frontmatter line and propose the body change separately.

Step 4: Don't bump last-reviewed: on your own

last-reviewed: records a real review against the current code. Bump it only when the user confirms "I read this doc against the current code and its shape and why still hold", or "I updated the body to match the current shape". A date bumped by reflex defeats the field.

When not to use

  • The pre-push hook already showed the failure and the fix is mechanical (one missing path): make the edit yourself. /docs-lint helps when there are several failures, when the category is unclear, or when staleness needs a decision.
  • You aren't touching docs: let CI report any drift on the PR.

Sub-agent invocation

To run it from a sub-agent, the parent passes Read .claude/skills/docs-lint/SKILL.md and follow the steps; report the failures grouped by category with proposed fixes; do not apply edits in the Agent prompt.

Reviews

No reviews yet. Tell others what you thought.

Comments

No login needed. Share how it worked for you, ask a question, or note where it did not run.

No comments yet. Be the first to write one.

Comments are published right away. Do not include personal information such as email addresses or phone numbers. Up to 2 URLs.

0 / 1,000 characters

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.

More skills from this repository

Session-start briefing: where did I leave off, what is in flight, what needs attention. One tested script reads git, the journal (followups, running work, cadences) and tracked projects and prints every fixed-threshold check that fires; JellyRock's own aggregator adds open PRs, high-engagement bugs, recent bug reports, current-branch CI, pending handoffs, open upstream-watch issues (Jellyfin releases and release candidates, Roku OS), recent ADRs, tech debt and architecture-doc staleness. Ends with one Suggested next move that hands off to /log, /done, /issue-triage, /runtime-triage, /ci-triage or /server-upgrade. Mandated by AGENTS.md's catchup-discipline rule: run at the start of any genuine new session, after a multi-day gap, or whenever you ask what the state of the world is.

The English summary is being prepared. Showing the original description.

jellyrock/jellyrock46Updated Oct 26, 2026

Diagnose a failed CI workflow run and fix it the /snag way. A tested read-only script fetches the run, reports every failed job and step with the log region around its errors (not the post-job cleanup), and classifies each against this repo's gates.tsv, printing the banner a gate carries when its obvious fix is the wrong one. Then: re-run only what is transient, reproduce locally, find the root cause, and show one decision screen; the chosen fix is built test-first and committed on a fix branch, never pushed. Use when a CI run failed on a pull request or on the default branch.

The English summary is being prepared. Showing the original description.

jellyrock/jellyrock46Updated Oct 26, 2026

DEPRECATED, replaced by the `enrich` phase built into /crash-report. The old flow filed crash issues first and enriched them one by one afterward. The new flow (stage, then enrich, then file) pulls the dashboard backtrace before filing, so issues are born complete and architectural-class crashes go to their epic instead of becoming standalone issues. Do not invoke it for new work: run /crash-report and paste the backtraces during its enrich step. It stays only as a redirect; the `enrich-issue` script subcommand still exists as a legacy escape hatch for a crash issue filed before the change.

The English summary is being prepared. Showing the original description.

jellyrock/jellyrock46Updated Oct 26, 2026

Process a Roku weekly crash-report CSV (or a zip holding one or more CSVs) into tracked GitHub issues and architectural-epic evidence, enriching before filing (stage, then enrich, then file). STAGE parses and filters the CSV, groups by pkg-path signature, builds each cited app version in a temporary git worktree, maps the transpiled `.brs` line back to the source `.bs` line, runs the GitHub dedup search, and writes a local worksheet where every crash starts pending; a mechanism hint (task-launch, network, other) orders which to pull first but never authorizes a file. ENRICH folds in the per-crash backtraces you paste from Roku's dashboard (a 7-day window, one click per crash, no bulk export), extracts each `&hNN` exception code, and routes every crash to a disposition (nothing files or aggregates without a backtrace): `file` (a scoped bug becomes a new per-signature [crash] issue, born enriched), `aggregate` (a known architectural class: `&h29` big-library too-many-task-threads, `&h23` render-thread execution timeouts, the `&hec` init `m.global.constants` race; upserted as one flat record comment per `file·function·line·version` onto the class epic, never a standalone issue), or `watch` (accepted noise, a spike comment only). FILE performs the GitHub writes (create, comment or reopen for scoped bugs; the epic record upsert for architectural classes) and writes a run-summary handoff. Dedup-aware and idempotent. Use when a fresh Roku crash CSV arrives (weekly). A deep dive on one crash goes to `/issue-triage <N>` after filing.

The English summary is being prepared. Showing the original description.

jellyrock/jellyrock46Updated Oct 26, 2026

Draft a GitHub issue body for the JellyRock repo from a Reddit/Discord post or free-form bug report and submit it via forge.sh. Reads the YAML form templates under .github/ISSUE_TEMPLATE/ to know which fields are required, fills them by extracting from the input, asks for any missing required fields, validates the body matches the chosen template's schema, then runs forge.sh issue create with the auto-labels the template defines. Use when you have a user report (paste from anywhere) and want to formalize it into a properly-structured GitHub issue.

The English summary is being prepared. Showing the original description.

jellyrock/jellyrock46Updated Oct 26, 2026

Walk a major dependency-version bump (a Renovate major PR, possibly a grouped one carrying several deps, or a package you name) through JellyRock's major-bump SOP so the judgment steps run the same way every time. Resolves each package and its from and to versions, fetches the upstream changelog/migration guide for that range, classifies the breaking changes, greps the codebase for the call sites those breaks actually hit, runs the mechanical gate that fits the dependency's type (a runtime BrightScript lib: validate, build, lint:bs, then test:unit and test:rta on a device; JS or Node tooling: test:scripts, then run the affected script; GitHub Actions: the PR's own CI plus a trace of the conditional paths CI doesn't exercise), and returns a go/no-go with any required migration surfaced (and applied on request). Majors never automerge (the org Renovate config), so this is the human-review path. Use when a Renovate major PR appears, or before bumping a dependency's major version by hand. Not for patch or minor bumps (those automerge after a soak) or for Jellyfin server releases (use /server-upgrade).

The English summary is being prepared. Showing the original description.

jellyrock/jellyrock46Updated Oct 26, 2026

See all skills by jellyrock

Report a problem with this skill