[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M71BMYCPSDC2AKW03HW0VPEY":3,"skill-same:01M71BMYCPSDC2AKW03HW0VPEY":119},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":29,"publishedAt":50,"linkOnly":51,"markdownContent":52,"markdownBody":53,"frontMatter":54,"refName":68,"commitSha":69,"skillDirectory":70,"forksCount":71,"repositoryHtmlUrl":72,"repositoryHomepageUrl":73,"ownerHtmlUrl":74,"ownerBlogUrl":6,"ownerDescription":75,"updatedAt":76,"install":77,"resources":90},"01M71BMYCPSDC2AKW03HW0VPEY","unikit-memory",null,"Curate the project's knowledge base and memory in .unikit\u002Fmemory\u002F — the indexed reference library of coding standards and framework usage patterns. ALWAYS use this skill whenever the user adds knowledge from a source: a URL, a file, a folder path, a PDF, an article, or a book — any path\u002Flink\u002Fdocument is a strong signal for the knowledge base, not a quick rule. Also use it to research or document how the project uses a framework, or to add a researched core\u002Fstack knowledge entry. Sub-commands by phrasing: \"migrate the rules\" or \"promote rules\" runs migrate-rules; \"optimize the knowledge base\" or \"optimize the rules\" runs optimise (extract large sections into references); \"validate\" re-syncs RULES_INDEX.md; \"--module \u003Cid>\" targets a module. For a quick one-line convention or correction typed as a prompt (\"always do X\", \"never use Y\", \"remember this\") with no source, use \u002Funikit-rules; for architecture decisions use ARCHITECTURE.md and its topics.","NintendaDev\u002Funikit-ai","NintendaDev","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F181320258?v=4","01M71BFH8JJ6EBGRXBWRZK894Y","Dmitrii Vasilev","01M71BFH9T4K66TTBFNV1ZWFN5",22,"MIT","https:\u002F\u002Fgithub.com\u002FNintendaDev\u002Funikit-ai\u002Fblob\u002Fmain\u002Fskills\u002Funikit-memory\u002FSKILL.md",[18,23,26],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000002","文档处理","SCENARIO","使用场景",{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000021","资料检索与研究",{"categoryNo":27,"categoryName":28,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",[30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49],"memory","unikit memory","coding","library","registry","paths","edit","write","read","how","stack","knowledge base","architecture","migrate","URL","knowledge","re","project","PDF","quick","2026-11-10 10:12:30",false,"---\nname: unikit-memory\ndescription: >-\n  Curate the project's knowledge base and memory in .unikit\u002Fmemory\u002F — the indexed\n  reference library of coding standards and framework usage patterns. ALWAYS use this\n  skill whenever the user adds knowledge from a source: a URL, a file, a folder path, a\n  PDF, an article, or a book — any path\u002Flink\u002Fdocument is a strong signal for the knowledge\n  base, not a quick rule. Also use it to research or document how the project uses a\n  framework, or to add a researched core\u002Fstack knowledge entry. Sub-commands by phrasing:\n  \"migrate the rules\" or \"promote rules\" runs migrate-rules; \"optimize the knowledge base\"\n  or \"optimize the rules\" runs optimise (extract large sections into references);\n  \"validate\" re-syncs RULES_INDEX.md; \"--module \u003Cid>\" targets a module. For a quick\n  one-line convention or correction typed as a prompt (\"always do X\", \"never use Y\",\n  \"remember this\") with no source, use \u002Funikit-rules; for architecture decisions use\n  ARCHITECTURE.md and its topics.\nargument-hint: \"[description | URL(s) | file\u002Ffolder | PDF\u002FFb2\u002FEpub paths | migrate-rules | optimise | validate | --module \u003Cid> | --skip-registry ]\"\nallowed-tools:\n  - Read\n  - Write\n  - Edit\n  - Glob\n  - Grep\n  - Bash\n  - Agent\n  - Skill\n  - WebFetch\n  - WebSearch\n  - AskUserQuestion\n---\n\n# UniKit Rules — Project Knowledge Base Router\n\nManage project rules in `.unikit\u002Fmemory\u002F`. This skill is a **module-agnostic router**:\nthe knowledge base is partitioned into top-level **modules** (laid out on disk as\n`.unikit\u002Fmemory\u002F\u003Cmodule>\u002F\u003Ctier>`), and this skill resolves which module a request\ntargets, loads that module's **contract**, and then drives the generic\nadd\u002Fresearch\u002Fmigrate\u002Fvalidate workflows against the module's tiers.\n\nThe list of registered modules and their structural fields (`tiers`,\n`enginePartitioned`, `skillPrefix`) comes from `.unikit\u002Fsystem\u002Fmodules.yml`. Each\nmodule's content semantics, file format, and path conventions come from its\ncontract file `{{skills_dir}}\u002F{{self_name}}\u002Freferences\u002Fmodule-\u003Cid>.md`.\n\nTwo modules are registered today: **`code`** (tiers `core` + `stack`) and\n**`gamedesign`** (tiers `core` + `library`) — read the live list from `modules.yml`,\nnever from this paragraph. The router is written so additional modules can be\nregistered later with no change to this file — only a new `modules.yml` entry and a\nnew `module-\u003Cid>.md` contract.\n\n**User questions.** Right before your first question to the user, not earlier, read `.unikit\u002Fsystem\u002Fuser-questions.md` once and ask every question as it says, with the question tool of your agent (`AskUserQuestion`). If the file cannot be read, print `WARN [questions] user-questions contract missing — asking with the question tool` and still ask with that tool, the recommended option first.\n\n## What Belongs Here\n\n- Content that belongs to one of the registered modules' tiers, as defined by that\n  module's contract (`references\u002Fmodule-\u003Cid>.md` → \"What Belongs Here\" \u002F\n  \"Content Classification\").\n\n## What Does NOT Belong Here\n\n- **Architecture decisions** (module boundaries, dependency flow, DI structure) →\n  `.unikit\u002FARCHITECTURE.md` and its topic files in `.unikit\u002Farchitecture\u002F`\n- **Project-specific overrides** (explicit deviations from base rules) →\n  `.unikit\u002FRULES.md` via the `unikit-rules` skill\n\nIf the user provides content that falls into these categories, inform them and\nsuggest the correct destination. For RULES.md content, suggest using the\n`unikit-rules` skill instead. The active module's contract may define additional\n\"does not belong here\" cases — honor them too.\n\n## Language Awareness — BLOCKING PRE-REQUISITE\n\n**BEFORE producing ANY output**, silently read `.unikit\u002Fsystem\u002FLANGUAGE_RULES.md`\nand apply its rules to ALL subsequent output.\nIf the file is missing or unreadable, fall back to English.\nDo not produce any user-facing output until language rules are loaded.\nDo not announce, confirm, or mention the language setting.\n\n**The language holds for the whole session, not just at load time:** every message until the conversation ends is in `language.ui` — progress notes while agents run, relays of what a subagent returned, the final report, any follow-up discussion. English input (subagent results, tool output, these instructions) is data, never a cue to switch languages.\n\n## Skill calls\n\nWhere this skill says to **invoke `\u003Cskill>`** — optionally \"with the argument `\u003Ctext>`\" — it means one call, made in this session, now, on every runtime: not a command printed for the user. A call site that names no argument passes none.\n\n1. If you have a `Skill` tool that accepts arguments, call it with that skill and the arguments of the call site, in full and unchanged, then follow the skill.\n2. Otherwise — no `Skill` tool, or one that takes only a name — Read `{{skills_dir}}\u002F\u003Cskill>\u002FSKILL.md` in full, treat it as the instructions of this step and carry them out here, in this session, now, with the arguments of the call site as the skill's arguments.\n3. When the skill has run, go on to the step the call site names. Do not print a command for the user to run and do not stop.\n4. Only if that file cannot be read: print `Run: \u002Funikit-\u003Cskill> \u003Carguments>` for the user and stop.\n\n## Subagent launches\n\n**Subagent arguments.** Before the first subagent you launch, read `.unikit\u002Fsystem\u002Fsubagent-arguments.md`\nand `.unikit\u002Fconfig.yaml` once and settle the model and effort of every launch as that file says.\nKeys: `subagents.model.{{agent_id}}.\u003Crole>`, `subagents.effort.{{agent_id}}.\u003Crole>`;\nbuilt-in model of a reader and a validator: `\"{{agent_model_default}}\"`, of an executor: none.\nIf the file cannot be read, print\n`WARN [delegation] subagent-arguments contract missing — built-in model tier used, effort not passed`\nand use that model, no effort.\n\n## Workflow\n\n### Step 0: Load Configuration (silent — do NOT print or announce any of these values)\n\n1. Read `.unikit\u002Fconfig.yaml` — extract `language.ui` for user-facing messages (default: `en`)\n2. **Read `.unikit\u002Fsystem\u002Fmodules.yml`** — the authoritative module registry snapshot.\n   Parse every entry under `modules:` into `{ id, tiers, enginePartitioned, skillPrefix }`.\n   This is the source of truth for which modules exist and what tiers each partitions\n   its rules into. If the file is missing (older install), fall back to a single\n   module `code` with tiers `core`, `stack` and surface a `WARN` suggesting\n   `unikit-ai update` to regenerate it.\n3. **Read `.unikit\u002Fskill-context\u002F{{self_name}}\u002FSKILL.md`** — MANDATORY if the file exists.\n\nThis file contains project-specific workflow rules added by `\u002Funikit-skills-context` or `\u002Funikit-evolve`.\nThese rules change how this skill operates (research priorities, cross-check behavior, file format conventions, etc.).\n\n**How to apply skill-context rules:**\n- Treat them as **project-level overrides** for this skill's general instructions\n- When a skill-context rule conflicts with a general rule written in this SKILL.md,\n  **the skill-context rule wins** (more specific context takes priority)\n- When there is no conflict, apply both: general rules from SKILL.md + project rules from skill-context\n- Do NOT ignore skill-context rules even if they seem to contradict this skill's defaults —\n  they exist because the project's experience proved the default insufficient\n\nDo NOT output status messages like \"Язык: X\" or \"Module: X\". Proceed directly to Step 0.5.\n\n### Step 0.5: Resolve the Active Module\n\nDetermine which module this request targets **before** classifying input. Never\nguess silently when the target is ambiguous.\n\n**Resolution policy (in order):**\n\n1. **Explicit `--module \u003Cid>` flag.** Scan `$ARGUMENTS` for `--module \u003Cid>`. If\n   present:\n   - Validate `\u003Cid>` against the ids parsed from `modules.yml`.\n   - Valid → set `moduleId = \u003Cid>`, strip the `--module \u003Cid>` tokens from\n     `$ARGUMENTS`, and skip the remaining resolution steps.\n   - Invalid (no such module) → report the unknown id and the list of registered\n     module ids via the question tool of your agent (`AskUserQuestion`) (options = registered modules), then use the\n     chosen id. Strip the flag tokens regardless.\n     Print the module ids with their one-line domain summaries to the screen as plain\n     markdown first.\n2. **No flag → infer from prompt context.** Match the request (rule content, URL,\n   file path, stated intent) against each registered module's **domain**. The\n   domain of a module is described in its contract file\n   `{{skills_dir}}\u002F{{self_name}}\u002Freferences\u002Fmodule-\u003Cid>.md` (its \"What Belongs\n   Here\" \u002F \"Content Classification\" sections) plus the `modules.yml` metadata. Read\n   the candidate contract files as needed to judge fit.\n3. **Confident single match → use it silently.** If exactly one module's domain\n   plausibly covers the request, set `moduleId` to it and continue without asking.\n   A neutral or code-oriented request when `code` is the only registered module\n   resolves silently to `code`.\n4. **Ambiguity → ALWAYS ask.** If zero modules fit, the content fits none of the\n   registered modules, or two or more modules are plausible, ask the user via\n   the question tool of your agent (`AskUserQuestion`). Options = every registered module id (with a one-line domain\n   summary) + a final \"help me choose — I'll describe what this is\" option. Never\n   fall back to a default module to avoid the question.\n   Print the module ids with their one-line domain summaries to the screen as plain\n   markdown first.\n   - Edge case with a single registered module: a request that is **explicitly not\n     about that module's domain** (and fits no registered module) must still trigger\n     the question — do not dump unrelated content into `code` just because it is the\n     only module.\n\nAfter resolution, the following are fixed for the rest of the run:\n\n- `moduleId` — the resolved module id.\n- `tiers` — that module's ordered tier list from `modules.yml` (for `code`: `core`, `stack`).\n- **Module contract** — read `{{skills_dir}}\u002F{{self_name}}\u002Freferences\u002Fmodule-\u003CmoduleId>.md`\n  now. It defines tier semantics, content classification, scope rules, and all file\n  formats. Apply it throughout the rest of the workflow.\n- **Memory root** — `.unikit\u002Fmemory\u002F\u003CmoduleId>\u002F`.\n- **Tier directories** — `.unikit\u002Fmemory\u002F\u003CmoduleId>\u002F\u003Ctier>\u002F` for each tier.\n- **Index file** — `.unikit\u002Fmemory\u002F\u003CmoduleId>\u002FRULES_INDEX.md`. Read it now for the\n  current index of all rule files in this module.\n\nEverywhere below, `\u003Cmodule>` means `moduleId` and `\u003Ctier>` means one of the resolved\nmodule's tiers. Concrete tier names, the \"what goes in which tier\" decision, and the\nfile-format templates are **always** taken from the module contract — this router\nnever hardcodes them.\n\n\u003C!-- unikit:extension-point:bootstrap -->\n\n### Step 1: Parse Input & Classify Intent\n\nTwo-phase classification determines both input type and user intent.\n\n**Phase A — Input type:**\n\n```\nFirst, strip the already-parsed flags from $ARGUMENTS before classifying input type:\n├── --skip-registry present → Remember skipRegistry=true, strip the flag (absent → false).\n│   The remaining text is classified normally.\n└── (The --module flag, if any, was already stripped in Step 0.5.)\n\nThen classify the (possibly stripped) $ARGUMENTS:\n├── First token is \"optimise\" or \"optimize\" (bare keyword, case-insensitive) → OPTIMISE\n│   (jump to Branch E). Consume the keyword; any remaining text is the optional rule scope\n│   (specific rule names\u002Fids). An empty remainder means \"ask which rules\" — Branch E handles\n│   it. OPTIMISE rewrites no content: it only relocates existing sections into reference files.\n│   NOTE: \"optimise\" is a bare positional keyword matched on the FIRST token (not exact\n│   equality, because it carries an optional scope) — there is NO \"--optimise\" flag form. A\n│   description that genuinely begins with the word \"optimise\" is therefore read as this\n│   intent; ask the user to rephrase if that was not the intent.\n├── Equals \"validate\" (case-insensitive) → VALIDATE INDEX (jump to Branch D)\n├── First token is \"migrate-rules\" (bare keyword) or \"--migrate-rules\" (legacy alias) →\n│   ├── $ARGUMENTS is exactly \"migrate-rules\" or \"--migrate-rules\" (no other text) → MIGRATE RULES (jump to Branch C)\n│   └── $ARGUMENTS has additional text besides the keyword →\n│       Report to user: \"migrate-rules must be used alone without additional arguments.\"\n│       STOP. Do not proceed.\n├── Matches RULES.md path (case-insensitive):\n│   \"RULES.md\", \"rules.md\", \".unikit\u002FRULES.md\",\n│   \".unikit\u002Frules.md\", or any path ending with \u002FRULES.md\n│   → MIGRATE RULES (jump to Branch C)\n├── Contains BOTH http(s):\u002F\u002F tokens AND file extension \u002F path tokens → Mixed input (URL + File)\n├── Starts with http:\u002F\u002F or https:\u002F\u002F → URL input (can be multiple, space-separated)\n├── Ends with a known file extension (.md, .txt, .json, .yaml, .pdf, .fb2, .epub), or\n│   names an existing file OR folder → File input (a folder, a PDF, an EPUB\u002FFB2 book, or\n│   an oversized text file is a LARGE source — see the note below; B.1 routes it through\n│   large-sources.md, not a naive Read)\n├── Has text content → Description input\n└── No arguments → Interactive mode: ask user what to document, then re-classify\n```\n\n**Large sources (folder \u002F PDF \u002F EPUB+FB2 book \u002F oversized file).** When the File-input\nbranch matches a **folder**, a **PDF**, an **EPUB or FB2 book** (`.epub`, `.fb2`,\n`.fb2.zip`), or a text file too large to read in one pass, the RESEARCH pipeline does\n**not** `Read` it naively. The actual gathering is delegated to the large-source workflow\nat `{{skills_dir}}\u002F{{self_name}}\u002Freferences\u002Flarge-sources.md`\n(TOC-first → topic-map → chunk → cleanup), which uses the **probe-gated** Python 3 helper\n`{{skills_dir}}\u002F{{self_name}}\u002Fscripts\u002Fmaterial-prep.py` when a Python 3 interpreter is\navailable and falls back to a manual extraction strategy otherwise. Book formats are\nextracted with the standard library (no new dependencies); **MOBI\u002FAZW is recognized but\nrejected** — ask the user for an EPUB export. Step 1 only *classifies* the input here;\nB.1 (\"File input\") performs the delegation.\n\nThe `--skip-registry` flag is an escape hatch for callers that have already performed a registry lookup at a higher level and do not want this skill to repeat it. When the flag is present, Step 1.5 is bypassed entirely and the skill proceeds directly to content classification (Step 2) and generation.\n\n**Phase B — Determine intent based on input type:**\n\n```\nIntent?\n├── OPTIMISE        → Branch E (always — retroactive reference extraction, no new content)\n├── MIGRATE RULES   → Branch C (always — explicit migration request)\n├── Mixed (URL + File) → RESEARCH (always — both inputs processed together)\n├── URL(s)           → RESEARCH (always — URLs signal delegation)\n├── File\u002FFolder path → RESEARCH (always — user provides source material for analysis)\n├── Description      → Analyze tone ↓\n│   ├── Exploratory  → RESEARCH\n│   └── Concrete     → ADD RULE\n└── Interactive      → Ask user, then re-classify\n```\n\n**Tone signals for Description input:**\n\n| Signal | Intent | Examples |\n|--------|--------|----------|\n| Vague topic, delegation words | **Research** | \"add rules for DOTween\", \"document how we use Addressables\", \"figure out best practices for R3\" |\n| Imperative, specific convention, code examples | **Add Rule** | \"add rule: always use `.SetEase(Ease.OutQuad)`\", \"never use coroutines\", \"use `NonLazy()` for controllers\" |\n\n**Phase C — Detect integration intent (contract-defined):**\n\nIf the active module's contract defines integration-gated tiers, detect\n`integrationIntent` per the contract's \"Integration Intent\" section and store it\nalongside the classified intent to thread into Branch A \u002F Branch B. The `code`\ncontract defines this for its `stack` tier (detection signals T1\u002FT2, plus T3\npost-fetch in the Research pipeline). Modules with no integration-gated tier skip\nthis phase and leave `integrationIntent=false`.\n\n### Step 1.5: Registry-first Lookup\n\n**Always try the registry before generating a rule from scratch.** If a matching rule already exists in the remote catalog, the user gets a vetted version by installing it via CLI — much better than spending tokens generating a local copy that duplicates upstream work.\n\n#### 1.5.1: Read CLI contract\n\nRead `.unikit\u002Fsystem\u002Fcli-contract.md` to confirm available `unikit-ai rules *` commands and exit codes.\n\n#### 1.5.2: Fetch catalog and installed state\n\nRun two CLI commands (sequential is fine). **Always pass `--module \u003CmoduleId>`** —\nthe router already resolved the active module (Step 0.5), and every machine consumer\nsends its `--module` so the CLI returns the stable flat-single form no matter how\nmany modules the registry carries (no-`--module` `rules list` now defaults to **all\nmodules** blocked + a flat-all JSON, which this skill does not want):\n\n```bash\nunikit-ai rules list --module \u003CmoduleId> --json\n```\n```bash\nunikit-ai rules status --module \u003CmoduleId> --json\n```\n\n`rules list --module \u003CmoduleId> --json` returns the flat-single shape\n`{ engine, module, rules: [...] }` — parse `catalog.rules` exactly as before (the\nscoped form carries **no** per-row `module` key, so the parser is unchanged).\n`rules status` **does** accept `--module` (it scopes the reported rows to that\nmodule); pass it so `status.rules[]` is already limited to the active module — no\nclient-side filtering needed.\n\nExit code handling:\n- `rules list` exit 2 (registry chain unreachable) → skip to Step 2 silently, proceed without registry\n- `rules list` exit 1 → **strictly** \"no `.unikit.json`\" (not a UniKit project) → skip to Step 2. Engine-missing is **no longer** exit 1: a valid project whose engine is absent from the registry now exits **0** with an empty `catalog.rules`, which flows normally into Step 2.\n- `rules list` exit 3 (unknown `--module`) → the resolved module id is not registered; report the error and skip to Step 2\n- any other non-zero → report the error and skip to Step 2\n\nParse `rules list --module \u003CmoduleId> --json` into `catalog.rules[]` and `rules status --module \u003CmoduleId> --json` into `status.rules[]`.\n\n#### 1.5.3: Semantic matching\n\nMatch the user's intent against `catalog.rules[]`:\n\n- **Exact id match (case-insensitive):** `\"DOTween\"` → `dotween`\n- **Description match:** `\"tweening library\"` → `dotween` via the `description` field\n- **Synonyms and localized names:** `\"контейнер внедрения зависимостей\"` → `zenject`\n\nCollect 0..N candidates. If N > 1, treat all as possible matches for the user prompt below.\n\n#### 1.5.4: Join with installed state\n\nFor each candidate, look it up in `status.rules[]` by `name` (case-insensitive):\n- **Already installed** → note `source`, `version`, and tier so the prompt can show accurate state.\n- **Not installed** → candidate is offerable as a fresh install.\n\n#### 1.5.5: Decision tree\n\n```\nMatch result?\n├── Exactly 1 match + already installed\n│   → Inform user: \"{name} is already installed (source={source}, v{version})\"\n│   → the question tool of your agent (`AskUserQuestion`): What should we do?\n│   │  Options:\n│   │  1. Leave as is         → STOP\n│   │  2. Edit manually       → Continue to Step 2\n│   │  3. Reinstall from registry → Bash: unikit-ai rules install \u003Cid> --force → STOP\n│\n├── Exactly 1 match + NOT installed\n│   → the question tool of your agent (`AskUserQuestion`): Matching rule \"{name}\" v{version} found in registry. Install it?\n│   │  Options:\n│   │  1. Yes, install from registry  → install path (below)\n│   │  2. Preview before deciding     → preview path (below)\n│   │  3. No, generate a new rule     → Continue to Step 2 (research\u002Fmanual generation)\n│   │\n│   ├── install path:\n│   │   Bash: unikit-ai rules install \u003Cid>\n│   │   → Report \"✓ Installed \u003Cid> from registry\" and STOP. The CLI already\n│   │     regenerates RULES_INDEX.md — no extra sync needed.\n│   │\n│   └── preview path:\n│       Bash: unikit-ai rules show \u003Cid> --module \u003CmoduleId> --references\n│       (rules show is module-agnostic: a bare id that collides across modules\n│        exits 3, so the already-resolved router always scopes with --module)\n│       → Show content to user, then ask again with the question tool of your agent (`AskUserQuestion`):\n│         1. Install → install path above\n│         2. Generate a new rule → Step 2\n│\n├── Multiple matches\n│   → the question tool of your agent (`AskUserQuestion`): present all candidates + a \"none of these, generate a new rule\" option\n│   → If user picks a candidate → treat as \"exactly 1 match\" (installed or not)\n│   → If \"none\" → Continue to Step 2\n│\n└── Zero matches\n    → Continue to Step 2 (research\u002Fmanual generation)\n```\n\n**Key behavior guarantees:**\n- The `Multiple matches` branch prints the candidates (name, version, module) to the screen as plain markdown first.\n- Agreeing to install always ends with `rules install \u003Cid>` and terminates the skill. The content in the registry is the source of truth; the skill does not second-guess it.\n- Declining the registry version always routes to Step 2, where the skill generates the rule from the user's description, URL, or file input as usual. No partial install, no mix of registry + local content.\n\n#### When to skip Step 1.5 entirely\n\nBypass the lookup completely when any of the following is true:\n\n- **`--skip-registry` flag** was present in $ARGUMENTS (a higher-level caller already queried the catalog and does not want redundant prompts)\n- **Intent is VALIDATE INDEX** (Branch D), **MIGRATE RULES** (Branch C), or **OPTIMISE** (Branch E) — none of them installs a new rule, so registry lookup is irrelevant\n- **Input is a file path** — the user explicitly wants to process a specific file, not search the catalog\n- **`cli-contract.md` doesn't exist** — the UniKit CLI is not available in this project, so `rules *` commands cannot be used\n\n---\n\n### Step 2: Classify Content Category\n\nUse the **active module's contract** (`references\u002Fmodule-\u003CmoduleId>.md` →\n\"Content Classification\") to:\n\n1. **Pick the target tier** for the content among the module's tiers, or determine\n   the content belongs to **none** of the module's tiers.\n   - If the content fits none of the tiers, redirect the user to the correct\n     destination named in the contract's \"What Does NOT Belong\" section\n     (architecture → `.unikit\u002FARCHITECTURE.md` and its topic files; project-specific overrides →\n     `.unikit\u002FRULES.md` via `unikit-rules`). **Stop here. Do NOT create any files.**\n   - If the content fits none of the tiers **and** seems to belong to a *different\n     module* than the one resolved in Step 0.5, return to Step 0.5 and re-ask the\n     module question rather than forcing a tier.\n2. **Identify the target file** within the chosen tier, following the contract's\n   filename conventions.\n3. **Check whether the file already exists** under `.unikit\u002Fmemory\u002F\u003Cmodule>\u002F\u003Ctier>\u002F`.\n\n### Step 3: Route by Intent\n\nBased on intent (Step 1) and classification (Step 2), follow the appropriate branch:\n\n```\nIntent?\n├── VALIDATE INDEX → Branch D (inline below; skip Steps 2-3 entirely)\n├── OPTIMISE       → Branch E (inline below; skip Step 2 — it operates on existing rules)\n├── MIGRATE RULES  → read references\u002Fmigrate-rules.md and follow it (skip Step 2)\n├── ADD RULE       → Branch A (inline below)\n└── RESEARCH       → read references\u002Fresearch-pipeline.md and follow it\n```\n\nBranches B (Research) and C (Migrate) are intent-gated and live in dedicated\nreference files loaded relative to this skill\n(`{{skills_dir}}\u002F{{self_name}}\u002Freferences\u002F`): open the matching file only when its\nintent is selected, then return here for the **Final Step: Confirm**. Branch A,\nBranch D, and Branch E stay inline below since they are short and on the common path.\n\n---\n\n## Branch A: Add Rule\n\nThe user has a concrete rule to save. No research, no enrichment — just store what the user explicitly stated.\n\n### A.1: Check Target File\n\n```\nFile exists?\n├── YES → A.2 (Cross-Check & Append)\n└── NO\n    ├── Tier is framework-agnostic (per the module contract, e.g. `code`\u002Fcore) → A.3 (Create File)\n    └── Tier may need research (per the module contract, e.g. `code`\u002Fstack)     → A.4 (Ask About Research)\n```\n\n### A.2: Cross-Check, Gap List & Append (file exists)\n\nBefore appending, compare the new content against existing rules:\n\n1. **Read the target file.**\n2. **Read related files** — scan `RULES_INDEX.md` for files with overlapping keywords, then read those too (across all tiers of the module). Also read `.unikit\u002FRULES.md` for project-specific overrides. **Rule topics:** plus the topic files listed under its `## Topics` whose `Load when` matches the new rule's area; when unsure, load.\n3. **Compare each new rule against existing formulations.** A contradiction is when the new content prescribes something different from an existing rule — e.g., \"use `await` directly\" vs existing \"always wrap in `UniTask.Create`\", or \"bind as Transient\" vs existing \"bind as Singleton\".\n4. **Build the gap list (the default for every update).** Classify the new material against what the file already says, and show the result to the user as the summary of what the update will do:\n   - **Add** — genuinely new rules not yet present in the file.\n   - **Change** — rules that refine or supersede an existing formulation (these are the contradictions resolved below).\n   - **Unchanged** — material the file already covers; skip it, do not restate.\n   This gap-list discipline is the **canonical cross-check\u002Fupdate behaviour** that `research-pipeline.md` B.4 defers to (\"Same logic as A.2\"). It runs on every existing-file update regardless of input.\n\n**If contradictions found:**\n\n- Report **each** contradiction to the user, quoting both the new statement and the existing rule with its source file.\n- For each contradiction, ask via the question tool of your agent (`AskUserQuestion`) (batch up to 3 contradictions per question):\n\n  Options:\n  1. Replace — update existing rule with new formulation\n  2. Keep existing — discard the conflicting part\n  3. Keep both — document both with a note on when each applies\n\n  Based on choice:\n  - Replace → overwrite the existing rule text in the target file with the new formulation\n  - Keep existing → discard the conflicting part from the new content, keep existing rule unchanged\n  - Keep both → add the new rule alongside the existing one with a note clarifying when each applies\n\n**After resolution (or if no contradictions):**\n\n- Apply the gap list: append the **Add** items and apply the **Change** items, merging into the appropriate sections. Skip **Unchanged** material. Do not overwrite useful existing content.\n- → Go to **Final Step: Confirm**\n\n### A.3: Create New File (framework-agnostic tier, no existing file)\n\n1. Create the rule file following the **File Format Template** from the module contract.\n2. Write the user's rule(s) as-is — no enrichment, no synthesis.\n3. Update `RULES_INDEX.md` — add a new row to the appropriate table in alphabetical order.\n4. → Go to **Final Step: Confirm**\n\n### A.4: Ask About Research (research-eligible tier, no existing file)\n\nAsk the user with the question tool of your agent (`AskUserQuestion`): *\"I don't have a rules file for {framework\u002Ftopic} yet. Research this and create a comprehensive document, or save your rule as-is?\"* Options: `Research it` (Recommended) · `Save my rule as-is`.\n\n```\nUser answer?\n├── YES (research) → read references\u002Fresearch-pipeline.md and follow it (start at B.1)\n└── NO (save as-is)\n    ├── Create the rule file with user's rule(s) only\n    ├── Update RULES_INDEX.md — add to the tier's table\n    └── → Go to Final Step: Confirm\n```\n\n---\n\n## Branch B: Research\n\nFull research pipeline — gather material, enrich, synthesize, then write into the\nactive module's tier. The complete workflow (B.1–B.5: gather → integration upgrade →\nContext7 → synthesize → reference candidates → cross-check → write) lives in\n`{{skills_dir}}\u002F{{self_name}}\u002Freferences\u002Fresearch-pipeline.md`. Read that file and\nfollow it, then return here for the **Final Step: Confirm**. All file-format and\nscope decisions in it defer to the module contract.\n\n---\n\n## Branch C: Migrate Rules from RULES.md\n\nTransfer mature entries from `.unikit\u002FRULES.md` (the quick-capture staging area owned\nby `unikit-rules`) into permanent rule files under `.unikit\u002Fmemory\u002F\u003Cmodule>\u002F`. The\ncomplete workflow (C.1–C.4: load → classify → present candidates → rephrase → apply)\nlives in `{{skills_dir}}\u002F{{self_name}}\u002Freferences\u002Fmigrate-rules.md`. Read that file\nand follow it, then return here for the **Final Step: Confirm**.\n\n---\n\n## Branch D: Validate Index\n\nSync `.unikit\u002Fmemory\u002F\u003Cmodule>\u002FRULES_INDEX.md` with the actual files on disk. No user interaction — fully automatic.\n\n### D.1: Scan Actual Files\n\n1. For each `\u003Ctier>` of the resolved module: `Glob: .unikit\u002Fmemory\u002F\u003Cmodule>\u002F\u003Ctier>\u002F*.md` — collect all real rule files in that tier.\n2. Read `.unikit\u002Fmemory\u002F\u003Cmodule>\u002FRULES_INDEX.md` — parse every table (one per tier), extract filenames from each row.\n\n### D.2: Diff\n\nCompare the two sets:\n\n- **Missing from index** — files that exist on disk but have no row in RULES_INDEX.md\n- **Phantom in index** — rows in RULES_INDEX.md whose files don't exist on disk\n\n### D.3: Fix Index\n\n**For each missing file** — read the file, extract the `> **Scope**:` and `> **Load when**:` lines from the header. Add a row to the appropriate tier's table in RULES_INDEX.md (alphabetical order), following the contract's \"RULES_INDEX.md Format\":\n\n```\n| {FILENAME}.md | {Scope value} | {Load when value} |\n```\n\nIf the file has no Scope\u002FLoad when header, use the first heading and first paragraph to generate a brief description and keywords.\n\n**For each phantom entry** — remove the row from RULES_INDEX.md using `Edit`.\n\n### D.4: Report\n\nOutput a short validation report (in user's configured language):\n\n```\nRULES_INDEX.md validation complete.\n\n{per-tier counts, e.g. Core: {N} files, Stack: {M} files}\n✅ Added to index: {X}\n🔄 Removed from index: {Y}\n\n{If X > 0: list added filenames}\n{If Y > 0: list removed filenames}\n```\n\nStop. Do not proceed to any other step.\n\n---\n\n## Branch E: Optimise (retroactive reference extraction)\n\nRetroactively shrink **existing** rules by moving their large\u002Foptional sections into\nreference files — the same outcome the on-add reference step (B.3.5) produces,\napplied after the fact. Branch E **synthesizes no new content**: it relocates text\nthat already lives in a rule, so a rule that grew too long (e.g. a distilled book\nthat landed entirely inline) becomes a lean conceptual rule plus on-demand\nreferences. The active `\u003Cmodule>` and its `\u003Ctier>`s were already resolved in Step\n0.5; the module contract's **Candidate Analyzer** is the engine.\n\nThis branch is **non-destructive**: content **moves**, it is never deleted, every\nproposal is confirmed before writing, and it leans on git as the safety net. It does\nnot touch the registry, `src\u002F`, or the helper script.\n\n### E.1: Determine scope\n\nParse the rule scope from the remaining `$ARGUMENTS` (after the `optimise` keyword was\nconsumed in Phase A):\n\n- **Named rules present** (e.g. `optimise dotween zenject`) → that is the scope.\n  Resolve each name to a file under `.unikit\u002Fmemory\u002F\u003Cmodule>\u002F\u003Ctier>\u002F` (match against\n  `RULES_INDEX.md`; ask if a name is ambiguous).\n- **No names** → the question tool of your agent (`AskUserQuestion`):\n\n  Options:\n  1. Specific rules — I'll name them → ask which, then resolve as above\n  2. All rules in this module → scope = every rule file across the module's tiers\n\nWhatever the scope, **process the rules in batches of 2-3 at a time** — analyze,\npresent, confirm, and write one batch before moving to the next. This keeps each\nconfirmation focused and the diff reviewable.\n\n### E.2: Analyze each rule\n\nFor each rule in the current batch:\n\n1. Read the rule file.\n2. Run the module contract's **Candidate Analyzer** (\"Reference Candidate\n   Extraction\") over its sections: score each block on **size** (≳ 40 lines \u002F ≳ 1500\n   chars), **optionality**, and **lookup shape**, and sort candidates into **Tier 1**\n   (clear wins) and **Tier 2** (borderline).\n3. Run the **merge guard** (`research-pipeline.md` B.3.5): before proposing any new\n   reference file, scan the tier's existing `references\u002F` for a file that already\n   covers the topic and target it instead of forking a near-duplicate.\n\n### E.3: Present and confirm\n\nPresent the candidates per rule, grouped into **Tier 1** and **Tier 2** (each with\nwhich signals fired and the target\n`.unikit\u002Fmemory\u002F\u003Cmodule>\u002F\u003Ctier>\u002Freferences\u002F{file}.md`), then ask with the question tool of your agent (`AskUserQuestion`)\nexactly as B.3.5 does:\n\nOptions:\n1. Extract **Tier 1 only**\n2. Extract **Tier 1 + Tier 2**\n3. Adjust — rename \u002F merge \u002F split \u002F drop, or move a block between tiers → revise and ask again\n4. None — leave this rule unchanged\n\n**Always report the result, including \"0 candidates\"** for a rule that is already\nlean — Branch E must say so rather than silently skip it.\n\n### E.4: Move the content (never delete)\n\nFor each approved candidate:\n\n1. **Write the reference file** following the contract's **Reference File Format**\n   (create new, or update the existing matching file per the merge guard).\n2. **Cut** the moved section from the main rule — the content is relocated, not\n   duplicated. Leave the conceptual rules intact.\n3. Add the file to the main rule's `> **References**:` header line and add\u002Fextend a\n   `## {Content} Lookup Workflow` section telling the LLM when to open it. The main\n   rule keeps only pointers, not the moved data.\n\nReference files are not indexed in `RULES_INDEX.md` (only main rules are); the main\nrule's row is unchanged unless its Scope\u002FLoad when changed (they should not).\n\n### E.5: Finish\n\nAfter the last batch, go to the **Final Step: Confirm** — it runs `unikit-ai rules\nsync` (reconciling the moved files into `.unikit.json` state and regenerating\n`RULES_INDEX.md`) and prints the report. The Quality Gate runs in **structural-only**\nmode for Branch E (no synthesis to grade — see the Quality Gate section).\n\n---\n\n## File Formats\n\nAll file-format specifications — the **File Format Template** (rule files, with\n`Scope`\u002F`Load when` prose guidance), the **Reference File Format**, the\n**Reference Candidate Extraction** strategies, and the **RULES_INDEX.md Format** —\nlive in the active module's contract:\n`{{skills_dir}}\u002F{{self_name}}\u002Freferences\u002Fmodule-\u003CmoduleId>.md`.\n\nAlways read the contract for the resolved module and follow its formats exactly.\nThis router intentionally does not restate them, so a new module can define its own\nconventions without touching this file.\n\n## Quality Gate (run before the Final Step)\n\nA cheap, automatic self-check that runs **after a branch finishes writing** and\n**before** the Final Step report. It is gated by intent: run it only for **ADD RULE**\n(Branch A, including the existing-file update path), **RESEARCH** (Branch B), and\n**OPTIMISE** (Branch E — **structural checks only**, since it synthesizes no new\ncontent; see below). **Skip it entirely** for **MIGRATE RULES** (Branch C), **VALIDATE\nINDEX** (Branch D — it already exited and never reaches here), and the Step 1.5\ninstall-from-registry short-circuit — none of those produce freshly synthesized\ncontent to grade (Migrate rephrases existing entries, Validate only reconciles the\nindex, an install pulls a vetted upstream file). This is a checklist, not a new\napproval prompt: run it silently and only surface a ⚠️ line if a check fails.\n\n**Always check (every gated write — cheap structural checks):**\n\n- The rule file carries a `> **Scope**:` and a `> **Load when**:` line, both written as\n  **prose** (not a bare dump of identifiers), per the module contract.\n- No placeholder leak — no `{Framework Name}`, `{Section 1}`, `TODO`, or other template\n  scaffolding survived into the written file.\n- `RULES_INDEX.md` has a row for the file (new files only).\n\n**For Branch E (Optimise)** these structural checks apply to the *relocation*: the\noptimised main rule still carries its `> **Scope**:` \u002F `> **Load when**:` lines, no\nplaceholder scaffolding leaked into the moved content or the new `## {Content} Lookup\nWorkflow`, and each created reference is wired into the main rule's `> **References**:`\nline. Reference files are not indexed, so the `RULES_INDEX.md` row check covers main\nrules only. Branch E runs **none** of the synthesis checks below.\n\n**Additionally — only when the branch actually synthesized content**, i.e. **Branch B\n(Research)** or **Branch A → A.4 with research**. Do **not** run these on the as-is\npaths (A.2 cross-check-append, A.3 create-as-is, A.4 save-as-is) or **Branch E\n(Optimise)** — those write the user's exact words (or merely relocate existing text)\nwith no synthesis, so there is no coverage or distillation to grade:\n\n- **Example coverage (#2)** — the major code-facing topics the rule raises are each\n  illustrated by an example (or explicitly waived with a stated reason), per the\n  example inventory from `research-pipeline.md` B.3. Many topics raised + only one or\n  two examples shown = fail. \"Example\" means whatever the active module contract\n  defines (code snippets for `code`; numeric tables \u002F worked formulas for `gamedesign`).\n- **Distilled, not copied (#8)** — no long verbatim source passages; guidance is\n  rewritten as actionable rules; any code snippets are original.\n- **Source Map (#6)** — when the rule was built from sources, the Source Inventory was\n  persisted into the rule file per the module contract's Source Map \u002F provenance format.\n\nIf any check fails, fix the written file before the Final Step report (or, when a\ncoverage gap is intentional, record the reason in the rule). Then continue to the\nFinal Step.\n\n## Final Step: Confirm\n\n**First, run the Quality Gate above** (ADD RULE \u002F RESEARCH \u002F OPTIMISE — structural-only\nfor Optimise; skip for Migrate, Validate, and the install short-circuit), then produce\nthe report below.\n\n\n\n**Reconcile `.unikit.json` state with disk (after Branch A \u002F B \u002F C \u002F E only):**\n\nIf the just-completed branch was **Branch A** (Add Rule), **Branch B** (Research), **Branch C** (Migrate Rules), or **Branch E** (Optimise) — i.e. anything that wrote a new or updated rule\u002Freference file into `.unikit\u002Fmemory\u002F\u003Cmodule>\u002F` — run the CLI sync command so the generated file is registered in `.unikit.json.rules.installed` and `RULES_INDEX.md` is regenerated from authoritative state + disk:\n\n```bash\nunikit-ai rules sync\n```\n\nWhy this matters: Branches A\u002FB\u002FC write files via `Write`\u002F`Edit` directly and never touch `.unikit.json`. Without a sync pass, the new rule lives on disk but remains invisible to `rules status`, `rules install \u003Cid> --force`, and — most importantly — to `\u002Funikit` Step 9.3, which builds its \"already installed\" set from `.unikit.json` state. Skipping sync here means the next `\u002Funikit` run can try to reinstall the same rule from the registry and fail with exit 4 (\"already installed\"). `syncRulesState` Phase 1 picks up untracked `.unikit\u002Fmemory\u002F**\u002F*.md` files and registers them as `source: local` entries; Phase 3 regenerates `RULES_INDEX.md`. That is exactly the reconciliation the skill needs before printing the report.\n\nTreat a non-zero exit code as non-fatal for the skill: log the CLI output to the report and continue. The file is still on disk — the user can re-run `unikit-ai rules sync` manually.\n\n**Skip the sync entirely when:**\n- The branch was **Branch D** (Validate Index) — Branch D already exited with `Stop. Do not proceed to any other step.` and never reaches this Final Step at all.\n- An install-from-registry short-circuit ran in Step 1.5 — `rules install` already updated state and regenerated the index, and the short-circuit terminates the skill before reaching Final Step.\n\n**Report to the user (in their configured language):**\n- Which module was targeted and which file was created or updated\n- Summary of what was added or moved (Optimise: which sections were relocated into which reference files)\n- Which branch was used (Add Rule \u002F Research \u002F Optimise)\n- Whether Context7 enrichment was applied (Research branch only)\n- Whether `.unikit.json` state was reconciled via `rules sync` (and whether the index was regenerated)\n- Whether RULES_INDEX.md was updated\n- If any content was redirected elsewhere (architecture, RULES.md)\n\n**Offer rules-registry promotion (after Branch A \u002F B \u002F C \u002F E only):**\n\nIf the just-completed branch was **Branch A** (Add Rule), **Branch B** (Research), **Branch C** (Migrate Rules), or **Branch E** (Optimise) — i.e. anything that actually wrote into `.unikit\u002Fmemory\u002F\u003Cmodule>\u002F` — check whether the project's registry is local:\n\n```bash\nunikit-ai rules registry show --json\n```\n\nParse the JSON. If `.kind == \"local\"`, ask the user whether to promote the memory changes into the registry **now** via the question tool of your agent (`AskUserQuestion`):\n\n```\nThe question tool of your agent (`AskUserQuestion`): A local rules registry is configured at \u003C.url from the JSON>.\nPromote the memory changes into the registry now by running \u002Funikit-rules-registry update?\n\nOptions:\n1. Yes — run \u002Funikit-rules-registry update after the Final Step report\n2. No  — skip promotion, keep the changes in memory only\n```\n\n- **Yes** → finish the Final Step report first (the user must see exactly what changed in memory before promotion), then invoke `unikit-rules-registry` with the argument `update` (`## Skill calls`). Do not collapse the memory report into the promotion run — they are separate, ordered events.\n- **No** → finish the Final Step report without adding any promotion hint. The user can always run `\u002Funikit-rules-registry update` manually later; do not repeat the question or nag on the next invocation.\n\nSkip the question entirely (do not ask, do not print a fallback hint) when:\n- The branch was **Branch D** (Validate Index) — no memory writes happened.\n- An install-from-registry short-circuit ran in Step 1.5 — the registry is already the source of truth for that rule.\n- `rules registry show --json` returned a non-zero exit code or `.kind` is not `\"local\"`.\n\n## Access Rules\n\n**Writable** (this skill can create and edit, for the resolved module):\n- `.unikit\u002Fmemory\u002F\u003Cmodule>\u002F\u003Ctier>\u002F` — rule files in each of the module's tiers\n- `.unikit\u002Fmemory\u002F\u003Cmodule>\u002F\u003Ctier>\u002Freferences\u002F` — supplementary reference docs, where the module contract allows them\n- `.unikit\u002Fmemory\u002F\u003Cmodule>\u002FRULES_INDEX.md` — index of all rule files in the module\n\n**Writable only during Branch C (Migrate Rules):**\n- `.unikit\u002FRULES.md` and its topic files in `.unikit\u002Frules\u002F` — removal of migrated entries only, plus two named edits: the `\u003C!-- @no-migrate -->` tag of Keep, and the deletion of a topic file that migration emptied, together with its `## Topics` row; adding new entries goes through `unikit-rules` skill\n\n**Read-only** (this skill must NEVER modify these files):\n- `.unikit\u002Fconfig.yaml` — project settings (language). Read-only for this skill.\n- `.unikit\u002Fsystem\u002Fmodules.yml` — module registry snapshot. Generated by `unikit-ai`; read-only here.\n- `{{skills_dir}}\u002F{{self_name}}\u002Freferences\u002Fmodule-\u003Cid>.md` — module contracts. Read-only here.\n","# UniKit Rules — Project Knowledge Base Router\n\nManage project rules in `.unikit\u002Fmemory\u002F`. This skill is a **module-agnostic router**:\nthe knowledge base is partitioned into top-level **modules** (laid out on disk as\n`.unikit\u002Fmemory\u002F\u003Cmodule>\u002F\u003Ctier>`), and this skill resolves which module a request\ntargets, loads that module's **contract**, and then drives the generic\nadd\u002Fresearch\u002Fmigrate\u002Fvalidate workflows against the module's tiers.\n\nThe list of registered modules and their structural fields (`tiers`,\n`enginePartitioned`, `skillPrefix`) comes from `.unikit\u002Fsystem\u002Fmodules.yml`. Each\nmodule's content semantics, file format, and path conventions come from its\ncontract file `{{skills_dir}}\u002F{{self_name}}\u002Freferences\u002Fmodule-\u003Cid>.md`.\n\nTwo modules are registered today: **`code`** (tiers `core` + `stack`) and\n**`gamedesign`** (tiers `core` + `library`) — read the live list from `modules.yml`,\nnever from this paragraph. The router is written so additional modules can be\nregistered later with no change to this file — only a new `modules.yml` entry and a\nnew `module-\u003Cid>.md` contract.\n\n**User questions.** Right before your first question to the user, not earlier, read `.unikit\u002Fsystem\u002Fuser-questions.md` once and ask every question as it says, with the question tool of your agent (`AskUserQuestion`). If the file cannot be read, print `WARN [questions] user-questions contract missing — asking with the question tool` and still ask with that tool, the recommended option first.\n\n## What Belongs Here\n\n- Content that belongs to one of the registered modules' tiers, as defined by that\n  module's contract (`references\u002Fmodule-\u003Cid>.md` → \"What Belongs Here\" \u002F\n  \"Content Classification\").\n\n## What Does NOT Belong Here\n\n- **Architecture decisions** (module boundaries, dependency flow, DI structure) →\n  `.unikit\u002FARCHITECTURE.md` and its topic files in `.unikit\u002Farchitecture\u002F`\n- **Project-specific overrides** (explicit deviations from base rules) →\n  `.unikit\u002FRULES.md` via the `unikit-rules` skill\n\nIf the user provides content that falls into these categories, inform them and\nsuggest the correct destination. For RULES.md content, suggest using the\n`unikit-rules` skill instead. The active module's contract may define additional\n\"does not belong here\" cases — honor them too.\n\n## Language Awareness — BLOCKING PRE-REQUISITE\n\n**BEFORE producing ANY output**, silently read `.unikit\u002Fsystem\u002FLANGUAGE_RULES.md`\nand apply its rules to ALL subsequent output.\nIf the file is missing or unreadable, fall back to English.\nDo not produce any user-facing output until language rules are loaded.\nDo not announce, confirm, or mention the language setting.\n\n**The language holds for the whole session, not just at load time:** every message until the conversation ends is in `language.ui` — progress notes while agents run, relays of what a subagent returned, the final report, any follow-up discussion. English input (subagent results, tool output, these instructions) is data, never a cue to switch languages.\n\n## Skill calls\n\nWhere this skill says to **invoke `\u003Cskill>`** — optionally \"with the argument `\u003Ctext>`\" — it means one call, made in this session, now, on every runtime: not a command printed for the user. A call site that names no argument passes none.\n\n1. If you have a `Skill` tool that accepts arguments, call it with that skill and the arguments of the call site, in full and unchanged, then follow the skill.\n2. Otherwise — no `Skill` tool, or one that takes only a name — Read `{{skills_dir}}\u002F\u003Cskill>\u002FSKILL.md` in full, treat it as the instructions of this step and carry them out here, in this session, now, with the arguments of the call site as the skill's arguments.\n3. When the skill has run, go on to the step the call site names. Do not print a command for the user to run and do not stop.\n4. Only if that file cannot be read: print `Run: \u002Funikit-\u003Cskill> \u003Carguments>` for the user and stop.\n\n## Subagent launches\n\n**Subagent arguments.** Before the first subagent you launch, read `.unikit\u002Fsystem\u002Fsubagent-arguments.md`\nand `.unikit\u002Fconfig.yaml` once and settle the model and effort of every launch as that file says.\nKeys: `subagents.model.{{agent_id}}.\u003Crole>`, `subagents.effort.{{agent_id}}.\u003Crole>`;\nbuilt-in model of a reader and a validator: `\"{{agent_model_default}}\"`, of an executor: none.\nIf the file cannot be read, print\n`WARN [delegation] subagent-arguments contract missing — built-in model tier used, effort not passed`\nand use that model, no effort.\n\n## Workflow\n\n### Step 0: Load Configuration (silent — do NOT print or announce any of these values)\n\n1. Read `.unikit\u002Fconfig.yaml` — extract `language.ui` for user-facing messages (default: `en`)\n2. **Read `.unikit\u002Fsystem\u002Fmodules.yml`** — the authoritative module registry snapshot.\n   Parse every entry under `modules:` into `{ id, tiers, enginePartitioned, skillPrefix }`.\n   This is the source of truth for which modules exist and what tiers each partitions\n   its rules into. If the file is missing (older install), fall back to a single\n   module `code` with tiers `core`, `stack` and surface a `WARN` suggesting\n   `unikit-ai update` to regenerate it.\n3. **Read `.unikit\u002Fskill-context\u002F{{self_name}}\u002FSKILL.md`** — MANDATORY if the file exists.\n\nThis file contains project-specific workflow rules added by `\u002Funikit-skills-context` or `\u002Funikit-evolve`.\nThese rules change how this skill operates (research priorities, cross-check behavior, file format conventions, etc.).\n\n**How to apply skill-context rules:**\n- Treat them as **project-level overrides** for this skill's general instructions\n- When a skill-context rule conflicts with a general rule written in this SKILL.md,\n  **the skill-context rule wins** (more specific context takes priority)\n- When there is no conflict, apply both: general rules from SKILL.md + project rules from skill-context\n- Do NOT ignore skill-context rules even if they seem to contradict this skill's defaults —\n  they exist because the project's experience proved the default insufficient\n\nDo NOT output status messages like \"Язык: X\" or \"Module: X\". Proceed directly to Step 0.5.\n\n### Step 0.5: Resolve the Active Module\n\nDetermine which module this request targets **before** classifying input. Never\nguess silently when the target is ambiguous.\n\n**Resolution policy (in order):**\n\n1. **Explicit `--module \u003Cid>` flag.** Scan `$ARGUMENTS` for `--module \u003Cid>`. If\n   present:\n   - Validate `\u003Cid>` against the ids parsed from `modules.yml`.\n   - Valid → set `moduleId = \u003Cid>`, strip the `--module \u003Cid>` tokens from\n     `$ARGUMENTS`, and skip the remaining resolution steps.\n   - Invalid (no such module) → report the unknown id and the list of registered\n     module ids via the question tool of your agent (`AskUserQuestion`) (options = registered modules), then use the\n     chosen id. Strip the flag tokens regardless.\n     Print the module ids with their one-line domain summaries to the screen as plain\n     markdown first.\n2. **No flag → infer from prompt context.** Match the request (rule content, URL,\n   file path, stated intent) against each registered module's **domain**. The\n   domain of a module is described in its contract file\n   `{{skills_dir}}\u002F{{self_name}}\u002Freferences\u002Fmodule-\u003Cid>.md` (its \"What Belongs\n   Here\" \u002F \"Content Classification\" sections) plus the `modules.yml` metadata. Read\n   the candidate contract files as needed to judge fit.\n3. **Confident single match → use it silently.** If exactly one module's domain\n   plausibly covers the request, set `moduleId` to it and continue without asking.\n   A neutral or code-oriented request when `code` is the only registered module\n   resolves silently to `code`.\n4. **Ambiguity → ALWAYS ask.** If zero modules fit, the content fits none of the\n   registered modules, or two or more modules are plausible, ask the user via\n   the question tool of your agent (`AskUserQuestion`). Options = every registered module id (with a one-line domain\n   summary) + a final \"help me choose — I'll describe what this is\" option. Never\n   fall back to a default module to avoid the question.\n   Print the module ids with their one-line domain summaries to the screen as plain\n   markdown first.\n   - Edge case with a single registered module: a request that is **explicitly not\n     about that module's domain** (and fits no registered module) must still trigger\n     the question — do not dump unrelated content into `code` just because it is the\n     only module.\n\nAfter resolution, the following are fixed for the rest of the run:\n\n- `moduleId` — the resolved module id.\n- `tiers` — that module's ordered tier list from `modules.yml` (for `code`: `core`, `stack`).\n- **Module contract** — read `{{skills_dir}}\u002F{{self_name}}\u002Freferences\u002Fmodule-\u003CmoduleId>.md`\n  now. It defines tier semantics, content classification, scope rules, and all file\n  formats. Apply it throughout the rest of the workflow.\n- **Memory root** — `.unikit\u002Fmemory\u002F\u003CmoduleId>\u002F`.\n- **Tier directories** — `.unikit\u002Fmemory\u002F\u003CmoduleId>\u002F\u003Ctier>\u002F` for each tier.\n- **Index file** — `.unikit\u002Fmemory\u002F\u003CmoduleId>\u002FRULES_INDEX.md`. Read it now for the\n  current index of all rule files in this module.\n\nEverywhere below, `\u003Cmodule>` means `moduleId` and `\u003Ctier>` means one of the resolved\nmodule's tiers. Concrete tier names, the \"what goes in which tier\" decision, and the\nfile-format templates are **always** taken from the module contract — this router\nnever hardcodes them.\n\n\u003C!-- unikit:extension-point:bootstrap -->\n\n### Step 1: Parse Input & Classify Intent\n\nTwo-phase classification determines both input type and user intent.\n\n**Phase A — Input type:**\n\n```\nFirst, strip the already-parsed flags from $ARGUMENTS before classifying input type:\n├── --skip-registry present → Remember skipRegistry=true, strip the flag (absent → false).\n│   The remaining text is classified normally.\n└── (The --module flag, if any, was already stripped in Step 0.5.)\n\nThen classify the (possibly stripped) $ARGUMENTS:\n├── First token is \"optimise\" or \"optimize\" (bare keyword, case-insensitive) → OPTIMISE\n│   (jump to Branch E). Consume the keyword; any remaining text is the optional rule scope\n│   (specific rule names\u002Fids). An empty remainder means \"ask which rules\" — Branch E handles\n│   it. OPTIMISE rewrites no content: it only relocates existing sections into reference files.\n│   NOTE: \"optimise\" is a bare positional keyword matched on the FIRST token (not exact\n│   equality, because it carries an optional scope) — there is NO \"--optimise\" flag form. A\n│   description that genuinely begins with the word \"optimise\" is therefore read as this\n│   intent; ask the user to rephrase if that was not the intent.\n├── Equals \"validate\" (case-insensitive) → VALIDATE INDEX (jump to Branch D)\n├── First token is \"migrate-rules\" (bare keyword) or \"--migrate-rules\" (legacy alias) →\n│   ├── $ARGUMENTS is exactly \"migrate-rules\" or \"--migrate-rules\" (no other text) → MIGRATE RULES (jump to Branch C)\n│   └── $ARGUMENTS has additional text besides the keyword →\n│       Report to user: \"migrate-rules must be used alone without additional arguments.\"\n│       STOP. Do not proceed.\n├── Matches RULES.md path (case-insensitive):\n│   \"RULES.md\", \"rules.md\", \".unikit\u002FRULES.md\",\n│   \".unikit\u002Frules.md\", or any path ending with \u002FRULES.md\n│   → MIGRATE RULES (jump to Branch C)\n├── Contains BOTH http(s):\u002F\u002F tokens AND file extension \u002F path tokens → Mixed input (URL + File)\n├── Starts with http:\u002F\u002F or https:\u002F\u002F → URL input (can be multiple, space-separated)\n├── Ends with a known file extension (.md, .txt, .json, .yaml, .pdf, .fb2, .epub), or\n│   names an existing file OR folder → File input (a folder, a PDF, an EPUB\u002FFB2 book, or\n│   an oversized text file is a LARGE source — see the note below; B.1 routes it through\n│   large-sources.md, not a naive Read)\n├── Has text content → Description input\n└── No arguments → Interactive mode: ask user what to document, then re-classify\n```\n\n**Large sources (folder \u002F PDF \u002F EPUB+FB2 book \u002F oversized file).** When the File-input\nbranch matches a **folder**, a **PDF**, an **EPUB or FB2 book** (`.epub`, `.fb2`,\n`.fb2.zip`), or a text file too large to read in one pass, the RESEARCH pipeline does\n**not** `Read` it naively. The actual gathering is delegated to the large-source workflow\nat `{{skills_dir}}\u002F{{self_name}}\u002Freferences\u002Flarge-sources.md`\n(TOC-first → topic-map → chunk → cleanup), which uses the **probe-gated** Python 3 helper\n`{{skills_dir}}\u002F{{self_name}}\u002Fscripts\u002Fmaterial-prep.py` when a Python 3 interpreter is\navailable and falls back to a manual extraction strategy otherwise. Book formats are\nextracted with the standard library (no new dependencies); **MOBI\u002FAZW is recognized but\nrejected** — ask the user for an EPUB export. Step 1 only *classifies* the input here;\nB.1 (\"File input\") performs the delegation.\n\nThe `--skip-registry` flag is an escape hatch for callers that have already performed a registry lookup at a higher level and do not want this skill to repeat it. When the flag is present, Step 1.5 is bypassed entirely and the skill proceeds directly to content classification (Step 2) and generation.\n\n**Phase B — Determine intent based on input type:**\n\n```\nIntent?\n├── OPTIMISE        → Branch E (always — retroactive reference extraction, no new content)\n├── MIGRATE RULES   → Branch C (always — explicit migration request)\n├── Mixed (URL + File) → RESEARCH (always — both inputs processed together)\n├── URL(s)           → RESEARCH (always — URLs signal delegation)\n├── File\u002FFolder path → RESEARCH (always — user provides source material for analysis)\n├── Description      → Analyze tone ↓\n│   ├── Exploratory  → RESEARCH\n│   └── Concrete     → ADD RULE\n└── Interactive      → Ask user, then re-classify\n```\n\n**Tone signals for Description input:**\n\n| Signal | Intent | Examples |\n|--------|--------|----------|\n| Vague topic, delegation words | **Research** | \"add rules for DOTween\", \"document how we use Addressables\", \"figure out best practices for R3\" |\n| Imperative, specific convention, code examples | **Add Rule** | \"add rule: always use `.SetEase(Ease.OutQuad)`\", \"never use coroutines\", \"use `NonLazy()` for controllers\" |\n\n**Phase C — Detect integration intent (contract-defined):**\n\nIf the active module's contract defines integration-gated tiers, detect\n`integrationIntent` per the contract's \"Integration Intent\" section and store it\nalongside the classified intent to thread into Branch A \u002F Branch B. The `code`\ncontract defines this for its `stack` tier (detection signals T1\u002FT2, plus T3\npost-fetch in the Research pipeline). Modules with no integration-gated tier skip\nthis phase and leave `integrationIntent=false`.\n\n### Step 1.5: Registry-first Lookup\n\n**Always try the registry before generating a rule from scratch.** If a matching rule already exists in the remote catalog, the user gets a vetted version by installing it via CLI — much better than spending tokens generating a local copy that duplicates upstream work.\n\n#### 1.5.1: Read CLI contract\n\nRead `.unikit\u002Fsystem\u002Fcli-contract.md` to confirm available `unikit-ai rules *` commands and exit codes.\n\n#### 1.5.2: Fetch catalog and installed state\n\nRun two CLI commands (sequential is fine). **Always pass `--module \u003CmoduleId>`** —\nthe router already resolved the active module (Step 0.5), and every machine consumer\nsends its `--module` so the CLI returns the stable flat-single form no matter how\nmany modules the registry carries (no-`--module` `rules list` now defaults to **all\nmodules** blocked + a flat-all JSON, which this skill does not want):\n\n```bash\nunikit-ai rules list --module \u003CmoduleId> --json\n```\n```bash\nunikit-ai rules status --module \u003CmoduleId> --json\n```\n\n`rules list --module \u003CmoduleId> --json` returns the flat-single shape\n`{ engine, module, rules: [...] }` — parse `catalog.rules` exactly as before (the\nscoped form carries **no** per-row `module` key, so the parser is unchanged).\n`rules status` **does** accept `--module` (it scopes the reported rows to that\nmodule); pass it so `status.rules[]` is already limited to the active module — no\nclient-side filtering needed.\n\nExit code handling:\n- `rules list` exit 2 (registry chain unreachable) → skip to Step 2 silently, proceed without registry\n- `rules list` exit 1 → **strictly** \"no `.unikit.json`\" (not a UniKit project) → skip to Step 2. Engine-missing is **no longer** exit 1: a valid project whose engine is absent from the registry now exits **0** with an empty `catalog.rules`, which flows normally into Step 2.\n- `rules list` exit 3 (unknown `--module`) → the resolved module id is not registered; report the error and skip to Step 2\n- any other non-zero → report the error and skip to Step 2\n\nParse `rules list --module \u003CmoduleId> --json` into `catalog.rules[]` and `rules status --module \u003CmoduleId> --json` into `status.rules[]`.\n\n#### 1.5.3: Semantic matching\n\nMatch the user's intent against `catalog.rules[]`:\n\n- **Exact id match (case-insensitive):** `\"DOTween\"` → `dotween`\n- **Description match:** `\"tweening library\"` → `dotween` via the `description` field\n- **Synonyms and localized names:** `\"контейнер внедрения зависимостей\"` → `zenject`\n\nCollect 0..N candidates. If N > 1, treat all as possible matches for the user prompt below.\n\n#### 1.5.4: Join with installed state\n\nFor each candidate, look it up in `status.rules[]` by `name` (case-insensitive):\n- **Already installed** → note `source`, `version`, and tier so the prompt can show accurate state.\n- **Not installed** → candidate is offerable as a fresh install.\n\n#### 1.5.5: Decision tree\n\n```\nMatch result?\n├── Exactly 1 match + already installed\n│   → Inform user: \"{name} is already installed (source={source}, v{version})\"\n│   → the question tool of your agent (`AskUserQuestion`): What should we do?\n│   │  Options:\n│   │  1. Leave as is         → STOP\n│   │  2. Edit manually       → Continue to Step 2\n│   │  3. Reinstall from registry → Bash: unikit-ai rules install \u003Cid> --force → STOP\n│\n├── Exactly 1 match + NOT installed\n│   → the question tool of your agent (`AskUserQuestion`): Matching rule \"{name}\" v{version} found in registry. Install it?\n│   │  Options:\n│   │  1. Yes, install from registry  → install path (below)\n│   │  2. Preview before deciding     → preview path (below)\n│   │  3. No, generate a new rule     → Continue to Step 2 (research\u002Fmanual generation)\n│   │\n│   ├── install path:\n│   │   Bash: unikit-ai rules install \u003Cid>\n│   │   → Report \"✓ Installed \u003Cid> from registry\" and STOP. The CLI already\n│   │     regenerates RULES_INDEX.md — no extra sync needed.\n│   │\n│   └── preview path:\n│       Bash: unikit-ai rules show \u003Cid> --module \u003CmoduleId> --references\n│       (rules show is module-agnostic: a bare id that collides across modules\n│        exits 3, so the already-resolved router always scopes with --module)\n│       → Show content to user, then ask again with the question tool of your agent (`AskUserQuestion`):\n│         1. Install → install path above\n│         2. Generate a new rule → Step 2\n│\n├── Multiple matches\n│   → the question tool of your agent (`AskUserQuestion`): present all candidates + a \"none of these, generate a new rule\" option\n│   → If user picks a candidate → treat as \"exactly 1 match\" (installed or not)\n│   → If \"none\" → Continue to Step 2\n│\n└── Zero matches\n    → Continue to Step 2 (research\u002Fmanual generation)\n```\n\n**Key behavior guarantees:**\n- The `Multiple matches` branch prints the candidates (name, version, module) to the screen as plain markdown first.\n- Agreeing to install always ends with `rules install \u003Cid>` and terminates the skill. The content in the registry is the source of truth; the skill does not second-guess it.\n- Declining the registry version always routes to Step 2, where the skill generates the rule from the user's description, URL, or file input as usual. No partial install, no mix of registry + local content.\n\n#### When to skip Step 1.5 entirely\n\nBypass the lookup completely when any of the following is true:\n\n- **`--skip-registry` flag** was present in $ARGUMENTS (a higher-level caller already queried the catalog and does not want redundant prompts)\n- **Intent is VALIDATE INDEX** (Branch D), **MIGRATE RULES** (Branch C), or **OPTIMISE** (Branch E) — none of them installs a new rule, so registry lookup is irrelevant\n- **Input is a file path** — the user explicitly wants to process a specific file, not search the catalog\n- **`cli-contract.md` doesn't exist** — the UniKit CLI is not available in this project, so `rules *` commands cannot be used\n\n---\n\n### Step 2: Classify Content Category\n\nUse the **active module's contract** (`references\u002Fmodule-\u003CmoduleId>.md` →\n\"Content Classification\") to:\n\n1. **Pick the target tier** for the content among the module's tiers, or determine\n   the content belongs to **none** of the module's tiers.\n   - If the content fits none of the tiers, redirect the user to the correct\n     destination named in the contract's \"What Does NOT Belong\" section\n     (architecture → `.unikit\u002FARCHITECTURE.md` and its topic files; project-specific overrides →\n     `.unikit\u002FRULES.md` via `unikit-rules`). **Stop here. Do NOT create any files.**\n   - If the content fits none of the tiers **and** seems to belong to a *different\n     module* than the one resolved in Step 0.5, return to Step 0.5 and re-ask the\n     module question rather than forcing a tier.\n2. **Identify the target file** within the chosen tier, following the contract's\n   filename conventions.\n3. **Check whether the file already exists** under `.unikit\u002Fmemory\u002F\u003Cmodule>\u002F\u003Ctier>\u002F`.\n\n### Step 3: Route by Intent\n\nBased on intent (Step 1) and classification (Step 2), follow the appropriate branch:\n\n```\nIntent?\n├── VALIDATE INDEX → Branch D (inline below; skip Steps 2-3 entirely)\n├── OPTIMISE       → Branch E (inline below; skip Step 2 — it operates on existing rules)\n├── MIGRATE RULES  → read references\u002Fmigrate-rules.md and follow it (skip Step 2)\n├── ADD RULE       → Branch A (inline below)\n└── RESEARCH       → read references\u002Fresearch-pipeline.md and follow it\n```\n\nBranches B (Research) and C (Migrate) are intent-gated and live in dedicated\nreference files loaded relative to this skill\n(`{{skills_dir}}\u002F{{self_name}}\u002Freferences\u002F`): open the matching file only when its\nintent is selected, then return here for the **Final Step: Confirm**. Branch A,\nBranch D, and Branch E stay inline below since they are short and on the common path.\n\n---\n\n## Branch A: Add Rule\n\nThe user has a concrete rule to save. No research, no enrichment — just store what the user explicitly stated.\n\n### A.1: Check Target File\n\n```\nFile exists?\n├── YES → A.2 (Cross-Check & Append)\n└── NO\n    ├── Tier is framework-agnostic (per the module contract, e.g. `code`\u002Fcore) → A.3 (Create File)\n    └── Tier may need research (per the module contract, e.g. `code`\u002Fstack)     → A.4 (Ask About Research)\n```\n\n### A.2: Cross-Check, Gap List & Append (file exists)\n\nBefore appending, compare the new content against existing rules:\n\n1. **Read the target file.**\n2. **Read related files** — scan `RULES_INDEX.md` for files with overlapping keywords, then read those too (across all tiers of the module). Also read `.unikit\u002FRULES.md` for project-specific overrides. **Rule topics:** plus the topic files listed under its `## Topics` whose `Load when` matches the new rule's area; when unsure, load.\n3. **Compare each new rule against existing formulations.** A contradiction is when the new content prescribes something different from an existing rule — e.g., \"use `await` directly\" vs existing \"always wrap in `UniTask.Create`\", or \"bind as Transient\" vs existing \"bind as Singleton\".\n4. **Build the gap list (the default for every update).** Classify the new material against what the file already says, and show the result to the user as the summary of what the update will do:\n   - **Add** — genuinely new rules not yet present in the file.\n   - **Change** — rules that refine or supersede an existing formulation (these are the contradictions resolved below).\n   - **Unchanged** — material the file already covers; skip it, do not restate.\n   This gap-list discipline is the **canonical cross-check\u002Fupdate behaviour** that `research-pipeline.md` B.4 defers to (\"Same logic as A.2\"). It runs on every existing-file update regardless of input.\n\n**If contradictions found:**\n\n- Report **each** contradiction to the user, quoting both the new statement and the existing rule with its source file.\n- For each contradiction, ask via the question tool of your agent (`AskUserQuestion`) (batch up to 3 contradictions per question):\n\n  Options:\n  1. Replace — update existing rule with new formulation\n  2. Keep existing — discard the conflicting part\n  3. Keep both — document both with a note on when each applies\n\n  Based on choice:\n  - Replace → overwrite the existing rule text in the target file with the new formulation\n  - Keep existing → discard the conflicting part from the new content, keep existing rule unchanged\n  - Keep both → add the new rule alongside the existing one with a note clarifying when each applies\n\n**After resolution (or if no contradictions):**\n\n- Apply the gap list: append the **Add** items and apply the **Change** items, merging into the appropriate sections. Skip **Unchanged** material. Do not overwrite useful existing content.\n- → Go to **Final Step: Confirm**\n\n### A.3: Create New File (framework-agnostic tier, no existing file)\n\n1. Create the rule file following the **File Format Template** from the module contract.\n2. Write the user's rule(s) as-is — no enrichment, no synthesis.\n3. Update `RULES_INDEX.md` — add a new row to the appropriate table in alphabetical order.\n4. → Go to **Final Step: Confirm**\n\n### A.4: Ask About Research (research-eligible tier, no existing file)\n\nAsk the user with the question tool of your agent (`AskUserQuestion`): *\"I don't have a rules file for {framework\u002Ftopic} yet. Research this and create a comprehensive document, or save your rule as-is?\"* Options: `Research it` (Recommended) · `Save my rule as-is`.\n\n```\nUser answer?\n├── YES (research) → read references\u002Fresearch-pipeline.md and follow it (start at B.1)\n└── NO (save as-is)\n    ├── Create the rule file with user's rule(s) only\n    ├── Update RULES_INDEX.md — add to the tier's table\n    └── → Go to Final Step: Confirm\n```\n\n---\n\n## Branch B: Research\n\nFull research pipeline — gather material, enrich, synthesize, then write into the\nactive module's tier. The complete workflow (B.1–B.5: gather → integration upgrade →\nContext7 → synthesize → reference candidates → cross-check → write) lives in\n`{{skills_dir}}\u002F{{self_name}}\u002Freferences\u002Fresearch-pipeline.md`. Read that file and\nfollow it, then return here for the **Final Step: Confirm**. All file-format and\nscope decisions in it defer to the module contract.\n\n---\n\n## Branch C: Migrate Rules from RULES.md\n\nTransfer mature entries from `.unikit\u002FRULES.md` (the quick-capture staging area owned\nby `unikit-rules`) into permanent rule files under `.unikit\u002Fmemory\u002F\u003Cmodule>\u002F`. The\ncomplete workflow (C.1–C.4: load → classify → present candidates → rephrase → apply)\nlives in `{{skills_dir}}\u002F{{self_name}}\u002Freferences\u002Fmigrate-rules.md`. Read that file\nand follow it, then return here for the **Final Step: Confirm**.\n\n---\n\n## Branch D: Validate Index\n\nSync `.unikit\u002Fmemory\u002F\u003Cmodule>\u002FRULES_INDEX.md` with the actual files on disk. No user interaction — fully automatic.\n\n### D.1: Scan Actual Files\n\n1. For each `\u003Ctier>` of the resolved module: `Glob: .unikit\u002Fmemory\u002F\u003Cmodule>\u002F\u003Ctier>\u002F*.md` — collect all real rule files in that tier.\n2. Read `.unikit\u002Fmemory\u002F\u003Cmodule>\u002FRULES_INDEX.md` — parse every table (one per tier), extract filenames from each row.\n\n### D.2: Diff\n\nCompare the two sets:\n\n- **Missing from index** — files that exist on disk but have no row in RULES_INDEX.md\n- **Phantom in index** — rows in RULES_INDEX.md whose files don't exist on disk\n\n### D.3: Fix Index\n\n**For each missing file** — read the file, extract the `> **Scope**:` and `> **Load when**:` lines from the header. Add a row to the appropriate tier's table in RULES_INDEX.md (alphabetical order), following the contract's \"RULES_INDEX.md Format\":\n\n```\n| {FILENAME}.md | {Scope value} | {Load when value} |\n```\n\nIf the file has no Scope\u002FLoad when header, use the first heading and first paragraph to generate a brief description and keywords.\n\n**For each phantom entry** — remove the row from RULES_INDEX.md using `Edit`.\n\n### D.4: Report\n\nOutput a short validation report (in user's configured language):\n\n```\nRULES_INDEX.md validation complete.\n\n{per-tier counts, e.g. Core: {N} files, Stack: {M} files}\n✅ Added to index: {X}\n🔄 Removed from index: {Y}\n\n{If X > 0: list added filenames}\n{If Y > 0: list removed filenames}\n```\n\nStop. Do not proceed to any other step.\n\n---\n\n## Branch E: Optimise (retroactive reference extraction)\n\nRetroactively shrink **existing** rules by moving their large\u002Foptional sections into\nreference files — the same outcome the on-add reference step (B.3.5) produces,\napplied after the fact. Branch E **synthesizes no new content**: it relocates text\nthat already lives in a rule, so a rule that grew too long (e.g. a distilled book\nthat landed entirely inline) becomes a lean conceptual rule plus on-demand\nreferences. The active `\u003Cmodule>` and its `\u003Ctier>`s were already resolved in Step\n0.5; the module contract's **Candidate Analyzer** is the engine.\n\nThis branch is **non-destructive**: content **moves**, it is never deleted, every\nproposal is confirmed before writing, and it leans on git as the safety net. It does\nnot touch the registry, `src\u002F`, or the helper script.\n\n### E.1: Determine scope\n\nParse the rule scope from the remaining `$ARGUMENTS` (after the `optimise` keyword was\nconsumed in Phase A):\n\n- **Named rules present** (e.g. `optimise dotween zenject`) → that is the scope.\n  Resolve each name to a file under `.unikit\u002Fmemory\u002F\u003Cmodule>\u002F\u003Ctier>\u002F` (match against\n  `RULES_INDEX.md`; ask if a name is ambiguous).\n- **No names** → the question tool of your agent (`AskUserQuestion`):\n\n  Options:\n  1. Specific rules — I'll name them → ask which, then resolve as above\n  2. All rules in this module → scope = every rule file across the module's tiers\n\nWhatever the scope, **process the rules in batches of 2-3 at a time** — analyze,\npresent, confirm, and write one batch before moving to the next. This keeps each\nconfirmation focused and the diff reviewable.\n\n### E.2: Analyze each rule\n\nFor each rule in the current batch:\n\n1. Read the rule file.\n2. Run the module contract's **Candidate Analyzer** (\"Reference Candidate\n   Extraction\") over its sections: score each block on **size** (≳ 40 lines \u002F ≳ 1500\n   chars), **optionality**, and **lookup shape**, and sort candidates into **Tier 1**\n   (clear wins) and **Tier 2** (borderline).\n3. Run the **merge guard** (`research-pipeline.md` B.3.5): before proposing any new\n   reference file, scan the tier's existing `references\u002F` for a file that already\n   covers the topic and target it instead of forking a near-duplicate.\n\n### E.3: Present and confirm\n\nPresent the candidates per rule, grouped into **Tier 1** and **Tier 2** (each with\nwhich signals fired and the target\n`.unikit\u002Fmemory\u002F\u003Cmodule>\u002F\u003Ctier>\u002Freferences\u002F{file}.md`), then ask with the question tool of your agent (`AskUserQuestion`)\nexactly as B.3.5 does:\n\nOptions:\n1. Extract **Tier 1 only**\n2. Extract **Tier 1 + Tier 2**\n3. Adjust — rename \u002F merge \u002F split \u002F drop, or move a block between tiers → revise and ask again\n4. None — leave this rule unchanged\n\n**Always report the result, including \"0 candidates\"** for a rule that is already\nlean — Branch E must say so rather than silently skip it.\n\n### E.4: Move the content (never delete)\n\nFor each approved candidate:\n\n1. **Write the reference file** following the contract's **Reference File Format**\n   (create new, or update the existing matching file per the merge guard).\n2. **Cut** the moved section from the main rule — the content is relocated, not\n   duplicated. Leave the conceptual rules intact.\n3. Add the file to the main rule's `> **References**:` header line and add\u002Fextend a\n   `## {Content} Lookup Workflow` section telling the LLM when to open it. The main\n   rule keeps only pointers, not the moved data.\n\nReference files are not indexed in `RULES_INDEX.md` (only main rules are); the main\nrule's row is unchanged unless its Scope\u002FLoad when changed (they should not).\n\n### E.5: Finish\n\nAfter the last batch, go to the **Final Step: Confirm** — it runs `unikit-ai rules\nsync` (reconciling the moved files into `.unikit.json` state and regenerating\n`RULES_INDEX.md`) and prints the report. The Quality Gate runs in **structural-only**\nmode for Branch E (no synthesis to grade — see the Quality Gate section).\n\n---\n\n## File Formats\n\nAll file-format specifications — the **File Format Template** (rule files, with\n`Scope`\u002F`Load when` prose guidance), the **Reference File Format**, the\n**Reference Candidate Extraction** strategies, and the **RULES_INDEX.md Format** —\nlive in the active module's contract:\n`{{skills_dir}}\u002F{{self_name}}\u002Freferences\u002Fmodule-\u003CmoduleId>.md`.\n\nAlways read the contract for the resolved module and follow its formats exactly.\nThis router intentionally does not restate them, so a new module can define its own\nconventions without touching this file.\n\n## Quality Gate (run before the Final Step)\n\nA cheap, automatic self-check that runs **after a branch finishes writing** and\n**before** the Final Step report. It is gated by intent: run it only for **ADD RULE**\n(Branch A, including the existing-file update path), **RESEARCH** (Branch B), and\n**OPTIMISE** (Branch E — **structural checks only**, since it synthesizes no new\ncontent; see below). **Skip it entirely** for **MIGRATE RULES** (Branch C), **VALIDATE\nINDEX** (Branch D — it already exited and never reaches here), and the Step 1.5\ninstall-from-registry short-circuit — none of those produce freshly synthesized\ncontent to grade (Migrate rephrases existing entries, Validate only reconciles the\nindex, an install pulls a vetted upstream file). This is a checklist, not a new\napproval prompt: run it silently and only surface a ⚠️ line if a check fails.\n\n**Always check (every gated write — cheap structural checks):**\n\n- The rule file carries a `> **Scope**:` and a `> **Load when**:` line, both written as\n  **prose** (not a bare dump of identifiers), per the module contract.\n- No placeholder leak — no `{Framework Name}`, `{Section 1}`, `TODO`, or other template\n  scaffolding survived into the written file.\n- `RULES_INDEX.md` has a row for the file (new files only).\n\n**For Branch E (Optimise)** these structural checks apply to the *relocation*: the\noptimised main rule still carries its `> **Scope**:` \u002F `> **Load when**:` lines, no\nplaceholder scaffolding leaked into the moved content or the new `## {Content} Lookup\nWorkflow`, and each created reference is wired into the main rule's `> **References**:`\nline. Reference files are not indexed, so the `RULES_INDEX.md` row check covers main\nrules only. Branch E runs **none** of the synthesis checks below.\n\n**Additionally — only when the branch actually synthesized content**, i.e. **Branch B\n(Research)** or **Branch A → A.4 with research**. Do **not** run these on the as-is\npaths (A.2 cross-check-append, A.3 create-as-is, A.4 save-as-is) or **Branch E\n(Optimise)** — those write the user's exact words (or merely relocate existing text)\nwith no synthesis, so there is no coverage or distillation to grade:\n\n- **Example coverage (#2)** — the major code-facing topics the rule raises are each\n  illustrated by an example (or explicitly waived with a stated reason), per the\n  example inventory from `research-pipeline.md` B.3. Many topics raised + only one or\n  two examples shown = fail. \"Example\" means whatever the active module contract\n  defines (code snippets for `code`; numeric tables \u002F worked formulas for `gamedesign`).\n- **Distilled, not copied (#8)** — no long verbatim source passages; guidance is\n  rewritten as actionable rules; any code snippets are original.\n- **Source Map (#6)** — when the rule was built from sources, the Source Inventory was\n  persisted into the rule file per the module contract's Source Map \u002F provenance format.\n\nIf any check fails, fix the written file before the Final Step report (or, when a\ncoverage gap is intentional, record the reason in the rule). Then continue to the\nFinal Step.\n\n## Final Step: Confirm\n\n**First, run the Quality Gate above** (ADD RULE \u002F RESEARCH \u002F OPTIMISE — structural-only\nfor Optimise; skip for Migrate, Validate, and the install short-circuit), then produce\nthe report below.\n\n\n\n**Reconcile `.unikit.json` state with disk (after Branch A \u002F B \u002F C \u002F E only):**\n\nIf the just-completed branch was **Branch A** (Add Rule), **Branch B** (Research), **Branch C** (Migrate Rules), or **Branch E** (Optimise) — i.e. anything that wrote a new or updated rule\u002Freference file into `.unikit\u002Fmemory\u002F\u003Cmodule>\u002F` — run the CLI sync command so the generated file is registered in `.unikit.json.rules.installed` and `RULES_INDEX.md` is regenerated from authoritative state + disk:\n\n```bash\nunikit-ai rules sync\n```\n\nWhy this matters: Branches A\u002FB\u002FC write files via `Write`\u002F`Edit` directly and never touch `.unikit.json`. Without a sync pass, the new rule lives on disk but remains invisible to `rules status`, `rules install \u003Cid> --force`, and — most importantly — to `\u002Funikit` Step 9.3, which builds its \"already installed\" set from `.unikit.json` state. Skipping sync here means the next `\u002Funikit` run can try to reinstall the same rule from the registry and fail with exit 4 (\"already installed\"). `syncRulesState` Phase 1 picks up untracked `.unikit\u002Fmemory\u002F**\u002F*.md` files and registers them as `source: local` entries; Phase 3 regenerates `RULES_INDEX.md`. That is exactly the reconciliation the skill needs before printing the report.\n\nTreat a non-zero exit code as non-fatal for the skill: log the CLI output to the report and continue. The file is still on disk — the user can re-run `unikit-ai rules sync` manually.\n\n**Skip the sync entirely when:**\n- The branch was **Branch D** (Validate Index) — Branch D already exited with `Stop. Do not proceed to any other step.` and never reaches this Final Step at all.\n- An install-from-registry short-circuit ran in Step 1.5 — `rules install` already updated state and regenerated the index, and the short-circuit terminates the skill before reaching Final Step.\n\n**Report to the user (in their configured language):**\n- Which module was targeted and which file was created or updated\n- Summary of what was added or moved (Optimise: which sections were relocated into which reference files)\n- Which branch was used (Add Rule \u002F Research \u002F Optimise)\n- Whether Context7 enrichment was applied (Research branch only)\n- Whether `.unikit.json` state was reconciled via `rules sync` (and whether the index was regenerated)\n- Whether RULES_INDEX.md was updated\n- If any content was redirected elsewhere (architecture, RULES.md)\n\n**Offer rules-registry promotion (after Branch A \u002F B \u002F C \u002F E only):**\n\nIf the just-completed branch was **Branch A** (Add Rule), **Branch B** (Research), **Branch C** (Migrate Rules), or **Branch E** (Optimise) — i.e. anything that actually wrote into `.unikit\u002Fmemory\u002F\u003Cmodule>\u002F` — check whether the project's registry is local:\n\n```bash\nunikit-ai rules registry show --json\n```\n\nParse the JSON. If `.kind == \"local\"`, ask the user whether to promote the memory changes into the registry **now** via the question tool of your agent (`AskUserQuestion`):\n\n```\nThe question tool of your agent (`AskUserQuestion`): A local rules registry is configured at \u003C.url from the JSON>.\nPromote the memory changes into the registry now by running \u002Funikit-rules-registry update?\n\nOptions:\n1. Yes — run \u002Funikit-rules-registry update after the Final Step report\n2. No  — skip promotion, keep the changes in memory only\n```\n\n- **Yes** → finish the Final Step report first (the user must see exactly what changed in memory before promotion), then invoke `unikit-rules-registry` with the argument `update` (`## Skill calls`). Do not collapse the memory report into the promotion run — they are separate, ordered events.\n- **No** → finish the Final Step report without adding any promotion hint. The user can always run `\u002Funikit-rules-registry update` manually later; do not repeat the question or nag on the next invocation.\n\nSkip the question entirely (do not ask, do not print a fallback hint) when:\n- The branch was **Branch D** (Validate Index) — no memory writes happened.\n- An install-from-registry short-circuit ran in Step 1.5 — the registry is already the source of truth for that rule.\n- `rules registry show --json` returned a non-zero exit code or `.kind` is not `\"local\"`.\n\n## Access Rules\n\n**Writable** (this skill can create and edit, for the resolved module):\n- `.unikit\u002Fmemory\u002F\u003Cmodule>\u002F\u003Ctier>\u002F` — rule files in each of the module's tiers\n- `.unikit\u002Fmemory\u002F\u003Cmodule>\u002F\u003Ctier>\u002Freferences\u002F` — supplementary reference docs, where the module contract allows them\n- `.unikit\u002Fmemory\u002F\u003Cmodule>\u002FRULES_INDEX.md` — index of all rule files in the module\n\n**Writable only during Branch C (Migrate Rules):**\n- `.unikit\u002FRULES.md` and its topic files in `.unikit\u002Frules\u002F` — removal of migrated entries only, plus two named edits: the `\u003C!-- @no-migrate -->` tag of Keep, and the deletion of a topic file that migration emptied, together with its `## Topics` row; adding new entries goes through `unikit-rules` skill\n\n**Read-only** (this skill must NEVER modify these files):\n- `.unikit\u002Fconfig.yaml` — project settings (language). Read-only for this skill.\n- `.unikit\u002Fsystem\u002Fmodules.yml` — module registry snapshot. Generated by `unikit-ai`; read-only here.\n- `{{skills_dir}}\u002F{{self_name}}\u002Freferences\u002Fmodule-\u003Cid>.md` — module contracts. Read-only here.\n",{"name":5,"description":7,"allowed-tools":55,"argument-hint":67},[56,57,58,59,60,61,62,63,64,65,66],"Read","Write","Edit","Glob","Grep","Bash","Agent","Skill","WebFetch","WebSearch","AskUserQuestion","[description | URL(s) | file\u002Ffolder | PDF\u002FFb2\u002FEpub paths | migrate-rules | optimise | validate | --module \u003Cid> | --skip-registry ]","main","ae3c6dfffd26d9b45b9d96d71ba2c122c50b67ae","skills\u002Funikit-memory",1,"https:\u002F\u002Fgithub.com\u002FNintendaDev\u002Funikit-ai","https:\u002F\u002Funikit.nintenda.dev","https:\u002F\u002Fgithub.com\u002FNintendaDev","Unity Developer. Building games and UniKit AI","2026-11-08 15:05:51",{"source":8,"skillName":5,"commands":78,"prompt":88,"zipAvailable":89},[79,82,85],{"tool":80,"command":81},"npx","npx skills add NintendaDev\u002Funikit-ai --skill unikit-memory",{"tool":83,"command":84},"bunx","bunx skills add NintendaDev\u002Funikit-ai --skill unikit-memory",{"tool":86,"command":87},"pnpm","pnpm dlx skills add NintendaDev\u002Funikit-ai --skill unikit-memory","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FNintendaDev\u002Funikit-ai\u002Fblob\u002Fmain\u002Fskills\u002Funikit-memory\u002FSKILL.md",true,[91,97,101,105,109,113],{"path":92,"resourceType":93,"resourceTypeDesc":94,"sizeBytes":95,"sourceHtmlUrl":96},"references\u002Flarge-sources.md","REFERENCE","参考文档",8226,"https:\u002F\u002Fgithub.com\u002FNintendaDev\u002Funikit-ai\u002Fblob\u002Fmain\u002Fskills\u002Funikit-memory\u002Freferences\u002Flarge-sources.md",{"path":98,"resourceType":93,"resourceTypeDesc":94,"sizeBytes":99,"sourceHtmlUrl":100},"references\u002Fmigrate-rules.md",9212,"https:\u002F\u002Fgithub.com\u002FNintendaDev\u002Funikit-ai\u002Fblob\u002Fmain\u002Fskills\u002Funikit-memory\u002Freferences\u002Fmigrate-rules.md",{"path":102,"resourceType":93,"resourceTypeDesc":94,"sizeBytes":103,"sourceHtmlUrl":104},"references\u002Fmodule-code.md",22867,"https:\u002F\u002Fgithub.com\u002FNintendaDev\u002Funikit-ai\u002Fblob\u002Fmain\u002Fskills\u002Funikit-memory\u002Freferences\u002Fmodule-code.md",{"path":106,"resourceType":93,"resourceTypeDesc":94,"sizeBytes":107,"sourceHtmlUrl":108},"references\u002Fmodule-gamedesign.md",15688,"https:\u002F\u002Fgithub.com\u002FNintendaDev\u002Funikit-ai\u002Fblob\u002Fmain\u002Fskills\u002Funikit-memory\u002Freferences\u002Fmodule-gamedesign.md",{"path":110,"resourceType":93,"resourceTypeDesc":94,"sizeBytes":111,"sourceHtmlUrl":112},"references\u002Fresearch-pipeline.md",14798,"https:\u002F\u002Fgithub.com\u002FNintendaDev\u002Funikit-ai\u002Fblob\u002Fmain\u002Fskills\u002Funikit-memory\u002Freferences\u002Fresearch-pipeline.md",{"path":114,"resourceType":115,"resourceTypeDesc":116,"sizeBytes":117,"sourceHtmlUrl":118},"scripts\u002Fmaterial-prep.py","SCRIPT","脚本",46370,"https:\u002F\u002Fgithub.com\u002FNintendaDev\u002Funikit-ai\u002Fblob\u002Fmain\u002Fskills\u002Funikit-memory\u002Fscripts\u002Fmaterial-prep.py",[120,141,166,188,207,223],{"skillNo":121,"name":122,"nameZh":6,"description":123,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":124,"categories":125,"keywords":127,"publishedAt":50},"01M71BQ00EXGX51PPCDY7VG334","unikit","Initialize the UniKit framework in a project. Scans the current project to detect the engine and real tech stack, then generates the base framework documents that give AI agents context about the project — the resolved project description, the architecture doc, AGENTS.md, and the user-editable .unikit\u002Fconfig.yaml. This is the one-time, whole-project setup run before any other unikit skill. Use whenever the user wants to initialize, set up, or onboard the framework, e.g. \"initialize unikit\", \"init the framework\", \"set up unikit\", \"set up the project\", \"configure AI context\", \"scan my project and set it up\", \"bootstrap the project\". It also actualizes the config of a project already set up — say \"update the config\", \"add missing settings\", \"actualize configuration\", \"fix my config\". On a set-up project it offers the actions to choose from.","https:\u002F\u002Fgithub.com\u002FNintendaDev\u002Funikit-ai\u002Fblob\u002Fmain\u002Fskills\u002Funikit\u002FSKILL.md",[126],{"categoryNo":27,"categoryName":28,"taxonomyType":21,"taxonomyTypeDesc":22},[122,47,128,129,130,131,42,40,132,133,38,37,134,36,135,136,137,138,139,140],"time","actions","fix","documents","run","update","config","git","context","initialize","tech","scan","use",{"skillNo":142,"name":143,"nameZh":6,"description":144,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":145,"categories":146,"keywords":151,"publishedAt":50},"01M71BPRTMKW7FRAZZBN44NW5Q","unikit-verify","Verify a completed implementation against the plan in .unikit\u002Fcode\u002Fplans\u002F. Checks that every task was implemented, nothing was forgotten, the code compiles, the recorded test run still matches the code, and {{engine_name}} conventions are followed. Use after \u002Funikit-implement completes, or when the user says \"verify\", \"check the work\", \"did we miss anything\". For code review use \u002Funikit-review instead.","https:\u002F\u002Fgithub.com\u002FNintendaDev\u002Funikit-ai\u002Fblob\u002Fmain\u002Fskills\u002Funikit-verify\u002FSKILL.md",[147,150],{"categoryNo":148,"categoryName":149,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000007","代码审查",{"categoryNo":27,"categoryName":28,"taxonomyType":21,"taxonomyTypeDesc":22},[152,153,154,155,156,157,132,38,37,36,135,158,159,140,160,161,162,163,164,165],"unikit verify","verify","powershell","code review","phase","plan","for","system","implement","check","engine","research","name","quality",{"skillNo":167,"name":168,"nameZh":6,"description":169,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":170,"categories":171,"keywords":172,"publishedAt":50},"01M71BPM35M5ETPA4E7EKQYRWD","unikit-todo","Manage the project's TODO list in .unikit\u002FTODO.md — capture work to remember for later, not to do right now. Use it to add a deferred item, mark a todo complete, or show the list. The point is to park tasks you don't want to act on in the moment but don't want to forget. Trigger on \"add a todo\", \"add this to the todo list\", \"put X on the todo list\", \"remind me to...\", \"don't forget to...\", \"note this for later\", \"we should do this later\", \"mark this todo done\", \"what's on the todo list\", \"what's left to do\". This is only for parking reminders — to actually plan or do the work now, use \u002Funikit-plan, \u002Funikit-implement, or \u002Funikit-execute.","https:\u002F\u002Fgithub.com\u002FNintendaDev\u002Funikit-ai\u002Fblob\u002Fmain\u002Fskills\u002Funikit-todo\u002FSKILL.md",[],[173,174,175,176,47,177,178,179,180,181,182,183,157,184,185,186,38,37,36,187],"unikit todo","todo","remind","show","todo list","only","now","you","done","tasks","work","me","reminders","later","act",{"skillNo":189,"name":190,"nameZh":6,"description":191,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":192,"categories":193,"keywords":195,"publishedAt":50},"01M71BPEQDVD7DTGFQBQJQ7JKY","unikit-skills-context","Customize how a built-in unikit skill behaves in this specific project by writing workflow overrides into its skill-context file. These are per-skill workflow rules (e.g. \"\u002Funikit-review should also flag TODO comments\", \"\u002Funikit-implement should run tests after each task\"), not coding conventions. Use when the user wants to change, customize, or override how a particular unikit skill works in this project — \"customize the review skill\", \"make \u002Funikit-fix always add logging here\", \"the implement skill should do X differently\", \"add a skill rule for \u002Funikit-commit\". Use \"validate\" to find stale overrides against updated base skills. For a general coding convention (not tied to one skill) use \u002Funikit-rules; to derive rules from past mistakes use \u002Funikit-evolve.","https:\u002F\u002Fgithub.com\u002FNintendaDev\u002Funikit-ai\u002Fblob\u002Fmain\u002Fskills\u002Funikit-skills-context\u002FSKILL.md",[194],{"categoryNo":27,"categoryName":28,"taxonomyType":21,"taxonomyTypeDesc":22},[196,136,47,130,197,198,199,200,201,202,203,204,174,205,39,132,206,38,37,36],"unikit skills context","coding conventions","writing","when","workflow","commit","review","general coding","text","change","past",{"skillNo":208,"name":209,"nameZh":6,"description":210,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":211,"categories":212,"keywords":216,"publishedAt":50},"01M71BP7K5KEGJV4ASRKPG1DM8","unikit-rules","Add a short, project-specific rule, convention, or override to .unikit\u002FRULES.md — the quick-capture inbox for this project's rules (common rules always load; topic files in .unikit\u002Frules\u002F load when the work matches), automatically loaded by \u002Funikit-implement (later promotable via \u002Funikit-memory migrate-rules). Works only with a rule typed as a prompt — it does NOT read files, folders, URLs, or PDFs. Cross-checks the knowledge base (RULES_INDEX.md) to avoid duplicating core\u002Fstack entries. Use for one-line conventions and corrections: \"add a rule\", \"remember this\", \"convention\", \"always do X\", \"never use Y\", \"from now on do Z\", or when the user corrects agent behavior and wants it remembered; also \"split the rules into topics\" (optimise), \"clean up the rules\" (prune), \"shorten RULES.md\" (compact), by keyword or in plain words. If the user points to a source (file, folder, URL, PDF, article, book) or wants to research\u002Fdocument framework usage, use \u002Funikit-memory; for architecture decisions use ARCHITECTURE.md.","https:\u002F\u002Fgithub.com\u002FNintendaDev\u002Funikit-ai\u002Fblob\u002Fmain\u002Fskills\u002Funikit-rules\u002FSKILL.md",[213,214,215],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":27,"categoryName":28,"taxonomyType":21,"taxonomyTypeDesc":22},[217,218,49,48,47,219,45,220,44,43,42,221,204,41,40,186,38,37,36,222],"Rules","unikit rules","clean","files","batch","prune",{"skillNo":224,"name":225,"nameZh":6,"description":226,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":227,"categories":228,"keywords":229,"publishedAt":50},"01M71BP02S49HHD4R5X6N12C9Q","unikit-rules-registry","Orchestrate the remote rules registry — the shared registry (often connected as a local folder or git repo) that the project's rules are published to and pulled from. Three modes, picked from the user's wording: create scaffolds a new local rules registry (\"create a local rules registry\", \"init a rules registry\"); update migrates\u002Fpromotes local knowledge-base rules from .unikit\u002Fmemory\u002F into the remote registry with automatic semver bumps (\"migrate local rules to the remote registry\", \"promote my rules to the registry\", \"push local rules\", \"publish local rules\", \"update the rules registry\"); sync pulls registry updates back into memory (\"sync the rules registry\", \"pull registry updates\"). Pass \"--module \u003Cid>\" to scope to one knowledge-base module. This skill ONLY orchestrates the CLI (`unikit-ai rules *`) — it never edits .unikit.json or .unikit\u002Fmemory\u002F sources directly.","https:\u002F\u002Fgithub.com\u002FNintendaDev\u002Funikit-ai\u002Fblob\u002Fmain\u002Fskills\u002Funikit-rules-registry\u002FSKILL.md",[],[34,217,230,231,47,232,45,233,43,234,133,38,37,135,235,236,237,238,239,240],"unikit rules registry","shared","local","remote","create","ai rules","automatic","semver","knowledge-base","as","three"]