audit — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited audit (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
A growing memory only stays useful if it stays clean. audit is the guardian: it scans the canonical Notion DBs for the failure modes that quietly degrade recall, reports them by severity, and — only with the user's go-ahead — applies the safe fixes. All reads go through notion-search (free plan); the canonical data is never duplicated locally. Report in the user's conversation language.
L="${CLAUDE_PLUGIN_ROOT}/scripts/_lib/config.ts"; IDX="${CLAUDE_PLUGIN_ROOT}/scripts/_lib/index.ts"
bun "$L" get decisions_ds_id # empty -> tell the user to run /iroha:init, then stop
bun "$L" get session_ds_id
bun "$L" get-state "$PWD" # the State page id (may be empty on a fresh project)
bun "$IDX" list "$PWD" decision # COMPLETE list of decision keys — the enumeration search lacks
bun "$IDX" list "$PWD" session # COMPLETE list of session keysEnumerate from the local index (index.ts list above) — it is the complete set of decision/session keys, which free-plan notion-search cannot reproduce. notion-fetch each id that needs its content inspected, and collect findings. (If the index is empty or stale — an older workspace created before the index existed — fall back to notion-search and say so: results are then best-effort, not complete. Offer to backfill: fetch the known rows and index.ts upsert each into the index so future audits are exhaustive.)
Status = Active rows sharing the same <topic>are a conflict (one should be Superseded). Now exhaustive via the index — every conflicted topic, not just what search surfaced. Use the typed subcommand (not sort | uniq -d, which mis-groups multibyte/Japanese topics under some locales, and not a jq pipe — both were real false-positive / fragility sources while dogfooding); it prints one offending topic per line, grouped ASCII-case-insensitively like find-topic: bun "$IDX" dup-topics "$PWD" (severity: high — the defect that most rots recall.)
Active decision whose Rationale is contradicted bya newer Active decision on the same topic, or which a later Session's decisions reversed. Flag the older one. (high)
Session URL is empty or does not resolve(notion-fetch 404). The "why" loses its anchor. (medium)
bun "${CLAUDE_PLUGIN_ROOT}/scripts/_lib/integrity.ts" "$PWD"flags a supersedes that points to an id missing from the index (broken lineage, the /iroha:history chain dead-ends). Also flag the inverse: a Superseded decision that no Active decision links back to via Supersedes (a dangling successor — the chain has a hole). Fix is reversible: set the missing Supersedes URL on the superseding decision (+ the index supersedes id) only when the predecessor is unambiguous (the newer Rationale names it, or a → …に置換 note); never guess a predecessor. (medium)
to the Notion page under save-session's single-source rule), then notion-fetch the page for the judgement checks below: bun "${CLAUDE_PLUGIN_ROOT}/scripts/_lib/state-lint.ts" "$(bun "$L" state-md-path "$PWD")" flags the escape-leak and dropped-section classes mechanically (the two that recurred); treat any issue it prints as a high-confidence finding. Then compare against Notion:
Summary (stale if it names an olderstate, e.g. "2 DB" when the newest session is "3 DB"); (medium)
\n or \t two-character sequence,or text like nt…n at a line's edge (a past save leaked \n\t into Notion as nt…n). The page should have real line breaks; flag it. (medium — corrupts the human-facing page.)
## Recent sessions, ## Unfinished / Next, a ## Decisions link). A State that is just a summary breaks the SessionStart continuity it exists to provide — and means it diverged from the .iroha/state.md mirror, which should be byte-identical. (medium)
- [ ] item carried for 3+ sessions (look for the[carried Nx] marker save-session writes, or infer from dates). (low — but nag-worthy.)
## Metrics,## Decisions, ## Progress, ## Highlights, ## Details) or whose Highlights look invented (a "You" line with no matching real prompt is impossible to verify — flag Sessions whose Highlights read as narration rather than real exchanges). (low)
Active decisions that are display/naming/wording tweaksrather than architecture/dependency/process (they belong in a Session's decision table, not the Decisions DB). (low — recall signal-to-noise.)
notion-search the Projects DB for this project's row andnotion-fetch it; flag: an Updated date far behind the newest Session; a field that contradicts the current repo (e.g. CI says "none/未設定" when .github/workflows/ exists, or a recall/stack note that a later Decision has since changed); or a file name auto-linkified into a bogus http://…sh / http://…md URL (it should be backticked). The cross-project layer is manually updated, so it rots silently. Fix = re-run /iroha:project. (low.)
committed docs can carry stale claims that readers (and recall) trust. Grep README.md and .claude/rules/architecture.md for hardcoded metrics or claims that no longer hold: a cited recall metric (Recall@k / MRR / abstention) that differs from the current bun tests/recall-eval.ts output; a DB/architecture count contradicting the 3-DB model; a feature described as present/absent that the code disproves. (medium — a doc that lies erodes the same trust a rotted decision does; hardcoded metrics in prose are the usual culprit, so prefer pointing readers at the live test output over pinning a number.)
authoritative if it actually holds every decision/session Notion has. Dogfooding found it silently ~22% short (Active decisions created in Notion but never index.ts upsert-ed), which makes proactive recall AND every index-based audit check (A/C above) under-enumerate without any signal. This is the check whose absence let that drift hide — run it every audit. First the deterministic offline floor (catches malformed rows, duplicate ids, duplicate Active topics, and a State that points at a session missing from the index): bun "${CLAUDE_PLUGIN_ROOT}/scripts/_lib/integrity.ts" "$PWD" — treat anything it prints as high-confidence. Also validate the cached ids — a non-empty but malformed id (a leftover DSID placeholder, a truncated value) passes every "is it set?" check yet silently breaks recall, this audit, and decision saves (a real dogfood defect): bun "$L" validate (offline shape check), then confirm each *_ds_id actually resolves by notion-fetch-ing collection://<id> — flag any that 404 (config points at a deleted / wrong data source). Then the Notion reconciliation the offline floor cannot do: enumerate the Decisions DB as completely as the free plan allows (several broad notion-search passes over decisions_ds_id plus the ids the index already knows), collect the distinct decision page ids Notion returns, and diff against index.ts list "$PWD" decision. Flag every Notion decision id absent from the index (it can never be recalled proactively) and every index id whose notion-fetch 404s (stale row). Because the free plan cannot list a DB exhaustively, report the Notion side as a lower bound — "≥ N decisions in Notion vs M in the index" — and never claim the index is complete just because the counts happen to match a partial search. (high — the rot that silently shrinks recall coverage.)
Print a findings report grouped by severity, each finding with: what, where (page link), why it hurts recall, and the suggested fix. End with a one-line health verdict (healthy / N issues / needs attention). If nothing is wrong, say so plainly — a clean audit is a real result.
--fix or explicit confirmation)Never mutate on a bare audit. When the user passes --fix (or confirms after the report), apply only the safe, reversible fixes and re-report each:
Status = Superseded withnotion-update-page (never delete — the change of mind is itself memory). Leave the current one Active.
save-session §8's single-source rule: compose the body ONCE (summary + ## Recent sessions + ## Unfinished / Next + ## Decisions link, real newlines, no literal \n/\t), write it to <repo>/.iroha/state.md (bun "$L" state-md-path "$PWD"), then notion-update-page replace_content with that same text so the page and mirror match; remind the user to commit it.
- [ ]; applythe user's call.
/iroha:project to rewrite the row from the current repo(it fully replaces the body + Updated). Reversible; safe to apply on confirmation.
apply on confirmation; for a live metric, prefer phrasing it as a dated snapshot so it does not re-rot.
it and index.ts upsert "$PWD" <type> <id> <topic> <status> <date> "<Name>" "<Project>" "<snippet>" (regenerate the ≤160-char snippet from its Rationale/Summary, ending on a word boundary), and drop any index row whose id 404s. Re-run integrity.ts and the Notion diff until they reconcile. Remind the user to commit .iroha/index.ndjson. This is the reindex repair; it is reversible (it only adds/refreshes keys — Notion stays the content source of truth) so it is safe to apply on confirmation. If config.ts validate flagged a malformed id, repair it: re-run /iroha:init against the same parent page (it re-reads the real ids), or set the correct id directly with bun "$L" set <key> <id>.
recommended action but do not auto-apply; ask.
top-N), so the duplicate-Active (A) and orphan (C) checks are exhaustive rather than heuristic. The content checks (B contradiction, F granularity) still need judgment via notion-fetch. Reconcile drift: if index.ts list and Notion disagree (an id 404s, or a status differs), fix the index with index.ts upsert. Better a flagged false positive than silent rot.
returning conflicting answers.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.