Skip to content
Back to skills

Status

ASecurity

Use when picking up a contextualizer after a gap, or checking reference freshness and pending review work at a glance — read-only, safe to run anytime.

  • 2 stars
  • 0 votes
  • 0 copies
  • 4 views
  • Added May 28, 2026
ai-agentspythongobashtestinggit

Security analysis

A100/100

Scanned September 22, 2026

npx -y skills add nick-railsback/skill-engine --skill status --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Status?

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

Security grade badge for Status
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/nick-railsback-status/badge)](https://www.skillsdirectory.com/skills/nick-railsback-status)

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: status
description: Use when picking up a contextualizer after a gap, or checking reference freshness and pending review work at a glance — read-only, safe to run anytime.
---

# Status

Read-only one-page dashboard. Lists fresh / stale / critical references by age,
notes pending proposals waiting on human review, and surfaces any recent
rejection-log clustering that suggests a doctrine gap.

## Contextualizer root

Engine workflows operate inside a contextualizer installed as a project
skill at one of three install levels:

- **User-level:** `~/.claude/skills/<slug>-context/`
- **Local-user-level:** `~/.claude/local/skills/<slug>-context/` (when in use)
- **Project-level:** `<repo>/**/.claude/skills/<slug>-context/`

Every path below — `research/...`, `references/...`, `verify.sh` —
resolves relative to whichever directory matches. Before reading
anything, locate the root by searching all three install levels in
order:

Run the script in [`shared/locator-block.md`](../../shared/locator-block.md) verbatim before proceeding.

### Selecting a contextualizer

`/skill-engine:status <name>` names the contextualizer to report on:
`<name>` is the directory name without the `-context` suffix, the same
grammar `review`/`apply`/`discard` use. Substitute it (or the empty
string) for `<name>` in the locator above. With no argument,
auto-detection applies — it succeeds when exactly one contextualizer is
installed and lists the matches and exits when more than one is.

Read every subsequent `research/foo` path as `$CTX_ROOT/research/foo`,
every `references/foo` as `$CTX_ROOT/references/foo`, and `verify.sh` as
`$CTX_ROOT/verify.sh`.

## Fleet (`--all`)

`/skill-engine:status --all` reports on every contextualizer the locator
enumerates instead of on one: it prints a table carrying one row per
contextualizer, six columns wide — root path, registered source count,
last refresh, pending proposal, review state, and owner. The enumeration
comes from running the script in
[`shared/locator-block.md`](../../shared/locator-block.md) with `--all`,
which prints one absolute root per line and exits without setting
`CTX_ROOT`. Supply the argv the block asks for rather than keeping a copy
of it here:

    ctx_roots=$(bash -s -- --all <<'LOCATOR'
    …the shared block at run time, with its `name="<name>"` line
    substituted to `name=""` — a fleet run names no contextualizer…
    LOCATOR
    ) || ctx_roots=""
    export ctx_roots

That substitution is not optional. Pasted with `<name>` left in place, the
block's `find -name "<name>-context"` matches nothing and the locator takes
its exit-1 path, which is the empty enumeration above by a second route.

The assignment and the `export` are two statements on purpose. The locator
writes its nothing-found diagnostic to **stdout**, not stderr, and exits 1;
`export ctx_roots=$(…)` would report the `export`'s own success and throw
that exit status away, leaving the diagnostic sentence in `ctx_roots` where
a root path belongs. Splitting them puts the `|| ctx_roots=""` on the
command substitution, which is the one thing that knows the locator failed —
the same guard `using-skill-engine` applies to the same paste.

The derivation reads that enumeration from `ctx_roots` in its environment
(hence the `export`) and does nothing when the locator found nothing.

```python
import json
import os
import re
import sys
from pathlib import Path

try:
    sys.stdout.reconfigure(encoding="utf-8")
except AttributeError:
    pass

NONE = "—"  # em dash: the cell for "no such thing recorded"

roots = [line.strip() for line in os.environ.get("ctx_roots", "").splitlines()]
# Absolute paths only. The locator's enumeration prints nothing else, but
# its *diagnostics* go to stdout too, so a caller that captured stdout
# without testing the exit status leaves a prose sentence here. Filtering
# on the one shape a root can have keeps that sentence from being rendered
# as a fleet row, and keeps the guard below reachable.
roots = [r for r in roots if r.startswith("/")]
if not roots:
    # The locator found nothing. Nothing to report is not an error.
    sys.exit(0)


def review_state(proposed):
    # The same read-only progress reading the "Pending proposals" section
    # renders for a single contextualizer, condensed to one cell.
    review = proposed / ".review" / "REVIEW.md"
    if not review.is_file():
        return "no review file"
    text = review.read_text(encoding="utf-8", errors="replace")
    if "___" in text:
        return "awaiting Step 1"
    # `again after filling Step 1` and not `(Run /skill-engine:review`:
    # the template's line is "(Run `/skill-engine:review <name>` again
    # after filling Step 1 to populate this section.)" — with backticks,
    # which the parenthesised form never matches. The branch was
    # unreachable, so an ungenerated Step 2 fell through to the tick
    # count and read as `signed off` whenever a reviewer had ticked a box
    # without running the second pass, which is precisely the state
    # `apply`'s pre-promotion gate refuses.
    if "again after filling Step 1" in text:
        return "Step 2 not generated"
    ticks = re.findall(r"(?mi)^- \[x\] (?:reviewed|provisional|reject)", text)
    return "signed off" if len(ticks) == 1 else "not signed off"


for raw in roots:
    root = Path(raw)
    registry = root / "research" / "source-paths.json"
    count, owner, last = 0, NONE, "never"
    if registry.is_file():
        try:
            data = json.loads(registry.read_text(encoding="utf-8"))
        except ValueError:
            data = {}
        sources = data.get("sources") or []
        count = len(sources)
        owner = data.get("owner") or NONE
        stamps = [s.get("lifecycle", {}).get("last_checked") for s in sources]
        stamps = [s for s in stamps if s]
        if stamps:
            last = max(stamps)[:10]
    proposed = Path(str(root) + ".proposed")
    staged = proposed.is_dir()
    print(" | ".join([
        str(root),
        str(count),
        last,
        "yes" if staged else "no",
        review_state(proposed) if staged else NONE,
        owner,
    ]))
```

`--all` cannot be combined with a named contextualizer. When a run is
given both a name and `--all`, halt with an error naming both selectors
rather than guessing which one was meant:

```
--all was combined with the named contextualizer 'acme'. Pass one or the other: a name reports on that contextualizer alone, --all reports on every contextualizer found.
```

## Pending proposals

A staged-but-unapplied proposal sits as a sibling of the live tree at
`${CTX_ROOT}.proposed/`. STATUS surfaces it (and how far its review has
progressed) so a pending review does not silently rot — this is the
"notes pending proposals waiting on human review" the intro promises.
Read-only: STATUS reports the proposal's state but never advances it.

```bash
slug=$(basename "$CTX_ROOT"); slug="${slug%-context}"
proposed="${CTX_ROOT}.proposed"
if [ ! -d "$proposed" ]; then
  printf 'No pending proposal (nothing staged).\n'
else
  manifest="$proposed/.review/manifest.json"
  review="$proposed/.review/REVIEW.md"
  if [ -f "$manifest" ]; then
    added=$(jq '[.entries[]|select(.status=="added")]|length'    "$manifest" 2>/dev/null); added=${added:-0}
    modified=$(jq '[.entries[]|select(.status=="modified")]|length' "$manifest" 2>/dev/null); modified=${modified:-0}
    removed=$(jq '[.entries[]|select(.status=="removed")]|length'  "$manifest" 2>/dev/null); removed=${removed:-0}
    printf 'Pending proposal: %s.proposed/  (%s added, %s modified, %s removed)\n' \
      "$slug" "$added" "$modified" "$removed"
  else
    printf 'Pending proposal: %s.proposed/  (incomplete — no manifest; DISCOVER/REFRESH did not finish)\n' "$slug"
  fi
  # Review progress, mirroring apply's pre-promotion gates (read-only here).
  if [ -f "$review" ]; then
    ticks=$(grep -ciE '^- \[x\] (reviewed|provisional|reject)' "$review" 2>/dev/null); ticks=${ticks:-0}
    if grep -q '___' "$review" 2>/dev/null; then
      printf '  Review: awaiting Step 1 predictions (run /skill-engine:review %s).\n' "$slug"
    elif grep -qF 'again after filling Step 1' "$review" 2>/dev/null; then
      printf '  Review: Step 1 filled; Step 2 not yet generated (re-run /skill-engine:review %s).\n' "$slug"
    elif [ "$ticks" -eq 1 ]; then
      state=$(grep -iE '^- \[x\] (reviewed|provisional|reject)' "$review" | head -1 | sed -E 's/^- \[[xX]\] +//')
      printf '  Review: signed off as %s — ready for /skill-engine:apply %s.\n' "$state" "$slug"
    else
      printf '  Review: not yet signed off (tick one Step 3 box, then /skill-engine:apply %s).\n' "$slug"
    fi
  fi
fi
```

## Doctrine surface

The STATUS workflow — what it renders, how it sorts, when it pre-renders vs.
runs on demand — lives in chapter [`04-delivery.md`](../../docs/04-delivery.md) and the `## Workflow: STATUS`
section of [`maintenance-agent.md.template`](../../engine-bootstrap-templates/maintenance-agent.md.template).

The freshness categories (fresh, stale, critical) and their default thresholds
are documented in chapter [`05-invariants.md`](../../docs/05-invariants.md).

## Slice grouping

A source carrying `slice_of` (a monorepo slice, per
[`07-monorepo-adapter.md`](../../docs/07-monorepo-adapter.md)) renders
grouped under its parent in the freshness listing: the parent's row
first, then each of its slices nested immediately beneath it, each shown
by its own `slice_id` and its own freshness (fresh / stale / critical,
computed the same way as any other source — see
[`05-invariants.md`](../../docs/05-invariants.md) for the thresholds).
This is purely additive — a contextualizer with zero `slice_of` entries
renders exactly as it does today.

## Cadence

Quick read; run anytime. STATUS does not write, so it is a safe first step on
returning to a contextualizer after a gap.

## Cache surface

The on-demand DISCOVER/REFRESH local clone cache lives at
`~/.cache/skill-engine/git-managed/<source_id>-<sha>/` (see
`engine-bootstrap/SKILL.md` for the convention). The cache is persistent
and not auto-cleaned at end of a workflow, so it can accumulate disk
usage as upstream SHAs advance.

STATUS surfaces the cache so the user can see what is on disk:

```bash
cache_root="${XDG_CACHE_HOME:-$HOME/.cache}/skill-engine"
if [ -d "$cache_root" ]; then
  printf '%s\n' "Cache root: $cache_root"
  total=$(du -sh "$cache_root" 2>/dev/null | awk '{print $1}')
  printf '%s\n' "Total size: ${total:-0}"
  printf '\n%-60s  %8s  %s\n' "Directory" "Size" "Last accessed"
  for d in "$cache_root"/*/; do
    [ -d "$d" ] || continue
    sz=$(du -sh "$d" 2>/dev/null | awk '{print $1}')
    accessed=$(stat -f '%Sa' -t '%Y-%m-%d' "$d" 2>/dev/null \
               || stat -c '%x' "$d" 2>/dev/null | cut -d' ' -f1)
    name=$(basename "$d")
    printf '%-60s  %8s  %s\n' "$name" "$sz" "$accessed"
  done
else
  printf '%s\n' "Cache root not present at $cache_root (cold cache; nothing to report)."
fi
```

The cache section is informational — STATUS does not delete anything.
REFRESH auto-GCs stale SHA directories; `/skill-engine:clean-cache`
deletes the cache on demand.

If multiple `<source_id>-*/` directories exist for the same `source_id`
(i.e., older SHAs were not GC'd because REFRESH has not run yet), flag
them as a hint in the Cache section, but do not delete.

### Cache listing

`~/.cache/skill-engine/git-managed/`:
| source_id | sha | last_fetched |
|---|---|---|
| ... | ... | ... |

`~/.cache/skill-engine/web-doc/`:
| source_id | crawl_id | page_count | crawl_date | decay_remaining |
|---|---|---|---|---|

```bash
cache_root="${XDG_CACHE_HOME:-$HOME/.cache}/skill-engine"
decay_json=$(python3 "$CLAUDE_PLUGIN_ROOT/tests/decay_check.py" research/source-paths.json "$cache_root" 2>/dev/null)
row_count=$(printf '%s' "$decay_json" | jq 'length' 2>/dev/null); row_count=${row_count:-0}
if [ "$row_count" -eq 0 ]; then
  printf '(No web-doc sources with a cached, decay-checkable snapshot yet.)\n'
else
  printf '%s' "$decay_json" | jq -r '
    .[] | "| \(.source_id) | \(.crawl_id) | \(.page_count) | \(.crawl_date) | " +
    (if .state == "non_expiring" then "no expiry"
     elif .state == "past_budget" then "\(.days) days past decay budget"
     else "\(.days) days remaining" end) + " |"'
fi
```

Old flat-layout entries (if present — directories sitting directly at the
cache root rather than under `git-managed/` or `web-doc/`):
| dir | last_modified |
|---|---|
| ... | ... |

(The old-layout listing exists until the user runs the REFRESH migration
prompt or `clean-cache`.)

## Priority surface

Render each in-scope source's `importance` (see
[`02-artifact-contract.md`](../../docs/02-artifact-contract.md) for
the field) and, when the root-level `probe_budget` is set, its
projected effect:

```python
import json
data = json.load(open('research/source-paths.json'))
in_scope = [s for s in data.get('sources', [])
            if not s.get('archived') and s.get('status') in ('confirmed', 'proposed')
            and (s.get('lifecycle') or {}).get('state') != 'removed']
# A monorepo parent covered by a LIVE slice is excluded, the same way
# REFRESH's pre-flight excludes it — otherwise the projected skip count
# disagrees with what REFRESH will actually do, by one per sliced monorepo.
covered = {s['slice_of'] for s in in_scope if s.get('slice_of')}
sources = [s for s in in_scope
           if s.get('slice_of') is not None or s.get('url') not in covered]
print('| id | importance |')
print('|---|---|')
for s in sorted(sources, key=lambda s: s['id']):
    imp = s.get('importance')
    print(f"| {s['id']} | {imp if imp is not None else '3 (default)'} |")
budget = data.get('probe_budget')
k = len(sources)
if budget is not None:
    would_skip = max(0, k - budget)
    print(f'\nprobe_budget={budget}: would skip the re-read of {would_skip} of {k} in-scope sources at the next refresh (worst case — assumes every source is promoted; all {k} are probed either way).')
else:
    print(f'\nprobe_budget not set: all {k} in-scope sources are probed every refresh.')
```

Run with `python3` against the contextualizer root
(`research/source-paths.json` relative to cwd), same convention as
`decay_check.py` elsewhere in this file. **Tag this fence `python`, not
`bash`** — `tests/status-decay/run.sh` sweeps every `` ```bash `` fence
in this file except the one inside whichever section's heading mentions
"probe" into its own decay-computation script; a `bash` tag here gets
swept in and breaks that sibling oracle.

`importance` defaults to `3 (default)` when the field is absent. The
skip count above is a worst-case estimate from the registry alone —
STATUS does not fetch upstream by default (see § Cadence), so it
cannot know in advance which sources will actually show drift this
session; `--probe` below can narrow that estimate for `git-managed`
sources at the cost of a live check.

## Provenance probe (`--probe`)

`/skill-engine:status <name> --probe` is an opt-in check: without
`--probe`, STATUS's behavior is exactly as documented above — it does
not fetch upstream. With `--probe`, STATUS runs one upstream check per
in-scope `git-managed` source in `research/source-paths.json` and
reports whether the locally recorded SHA still matches upstream today,
without waiting for a full REFRESH pass:

```bash
python3 "$CLAUDE_PLUGIN_ROOT/tests/status_probe.py" research/source-paths.json
```

For each in-scope `git-managed` source (the same filter REFRESH's own
pre-flight uses: `status` confirmed or proposed, not archived, upstream
lifecycle state not removed, and not a monorepo parent already covered by
a live slice), render one line from the script's JSON:

- **current** — the live SHA matches the recorded `last_checked_sha`.
- **mismatch** — the live SHA differs; show both the recorded SHA and
  the live SHA so the user can see how far behind it is.
- **never been probed** — `last_checked_sha` is null; this source has
  no prior probe on record, reported distinctly rather than compared
  against an absent value.
- **error** — the probe itself failed (unreachable remote, no such branch); shown inline with the diagnostic. One source's error does not stop the remaining in-scope sources from being probed and reported.

With zero in-scope `git-managed` sources, print `Nothing to probe.`
rather than no output.

`--probe` does not write `source-paths.json` — `lifecycle.last_checked_sha`
and `lifecycle.last_checked` are unchanged by this command. It does not
modify anything; it only reports. Persisting a probe result is REFRESH's
job, not this one's.

## Invariants

STATUS is read-only. It surfaces findings; it does not propose edits, does not
fetch upstream, and does not modify `research/.research-state.json`. The
underlying state read uses a pre-render guard so the dashboard never blocks on
a partial write. The Cache section is read-only too: STATUS reports cache
state but never deletes from it.

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.