{{engine_name}} Feature Implementation
Execute tasks from a feature plan stored in .unikit/code/plans/. This skill reads the plan, identifies pending work, and implements tasks inline with Read/Edit/Write/Bash after a one-time Bootstrap of rules and principles. The develop-agent alias is reserved for true parallel scopes or deep-dive single tasks.
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.
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.
Delegation agents
This skill uses named delegation aliases for Agent(...) calls. Each alias expands to an Agent(subagent_type: "general-purpose", ...) invocation with the matching skill loaded.
develop-agent— used ONLY for true parallel scopes or deep-dive single tasks. Sequential tasks are implemented inline by this skill using rules loaded in Bootstrap. Expands to:Agent( subagent_type: "general-purpose", prompt: "/unikit-devcontext <task details>", description: "Implement <task>", skills: ["unikit-devcontext"] )<task details>is a closed hand-off: whatever is not in it, the delegate does not see. When the task carriesEditor:lines, they go into the prompt verbatim, together with the resolvedEditor tasksmode and the matching### EDITOR TARGETSrows from the manifest's## Technical Context(Step 3.2, Delegated execution). In an ultra bundle those rows are not in the manifest — the task's editor targets live in the### Required Interfaces and Contractsof its own section in the phase file, and that is where they are taken from.Fallback: if the
Agenttool is unavailable, invoke/unikit-devcontextinline.rules-agent— capture a new project rule. Expands to:Agent( subagent_type: "general-purpose", prompt: "/unikit-rules Add rule: <rule text>", description: "Record project rule", skills: ["unikit-rules"] )Fallback: if the
Agenttool is unavailable, invoke/unikit-rulesinline, one rule at a time.docs-agent— update or create documentation. Expands to:Agent( subagent_type: "general-purpose", prompt: "/unikit-docs <context>", description: "Update documentation", skills: ["unikit-docs"] )Fallback: if the
Agenttool is unavailable, invoke/unikit-docsinline.
Input
$ARGUMENTS — optional. Can be:
- Empty — execute all pending tasks from the latest feature, in order
--list— list available feature plans in.unikit/code/plans/and STOP (no implementation)@<path>— explicit path to a feature folder, resolved from project root. Bypasses all auto-detection. Use when you need to point to a plan outside.unikit/code/plans/or want an unambiguous full path (e.g.@.unikit/code/plans/2026-03-10_core-loop,@/absolute/path/to/plan-folder)status— show progress without executing any tasksPhase N(e.g.Phase 3) — execute only tasks from Phase NPhases N-M(e.g.Phases 1-3) — execute tasks from Phases N through MTask N.MorTasks N.M N.K(e.g.Tasks 2.1 2.3 5.2) — execute only the specified tasks- Feature name (e.g.
core-loop) — shorthand lookup: scans.unikit/code/plans/for a folder whose name contains this value. Compared to@<path>, this is a convenience shorthand that only searches inside.unikit/code/plans/
@<path> vs Feature name: @ takes an explicit path (relative or absolute) and expects a folder holding a plan manifest — .unikit/code/plans/<folder>/PLAN.md — inside; no searching. A bare name without @ is a fuzzy match inside .unikit/code/plans/. When both could apply, @ wins (highest priority).
Mixed input is supported: @.unikit/code/plans/2026-03-08_customers-system Phase 3 (explicit path + phase), core-loop Phase 3 (name search + phase), Tasks 2.1 2.3 (specific tasks from latest feature).
Workflow
Step 0: Pre-flight Checks
0.1: Parse Arguments & Find the Feature Folder
Parse $ARGUMENTS (priority order):
- If
$ARGUMENTScontains--list→ skip to List Available Plans section - If
$ARGUMENTScontains@<path>→ extract path after@, use as explicit feature folder (skip all auto-detection). See Explicit Folder Override below. - If
$ARGUMENTSis or containsstatus→ skip to Status Display section (can combine with@<path>) - Look for explicit selectors (can combine with
@<path>or feature name):Phase N— single phasePhases N-M— phase rangeTask N.MorTasks N.M N.K— specific tasks
- If no
@<path>was found, check remaining args for a feature name — a bare string (no@prefix) that matches a folder name in.unikit/code/plans/by substring (e.g.core-loopmatches2026-03-10_core-loop). This is a convenience shorthand that only searches inside.unikit/code/plans/. - Bare numbers without prefix are NOT selectors — they might be part of the feature name. Phases and tasks must be explicitly prefixed.
List Available Plans (--list)
If $ARGUMENTS contains --list, run read-only plan discovery and stop.
- Get current branch:
git branch --show-current(if git is unavailable, skip branch matching) - Scan
.unikit/code/plans/for all feature folders - Check existence of
.unikit/code/FIX_PLAN.md - For each feature folder, read its manifest (
.unikit/code/plans/<folder>/PLAN.md) and count completed/total tasks - Print plan availability summary:
Available plans in .unikit/code/plans/:
Branch match:
core-loop (12/40 tasks, 30%) ← matches current branch
Other plans: (newest first, by manifest Updated:)
customers-system (18/18 tasks, 100% — completed)
2026-03-08_inventory-rework (5/22 tasks, 23%)
003-legacy-shop-rework (7/9 tasks, 78%)
Fix plan: .unikit/code/FIX_PLAN.md — exists
Usage:
/unikit-implement — auto-detect by branch
/unikit-implement @.unikit/code/plans/<folder> — use specific plan
/unikit-implement <folder-name> Phase 3 — specific folder + phase
Important: In --list mode — do not execute tasks, do not modify files. STOP after displaying the list.
Explicit Folder Override (@<path>)
If $ARGUMENTS contains @<path>:
- Extract path after
@(e.g.@.unikit/code/plans/2026-03-08_customers-system→.unikit/code/plans/2026-03-08_customers-system) - Resolve relative to project root (absolute paths are also valid)
- If folder does not exist or does not contain a plan manifest (
<path>/PLAN.md):
→ STOPFeature folder not found or invalid: <path> Expected a folder with a PLAN.md manifest inside, for example: /unikit-implement @.unikit/code/plans/2026-03-10_core-loop If this plan predates the manifest merge, run: unikit-ai update - Use this folder as the active feature — skip all auto-detection logic
The @<path> argument can be combined with selectors: /unikit-implement @.unikit/code/plans/2026-03-08_customers-system Phase 3
Feature folder resolution priority:
@<path>— explicit path, no searching (highest)- Feature name — bare string, substring match inside
.unikit/code/plans/ - Auto-detect — git branch match or latest by date (lowest, see below)
If no feature folder specified (no @<path>, no feature name in args) — auto-detect:
Use unified plan detection (priority order):
Fast plan check — if
.unikit/code/PLAN.mdexists, use it (flat fast-mode plan). Both plan forms are a single manifest: the flat.unikit/code/PLAN.mdand the folder's.unikit/code/plans/<folder>/PLAN.mdcarry checklist, settings and## Technical Contextinline. There is no second file to read.Git branch match — get current branch via
git branch --show-current. If git is unavailable, skip to the next priority level.Branch match. From branch
<prefix><name>, collect every folder in.unikit/code/plans/that matches any of the three name formats: (1) exactly<name>— the current format; (2) ending with_<name>— theYYYY-MM-DD_<name>format; (3) ending with-<name>and beginning with three digits — the legacyDDD-<name>format. Exactly one match → use it. More than one → ask the user which one, listing each with itsUpdated:— do not pick by format precedence: two folders for one feature is exactly the state the date used to prevent, and choosing silently is how the resolver starts finding the wrong one. No match → fall through to latest.Latest (fallback) — read the
Updated:line from each candidate's.unikit/code/plans/<folder>/PLAN.mdand sort descending; ties break onCreated:descending, then on folder name descending. A manifest with noUpdated:is excluded and named —WARN [plan] <folder>: manifest has no Updated: — excluded; run unikit-ai update to backfill it— never guessed from the folder name and never from the file's mtime, whichgit checkoutand a fresh clone rewrite.latest fallbackis a guess, not a resolution: the branch named no plan. With two or more plans present, print the candidate table (folder,Updated:, tasks remaining) and ask — never auto-select. With exactly one plan present there is nothing to choose between: announce it with the branch miss named in the reason and continue.
Announce the resolution. Print exactly one visible line before any other output:
INFO [plan] resolved: <path> (<reason>)
<reason> is exactly one of: explicit path · feature name · fast plan · fix plan ·
branch match: <branch> · latest fallback. This is plain output, never the payload of an
interactive question.
- If
.unikit/code/plans/is empty or doesn't exist (and no.unikit/code/PLAN.md):
First, check for .unikit/code/FIX_PLAN.md:
If .unikit/code/FIX_PLAN.md exists — a fix plan was created by /unikit-fix in plan mode. Redirect to fix workflow:
Fix plan detected (.unikit/code/FIX_PLAN.md).
This plan was created via /unikit-fix and should be executed through the fix workflow
(it creates a patch and automatically cleans up the plan after execution).
Launching /unikit-fix to execute the plan...
→ /unikit-fix (without arguments — it will detect FIX_PLAN.md and execute it).
→ STOP — do not continue with implement workflow.
If no plan found at all:
Instead of silently stopping, present an interactive menu:
No active plan found. Current branch: <current-branch>.
Options:
1. Plan a new feature — /unikit-plan full <description>
2. Plan a quick task — /unikit-plan fast <description>
3. Fix a bug — /unikit-fix <description>
4. Just checking status — show branch info and stop
Based on choice:
- Plan feature → ask for description via AskUserQuestion, run
/unikit-plan full <description> - Quick task → ask for description, run
/unikit-plan fast <description> - Fix bug → ask for description, run
/unikit-fix <description> - Just checking → show
git branch --show-current+git log --oneline -5→ STOP
STOP here after handling the choice.
If both .unikit/code/PLAN.md and a matching folder plan exist, ask the user which one to use.
Ultra bundle check. Read the first line of the resolved plan manifest. If it equals <!-- unikit:plan-mode:ultra -->, this is an ultra bundle: follow .unikit/system/ultra-plan-read.md for reading depth, integrity and mutability. Otherwise continue unchanged. Discovery itself does not change — the folder is found the way it always was; only what is read inside it differs.
Reading depth: read the manifest plus the phase file of the active task — one task is executed at a time, so holding every phase in context means holding what is not being executed. Re-read the active phase file on resume, even when a previous session already read it.
0.2: Check for Uncommitted Changes
Skip this step for read-only modes (--list, status) — they already STOPped in Step 0.1.
Before any implementation work, check git status. If git is unavailable (not initialized), skip this step entirely and proceed to plan loading.
git status
If uncommitted changes exist:
Uncommitted changes detected.
Options:
1. Commit now (recommended)
2. Stash and continue (git stash)
3. Continue as is
4. Cancel — I'll handle it myself
Based on choice:
- Commit now → run /unikit-commit, then continue to plan discovery
- Stash →
git stash push -m "unikit-implement: stash before execution", then continue - Continue as is → leave the working tree untouched, continue to plan discovery
- Cancel → inform "Implementation cancelled." → STOP
0.3: Resume / Recovery (after /clear or session break)
If the user is resuming after a break, says the session was abandoned, or context was likely lost (e.g. after /clear), rebuild context from the repo before continuing. If git is unavailable, skip git commands and rely on plan file state only.
git status
git branch --show-current
git log --oneline --decorate -15
git diff --stat
Then reconcile plan state with reality:
- Read the plan manifest (
.unikit/code/plans/<folder>/PLAN.md, or the flat.unikit/code/PLAN.md) and check which tasks are marked[x] - For tasks marked
[x], spot-check that the corresponding code actually exists (read a key file or check for expected classes/methods) - If code for a completed task is missing (e.g. after reset/rebase), revert the checkbox back to
- [ ]and inform the user - If code exists but the task isn't marked complete, mark it
[x]and inform the user
Step 1: Load Plan Context
- Read the plan manifest —
.unikit/code/plans/<folder>/PLAN.mdfor a folder plan,.unikit/code/PLAN.mdfor a flat fast-mode plan. In fast and full one file carries everything:## Overview,## Settings, the## Checklistwith phases, dependencies and completion status, and## Technical Context(constraints, interfaces, key patterns, dependency graph, files, editor targets, DI bindings). In an ultra bundle it does not: the manifest carries the checklist and only the cross-phase part of## Technical Context, while every task's own detail lives in its phase file — the reading depth is stated in.unikit/system/ultra-plan-read.md. For the full section list seeunikit-plan/references/TASK-FORMAT.md→ Plan Manifest Template; it is not restated here. - If the manifest has a
## Based onsection pointing to a research, do NOT read that research'sRESEARCH.mdas a substitute for the plan's own context. The plan's## Technical Contextis authoritative and supersedes the research summary (/unikit-plan: it was synthesized from the research and then verified against the code). The research is read for one purpose only — the drift check below. - Read
.unikit/DESCRIPTION.md— project specification, tech stack, constraints - Read
.unikit/ARCHITECTURE.md— project structure, tech stack, and pointers to detailed rules
Research drift check. For each entry in ## Based on:
- Only when the entry carries a
Summary SHA256, recompute the SHA256 of the region between the## Active Summarymarkers of that research'sRESEARCH.md, by the canonical procedure. An entry that carries noSummary SHA256is resolved by branch 5 or branch 6 and nothing is recomputed for it — the branches are read in order, so this precondition is settled before the first comparison, and skipping it is how a pre-manifest entry gets reported as drifted instead of unknown. Rule 0 — extract the text between<!-- unikit:active-summary:start -->and<!-- unikit:active-summary:end -->, excluding the marker lines themselves; both markers are matched as whole lines. Then the five normalization rules — strip a leading UTF-8 BOM, LF line endings, trailing spaces trimmed from every line, exactly one final newline, no reformatting (line order and leading whitespace preserved) — fed through stdin, never a temp file:… | shasum -a 256 | awk '{print $1}', falling back tosha256sum. Rule 0 runs on text already read; it needs no grant of its own. - Recomputed == the recorded
Summary SHA256→ say nothing and continue. - Recomputed ≠ the recorded
Summary SHA256→ emitWARN [research-drift]: <folder> — the linked Active Summary is no longer byte-identical to the one this plan was built fromand continue against the plan, not against the research. Do not expand scope, do not add tasks, do not rewrite the hash. A rebase is/unikit-improve's job and happens only when the user explicitly asks for it. The wording is deliberate: the summary is the declared input and is rewritten wholesale whenever the research is saved, so a mismatch proves the input is not the same bytes — not that the author changed their mind. Claiming the latter would make the warning read as a finding. RESEARCH.mdmissing or unreadable, or its## Active Summarymarkers absent or duplicated → emitWARN [research-drift]: <folder> source missingand continue against the plan.- The entry carries a
Brief SHA256and noSummary SHA256→ emitWARN [research-drift]: <folder> drift unknown (recorded against the retired brief field). Nothing is recomputed: the recorded digest describes a different object, and comparing it against the summary would print "the research changed" where the honest answer is "there is no mechanism here". The repair is the standard re-link in/unikit-improveStep 5.5. - No hash field of either name recorded (a plan predating both) → drift is unknown, not absent. Emit
WARN [research-drift]: <folder> drift unknown (no hash recorded). - Neither
shasumnorsha256sumavailable → emitWARN [research-drift]: no SHA256 tool available — drift checks skippedonce for the whole run, and continue.
The label WARN [research-drift] is canonical and the same for every outcome; per-branch labels would make them indistinguishable when a log is grepped for drift. Branches 5 and 6 both report "unknown" and are worded apart on purpose: one needs a re-link, the other is merely older than the field, and the log line is the only place that difference is visible.
There is no bundle-validation branch here. ## Based on always names a folder under .unikit/code/researches/, and the hashed object is always one fixed section in one fixed file — one shape, one region. A source path that varies between a single configured file and a bundle entry point would need such a branch; UniKit's does not.
Drift is printed once, here at plan load — not before each task. Execution continues on the scope of the plan; the offer to re-plan goes into the Step 5 final report as the single line Research drifted — consider /unikit-improve <plan> before continuing.
The manifest's ## Overview tells you WHAT to do and WHY; its ## Technical Context tells you HOW; DESCRIPTION.md and ARCHITECTURE.md give project-wide context.
Read .unikit/skill-context/unikit-implement/SKILL.md — MANDATORY if the file exists.
This file contains project-specific workflow rules added by /unikit-skills-context or /unikit-evolve.
These rules change how this skill orchestrates work (priorities, delegation, commit behavior, etc.).
How to apply skill-context rules:
- Treat them as project-level overrides for this skill's general instructions
- When a skill-context rule conflicts with a general rule written in this SKILL.md, the skill-context rule wins (more specific context takes priority)
- When there is no conflict, apply both: general rules from SKILL.md + project rules from skill-context
- Do NOT ignore skill-context rules even if they seem to contradict this skill's defaults — they exist because the project's experience proved the default insufficient
Parse Settings:
Read the ## Settings section from the plan manifest:
Testing: yes→ after completing each phase, write tests inline (default) for the code created in that phase, or viadevelop-agentfor parallel/deep-dive (same execution-mode logic as Step 3.2)Testing: no→ skip test creation entirelyDocs: yes→ after all tasks are completed, show a mandatory documentation checkpoint (Step 5.3)Docs: no→ skip documentation checkpoint, emit warningEditor tasks: mcp | manual | direct→ how tasks carrying anEditor:line are carried out (Step 3.2). Default when the line is absent:mcpif the engine MCP is configured (MCP server{{engine_mcp_tool}}present in{{settings_file}}at the project root — the same probe as Step 3.6), otherwisemanual. Never default todirect: it is irreversible and requires a git commit first, so it is only ever an explicit choice.
If ## Settings section is missing, default to Testing: no, Docs: no, and resolve Editor tasks by the same probe (mcp when the engine MCP is configured, otherwise manual).
Store the parsed settings — they affect behavior in Step 3.2 (editor targets), Step 3.8 (tests), Step 3.9 (commit), and Step 5.3 (documentation).
Understand:
- Which tasks are completed (
- [x]) and which are pending (- [ ]) - Phase dependencies (a phase can only start when its dependencies are done)
- The overall architecture and technical decisions from the description
Step 1.5: Bootstrap Rules & Principles
Load the project knowledge base ONCE at the start of execution. This replaces per-task delegation to /unikit-devcontext for sequential work.
Read in parallel:
.unikit/system/dev-principles.md— engine development principles (Core Principles + Workflow that used to live in /unikit-devcontext).unikit/RULES.md— project overrides (highest priority).unikit/memory/code/RULES_INDEX.md— index of core/stack rules- For EACH row in the Core table where Required By =
allor containsunikit-implement— read that file from.unikit/memory/code/core/using the Read tool.
Stack rules are NOT loaded here — they are loaded lazily per-phase in Step 3.0.
Engine-MCP rules (conditional, engine-neutral) — once per session, zero calls:
.unikit/system/engine-mcp/INDEX.md, base section only — the delivery stamp (server:) plus every section except the## Checktable — access, the live failure classes, shape and cost, what is irreversible, the lane, and what to do when the file is silent. Those are the exceptions that hold for every task here. Do not read the## Checktable now — it is grepped per task, by area (Step 3.2)..unikit/MCP-RECHECK-NOTES.md, header only (server:/audited:) — this project's own accumulated findings. Compare that header against the delivery stamp from item 5. On a mismatch print exactly one line and apply the entries anyway:WARN [engine-mcp] notes header ≠ configured server (<notes> ≠ <configured>)The entries are suspect, not void, and a suspect check still fails safe. Retiring them belongs to
/unikit-mcp-audit, never to this skill.
Either file absent → skip it, print one line, and continue with every right you had:
MCP rules: no INDEX.md — no known exceptions for this server, rights unchanged
No rules means no known exceptions, never no capabilities. Absence never disables the engine MCP and never turns a target into ⏸️ MANUAL (.unikit/system/dev-principles.md → A9).
Ultra plan bundle reader contract — once, before the first task is executed:
.unikit/system/ultra-plan-read.md— how to read an ultra plan bundle: detection, per-consumer reading depth, what is mutable during execution, and the blocking integrity checks. Name it and follow it; never restate it here — one contract, one place. If.unikit/system/ultra-plan-read.mdis missing or unreadable, do not block: treat every plan as a single-file plan and continue exactly as before — a project that predates the ultra port has no bundles to read.
Keep an in-memory list of loaded rule file paths (loaded_rules). Used in Step 3.0 for delta detection.
Step 2: Determine Work Scope
If all tasks are completed (- [x]):
All tasks in {feature-folder} are completed.
Nothing to implement.
STOP here.
Counting rule for ⏸️ MANUAL. A task marked - [x] … ⏸️ MANUAL (Step 3.4) counts as out of scope, not as pending: it does not block "all tasks are completed" and it is never picked up again by a later run. It is also not counted as implemented — Step 4 reports it on its own line.
If $ARGUMENTS contains phase/task selectors:
Phase N(e.g.Phase 3): collect all pending tasks from Phase NPhases N-M(e.g.Phases 1-3): collect all pending tasks from Phases N through MTask N.MorTasks N.M N.K(e.g.Tasks 2.1 2.3): collect only those specific pending tasks- If a specified task is already completed, skip it and note this to the user
- If a phase depends on an incomplete phase, warn the user but proceed if they confirm
If no selectors (execute all pending):
Collect all pending tasks across all phases, respecting dependency order:
- Start with phases that have no unmet dependencies
- Within a phase, execute tasks in order (1.1, 1.2, 1.3...)
- After completing a phase, check if any new phases are now unblocked
Step 3: Execute Tasks
Keep a running list of files you create, modify, or delete during execution — you'll need it for the completion summary and commit.
3.0: Phase Rules Refresh (before starting each phase)
Before executing the first task of any phase (including the first phase):
- Re-read
.unikit/memory/code/RULES_INDEX.md(it may have been updated by/unikit-memorysince Bootstrap). - Match the phase name and its task descriptions against the Stack table's
Load Whencolumn. - Compute delta: stack rules needed for this phase that are NOT in
loaded_rules. - Read each delta rule from
.unikit/memory/code/stack/using the Read tool. - Add them to
loaded_rules.
Inside a phase, do NOT re-check rules between individual tasks — they share the same loaded set.
Before starting the first task, display the execution overview:
## Implementation Progress
✅ Completed: {X}/{total} tasks
🔄 Executing: Phase {N} — {Y} tasks pending in scope
⏳ Remaining after scope: {Z} tasks
For each task to execute:
3.1: Present the task
Show the user what you're about to implement:
## Phase {N}: {Phase Name}
### Task {N.M}: {task description}
Status: Pending
Dependencies: {met/unmet}
3.2: Implement the task
This skill OWNS code-writing for sequential tasks. Use Read/Edit/Write/Bash directly with the rules already loaded in Step 1.5 + Step 3.0. Do NOT invoke /unikit-devcontext via Skill(...) — that defeats the rules-loading optimization.
Choose execution mode:
- Sequential within phase (default for tasks that depend on each other or share files) → inline implementation. The skill writes code itself.
- Independent across phases (per the manifest's
## Dependency Graph, e.g. Phase 3 and Phase 4 can run in parallel) → spawndevelop-agent(Agent + /unikit-devcontext) per independent scope. Use ONLY for true parallelism. - Deep-dive single task (requires extensive codebase exploration that would bloat parent context) → spawn
develop-agentto isolate the exploration.
When implementing inline, use the rules from Bootstrap + Phase Rules Refresh, the principles from dev-principles.md, the task description from the manifest's ## Checklist, and the technical context from its ## Technical Context.
In an ultra bundle the checklist line is a pointer, not the specification. The task's specification is its ## Task N.M: section in the phase file — ### Intent through ### Verification — and the manifest's ## Technical Context supplies only the cross-phase part.
Fallback: If Agent tool is unavailable, do NOT invoke /unikit-devcontext inline (rules and dev-principles are already loaded in Step 1.5 / Step 3.0). Instead, degrade parallel scopes to sequential and continue the inline implementation cycle for ALL tasks. Each phase still triggers Step 3.0 Phase Rules Refresh.
Tasks carrying an Editor: line target the editor's serialized state, not source files. Handle each Editor: line — [kind] <container> → <target> : <action> — by the Editor tasks mode parsed in Step 1:
mcp— carry it out through the engine MCP, in this order, on every such task:- Candidates from the live catalog, by intent. Take the task's
kindand its action, and pick 3-5 candidate affordances out of the tool list you actually hold. That list is the only place a name may come from — not this file, not a rules file, not memory. A name recalled instead of read is acatalog phantomyou invented. - Ask the server for the schema of those 3-5 before calling any of them. A one-line or empty declaration does not mean "no parameters".
- Grep by area. Read the
## Checktable of.unikit/system/engine-mcp/INDEX.mdand of.unikit/MCP-RECHECK-NOTES.md, filtered to this task's own area — the one itskindnames — plus every cross-cutting area:rollback · console · batch · compile · transport · visual. The cross-cutting six are read always; the lines are short, and the moment one becomes applicable is not knowable in advance. - Execute, then read the changed state back. Close the claim with the evidence class its claim class requires (
dev-principles.md→ A2). A response code is not evidence; the evidence is the read-back of what you claimed to change.
No rules file, or no check line for this area → nothing changes. Every right you had, you keep: an absent exception is not an absent capability, and it is never a reason to mark the target
⏸️ MANUAL(A9).⏸️ MANUALis reached only by trying, finding no route at all, and having the evidence of that absence to show.- Candidates from the live catalog, by intent. Take the task's
manual— do not touch any file. Mark the task⏸️ MANUAL(Step 3.4) and hand the user the exact instruction in the form[kind] container → target : action, one line per target.direct— commit to git before editing (this is mandatory and the whole reason the mode is gated), then edit the serialized format directly, staying inside the bounds §6 allows for that format. Never usedirectfor a format §6 rates 🔴.§6 is owned by the
unikit-planskill — read it fromreferences/ENGINE_RULES.mdinside that skill's own directory under{{skills_dir}}. This skill has no engine template of its own, so there is no local copy of §6 to read and none to keep in sync.If that file is not there, treat every format as 🔴: refuse
direct, put the task back onmanual, and state the reason in one line. Continuing silently is not an option here — a binary serialized format edited as text is not reversible by review, and this gate is the only thing standing in front of that. This is not the A9 case: what is missing is not a rule that would grant a right, it is the permission for an irreversible text edit, and withholding it changes nothing about themcproute.
A call that misled you is a finding — and it goes in two places, neither of them the notes file.
- the run report for this task, as a candidate line: the
area, what has to be confirmed, and the raw call with the raw answer it gave; - the plan's
## MCP Findingstable — the half that survives the session. Columns and their contract:references/TASK-FORMAT.md→### MCP findings section.
When it is written: in Step 3.4, by the same Edit pass that ticks the checkbox — not at the end of the run. The finding and the task that produced it are one unit of work, and a table filled only at the end is lost to every /clear, every context overflow and every session that simply stops. Ticking the box and appending the row together is what makes the two survive or fail as one.
Never write .unikit/MCP-RECHECK-NOTES.md from here. One observation is a bad sample and a bad line lives for months; the durable surface passes through a human running /unikit-mcp-trap.
The library reference — two triggers, and never on Bootstrap.
Reach for it on exactly two occasions:
- an unfamiliar area — what approaches the authors propose; once per area per session;
- a dead end — you hold the schema and the capability still is not there.
Never routinely, and never at Bootstrap. It is a network dependency inside the editor lane, a few thousand tokens per query, and it makes the run irreproducible — two runs of the same plan diverge. It also mixes a source with a systematic bias toward confidence into the hot path: retrieval returns what is most relevant, and a caveat is almost never the most relevant answer to "how do I do this".
The identifier is already known. It is carried in the header of .unikit/system/engine-mcp/INDEX.md, which names the reference for the configured server — so nothing has to be resolved at run time.
Say when you reached for it, and why. One line into the run report, at the moment of the call — the network was touched and the report has to show it:
Reference: trigger <1|2> — <the area, or the dead end>
Without it the run reads as if everything came from observation, which is exactly the confusion a source biased toward confidence should not get for free.
How the answer is treated. The reference describes intent, not behaviour. Anything taken from it carries the same evidence obligations as anything else, and with heightened attention: it has been caught presenting a structurally broken path as an exemplary example. It never closes a claim — only an observation does (dev-principles.md → A2).
The reference is optional in the wizard. If it was not configured, trigger 2 simply has no fallback: descend the degradation ladder (dev-principles.md → D3) and reach ⏸️ MANUAL at its proper rung only — by absence of a route, established by trying. An unconfigured reference is not itself a missing capability.
Delegated execution. When a task with Editor: goes to develop-agent or to unikit-implement-worker, the dispatch prompt MUST carry the Editor: lines verbatim and the already-resolved mode. A delegate that receives only the description implements the task as pure code and both mode gates are bypassed silently. In an ultra bundle the whole task section goes into the prompt, not just the Editor: lines: a delegate that receives only the checklist line loses the implementation steps, the contracts and the acceptance criteria along with the targets. manual is never executed by a delegate — the task comes back up marked ⏸️ MANUAL.
3.3: Handle Blockers
If a task cannot be completed (compilation error, missing dependency, unclear requirement, etc.):
Blocker on task {N.M}
Problem: {description of what went wrong}
Options:
1. Skip and continue (task will be marked as blocked)
2. Change implementation approach
3. Stop implementation and discuss
Based on choice:
- Skip → mark task as blocked in the manifest, continue to next task
- Change approach → discuss alternative with user, retry task
- Stop → pause implementation → STOP
3.4: Mark task as completed
After successful implementation, update the manifest:
- Change
- [ ] {task}to- [x] {task} - If all tasks in a phase are done, update the phase status:
**Status:** [x] Completed
Editor task handed to the user (Editor tasks: manual) — a third outcome, neither done nor pending:
- Write the checkbox as
- [x]and append the marker⏸️ MANUALto the task text, right after the description:- [x] Task 2.1 — wire the pause button ⏸️ MANUAL. The checkbox must be[x]so Step 2 does not pick the task up again on every subsequent run; the marker is what keeps it honest, and it sits in the task text so/unikit-verifysees it during the task audit. - A
⏸️ MANUALtask does not block "all tasks completed" — the user took it on deliberately. It is not counted as implemented either: report it separately (Step 4).
The task produced an MCP finding (Step 3.2) — a third outcome to record in the same pass:
- Append the row to the plan's
## MCP Findingstable now, in the sameEditthat ticks the checkbox. Not at the end of the phase, not at the end of the run. - Id:
F<n>, where<n>is one more than the highest already in the table. Read the table before appending — a re-run of the same task must not restart the numbering and collide with rows written earlier. observed: the date you observed it,Bash(date *).- Dedup is semantic, not mechanical. Drop a candidate that says the same thing about the same
areaas a row already there, judging by meaning rather than by string match; only the id allocation is mechanical. Being loose here is deliberate — the error is cheap in both directions. A duplicate that slips through costs one extra line, which/unikit-mcp-trapor/unikit-mcp-auditdrops later; merging two observations that were not the same thing destroys theevidenceof one of them, and evidence is the half that cannot be reconstructed.
Use the Edit tool to make these changes surgically.
3.5: Progress report
After each task (or batch of parallel tasks), briefly report:
✅ Task {N.M}: {one-line summary of what was done}
Progress: {completed}/{total} ({percent}%) · {remaining} remaining in scope
3.6: Compilation & Console Check (after completing a phase)
After all tasks in a phase are done, check {{engine_name}} console for compilation errors.
Prerequisite: Check if MCP server {{engine_mcp_tool}} is configured in {{settings_file}} at the project root. If MCP server {{engine_mcp_tool}} is not present in MCP settings — skip this step entirely and proceed to 3.7.
If MCP server {{engine_mcp_tool}} is available:
- Read the {{engine_name}} console log via MCP server
{{engine_mcp_tool}}, filtering for errors - Analyze each error:
- Error relates to code created/modified in the current phase → fix it inline using the same execution mode logic as Step 3.2 (default: inline; develop-agent only for true parallel/deep-dive)
- Error relates to code planned in a future phase (check remaining tasks in the manifest's
## Checklist) → skip, note in progress report:"Known error: {description} — will be resolved in Phase {N}, task {N.M}" - Error is pre-existing and unrelated to the current feature → skip, do not touch
- After fixing, re-read the console log to verify fixes didn't introduce new errors
- Repeat the check→fix cycle until no errors from the current phase remain
This step is critical: do NOT proceed to commit (3.9) with compilation errors that belong to the current phase. Future-phase errors are acceptable — they indicate planned work, not broken code.
3.7: Update context artifacts (if project structure changed)
After completing a phase, check whether the implementation introduced structural changes that should be reflected in context files:
- **If the
…(truncated)