config — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited config (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.
Interactively edit one run's configuration. Two surfaces: (1) run-level settings that state.json is authoritative for (profile.*, parallelism, thresholds, naming) - written through bin/state.sh and mirrored into config.yaml as a human record; (2) the bucket role display labels and other record-only knobs that live in config.yaml; (3) the active SOURCE/SINK connector contract (source-connector.md / sink-connector.md), which you can swap to a shipped template or re-author via interview. This skill applies changes FORWARD only and refuses edits that would corrupt work already committed (a synthesize/apply already in flight).
/claude-migrate:config [<run-name>] [<area>]
<run-name> optional. If omitted, auto-detect: list .planning/claude-migrate/ and if exactly one run dir exists, use it; otherwise print available runs and exit.<area> optional shortcut: one of tier | parallelism | thresholds | naming | buckets | source | sink. If omitted, present the full menu (Step 2).<run-name> and the optional <area> from $ARGUMENTS.<run-name> absent: 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."CUR_STEP=$(bash ${CLAUDE_PLUGIN_ROOT}/bin/state.sh get "$RUN_PATH" .current_step)
jq '{profile, decisions:{naming_convention:.decisions.naming_convention}, input:.input.mode, output:.output.mode}' "$RUN_PATH/state.json"
sed -n '1,200p' "$RUN_PATH/config.yaml"<area> was given)Use AskUserQuestion with header "Which setting do you want to change?" and options:
Before writing, gate on CUR_STEP:
CUR_STEP == "synthesize" or later (build-page, verify-gate, ready, pre-apply-gate, apply, finalize, done), REFUSE a tier change: "synth_model and the gate rigor are already committed for this run; a new tier applies forward only and there is no forward work left to apply it to. Start a new run if you need a different tier."launch-worker.sh terminals. Already-running workers keep the model and count they started with - say so.hard_stop_usd retroactively if decisions.cost_acknowledged == true and CUR_STEP is past filter-gate (the cost was already approved). max_brief_tokens / inline limits are safe to change before distill / build-page respectively; warn if changed after, because existing briefs/pages will not be regenerated unless re-run.distill; after distill the briefs already hold derived titles, so warn that a change only affects re-distilled units.CUR_STEP is past split (units are already extracted under the current source contract; changing the source mid-run would desync the corpus). For sink: refuse a swap once apply has started. Before split, a swap is free.If a change is refused, explain why and stop - do NOT partially apply.
Validate against the closed enum {small, medium, large, xl}; reject others with the valid list. Set the whole profile sub-object so downstream skills read it without re-deriving. Per-tier values:
| tier | preflight_model | distill_model | synth_model | validator_model | ultra_gate_tier | parallelism | seed_parallelism |
|---|---|---|---|---|---|---|---|
| small | haiku | haiku | sonnet | sonnet | --small | 1-2 | 1 |
| medium | haiku | sonnet | sonnet | opus | --medium | 2-3 | 1 |
| large (default) | haiku | sonnet | opus | opus | --large | 4 | 1 |
| xl | haiku | opus | opus | sonnet | --xl | 5-10 | 1 |
Cross-model rule (runtime-enforced by verify): validator_model != distill_model. The table satisfies it; if you ever edit the table re-verify it. seed_parallelism stays 1 in v0.1.0 regardless of tier (in-session serial apply). Write:
bash ${CLAUDE_PLUGIN_ROOT}/bin/state.sh set "$RUN_PATH" .profile '<full-profile-json-object>'profile.parallelism (integer >= 1): worker terminals for preflight/distill.profile.seed_delay_ms (integer >= 0): pacing between seed submissions in browser apply.profile.seed_parallelism: MUST remain 1 in v0.1.0. If the user asks for more, refuse and explain it is reserved for the future CDP-library path.bash ${CLAUDE_PLUGIN_ROOT}/bin/state.sh set "$RUN_PATH" .profile.parallelism <N>
bash ${CLAUDE_PLUGIN_ROOT}/bin/state.sh set "$RUN_PATH" .profile.seed_delay_ms <MS>State.json profile fields: max_brief_tokens, inline_card_limit, inline_byte_limit, ok_wait_ms, breaker_threshold, capture_screenshots. Cost guardrails (warn_usd, hard_stop_usd, warn_chat_count, warn_chat_tokens) live in config.yaml under cost: and are read at the G-COST gate. If the user turns capture_screenshots ON, WARN: per-attempt screenshots may capture PII; they are excluded from git by the run-dir .gitignore, and a banner warning fires in apply.
bash ${CLAUDE_PLUGIN_ROOT}/bin/state.sh set "$RUN_PATH" .profile.max_brief_tokens <N>Then mirror the cost block into config.yaml (Step 5).
decisions.naming_convention: keep (default; derive a title only when the original name is empty/generic) or custom:<scheme>. For custom, drive a structured pick with a prefilled worked example (Name DD.MM tag) via AskUserQuestion, then store the resolved scheme string.bash ${CLAUDE_PLUGIN_ROOT}/bin/state.sh set "$RUN_PATH" .decisions.naming_convention '<keep|custom:SCHEME>'The four ROLES are a closed enum (GROUPED | STANDALONE | REFERENCE | DROP); you may relabel how each is shown but NEVER add or remove a role. Edit the bucket_labels: map in config.yaml only (the core switches on the role enum, never on the label). Read the current labels, ask for new strings, and write config.yaml.
A connector is a markdown CONTRACT (not code) copied into the run dir. Two paths via AskUserQuestion ("Swap to a shipped template, or re-author the current one?"):
# SOURCE options: export-file (default) | browser (live)
cp ${CLAUDE_PLUGIN_ROOT}/templates/sources/export-file.md "$RUN_PATH/source-connector.md"
# SINK options: copy-page (the reliable floor) | browser (accelerator)
cp ${CLAUDE_PLUGIN_ROOT}/templates/sinks/browser.md "$RUN_PATH/sink-connector.md"If the swap changes input.mode (export <-> live) or output.mode (copy-page <-> auto), update the matching state.json field too:
bash ${CLAUDE_PLUGIN_ROOT}/bin/state.sh set "$RUN_PATH" .input.mode '<export|live>'
bash ${CLAUDE_PLUGIN_ROOT}/bin/state.sh set "$RUN_PATH" .output.mode '<copy-page|auto>'enumerate, extract_unit, extract_projects, unit_project_ref, account_check, citation_anchor, forbidden_fields. Required SINK sections (§5.2): prepare, dedupe_probe, create_project, seed_unit, finalize_unit, finalize_run, rate_limit_check. Open the file with the copy-first banner and, for browser/live sources, the mandatory secret-strip note. Never hardcode a secret in a connector - reference an env var. After re-authoring, advise re-running /claude-migrate:run so /ultra Gate 1 re-validates the new contract.For any state.json field that also appears in config.yaml (tier, parallelism, thresholds, naming, cost block, bucket_labels), update the config.yaml copy so the human record stays consistent (state.json remains authoritative for the fields it tracks). Then print a confirmation:
Config updated for run <run>:
<field>: <old> -> <new>
...
Effect: applies on the NEXT step. Already-running workers keep their started settings.
Next action: /claude-migrate:run <run> (or /claude-migrate:progress <run> to review)synthesize has committed it. Refuse with a clear reason rather than corrupting state.state.json mutations go through bin/state.sh (locked, atomic, injection-defended). NEVER hand-edit state.json.config.yaml is a human record for the fields state.json also tracks; on conflict state.json wins. Keep them consistent after every change.config.yaml; you may NEVER add or remove a role.seed_parallelism stays 1 in v0.1.0. Refuse any higher value.Project Alpha, topic-1).~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.