| name | agent-introspect |
| description | Weekly self-audit of the Zo skill/identity/script-health surface. Walks Skills/*/scripts/, probes each script's --help under a bounded retry budget, checks identity files, and emits findings plus an atomic machine-status file. Use when running or maintaining the "[SYS] Audit Skills & Personas" scheduled agent, when investigating introspection findings, or when changing the SKIP_HEALTH skip list. |
| compatibility | Created for Zo Computer |
| metadata | {"author":"marlandoj.zo.computer"} |
Agent Introspect
Hardened, version-controlled audit that replaces the formerly-inline Python
heredoc inside the [SYS] Audit Skills & Personas scheduled agent
(automation_id 1f8e4dbc-d879-4e2b-bc45-3cfae24d4333, weekly Sun 14:00 Phoenix).
Detection criteria are unchanged from the inline version; the script adds
operational safety the inline block lacked.
Run it
python3 Skills/agent-introspect/scripts/introspect.py
python3 Skills/agent-introspect/scripts/introspect.py --compat --findings-only
python3 Skills/agent-introspect/scripts/test_introspect.py
What it checks
- Skills — every
Skills/*/SKILL.md for an empty description:; flags a
scripts/ dir that has no runnable file (.ts/.py/.sh/.mjs/.js).
- Identity —
AGENTS.md present; IDENTITY/*.md not stale (>30 days).
- Script health — probes each
Skills/*/scripts/ file with --help
(.ts→bun, .py→python3, .sh→bash). Flags exit codes outside {0,1} and
timeouts. Files named in config.json:skip_health are skipped.
Architecture Hotspots (advisory, not a check)
The report carries an additive Architecture Hotspots appendix sourced from
the codebase-memory graph (DeusData/codebase-memory-mcp). For each of
home-workspace-packages and home-workspace-Skills it lists the top fan-in
functions (widest regression blast radius) and the lowest-cohesion Leiden
clusters (fuzziest module seams — refactor candidates). This is context, not a
finding: it never adds to the findings count, never changes the exit code, and
a missing/timed-out graph degrades to a one-line note. Because it lives outside
the findings set, compat parity (--compat --findings-only) is unaffected.
Knobs are module constants in introspect.py (ARCH_BIN, ARCH_PROJECTS,
ARCH_TIMEOUT_S, ARCH_TOP_HOTSPOTS, ARCH_LOW_COHESION) — deliberately not in
config.json, so the schema version and fail-closed key guard stay frozen.
Note: advisory content rides the email rule unchanged — a zero-finding week
writes the report to disk but does not email it.
Contract (how the agent consumes it)
- The agent deletes
Reports/Introspections/.introspect-status.json before
invoking the script, then requires the file to exist afterward. Absence ==
ERROR (proves the status is from the current run — no time-window heuristic).
- Exit codes:
0 OK · 1 ERROR · 3 PARTIAL · 4 lock-contention. PARTIAL and
ERROR are non-zero, so a consumer reading only the exit code never mistakes
them for success.
- Status file keys:
status, exit_code, findings, report, partial_reason, unprobed, unprobeable_ext, error, ran_at.
- Email rule: email on ERROR (always), PARTIAL (always), OK only if
findings > 0.
config.json
All keys are validated; any failure is a fail-closed ERROR (no defaults, no
fail-open). version is checked against EXPECTED_CONFIG_VERSION in
introspect.py — config and script ship in the same commit, so a desync is a
loud error, not silent misbehavior.
| key | meaning | range |
|---|
version | config schema version | must equal 1 |
probe_timeout_s | per-attempt --help timeout | 1..120 |
retries | extra attempts on timeout only | 0..3 |
audit_budget_s | global monotonic deadline | 60..3600 |
max_timeouts | timeout events before retries disable | 1..100 |
skip_health | filenames skipped by the health probe | list, no dups |
Changing skip_health means editing both config.json and the
FROZEN_SKIP_HEALTH snapshot in test_introspect.py — the parity test fails
otherwise. This is intentional: the skip list cannot drift silently.
Hardening notes
- Probe child stdout/stderr is captured into variables, never echoed to the
audit's own stdout — a probed script cannot spoof the status.
- Retry is timeout-only; one timeout event per script even under retries.
- Interpreter preflight (
shutil.which): a missing bun/python3/bash becomes a
finding, never a silent pass.
- Runnable-but-unprobeable files (
.mjs/.js) are counted (unprobeable_ext) and
listed under "skipped (no probe strategy)".
- No secrets are read, passed on argv, or logged —
--help probes need none.