Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Migrate pre-fn-30 legacy flat memory files (`.flow/memory/pitfalls.md`, `conventions.md`, `decisions.md`) into the categorized YAML schema. Triggers on /flow-next:memory-migrate, "migrate memory", "convert legacy memory", "lift pitfalls into categorized schema", "convert old memory format". Optional `mode:autofix` token in arguments runs without questions and accepts mechanical defaults for ambiguous classifications. Optional scope hint after the mode token narrows the migration to a specific le
.claude/skills/gmickel-flow-next-memory-migrate/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-07 | ✗→✓ | ▲ Improved | 204% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 90% | 0% |
| case-12 | ✗→✓ | ▲ Improved | 155% | 0% |
| case-13 | ✗→✓ | ▲ Improved | 171% | 0% |
| case-14 | ✗→✓ | ▲ Improved | 88% | 0% |
Pre-fn-30 flow-next stored memory as three flat markdown files: .flow/memory/pitfalls.md, conventions.md, decisions.md. Each was a sequence of ----delimited segments with ad-hoc headings and no schema. fn-30 introduced the categorized schema (track / category / module / tags / status frontmatter, one entry per file). Existing flat files persisted but became invisible to memory list, memory search, and flow-next-audit because there's no frontmatter to scope or stale-flag.
This skill IS the migration. The host agent (Claude Code / Codex / Droid) reads each legacy entry, applies the mechanical default (track, category) from the source filename, overrides only when the entry's content warrants, and writes a categorized entry via flowctl memory add. Optional autofix mode accepts every mechanical default and marks ambiguous entries as needs-review in the report.
There is no Python classifier subprocess, no codex/copilot dispatch, no fast-model probability scoring. The host agent is already an LLM with full repo context and does the work directly. flowctl provides only thin parsing + persistence plumbing (memory list-legacy --json, existing memory add).
Read workflow.md for the full phase-by-phase execution. Read phases.md for the (track, category) decision tree with mechanical baseline + override examples.
CRITICAL: flowctl is BUNDLED — NOT installed globally. which flowctl will fail (expected). Define once; subsequent blocks (here and in workflow.md) use $FLOWCTL:
bashFLOWCTL="${CODEX_HOME:-$HOME/.codex}/scripts/flowctl" [ -x "$FLOWCTL" ] || FLOWCTL="<plugin-root>/scripts/flowctl" # <plugin-root> = the directory two levels above this skill's SKILL.md file (the harness gave you that file's absolute path when the skill loaded); substitute it literally [ -x "$FLOWCTL" ] || FLOWCTL=".flow/bin/flowctl"
Inline skill (no context: fork) — plain-text numbered prompt must stay reachable across phases. Subagents can't call plain-text numbered prompts (Claude Code issues #12890, #34592). Phase 1 (Classify) needs user choice on ambiguous entries in interactive mode; Phase 4 (Cleanup) needs consent before renaming originals.
Parse $ARGUMENTS for the literal token mode:autofix. If present, strip it from the arguments — the remainder is the scope hint (a legacy filename like pitfalls.md to narrow the run, or empty to migrate all).
bashRAW_ARGS="$ARGUMENTS" MODE="interactive" if [[ "$RAW_ARGS" == *"mode:autofix"* ]]; then MODE="autofix" # Strip token, collapse whitespace, trim. SCOPE_HINT=$(printf "%s" "$RAW_ARGS" | sed 's/mode:autofix//' | tr -s ' ' | sed 's/^ //;s/ $//') else SCOPE_HINT="$RAW_ARGS" fi
| Mode | When | Behavior | |------|------|----------| | Interactive (default) | User is at the terminal | Ask via plain-text numbered prompt when an entry's content suggests overriding the mechanical default; confirm Phase 4 cleanup; show triage summary before writes | | Autofix (mode:autofix in arguments) | Ralph or batch usage | No user questions. Apply mechanical defaults for every entry. Override only when the agent has high-confidence evidence from the entry body. Mark genuinely ambiguous entries as needs-review in the report. Default-decline Phase 4 cleanup. Print full report |
(track, category) (e.g. an entry titled "race condition in worker pool" inside pitfalls.md clearly warrants bug/runtime-errors over the mechanical bug/build-errors).needs-review. Genuine "could be A or B" cases take the mechanical default and surface in the report so the user can re-classify later.In autofix mode, skip user questions entirely and apply the rules above.
In interactive mode, follow these principles:
Ask the user via plain text. Render the options below as a numbered list 1. … N., followed by a final option N+1. Other — type your own answer. Print the question, then the numbered list, then stop and wait for the user's next message before continuing. Parse the reply as: a bare number 1–N+1 → that option; the literal text of an option label → that option; free text after Other → custom answer.
plain-text numbered prompt. Never silently skip the question.The goal is automated migration with human oversight on judgment calls — not a question for every entry.
This skill runs almost entirely on the main thread. Phase 1's "one entry per prompt turn" rule means classification iterates serially in the orchestrator — there is no investigation step independent enough to dispatch in parallel. Cross-platform tool naming (Task on Claude Code, spawn_agent on Codex, platform-equivalent on Droid) is documented here only for the rare case where the agent needs to spawn a focused investigation subagent (e.g. resolving an ambiguous override by reading a referenced file): keep such dispatches read-only (Read / Grep / Glob), do not let subagents call flowctl memory add directly, and merge results back on the main thread before Phase 2.
MEMORY_LEGACY_FILES (pitfalls.md, conventions.md, decisions.md at .flow/memory/ root). Any other .md at the memory root is user data — leave it alone..flow/memory/{bug,knowledge}/<category>/*.md). Those are already migrated; re-running on them is a bug..flow/memory/_migrated/<filename>.bak for traceability — never rm. User can git rm later if they want.memory list-legacy. Phase 2 writes via existing flowctl memory add. Mechanical map is documented in phases.md so the agent doesn't need to call a flowctl helper for it.context: fork — plain-text numbered prompt must stay reachable..flow/memory/_migrated/<filename>.bak and skips with an "already migrated" log line.Execute the phases in workflow.md in order:
flowctl memory list-legacy --json, check _migrated/ for prior runs, apply scope hint, decide interaction path.(track, category), override only with body-driven evidence. Interactive: ask on ambiguity. Autofix: take mechanical default + log needs-review.flowctl memory add --track <t> --category <c> --title "..." --body-file <tmpfile> per classified entry. Slug uniqueness handled by existing helper..flow/memory/_migrated/<filename>.bak. Autofix: default-decline + surface as recommendation. On first cleanup, write .flow/memory/_migrated/.gitignore containing * (self-ignoring directory pattern). Legacy originals are renamed, never deleted — a run that removed a legacy file has broken this.The full report is the deliverable — print it as markdown to stdout. Do not summarize internally and emit a one-liner.
The report's exact shape lives in one place — workflow.md §3.2 (summary skeleton) and §3.3 (the autofix Applied / Recommended split). Render it from there; this file does not restate it.
What the report must carry either way: files processed, entries migrated, overrides, needs-review, plus per-entry detail (id, source filename, mechanical default, final classification, override rationale) and, for each needs-review entry, why the agent could not decide.
Done when: the full report reached stdout as markdown. A run that summarized internally and emitted a one-liner has broken this.
Other measured skills in the registry, with their headline benchmark lift.