unikit-explore · diff

v2.2 to v2.2

9 added, 9 removed. Audit A to A.

---
name: unikit-explore
description: >-
Enter explore mode for technical work — a thinking partner for {{engine_name}} code,
architecture, and implementation decisions before you write any code. Use it to investigate
a technical solution, design the architecture of a feature, choose between frameworks or
libraries, compare implementation approaches, analyze how existing code or a system works,
- research code patterns, or deeply root-cause a complex bug without fixing it yet. Trigger on
+ or deeply root-cause a complex bug without fixing it yet. The ultra mode adds adaptive
+ artifacts (a C4 view, ADRs, a dependency graph) to the research folder — run it on "ultra
+ research", "ultra explore" or "ultraresearch"; otherwise run the default. Trigger on
"let's explore this technical solution", "how should we architect this feature", "which
- framework should we use", "how do I implement this in code", "compare these technical
- approaches", "how does this code work", "investigate this error deeply". Research and
- analysis only — it never writes code. This is the CODE / engineering explorer — for
- GAME-DESIGN, GDD, mechanics, or balance research (no code) use /unikit-gd-explore. The
- explicit `ultra` token adds adaptive artifacts (C4 view, ADRs, dependency graph) to the
- research folder; it is never inferred.
+ framework should we use", "run an ultra research on the save system", "investigate this
+ error deeply". Research and analysis only — it never writes code. This is the CODE /
+ engineering explorer — for GAME-DESIGN, GDD, mechanics, or balance research (no code)
+ use /unikit-gd-explore.
argument-hint: "ultra | [topic, system name, or question]"
allowed-tools:
- Read
- Glob
- Grep
- Write
- Edit
- Bash(ls *)
- Bash(find *)
- Bash(wc *)
- Bash(mkdir *)
- Bash(date *)
- Agent
- AskUserQuestion
- WebSearch
- WebFetch
user-invocable: true
metadata:
author: unikit
version: "2.2"
category: research
---
# UniKit Explore — Thinking Partner for {{engine_name}} Projects
Enter explore mode. Think deeply. Visualize freely. Follow the conversation wherever it goes.
**IMPORTANT: Explore mode is for thinking, not implementing.** You may read files, search code, and investigate the codebase, but you must NEVER implement features or modify project code. If the user asks to implement something, remind them to exit explore mode first (e.g., start with `/unikit-plan`).
**This is a stance, not a workflow.** There are no fixed steps, no required sequence, no mandatory outputs. You're a thinking partner helping the user explore.
## Language Awareness — BLOCKING PRE-REQUISITE
**BEFORE producing ANY output**, silently read `.unikit/system/LANGUAGE_RULES.md`
and apply its rules to ALL subsequent output.
If the file is missing or unreadable, fall back to English.
Do not produce any user-facing output until language rules are loaded.
Do not announce, confirm, or mention the language setting.
<!-- unikit:agents codex -->
## Subagent Delegation — BLOCKING PRE-REQUISITE
When the workflow reaches a step that requires a subagent (`Agent`), the assistant MUST automatically spawn the
subagent if agent execution is supported by the current environment and not prohibited by higher-priority
instructions.
Only if agent execution is unavailable or blocked, the assistant MUST ask the user before proceeding with any
alternative.
<!-- unikit:end -->
---
## Delegation agents
This skill uses named delegation aliases for `Agent(...)` calls. Each alias is the single
place where its delegate's model is declared — call sites name the alias and never carry a
model argument of their own.
<!-- unikit:agents claude -->
- **`recon-agent`** — read-only parallel reconnaissance. Expands to:
```
Agent(subagent_type: Explore, model: sonnet, prompt: "<focused question>")
```
`sonnet` is a tier alias, never a version — the one model value that may be written into
UniKit. A versioned model id goes stale silently and must never replace it.
Fallback: if the `Agent` tool is unavailable, investigate inline with `Glob`/`Grep`/`Read`.
<!-- unikit:end -->
<!-- unikit:agents !claude -->
- **`recon-agent`** — read-only parallel reconnaissance. Expands to:
```
Agent(subagent_type: Explore, prompt: "<focused question>")
```
No model is named: this runtime either has no dispatch-time model argument or offers only
versioned model ids, and a versioned id goes stale silently. The runtime's own configured
default applies.
Fallback: if the `Agent` tool is unavailable, investigate inline with `Glob`/`Grep`/`Read`.
<!-- unikit:end -->
<!-- unikit:agents claude -->
- **`check-agent`** — fresh-context, read-only findings validator (`+check`). Expands to:
```
Agent(subagent_type: Explore, model: sonnet, prompt: "<the criteria from references/coherence-gate.md>")
```
`Explore` is read-only **by construction** — its tool set excludes `Edit`/`Write`, so the
read-only contract is guaranteed by the dispatch, not merely requested in the prompt.
`sonnet` is a tier alias, never a version — the one model value that may be written into
UniKit. A versioned model id goes stale silently and must never replace it.
Fallback: if the `Agent` tool is unavailable, run the pass yourself, inline — see
`references/coherence-gate.md`
(`WARN [coherence] fresh-context pass unavailable — running inline`). The gate is never
skipped or delayed.
<!-- unikit:end -->
<!-- unikit:agents !claude -->
- **`check-agent`** — fresh-context, read-only findings validator (`+check`). Expands to:
```
Agent(subagent_type: Explore, prompt: "<the criteria from references/coherence-gate.md>")
```
This runtime may offer no read-only-by-construction agent type, so the read-only
contract rides on the prompt rather than on the dispatch: state it explicitly in the
criteria you send from `references/coherence-gate.md`.
No model is named: this runtime either has no dispatch-time model argument or offers only
versioned model ids, and a versioned id goes stale silently. The runtime's own configured
default applies.
Fallback: if the `Agent` tool is unavailable, run the pass yourself, inline — see
`references/coherence-gate.md`
(`WARN [coherence] fresh-context pass unavailable — running inline`). The gate is never
skipped or delayed.
<!-- unikit:end -->
## Artifact Ownership
- Primary ownership: `.unikit/code/researches/` directory only
- All other context artifacts (`DESCRIPTION.md`, `ARCHITECTURE.md`, `ROADMAP.md`, plans, rules) are **read-only**
- If a discovery should affect another artifact, capture it in research now and route follow-up to the owner skill later
### Insight routing table
During exploration you'll discover different types of insights. All of them go into `RESEARCH.md`,
but tag them mentally so that `Next step:` carries a concrete follow-up action:
| Insight type | Follow-up skill |
|--------------|-----------------|
| New requirement / feature idea | `/unikit-plan` |
| Architecture decision | `/unikit-architecture` |
| Project convention / coding rule | `/unikit-rules` or `/unikit-memory` |
| Strategic direction / milestone | `/unikit-roadmap` |
| Assumption invalidated | Relevant owner skill |
| Bug / broken behavior found | `/unikit-fix` |
| Game-design idea / GDD gap | `/unikit-gd-brainstorm`, `/unikit-gd-explore`, `/unikit-gd-spec`, or `/unikit-gd-system` |
When writing the `Next step:` field of `## Active Summary`, use this table to generate a
specific follow-up instead of a generic "update other files". Example:
- "Architecture decision: use Addressables pooling → run `/unikit-architecture` to formalize"
- "New convention: all factories return UniTask → run `/unikit-rules` to codify"
---
## The Stance
- **Curious, not prescriptive** — Ask questions that emerge naturally, don't follow a script
- **Open threads, not interrogations** — Surface multiple interesting directions and let the user follow what resonates
- **Visual** — Use ASCII diagrams liberally when they'd help clarify thinking
- **Adaptive** — Follow interesting threads, pivot when new information emerges
- **Patient** — Don't rush to conclusions, let the shape of the problem emerge
- **Grounded** — Explore the actual codebase when relevant, don't just theorize
---
## What You Might Do
Depending on what the user brings, you might:
**Explore the problem space**
- Ask clarifying questions that emerge from what they said
- Challenge assumptions
- Reframe the problem
- Find analogies from game development
**Investigate the codebase**
- Map existing architecture relevant to the discussion
- Find integration points and Zenject bindings
- Identify patterns already in use (DI containers, signals, factories)
- Surface hidden complexity and coupling
- Trace data flow through systems
Use the `recon-agent` alias for parallel codebase investigation. When the exploration topic touches multiple systems or modules, launch 1-5 of them to gather context faster:
```
recon-agent(prompt:
"In [project root], find files and modules related to [topic keywords].
Report: key directories, relevant files, existing patterns, integration points.
Thoroughness: quick|medium. Be concise — return a structured summary, not file contents.")
```
**Fallback:** If Agent tool is unavailable, use Glob/Grep/Read directly.
**Compare options**
- Brainstorm multiple approaches
- Build comparison tables
- Sketch tradeoffs (performance, complexity, extensibility)
- Recommend a path (if asked)
**Visualize**
```
+------------------------------------------+
| Use ASCII diagrams liberally |
+------------------------------------------+
| |
| +----------+ +----------+ |
| | System A |------->| System B | |
| | (State) | | (View) | |
| +----------+ +----------+ |
| | |
| v |
| +----------+ |
| | Zenject | |
| | Binding | |
| +----------+ |
| |
| System diagrams, state machines, |
| data flows, DI graphs, component |
| hierarchies, scene compositions |
+------------------------------------------+
```
**Surface risks and unknowns**
- Identify what could go wrong
- Find gaps in understanding
- Suggest spikes or investigations
- Flag performance concerns
---
## Step 0: Bootstrap Context (MANDATORY)
Before responding to the user — before any exploration, questions, or analysis — you MUST load the project context. This is not optional. Do it silently (don't narrate the loading process to the user), but do it completely.
This step has **no exceptions**. It used to have exactly one — `init` rebuilt the researches
index and needed no project context — and that mode no longer exists: the registry is
re-rendered as part of every save. The absence is recorded here rather than left silent,
because a MANDATORY step that once had a hole reads like an oversight when the hole simply
closes.
### Required reads (always, every time)
Read ALL of these files in parallel before doing anything else:
1. **`.unikit/DESCRIPTION.md`** — project description, tech stack, constraints
2. **`.unikit/ARCHITECTURE.md`** — architecture decisions, folder structure, module rules
3. **Read `.unikit/memory/code/RULES_INDEX.md`**. Load rules:
- **RULES.md**: ALWAYS read `.unikit/RULES.md` first (highest priority)
- **Core**: read the Core table. For EACH row where Required By = `all` or contains `{{self_name}}` — read that file from `.unikit/memory/code/core/` using the Read tool. Do NOT skip any matching row. Always re-read at skill start, never rely on prior conversation cache
- **Stack**: load dynamically when the current task or context matches "Load When" column, or when a need arises during work
4. **`.unikit/skill-context/{{self_name}}/SKILL.md`** — project-specific skill overrides (if exists)
### Stack documentation enrichment (context7)
When the exploration topic involves a library or framework from the project's tech stack,
assess whether the loaded Stack rules provide enough information:
1. **Stack rule loaded and covers the topic** → proceed with available knowledge, no external lookup needed.
2. **Stack rule loaded but doesn't cover the specific question** (user asks about
API methods, configuration options, or features not described in the rule) →
keep the rule for project conventions, additionally query context7 for the
specific API documentation gap.
3. **No matching stack rule exists** but the topic involves a library/framework
from the project's tech stack (check `DESCRIPTION.md`) → query context7 as the
primary documentation source for that library.
**context7 query flow:**
1. `mcp__context7__resolve-library-id` — find the library ID.
2. `mcp__context7__query-docs` — focused query matching the specific aspect the user
is exploring (not a broad "everything about X" — target the concrete question).
**Fallback:** If context7 tools are unavailable or the lookup fails — proceed with
your own training knowledge, but explicitly tell the user that the information was not
verified against current documentation and may be outdated.
**Priority:** Stack rules (project conventions — "how we use it here") always take
precedence over context7 / web results (API reference — "what the library offers").
When both are loaded, use stack rules for coding patterns and project-specific decisions,
and external docs for API details and feature capabilities.
**Mid-exploration enrichment:** If the topic shifts during exploration and a new library
becomes relevant — apply the same logic at that point. Don't wait until the next full
context bootstrap.
### Optional reads (check if relevant)
- `.unikit/ROADMAP.md` — strategic milestones (if any). If ROADMAP.md contains a `## References` section with linked documents, and the exploration topic relates to a specific milestone — read the reference documents associated with that milestone (listed in the `Milestones` column of the References table). This provides the original requirements/design context behind the milestone without asking the user for additional input.
- `.unikit/code/researches/` — prior researches (check for related topics)
- `.unikit/code/plans/` — active feature plans (if any)
- **Game-design grounding** (only if a design workspace exists) — check `.unikit/gamedesign/GD-IDS.yaml`. **Schema guard:** it MUST be `version: 2` — on a pre-v2 `version: 1` registry, skip design grounding and emit a loud `WARN [design] GD-IDS.yaml is version 1 (pre-v2 layout); design grounding skipped` rather than silently misreading the old layout. When valid, **load the shared READ contract** `.unikit/system/gamedesign/design-read.md` and apply it: its **read surfaces** (read the registry — system `doc_status`/`version`/`depends_on`, flow `mode`/`goals`/`depends_on`, content `scale`/`belongs_to`/`fields` — and follow each entry's `source` path to `.unikit/gamedesign/systems/*.md` / `.unikit/gamedesign/flows/*.md` / `.unikit/gamedesign/content-types/*.md`; the human-readable views are GAME.md's `## System Map [gen]` / `## Flow Map [gen]` / `## Content Map [gen]`), its **Flow-First Resolution** (*intent decides the door*), and its **one-way boundary**. **First-class flow input:** when the exploration topic names or implies a **flow** (a player-facing sequence, onboarding / progression / pacing, a `FLOW-<slug>` id), ground **first-class on that flow** — not merely as a reactive add-on to a system; a system-shaped topic grounds on the system; ambiguous → ask (per design-read). An empty `flows: []` (or no `flows` key yet) → skip the flow read silently, never an error. **First-class content input:** when the topic names or implies a **content type** (a catalog, "the item types", a `CT-<slug>` id), ground **first-class on that content type** via the content door of the design-read ladder — its `CT.fields` schema, `scale`, and `belongs_to`; an empty `content_types: []` (or no `content_types` key) → skip the content read silently, never an error. **One-way boundary: explore may *read* design for grounding; it never writes or edits design — that flows through the `/unikit-gd-*` skills.**
### Why this matters
Without this context you'll give generic {{engine_name}} advice instead of advice grounded in this project's actual architecture, conventions, and patterns. The quality difference is enormous — this is the foundation that makes explore mode valuable.
### Input handling
The argument after `/unikit-explore` can be:
- **The slug of an existing research folder** in `.unikit/code/researches/` — this is an
**entry into the continuation cycle**, not a new topic. Read the manifest and continue that
research (see [Continuing a research](#continuing-a-research)).
- - **`ultra`** — the leading token switches on adaptive research artifacts. Load `{{skills_dir}}/{{self_name}}/references/ULTRA-RESEARCH-FORMAT.md` and follow it when saving. Everything before saving — the stance, the exploration itself — is unchanged. `ultra` is recognised **only** as the leading token; it is never inferred from the size or difficulty of the topic.
+ - **An ultra request** — the leading `ultra` token, or the same request in the user's own wording ("ultra research", "ultraresearch", "ultra explore", "ультраисследование", "run an ultra research on the save system") — switches on adaptive research artifacts. Load `{{skills_dir}}/{{self_name}}/references/ULTRA-RESEARCH-FORMAT.md` and follow it when saving. Everything before saving — the stance, the exploration itself — is unchanged. Ultra is **user-named, never model-inferred**: it is never chosen because the topic is large or difficult, and wording that only asks for care ("research this deeply", "a thorough investigation") is not an ultra request — explore normally.
- A vague idea: "object pooling system"
- A specific problem: "the save system is getting unwieldy"
- A system name: to explore its architecture
- A flow or player sequence: "the first-session flow", "the onboarding", a `FLOW-<slug>` id — a **first-class flow input** that grounds on the dynamics axis (per the design-read Flow-First Resolution)
- A content type or catalog: "the item types", "the loot catalog", a `CT-<slug>` id — a **first-class content input** that grounds on the catalog axis (per the design-read Flow-First Resolution)
- A comparison: "UniTask vs coroutines for this"
- A question: "how does the DI container handle scene transitions?"
- Nothing: just enter explore mode
If the argument matches the name of an existing folder in `.unikit/code/researches/`, treat it
as a continuation rather than a new subject, and follow
[Continuing a research](#continuing-a-research).
- If the leading token is `ultra`, strip it, treat the rest as the topic and explore normally; the mode only changes what is written at save time. `ultra` with no topic falls into the ordinary no-topic branch — ask for the topic, then work in ultra. If `references/ULTRA-RESEARCH-FORMAT.md` cannot be read, **degrade to a standard research** and print one line `WARN [ultra] reference missing — saving a standard research`: the exploration has already happened, and losing it over a missing reference file is not an acceptable trade.
+ On an ultra request, strip the ultra wording and the verb that carried it, treat the rest as the topic and explore normally; the mode only changes what is written at save time. An ultra request with no topic falls into the ordinary no-topic branch — ask for the topic, then work in ultra. If `references/ULTRA-RESEARCH-FORMAT.md` cannot be read, **degrade to a standard research** and print one line `WARN [ultra] reference missing — saving a standard research`: the exploration has already happened, and losing it over a missing reference file is not an acceptable trade.
### Exploration mode detection
Determine the exploration mode based on user input:
- **File-based exploration**: The user's request contains explicit references to files or folders with documentation to research (e.g., "Сделай исследование на основе документов `docs/feature.md`", "Research these files: `path/to/spec.md`"). In this mode, the primary source of truth is the referenced documents.
- **Prompt-based exploration**: The user's request is a topic, question, idea, or problem statement WITHOUT references to specific documentation files. Examples: "explore object pooling", "how should we refactor the save system?", "compare UniTask vs Coroutines". The primary source is the interactive dialogue with the user.
Remember this mode — it determines whether `SOURCE.md` is generated when saving (see [SOURCE.md for prompt-based explorations](#sourcemd-for-prompt-based-explorations)).
### When a plan exists
If the user mentions a plan or you detect one is relevant:
1. Read the existing plan from `.unikit/code/plans/`
2. Reference it naturally in conversation
3. Offer to capture insights in a research when decisions are made
---
## Saving Research Results
When the conversation crystallizes — insights have emerged, decisions were made, or the user wants to preserve context — offer to save the research.
### Research directory structure
All researches live in `.unikit/code/researches/`. Each research gets its own folder:
```text
.unikit/code/researches/<slug>/
├── RESEARCH.md ← the manifest
├── SOURCE.md ← dialogue log (prompt-based explorations only)
└── [adaptive artifacts] ← ultra only
├── CONTRACTS.md
├── C4-CONTEXT.md
├── C4-CONTAINER.md
├── C4-COMPONENT-<scope>.md
├── DEPENDENCY-GRAPH.md
└── ADR-NNNN-<slug>.md
```
### Naming convention
- **Name**: the folder is named `<slug>` — 4-5 words max, kebab-case, derived from the
research topic. **No date.**
- The date lives in the `Created:` and `Updated:` fields of the manifest header, which is
also where every age filter and all sorting read it from.
- The reason the date left the name is structural, not cosmetic: a dated folder makes the
continuation cycle impossible to express. `<date>-<slug>` cannot be *continued* tomorrow
without the name becoming a lie, so the format would quietly push every follow-up into a
second folder — which is exactly the duplication this format exists to remove.
### How to save
Ask:
```
Save this research to .unikit/code/researches/?
Research name: <generated-folder-name>
Options:
1. 💾 Yes — save research
2. 🚫 No
```
Based on choice:
- Yes → save the research to `.unikit/code/researches/<slug>/`, then re-render `researches/INDEX.md`
- No → skip saving → **STOP**
If the user agrees:
1. Determine the folder name: generate `<slug>` from the research topic (4-5 words,
kebab-case, no date).
**If that slug already names a folder in `.unikit/code/researches/`**, do not resolve it
silently. Ask:
```
AskUserQuestion: A research named <slug> already exists. What should happen?
Options:
1. Continue the existing research — append a session to it
2. Use another name — you type the slug
```
- *Continue* → enter [Continuing a research](#continuing-a-research); print
`WARN [research] <slug> exists — continuing it`.
- *Another name* → save under the slug the user gave; print
`WARN [research] <slug> exists — saving under <new-slug>`.
Both lines are printed **after** the answer, never instead of the question. An automatic
suffix (`-2`) is **forbidden**: the date used to be a separator as well as a sort key, and
a silently appended suffix is what makes addressing-by-meaning start finding the wrong
folder again. Refusing outright is not an option either — a continuation verb exists here,
and offering it costs less than a refusal.
2. Create the research directory:
```
mkdir -p .unikit/code/researches/<slug>
```
The order of writing is owned by `{{skills_dir}}/{{self_name}}/references/ULTRA-RESEARCH-FORMAT.md` → `## Write order`, and it is not restated here. **In a standard research, items 1 and 5 — the adaptive artifacts and the Integrity checks — simply do not apply**; the rest of the order holds unchanged, including that the registry is re-rendered before the gate runs.
**In ultra mode** the artifacts are written first and `RESEARCH.md` second. Writing the index of artifacts before the artifacts would point its links at files that do not exist yet.
3. Write `RESEARCH.md` — the manifest. One file carries the whole research: the machine-read header, the planner's input between the `## Active Summary` markers, the evidence in `## Findings`, and the append-only `## Sessions` log.
**In ultra mode**, the very first line of the file is the research mode marker `<!-- unikit:research-mode:ultra -->`, and a `## Artifact Index` section follows immediately after `## Table of Contents`. Both are specified in `references/ULTRA-RESEARCH-FORMAT.md`; neither is restated here.
Take `Created:` and `Updated:` from `date`, never from memory. Both feed the registry and `Updated:` is the sort key every reader uses, so a remembered date fails **silently** — it surfaces to the user as "no researches found", not as an error.
```markdown
# <Research Title>
Created: YYYY-MM-DD HH:MM
Updated: YYYY-MM-DD HH:MM
Status: completed | in-progress | needs-follow-up
Lifecycle: active | paused | superseded
Research: <slug>
Target: SYS-<slug> | FLOW-<slug> | CONTENT-<slug> (optional)
Kind: feature | improvement (optional)
Supersedes: <slug> (optional)
## Table of Contents
- [Artifact Index](#artifact-index) — ultra mode only; omit this line in a standard research
- [Active Summary](#active-summary)
- [Findings](#findings)
- [Sub-section 1](#sub-section-1)
- [Sub-section 2](#sub-section-2)
- [Sessions](#sessions)
- [References](#references)
## Active Summary
<!-- unikit:active-summary:start -->
Topic: <1-2 sentences: what was explored>
Goal: <what this research is for — the decision it has to enable>
Scope: <in / out — the out-half carries the stop condition>
Constraints: <`C-<n>` — what the subject imposes>
Requirements: <`REQ-<n>` — established by evidence>
Decisions: <`DEC-<n>` — taken, each with its reason in one line>
Risks: <`RISK-<n>` — material, not hypothetical>
Open questions: <`OQ-<n>` — unresolved; say which ones block>
Success signals: <how we will know the work landed>
Next step: <the one action that follows>
<!-- unikit:active-summary:end -->
## Findings
<Everything presented to the user during the exploration. This is the EVIDENCE and the
reasoning, never the requirement. Include ALL:
- ASCII diagrams and visualizations
- Detailed descriptions of systems and components
- Code examples and patterns found
- Comparison tables
- Architecture analysis
- Data flow descriptions
- Risk analysis and performance considerations>
## Sessions
<!-- unikit:sessions:start -->
### <YYYY-MM-DD HH:MM> — <session title>
- **What changed**: <one line per changed item, as `<ID> <name>: <old> → <new>`, with the
literal values and the tokens that carry them elsewhere. This line is the input to the
coherence gate's value sweep on the next save — prose here is paid for later in gate passes>
- **Key notes**: <what was learned>
- **Gate**: <`passed (N passes)` | `stopped at budget: <k> unresolved — OQ-…`>
- **Links (paths)**: <files read or written>
<!-- unikit:sessions:end -->
## References
<Relevant files, documentation, external resources.
If context7 or web search was used during exploration, include the library names
and specific topics that were queried — this helps reproduce or update the research later.
Example: "R3 (context7: Observable.CombineLatest usage patterns)", "DOTween (web: sequence API)">
```
Filling the `What changed` line — one item per line, values and their carriers named:
```markdown
- **What changed**: `DEC-51` direction_count: base 3 → 5 (carriers: `direction_count`, "base 3")
`DEC-49` card catalogue: 12 → 13 (carriers: `DEC-49`, "13", "thirteen")
```
**The two state axes are separate.** `Status` is completeness, and its three values never
change — the `/unikit-plan` registry filter greps this field by name and answers "no
researches" rather than an error when it is renamed. `Lifecycle` is currency. Neither is
derivable from the other.
**Table of Contents is mandatory.** Place it immediately after the header block and before
`## Artifact Index` / `## Active Summary`. It must reflect the document's actual sections and
sub-sections — not a copy of the template above. Research documents get long, and the TOC is
how both humans and agents reach the section they need.
**`## Active Summary` is the planner's input and the only hashed region.** Write it to be read
cold, by someone who never saw the conversation. `## Findings` holds the reasoning that
produced it; the summary holds the conclusion. A fact belongs to exactly one of the two — the
other refers to it by ID, never by retelling it.
**Language Awareness for `RESEARCH.md`**: the manifest follows the same language rules as
every other artifact. When the configured language is not English, translate section headings
and prose into the target language. Field **names** in the header (`Created:`, `Status:`,
`Lifecycle:`, …), the marker comments, ID prefixes, code identifiers, code blocks and file
paths stay in English — they are read by machines.
**Where the previous sections went.** The retired three-file format put seven owning sections
in its result document. They are gone *as owners* and their content is redistributed; recorded
here so the next edit does not restore them "for completeness":
| Previous section | New owner |
|------------------|-----------|
| `## Topic` | `## Active Summary` → `Topic:` |
| `## Context` | `## Active Summary` → `Goal:` / `Scope:` |
| `## Exploration` | `## Findings` |
| `## Conclusions` | `## Findings` for the reasoning; `## Active Summary` → `Requirements:` / `Risks:` for the requirement |
| `## Decisions` | `## Active Summary` → `Decisions:` (`DEC-<n>`) |
| `## Open Questions` | `## Active Summary` → `Open questions:` (`OQ-<n>`) |
| `## Next Steps` | `## Active Summary` → `Next step:` |
| `## References` | stays its own section, at the end |
`## References` stays standalone rather than folding into `## Findings` on purpose: `## Findings`
is the section that grows without bound, and a reference list buried inside it stops being
findable.
### SOURCE.md for prompt-based explorations
If the exploration was **prompt-based** (see [Exploration mode detection](#exploration-mode-detection)), generate an additional artifact `SOURCE.md` in the same research directory. This file captures the full dialogue context so that the exploration can be reproduced or continued later without losing any context.
`SOURCE.md` is a **log, not a derived representation of the research.** Two consequences,
both deliberate: it is **not** part of the hashed region (only `## Active Summary` inside
`RESEARCH.md` is), and it is **not** in the coherence gate's durable scope. A log is allowed
to be redundant with the manifest — that is what a log is for, and admitting it to the gate
would hand back exactly the job of reconciling two differently-written texts.
**When to generate**: Only for prompt-based explorations (user gave a topic/question/idea without referencing specific documentation files). Do NOT generate for file-based explorations (user referenced specific files/folders as input documentation).
**Template**:
```markdown
# Exploration Request
## Original Request
<The exact text of the user's initial request/prompt that started this exploration>
## Questions & Answers
### Q1: <Exact question text as it was asked>
**Answer**: <The answer that was given — by user or discovered during exploration>
### Q2: <Exact question text>
**Answer**: <The answer>
<!-- Continue for all questions asked during the exploration -->
## Additional Clarifications
<All additional details, corrections, and clarifications the user provided during the exploration that were not direct answers to questions. If none — write "None">
## Conclusion
<The final result of the exploration: what was decided, what approach was chosen, what understanding was reached. This should be a concise summary of the outcome, not a copy of RESEARCH.md>
```
**On a continuation, append — never rewrite.** A new session adds a fresh block
`## Session <YYYY-MM-DD HH:MM>` at the end of the file, carrying that session's questions,
answers and clarifications. Everything already in the file stays exactly as it is. The point
of a dialogue log is that it records what was actually said at the time, and an edited log
records only what the last session believed.
**Language Awareness**: Follow the same language rules as other artifacts. Translate section headings and prose into the configured language. Keep code identifiers and file paths in English.
**Important**: Capture the actual dialogue content faithfully. The value of this artifact is in preserving the exact questions, answers, and clarifications — not in summarizing or rephrasing them.
### Step 4: Re-render the Researches Index
`.unikit/code/researches/INDEX.md` is a **generated** registry. It is not edited and it is not
appended to: on every save it is re-rendered whole from the folders on disk, so it cannot fall
behind them.
1. List the subfolders of `.unikit/code/researches/`.
2. For each, read its `RESEARCH.md` and take: the **first line** (the mode marker — present
means `ultra`, absent means `standard`), the H1 title, the header fields `Created` /
`Updated` / `Status` / `Lifecycle` / `Target`, and the `Topic:` line from
`## Active Summary` — that line **is** the `Summary`.
3. A folder with no readable `RESEARCH.md` is skipped, and the skip is **printed**:
```
WARN [research] skipped <folder> — no readable RESEARCH.md
```
Skipping in silence is forbidden. An unreadable manifest and an honestly empty registry
look identical from the outside, so an unannounced skip reports "no researches" for a
research that is sitting right there on disk.
4. Overwrite the file whole. The header is always:
```markdown
# Researches Index
> Generated by /unikit-explore on every save. Do not edit manually — edits are overwritten.
```
5. Each record:
```markdown
---
### <Research Title>
- **Created**: YYYY-MM-DD HH:MM
- **Updated**: YYYY-MM-DD HH:MM
- **Status**: completed | in-progress | needs-follow-up
- **Lifecycle**: active | paused | superseded
- **Mode**: standard | ultra
- **Summary**: <1-2 sentences, from `Topic:`>
- **Path**: `<slug>/`
- **Target**: SYS-<slug> (optional, omit the line when absent)
```
6. Sort by `Updated` descending; ties broken by `Created` descending; then by folder name.
`Updated` is the key on purpose — in a research with a continuation cycle, freshness means
"when this was last confirmed", not "when the folder was opened".
7. After the re-render, print the reconciliation summary — the same three lines the retired
`init` command printed:
```
researches/INDEX.md re-rendered:
- Kept: N
- Added: N (list names)
- Removed: N (list names)
```
**Reconciliation is no longer a separate verb.** There used to be an `init` argument whose
whole job was to rebuild this file from disk; it is gone, and its work is now part of every
save — the same pattern as `syncRulesState` Phase 1 and the `## System Map [gen]` re-render in
game-design. It stopped being a separate command, but it did **not** stop being **visible**,
which is what step 7 is for.
The cost is worth naming: the registry can no longer be repaired by a dedicated command. In
exchange it can no longer fall behind, because it is rebuilt from the folders — the actual
source of truth — before the coherence gate reads the same files from disk.
### Research Coherence Gate
After **all** writing is done — the artifacts, `RESEARCH.md`, `SOURCE.md` and the re-rendered
`researches/INDEX.md` — and **before** confirming the save to the user, read
`{{skills_dir}}/{{self_name}}/references/coherence-gate.md` and run the gate it specifies as a `check-agent` dispatch.
The read is conditional: this is the only moment the file is needed, so it is not loaded at
the start of an exploration.
Its position is fixed: **after Step 4, before Step 5.** The order matters in both directions.
The gate re-reads the durable files from disk, so running it before the write has nothing to
read; and confirming before it runs tells the user the research is safe while it may still be
incoherent.
In ultra the gate runs **after** the bundle integrity checks, not instead of them.
If `references/coherence-gate.md` cannot be read, print one line
`WARN [coherence] reference missing — saving without the coherence pass` and continue — the
same trade as the ultra reference above: the research has already been done and written, and
losing it over a missing reference file is not acceptable.
### Step 5: Confirm the save
Only once the gate has **finished** — passed, or stopped at its budget with the user's answer
in hand — tell the user what was written: the folder, the manifest, any adaptive artifacts,
and the registry line. Until then the save is not confirmed — a gate that runs after the
confirmation is a gate that reports on a decision already announced.
A save the user authorised over surviving findings is confirmed like any other; its session
entry then reads `stopped at budget: <k> unresolved`, not `passed`. That record is where the
override lives — not a withheld confirmation.
### Important rules for saving
- **Don't auto-save** — Always offer and let the user decide
- **Generate the name** from the research context — don't ask the user to name it
- **One manifest** — `RESEARCH.md` carries the research. There is no second canonical file and
no brief: `## Active Summary` *is* the machine input, and `## Findings` holds the evidence
that produced it
- **`SOURCE.md` only for prompt-based explorations** (see [SOURCE.md for prompt-based explorations](#sourcemd-for-prompt-based-explorations)), appended to on a continuation, never rewritten
- **The registry is re-rendered whole on every save** — never edited, never appended to; this
is how other skills discover researches, and how it stays in step with the folders
- **Run the coherence gate** — it is part of saving, not an option. It runs *after* the user has agreed to save, so it neither replaces the question nor weakens `Don't auto-save`
- The user may edit the suggested name before you save
---
## Continuing a research
A research is not finished when it is saved — it is **continued**. This is the reason the
folder name carries no date.
**Entry.** Either the argument named an existing folder in `.unikit/code/researches/`, or the
user chose *Continue the existing research* in the collision dialogue during a save.
**Procedure.**
1. Read the folder's `RESEARCH.md` in full — the header, `## Active Summary`, `## Findings`
and every past `## Sessions` entry. In ultra, read the files in `## Artifact Index` too.
2. Explore further, exactly as in a fresh session.
3. When saving:
- **Append** a new entry to `## Sessions`, immediately **before** the closing marker.
Past entries are reproduced verbatim — the section is append-only.
- Move `Updated:` to now (from `date`). `Created:` never changes.
- **Revise `## Active Summary` in place.** New IDs continue the existing numbering; an ID
is never reused; a superseded item **keeps its number**, is marked superseded, and names
what replaced it. Revising the summary is the point of a continuation — a session that
only appends to `## Findings` has recorded evidence without ever updating the conclusion.
- Reconsider `Status` and `Lifecycle` **explicitly**, and say what they became. Neither
carries over by default; a research that has quietly stayed `in-progress` across four
sessions is telling the registry something nobody decided.
- Append the session's dialogue to `SOURCE.md` if the exploration is prompt-based.
- Re-render the registry and run the coherence gate, exactly as on a first save.
4. **Say it out loud when the folder has outgrown its question.** From the fourth session, or
past fifteen artifacts, print one line and continue — a note, never a gate:
```
NOTE: 4th session, 17 artifacts — a research that keeps growing past its original question
is cheaper to close and restart with `Supersedes:` than to extend.
```
The threshold counts **sessions**, not artifacts: repeated passes are what multiply the
carriers of one value. A large folder written in one sitting is not the problem this note
is about.
**Superseding a whole research.** When a new research replaces an old one rather than
continuing it, the new one carries `Supersedes: <slug>` in its header and the old one is set
to `Lifecycle: superseded`. The superseded folder is **not deleted** — it is the trace of the
reasoning, and removing it makes the replacement look unmotivated.
---
## What You Don't Have To Do
- Follow a script
- Ask the same questions every time
- Produce a specific artifact
- Reach a conclusion
- Stay on topic if a tangent is valuable
- Be brief (this is thinking time)
---
## Handling Different Entry Points
**User brings a vague idea:**
```
User: I'm thinking about adding an object pooling system
You: Object pooling is a broad space in {{engine_name}}. Let me think about this...
POOLING APPROACHES IN {{engine_name}}
Simple Managed Advanced
| | |
v v v
+--------+ +---------+ +----------+
|Queue<T>| |Pool with| |Addressable|
| Manual | |Auto-grow| | + Pool |
| return | |+ Limits | | Async Load|
+--------+ +---------+ +----------+
| | |
trivial moderate complex
What are you pooling? Projectiles? UI elements? Enemies?
```
**User brings a specific problem:**
```
User: The inventory system is a mess, everything is coupled
You: [reads codebase]
+----------------------------------------------+
| CURRENT INVENTORY FLOW |
+----------------------------------------------+
|
+-------------+-------------+
v v v
+---------+ +---------+ +---------+
| Item | | Slot | | UI |
| Manager | | System | | Display |
+----+----+ +----+----+ +----+----+
| | |
+------+------+------+------+
| |
v v
+---------+ +---------+
| Save | | Zenject |
| System | | Binding |
+---------+ +---------+
I see tight coupling in three places. Which one hurts most?
```
**User wants to compare options:**
```
User: UniTask vs Coroutines for our async loading?
You: Context matters here. Let me check what you're already using...
[reads codebase, finds patterns]
+----------------------------------------------+
| ASYNC PATTERNS IN YOUR PROJECT |
+----------------------------------------------+
Coroutines UniTask
Cancellation manual CancellationToken
Error handling silent fail try/catch
Return values callback await result
Testability hard easy
Zenject DI awkward natural
Performance GC alloc zero-alloc
You already use UniTask in 3 systems. Consistency
alone makes the case. But there's more...
```
**User is stuck mid-implementation:**
```
User: /unikit-explore save-load-system
The serialization is more complex than expected
You: [reads plan from .unikit/code/plans/]
You're on task 4: "Implement save serialization"
Let me trace what's involved...
[draws diagram, explores options, suggests paths]
Want to capture this as a research for reference?
```
---
## Ending Discovery
There's no required ending. Discovery might:
- **Flow into action**: "Ready to plan? Run `/unikit-plan`"
- **Result in saved research**: "Saved to `.unikit/code/researches/inventory-decoupling/`"
- **Just provide clarity**: User has what they need, moves on
- **Continue later**: "We can pick this up anytime"
When it feels like things are crystallizing, you might summarize:
```
## What We Figured Out
**The problem**: [crystallized understanding]
**The approach**: [if one emerged]
**Open questions**: [if any remain]
**Next steps** (if ready):
- Save research: I'll create a research record
- Create a plan: /unikit-plan [fast|full|ultra] <description>
- Keep exploring: just keep talking
```
But this summary is optional. Sometimes the thinking IS the value.
---
## Guardrails
- **Don't implement** — Never write feature code. Saving research files is fine, writing application code is not
- **Don't fake understanding** — If something is unclear, dig deeper
- **Don't rush** — Discovery is thinking time, not task time
- **Don't force structure** — Let patterns emerge naturally
- **Don't auto-save** — Offer to save research, don't just do it
- **Do visualize** — A good diagram is worth many paragraphs
- **Do explore the codebase** — Ground discussions in reality
- **Do question assumptions** — Including the user's and your own