health-817170 — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited health-817170 (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.
Diagnostic only. Run a battery of read-only checks against one run's state.json plus its work-queue dirs, then report each finding with a SEVERITY and a suggested repair COMMAND. This skill PROPOSES repairs; it NEVER applies them. The user copy-pastes the command they choose. There is no --fix auto-apply mode by design - a migration moves real chats into a real account, so every mutation stays under human control.
/claude-migrate:health [<run-name>]
<run-name> optional. If omitted, auto-detect: list .planning/claude-migrate/ and if exactly one run dir exists, use it; otherwise print the available runs and exit.<run-name> from $ARGUMENTS.ls .planning/claude-migrate/ - if exactly one dir, use it; else print available runs and exit.RUN_PATH=".planning/claude-migrate/<run-name>".$RUN_PATH/state.json is missing, STOP: "No such run. Initialize with /claude-migrate:init <run-name> first."$RUN_PATH/state.json exist and parse as JSON (jq -e . "$RUN_PATH/state.json")?run, current_step, status, input, output, profile, gates, decisions, counters?current_step a member of the §3.1 enum (init, pre-split-gate, split, preflight, filter-gate, distill, synthesize, build-page, verify-gate, ready, pre-apply-gate, apply, finalize, done, failed)? ls -t "$RUN_PATH/checkpoints"/*.json | head -1 # newest snapshot
# then, after reviewing it: cp "<that-file>" "$RUN_PATH/state.json"claude-migrate uses mkdir-based locks. Candidate lockdirs:
$RUN_PATH/state.json.lock.d (the state writer)$RUN_PATH/units/.claim.lock.d (preflight/distill queue claims)$RUN_PATH/seed/.claim.lock.d (apply queue claims)$RUN_PATH/project/*/.create.lock.d (per-project create prelude)For each lockdir that exists:
holder.pid file is inside it and kill -0 <pid> succeeds, a live process holds it - leave it alone (a worker is mid-write).stat -f %m "$lockdir" on macOS / stat -c %Y "$lockdir" on Linux; compare to date +%s):rmdir "<lockdir>".rmdir "<lockdir>".This mirrors the auto-heal that /claude-migrate:resume performs; health only surfaces it as a finding and proposes the rmdir, never running it.
For BOTH queues - $RUN_PATH/units/in-progress/ and $RUN_PATH/seed/in-progress/:
run.log is likely orphaned (its worker died after claiming but before releasing).pending/ with a retry tag (this is exactly what /claude-migrate:resume does automatically): # units queue:
bash ${CLAUDE_PLUGIN_ROOT}/bin/release.sh "<orphan-item-path>" requeue orphaned
# seed queue item: resume re-derives its status from seed/UNNN.json; prefer:
/claude-migrate:resume <run-name>Assert every invariant against live state. A broken invariant means a bug, a manual edit, or a half-completed move corrupted the bookkeeping:
jq -r '
.counters as $c
| [ ($c.chats_total == ($c.preflight_pending + $c.preflight_in_progress + $c.preflight_done + $c.preflight_failed)),
($c.kept == ($c.distill_pending + $c.distill_in_progress + $c.distill_done + $c.distill_failed)),
($c.kept == ($c.seeded_units + $c.doc_only_units)),
($c.seeded_units== ($c.seed_pending + $c.seed_in_progress + $c.seed_done + $c.seed_failed)),
($c.projects_total == ($c.projects_pending + $c.projects_created)) ]
| to_entries[] | "\(.key): \(.value)"
' "$RUN_PATH/state.json"Map index 0->chats_total, 1->kept(distill), 2->kept(routing), 3->seeded_units(seed queue; auto mode only), 4->projects_total. Index 3 only applies when output.mode == "auto" (the seed queue is sized to seeded_units, not kept). Any false -> SEVERITY=CRITICAL.
status=passed): projects_created == projects_finalized. If current_step is at/after finalize and these differ -> SEVERITY=CRITICAL: "a project never swapped to steady - never reach done in migration mode."state.sh set/inc/dec calls needed, derived from the queue-dir counts in Check 6, and tell the user to apply them one at a time and re-check the invariant after each.Compare each counter against the directory that IS its state:
ls "$RUN_PATH/units/pending" 2>/dev/null | wc -l # vs .counters.preflight_pending
ls "$RUN_PATH/units/in-progress" 2>/dev/null | wc -l # vs .counters.preflight_in_progress
ls "$RUN_PATH/units/done" 2>/dev/null | wc -l # vs .counters.preflight_done
ls "$RUN_PATH/units/failed" 2>/dev/null | wc -l # vs .counters.preflight_failed
ls "$RUN_PATH/units/dropped" 2>/dev/null | wc -l # vs .counters.dropped
ls "$RUN_PATH/seed/pending" 2>/dev/null | wc -l # vs .counters.seed_pending (auto mode)
ls "$RUN_PATH/seed/in-progress" 2>/dev/null | wc -l
ls "$RUN_PATH/seed/done" 2>/dev/null | wc -l
ls "$RUN_PATH/seed/failed" 2>/dev/null | wc -l
ls "$RUN_PATH/briefs"/*.brief.md 2>/dev/null | wc -l # rough vs distill_doneA mismatch -> SEVERITY=WARN. PROPOSE the single state.sh set that reconciles each drifting counter to the filesystem count (filesystem is ground truth for queue state). The repair is idempotent: re-running it after a correct value does nothing.
$RUN_PATH/source-connector.md and $RUN_PATH/sink-connector.md exist?$RUN_PATH/config.yaml and $RUN_PATH/selectors.json exist? cp ${CLAUDE_PLUGIN_ROOT}/templates/sources/export-file.md "$RUN_PATH/source-connector.md"or re-author via /claude-migrate:config <run-name>.
For each of gates.pre-split, gates.verify, gates.pre-apply: if verdict == "PASS" but the recorded report path does not exist on disk -> SEVERITY=WARN (the audit trail is broken; likely safe to proceed but unverifiable). PROPOSE: manual review - re-run the relevant /claude-migrate:run <run> gate to regenerate the report, or accept the gap knowingly.
The sole resume authority for a seeded unit is seed/<queue>/UNNN.json; apply/UNNN.result.json is a report only. Scan for units whose seed/*/UNNN.json says status in {seeded, awaited_ok} but renamed was never reached, or status == opened (AMBIGUOUS - a crash may have happened mid-submit). SEVERITY=WARN. PROPOSE: /claude-migrate:resume <run-name> (it re-polls seeded, renames awaited_ok-not-renamed, and runs a SINK dedupe_probe on opened before any re-seed). Never propose deleting an opened unit.
df -h . on the run's filesystem. If < 5% free -> SEVERITY=WARN. PROPOSE: free space before the opus synthesize/verify steps (they load the full briefs corpus).claude-migrate health: <run> (output.mode=<auto|copy-page>, step=<current_step>, status=<status>)
Checks: 9 Passed: <P> Warn: <W> Critical: <C>
=== CRITICAL ===
[CRIT] <finding one line>
Cause: <one line>
Repair (RUN IT YOURSELF): <exact command>
=== WARN ===
[WARN] <finding one line>
Repair (RUN IT YOURSELF): <exact command>
=== PASSED ===
ok state.json integrity
ok no stale locks
ok counter-sum invariants (§3.3)
...If there are zero CRITICAL/WARN findings, print "Run looks healthy. Next action: /claude-migrate:progress <run>."
state.json, NEVER move or delete a queue item, NEVER rmdir a lock. Print the command; the user runs it.bin/state.sh, bin/release.sh, bin/requeue.sh, or /claude-migrate:resume, never a raw edit of state.json.dest_chat_url, raw briefs, emails, or tokens.config.yaml.~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.