# Writing

> Use this skill when writing nodes into an NKS graph — creating phenomena, kriyas, vimarshas, holons, or kartas. Triggers: 'запиши', 'зафиксируй', 'добавь узел', 'создай крию', 'create phenomenon', 'create entity', 'add to graph', 'nks_add', 'положи в граф', or whenever the agent is about to call any nks_add_* tool or nks_batch with creates. Also when unsure which node type, given_as, or modes to pick. Use even for single-node writes — one wrong type propagates through the graph. Distinct from design (plans paths from goals), weaving (repairs existing structure).

- Skill: `verstak-ai/writing` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add verstak-ai/writing`
- Raw SKILL.md: https://api.skillmd.com/api/skills/verstak-ai/writing/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: verstak-ai (https://skillmd.com/u/verstak-ai)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/verstak-ai/writing

---


# NKS Writing

You are about to write a node into the graph. Every node you write will be navigated by future agents, linked to other nodes, traced through estafetas. A wrong type, a lazy name, a mechanical mode — each one degrades the graph for everyone downstream.

Five decisions, in order. Do not skip ahead.

## Before anything: realm and cross-realm

Every NKS tool call requires `realm=<token>`. Confirm which realm you're writing into before the first call.

**Cross-realm arrows do not work.** `nks_arrow(action="link", source="739", target="29")` resolves both seq numbers inside the current realm. If #29 in your realm is not the node you mean — you just created a wrong arrow. For cross-realm references, use text in the sense ("see <realm> #29") — never arrows.

### Reader-and-use novelty gate

Before every create or semantic update, name:

1. the later role/session — or the named reader/query class — expected to retrieve this state;
2. the concrete decision, answer, verification, or handoff that retrieval can change;
3. what is new relative to the accepted requirement, repository, relay, and existing graph.

Model only what is load-bearing across rounds. A requirement is not graph-worthy merely because it
exists; its durable correction, dependency, ownership boundary, or unresolved ambiguity may be.

**The test is kind, not recoverability.** Two kinds, both first-class:

- **Transcription — skip.** What the accepted artifacts already encode, restated in prose:
  requirement bullets, work logs, test transcripts, feature existence, public output shape,
  implemented algorithm, a prose copy of repository state. Reference the source instead.
- **Structure — write.** Load-bearing structure and relations the artifacts do **not** encode as
  *traversable relations*: composition (what a thing is made of, which phases it runs through),
  blast radius and cross-artifact dependency, ownership boundary, correspondence-or-drift between
  artifacts. Write these even when the underlying content is recoverable by reading — recovering
  the text still leaves the relation untraversable.

**Where the two meet — algorithm is not composition.** Mirroring an artifact's internal algorithm
into nodes is not new structure: a step-by-step re-encoding of code the reader can simply read stays
source-only, unless an ontology obligation demands the model (Decision 1's vollzug/grundsatz rule)
or a named cross-node reasoning use needs that relation traversable.

A durable decision delta is always graph-worthy: an accepted correction, contradiction, dependency,
evidence verdict, ownership boundary, or open question whose loss would change later action.

An unknown exact future task or session is not by itself a veto — but only once the test above is
met: a named reader/query class ("whoever traces this method's phases", "whoever asks what breaks if
X changes") *together with* the reasoning or action it enables. Fail that test and the write is
skipped as before; speculative or empty structure — relations with no reader class and no reasoning
they enable — is never licensed.

**This gate never blocks Decision 1's method obligation** («A method is half a node»: name the kriya
that runs the method, and model its phases as that kriya's children). A `vollzug`/`grundsatz`
method's applying kriya and its phase
`contains`-children are structural modeling, not transcription — write them; the obligation stands
however recoverable the protocol text is. The converse stands too: prose-retelling that protocol in
the phenomenon's description remains forbidden.

## Decision 1: What type of node?

| If it… | Type | Tool |
|---|---|---|
| **does something** — transforms, produces, consumes | **kriya** | `nks_add_kriya` |
| **is acted upon** — thing, state, concept, seed, method, or rule that some kriya consumes / produces / conditions | **phenomenon** | `nks_add_phenomenon` |
| **asks a question** — doubt, risk, counter-thesis | **vimarsha** | `nks_add_vimarsha` |
| **draws a boundary** — separates inside from outside | **holon** | `nks_add_holon` |
| **names a role with a motivation** | **karta** | `nks_add_karta` |
| **transforms the system qualitatively** — a cross-holon becoming with a *telos* ("what the system becomes") | **bianhua** | `nks_add_bianhua` |

**bianhua is an assembly-level type, not a routine write** — the **assembly** skill's work. Test: "the system will be X, which it isn't yet" — can't say it → not a bianhua. Never for a single vimarsha: locate the existing transformation first (`lens="bianhua"`, `nks_semantic_search(node_type="bianhua")`); unsure → ask the user. Vimarshas the agent writes for itself; **bianhua are the owner's interface** — the name must read for the user, the telos is verified by them. See Decision 5 for its arrows.

A phenomenon does not exist on its own — it exists *for* a kriya (noema for noesis). If no kriya consumes, produces, or conditions it, you are about to write an orphan.

**A method is half a node.** `vollzug` 行 *is* conduct — a way of acting, reified into a noun. The reification is legal, and it is exactly where activity hides: a method-phenomenon whose `description` narrates the protocol is legal, `CHECKS`-clean, and carries **zero tension** — no detector can tell a modeled method from a narrated one, because absence of a model is invisible from inside the model. So a vollzug (and a grundsatz) obliges you: **name the kriya that runs it**, and if the method has phases, they are `contains`-children of *that kriya* — never prose in the phenomenon's description. One-line test: does the description carry an arrow, a numbered step, or the word "then"? You are narrating an activity. Model it.

### Traps

**Phenomenon in kriya disguise.** "Token creation" is the act. "⚙️ Access token" is what the act produces. Test: does the name carry a before/after? → kriya. Does it name what *stands* through that before/after? → phenomenon.

**Kriya in phenomenon disguise.** "⚙️ Authentication flow" — if it transforms state, it's a kriya. A noun on a kriya is a smell, not a license.

**Activity reified into a method-noun.** The subtlest trap, because the type is *right*: a skill, a recipe, an idiom really is a vollzug phenomenon. The error is stopping there — parking the protocol in its description instead of modeling the kriya that runs it and the steps it runs through. Unlike the two traps above, nothing here looks wrong: the name is a proper noun, the given_as is correct, the node validates. Test: if the description tells you *how to do it*, the doing belongs in a kriya. The phenomenon **names** the method; it never **replaces** it.

**Task in kriya disguise.** The mirror of the trap above — read them as a pair. Not everything that *gets done* is a kriya. "Build the API", "Integrate Authentik" are project activities: one-off, no repeating estafeta, a different ahara/utpatti every run. Test: imagine it performed many times — same ahara and same utpatti each time? → kriya. Different each time? → a task, and it lives in a tracker, not here. The kriyas *inside* it are real: "Serving an HTTP request" (ahara request, utpatti response, actor API server) repeats on every request.

Together the last two traps hold the kriya boundary from both sides: **not everything done is a kriya, but everything that is a kriya must be modeled as one — never narrated inside a phenomenon.** Over-correcting either way costs the same: tasks masquerading as kriyas, or activity flattened into nouns.

**Karta vs phenomenon.** Gated by the operational test — *can you address a vimarsha to it and get an answer?* No → not a karta (a machine → ding-phenomenon; a theory/method/principle → sinn/vollzug/grundsatz). The full gate and the four karta kinds live in **Decision 2b**.

**Holon vs phenomenon(sinn).** "📦 Auth contour" — what's inside, outside? Can't answer → probably phenomenon(sinn). Holons-as-folders are an anti-pattern.

## Decision 2: given_as (phenomenon only)

How does this phenomenon give itself? See `references/given_as.md` for the full decision tree.

| Ask yourself | given_as |
|---|---|
| Can I point at it outside the graph? (file, container) | **ding** 物 |
| State of affairs — before/after of a kriya? | **sachverhalt** 勢 |
| Named concept — what-is-it? | **sinn** 名 |
| Seed — something becoming? | **bildung** 理 |
| Method — "this is how"? | **vollzug** 行 |
| Principle — "this is how it must be"? | **grundsatz** 法 |

**Critical:** vollzug/grundsatz cannot be ahara or utpatti — API 422. Applied via upadhi only.

## Decision 2b: manifested_as (karta only)

`manifested_as` is **required on every karta** — the mode-of-manifestation (āvirbhāva), parallel to given_as. Run the gate first, then pick the kind.

**Gate — can you address a vimarsha to this doer and get an answer?**
- **No — it acts but can't answer** (cron, worker, CI, process): **not a karta.** Make a ding-phenomenon, wire it to a kriya as `upadhi`.
- **No — it doesn't act, it stands as theory / method / principle** (Erikson, Nyāya, a how-to): **not a karta.** Make a sinn / vollzug / grundsatz phenomenon (entered via **intake**).
- **Yes → karta.** Which kind?

| The doer… | manifested_as | Example |
|---|---|---|
| answers, and **decides itself** whether to act (gives adhimoksha/virodha) | **svatantra** 主 | product owner, architect — stewards **root** holons |
| answers, but takes its **impulse from another** — discriminates and acts, doesn't originate | **adhikarin** 能 | nks-api dev, a Claude-agent responsible for a holon — stewards **concrete** holons |
| **won't answer** — needed as actor on kriyas, its path is *modelled*, not lived | **pratibimba** 象 | CJM-persona, "the becoming self" |
| answers, but **on its own time** — its 時-cycle isn't synced with the realm | **agantuka** 客 | regulator, external counterparty, the market |

**Addressing by kind** (where a `posed_to` arrow may point): **主** — strategic questions ("do we take this?", "what's the priority?"); you don't assign it tasks, it assigns them. **能** — work questions and tasks; find the addressee by the `steward` arrow (who stewards the holon your question lives in); out of its scope → escalate to 主. **象** — **never** `posed_to`; use only as actor for path-modelling, decisions about its path go to the 主/能 who designs it. **客** — `posed_to` is allowed, but don't expect a fast answer; its actor-edges cross the boundary and tracing stops there by design.

**Finding the addressee.** Never pick one from orient's ROOT KARTAS line — it shows root roles only (sub-roles fold into "· N sub"), and a name that merely contains your keyword is not the role: an 象-image often carries the system's name, while the 能 who answers for its code is a sub-role of a developer archetype. List the real set — `nks_search(q="", node_type="karta")` — or follow the `steward` arrow from the holon where the work lives. Every karta row carries its род glyph (主/能/象/客); 象 is never an addressee. And roles for another repo live in the *same* realm as sub-kartas — don't go hunting for a realm named after the repo.

Traps:
- **A person's name is not a karta** — but the `user` field binds one to the other. "Дмитрий" → "Product owner" is still the role; pass `user="me"` (or another member's `sub` from `nks_admin(action="list_members")`) on `nks_add_karta` / `nks_update` when a real person stands behind that role. The binding is what makes them findable from outside the realm: `nks_me(action="kartas")` returns every such karta across all realms in one call, which is what a cross-realm agenda is built from (**minding**). Never bind a role nobody currently occupies, and never a `pratibimba` (422).
- **One external entity is often two nodes**: Stripe-API (ding-phenomenon, a machine) and Stripe-account-manager (**agantuka** karta). Split by addressability.
- **A modus (Сборщик, Ткач, Explorer) is a sub-karta via `group`, not a separate type** — `manifested_as` is inherited from the parent role.
- Only **svatantra / adhikarin** may `steward` a holon; a `pratibimba` / `agantuka` does not answer for a boundary.

## Decision 3: Modes

Three axes, each required. The tool descriptions on each factory already list enum values and contextual questions — read them. The principle here:

**Each mode is a question you answer, not a box you check.**

See `references/modes.md` for the self-check and stable triads.

The critical trap: **upeksha is not a default.** anagata + upeksha = "this will exist in the future and I don't care." Almost always wrong for projected nodes. anagata + chanda or adhimoksha is more honest.

## Decision 4: Name and description

### Naming (正名)

| Type | Grammar | Example | Anti-example |
|---|---|---|---|
| kriya | Verbal noun | 🔄 Аутентификация | "Build the API" |
| phenomenon | Noun | ⚙️ Токен доступа | "Token creation" |
| holon | Boundary name | 📦 Контур авторизации | "📦 Папка auth" |
| karta | Role name | 👤 Проектирующий | "Дмитрий" |
| vimarsha | The question | 🕮 CXDB — холон или сущность? | "Проблема" |

🔥 for sachverhalt-incidents by convention.

### Description (the body)

The body is addressed by its **per-type name** on every surface — the name you *read* is the name you *write*, on create and update. `nks_look` renders it under that heading; the factories and `nks_update` / batch-update accept it under that name. Pass the per-type name **or** `description`, never both — a guard rejects double-passing.

| Type | Body param | `nks_look` heading |
|---|---|---|
| bianhua | `telos` | TELOS |
| kriya | `essence` | ESSENCE |
| karta | `motivation` | MOTIVATION |
| phenomenon · vimarsha · holon | `description` | DESCRIPTION |

What goes in it, by type:

- **Kriya** (`essence`): pariṇāma — "Before: X. After: Y." If it reads like a task list, rewrite.
- **Phenomenon** (`description`): what it IS. If you can't name a kriya that consumes, produces or conditions it, you don't yet know what you're writing — but naming one *here* does not connect it. The arrows in Decision 5 carry the link; the body only says what it means.
- **Vimarsha** (`description`): the question. What would count as an answer?
- **Holon** (`description`): what principle separates inside from outside. nks_add_holon enforces 4 questions — answer them.
- **Karta** (`motivation`): what drives the role. nks_add_karta requires it.
- **Bianhua** (`telos`): the destination quality — "the system becomes …" (see Decision 5).

**Timelessness — a guard, not a nicety.** Every description states what IS — the resolved, the asked — never how it came to be discussed. The body is read *out of time*: a future agent meets it with no session around it, so a chronicle in the body is noise to everyone but the writer.

- **Out of the body:** dates, session markers, people's names (attribution → `attrs.posed_by`), git refs (SHAs/branches/PRs), and DONE/changelog journals. History lives in `nks_history` and git; done work changes the graph *itself* — modes, arrows, descriptions — it is not appended as a log.
- **Violation smells:** "now" / «теперь», "after we…" / «после того как», "in this session", a date in prose, a «✅ done» tail, any narration of what was wrong *before*.
- **Where time is legitimate:** a `phenomenon(given_as=sachverhalt)` — an incident/state — carries its timestamp in `attrs`, not the prose; `shabda` (quoted external testimony) is dated by its nature; a closed vimarsha reads as archive (its body froze at closure). Everywhere else: tenseless.

## Decision 5: Arrows

Arrowless = orphan = invisible.

**The link goes in the edge; its explanation goes in that edge's `sense`.** The commonest way to leave a node orphaned is not carelessness — it is knowing exactly who consumes it and writing that down in prose instead of drawing it. Observed independently across five contours by different authors: a body saying "consumed by every applying kriya", or naming its contract by number outright, with not one edge beneath it. A reading agent travels by edges — trace, lenses, connectivity search — and reaches a body only once it is already standing on the node, so a link that lives in prose is available only to whoever no longer needs it.

**And the same holds one layer up, which is where the rule catches its own author.** Having drawn the edge, the reason for it goes in `sense` — never into the body as a sentence about the edge. `sense` travels with the edge and is read by anyone following connectivity; the body opens only to whoever already arrived. A why left in the body is handed, once again, to the reader who no longer needs it. The division is clean: the body says what the node **is**, the edge says what it connects, and the edge's `sense` says why it connects that way.

**Several consumers is the instruction to draw them all, not a reason to draw none.** This is where the trap springs, and it springs on conscientiousness: with one consumer the edge is obvious, and with five, singling one out feels like a distortion — so prose looks *more honest*, since it names everyone without privileging anyone. It isn't. `upadhi` is cheap, any number may exist, and not one of them claims to be the only one. Choosing a single consumer would indeed be arbitrary; the conclusion is that you don't choose. And where the consumer lies outside the graph — a person reading the page, an agent handed the result — that is an edge of the world, and it is marked as an edge rather than by silence.

Of the two errors, an edge you later judge too weak costs one call to remove; a link left in prose costs every future traversal that will never find it, and it trains you to read a correct `leaked` report as a false alarm.

### Kriya (six questions)

The factory holds 1–2 as a gate: `nks_add_kriya` refuses a kriya with neither `ahara` nor `utpatti` (a genuine realm inlet passes `attrs.boundary="init"` — see *Realm boundary*).

1. **Consumes?** → `ahara` to phenomenon. ahara = DESTRUCTION. Just read → upadhi.
2. **Produces?** → `utpatti` to phenomenon. Can't name utpatti? Stop — you don't understand the kriya.
3. **Who acts?** → `actor` to karta.
4. **Context?** → `upadhi` to phenomenon. `attrs.mutable=true` if modified.
5. **Belongs to what?** → search for a candidate parent kriya before writing top-level (locate-before-write). `nks_semantic_search(q=<what this kriya is part of>)`; on a real hit, pass `parent_id=<seq>` (creates a `contains` edge from parent). **No coercion** — a wrong parent is worse than none; when you can't honestly name the umbrella, stay top-level consciously. The most compressing axis is the one factories never forced — ask it yourself.

6. **Made of what steps?** → `contains` to sub-kriyas. If the pariṇāma names phases — "through five decisions", "four phases", a `→` chain — those phases are children: one sub-kriya each, with its own pariṇāma, ahara/utpatti, actor. **Can't name the steps? Stop — you have a label, not a model of the activity.** This is the mirror of question 2: utpatti proves you understand *what the kriya does*; the steps prove you understand *how it unfolds*. Question 5 decomposes upward (whose part am I?), this one downward (what am I made of?) — 5 without 6 leaves a black box neatly filed under a parent. A leaf kriya is legitimate: a single tool call has no phases. A kriya whose body *promises* phases and contains none is not a leaf — it's a narration.

A phase whose actor is **not** the actor of the parent — an owner accepting a telos, a goal, a gate — is its own kriya, not a bullet in the parent's body: one kriya, one actor (see the decomposition rule in **weaving**).

Plus: `next` (sense = praśna — yes/no question). `contains` for sub-steps.

Realm boundary is topological: no detector demands ahara at the realm edge, and `attrs.boundary="init"` never silences a tension. The marker is a positive claim with two effects — at creation it lifts the factory's ahara/utpatti gate, and in reading it renders as a sanctioned inlet. Setting it to dodge an honest ahara is the antipattern.

### Phenomenon

- `context` → holon. **Only phenomenon → holon.** Kriya/karta/vimarsha → holon is forbidden.
- `derived_from`, `specifies` → phenomenon-to-phenomenon lineage.
- Expectations depend on given_as — see `references/given_as.md`.

### Karta

- `steward` → holon: who answers for this boundary. Only a **svatantra** (root holons) or **adhikarin** (concrete holons) karta may steward; a pratibimba / agantuka may not. An `adhikarin` acting with no `steward` edge is a warning — it works but answers for nothing.
- `group` → senior karta (sub-role); `actor` is incoming — from every kriya this role performs.

### Vimarsha

- `vimarsha_of` → node(s) this question is about. **Anchor every vimarsha — one carrying an expectation (`posed_to`, anga to a bianhua) doubly so**: agents discover work by orienting on a holon, and neither anga nor posed_to scopes the vimarsha into anyone's contour — unanchored, it is invisible to the addressee and will never be done. Minimum — the holon where the expected work lives; better — the precise phenomenon/kriya within it. **That holon is where the ADDRESSEE orients, which is often not where you stand** — a tool defect you hit while editing skills anchors in the tool's contour, not yours. Anchored in your own territory the vimarsha passes the `unanchored` check and is still invisible to the one who could answer it.
- `posed_to` → karta: the **inbox edge** — address the inquiry to a doer who can answer, so they can poll "my open questions" (`nks_search(posed_to=<karta>)`). **It is an arrow to a karta node, not a field** — create it inline (`arrows: [{arrow_type:"posed_to", target:<karta>}]`) or via `nks_arrow(action="link", arrow_type="posed_to", …)`. **Forbidden to a pratibimba** (an image can't answer). Choose the target per Decision 2b — the 能 who stewards the holon your question is in, the 主 for strategic scope. It does not replace `vimarsha_of`: the inbox edge alone places the question in no one's holon-orientation. **The mirror failure is just as real:** `vimarsha_of` without `posed_to` on a question that *expects another doer to act* is a delegation degraded to a note-into-the-void — anchored, visible in the territory, in no one's inbox. A delegating vimarsha is not finished until the inbox edge is set. **No urgency stamps:** ranking a queue is the queue owner's act, never the poser's — don't set priority attrs or fill a priority-shaped tool param (volition graduates `chanda → adhimoksha`; an affordance in a tool schema is not a mandate).
- **`vimarsha_of` (о ЧЁМ) vs `anga` (куда двигаю) — don't collapse them.** `vimarsha_of` names the *subject*: the present, as-is node the doubt is *about*. `anga` names the *becoming* the answer drives: the bianhua, the future telos. The trap is the pull toward the answer — dropping the **actor** or the **work's destination** into `vimarsha_of` when they belong on `anga`. Meta-move: answer two questions separately — «about WHAT is the doubt?» (→ `vimarsha_of`), then «which becoming does the answer drive?» (→ `anga`). One vimarsha legitimately carries both.
- `arose_from` → observation origin.
- Genre determines lifecycle: risk → may `realized_as` sachverhalt. hint → read and close.
- A **hint is a pointer, not a payload**: it carries only what orient and the lenses can't show — external-world state, chosen priorities, conventions. Work-in-flight belongs on the bianhua map via `anga`, not in a seed.

### Bianhua

- `anga` (part→whole): a constituent → the bianhua it *drives*. Three carrier kinds — a **vimarsha**, a **sub-bianhua**, or a **kriya**. Pass `anga=<refs>` on `nks_add_bianhua`, or `nks_arrow(action="link", arrow_type="anga", source=<ref>, target=<bianhua>)` later. The carrier keeps its own anchoring (a vimarsha its `vimarsha_of`) — anga is additional. A bianhua with zero anga is an *empty transformation* — the factory warns. Acyclic tree: one anga-parent per source.
- **kriya as anga-carrier**: a vimarsha-anga carries the *path* (a question whose resolution moves the change); a kriya-anga carries the *arrival* — the deed that itself constitutes the transformation. Two readings, **inferred from the kriya's own triputi, never a separate field** (there is no `anga_kind`): a **возведение** is a deed entering the fabric (kriya ontic `anagata→vartamana`, volitive `chanda`/`adhimoksha`); a **депрекация** is a deed leaving it (`vartamana→atita`, `virodha`). **A completed kriya still links** — finishing the deed is the debt repaid (отдача долга), not a block; no 422 on a done carrier. Each kriya-anga counts toward the bianhua's progress, its `resolved` read from the carrier's triputi.
- `anantara` (ordering): bianhua → the bianhua that must complete first. `anantara_after=<refs>`. Acyclic; sets the critical path.
- `telos` is the description: write the *destination quality* ("the system becomes …"), rendered as `TELOS:` in `nks_look`. No given_as, no `context`, no ahara/utpatti/upadhi on a bianhua (422). The lifecycle and field work belong to the **inquiry** and **assembly** skills.

### Sense on arrows

Every arrow carries a sense explaining WHY.

- `next` → praśna. ✓ "Path built — where can it break?" ✗ "Go to next step."
- `upadhi` → why this phenomenon matters HERE.
- `ahara` → what consumed and why.

## After writing

1. **Read the `CHECKS:` block the create response prints.** The factory self-validates — no separate call needed. Clean? Move on. Fix warnings first. Note: `not_orphan` on a fresh phenomenon is expected until a kriya picks it up (ahara/utpatti/upadhi) — a `context` arrow to a holon does NOT clear it. Wire it to a kriya. **A nudge in the response is a work item, not an FYI**: "Not attached to any transformation — check the map" means run the check it names (`lens="bianhua"`) and either attach or surface the decision to the user explicitly — never relay the line in passing and move on.
2. **Phenomenon with ahara/utpatti**: `nks_orient(lens="trace", focus=<seq>)` — lifecycle connected?
3. **Kriya**: actor, ahara, utpatti phenomena all exist? And — if the pariṇāma names phases — are they `contains`-children, or still prose? `nks_look` renders them as `HOW`; an empty `HOW` under a body that promises steps is a black box, and it is silent: nothing will flag it for you.
4. **Method phenomenon (vollzug / grundsatz)**: does a kriya apply it via `upadhi`, and are that kriya's steps modeled? A method nobody runs is a dead recipe; a method whose running isn't decomposed is a description pretending to be a model.
5. **Release what you replaced.** Locate-before-write looks for duplicates *before* the write; this is its mirror *after*. The live arrow matrix permits `supersedes` only for **vimarsha→vimarsha**: use it there, migrate the old question's load, and close it (`visarjana`). For every other node type, never invent a generic successor edge: migrate `key:true`, anchors, and consumers that should move; add another legal relation (`derived_from`, `specifies`, etc.) only when its meaning is true; retire the predecessor through its carrier mode. Re-check `nks_arrow(realm="?")` before teaching or automating a replacement pattern. A successor that does not release its predecessor leaves a live duplicate canon.
6. **Do not confuse graph checks with reality evidence.** `CHECKS:`, trace connectivity, actors, and legal arrows establish graph integrity only. For a behavioral `sachverhalt`:
   - code inspection justifies `anumita`; a focused internal/mock-only test can justify `pratyakshita` (evidence the audit grades `provisional` mints at most that); `pramanita` requires the separate **reality-audit** skill (observable contract, canonical public boundary, attempted falsifier, fresh independently observable evidence);
   - executable evidence counts only with a recorded successful exit status — the canonical rule («exit status is the verdict») lives in reality-audit. A failing broad suite does not automatically refute a separately isolated fact, but without a focused exit-zero falsifier for that exact fact, keep it `anumita` and attach a reverify vimarsha;
   - a newly written black-box test qualifies when it rebuilds and executes that exact boundary; authorship alone neither upgrades nor downgrades it;
   - mint behavioral `pramanita` only after the audit verdicts are frozen and no material artifact change remains in the phase — never between probes; a later patch invalidates that confidence until affected public evidence is rerun and the node reverified. If the evidence surface is unavailable, keep the claim provisional and anchor a reverify vimarsha instead of stamping confidence.

## Operational reminders

**reasoning.** Every write tool accepts `reasoning="..."`. Use it — it is not only the audit trail. Where a doer watches its own inbox through a channel, that line is what rides the wake-up into it: the next agent is woken by your one sentence and judges from it whether to act. A write with no reason wakes someone with nothing to judge by, so they must fetch the node to learn they didn't need it. Write it for that reader, not for the log — what changed and why it might matter to them, in one line.

**basis_version.** Every `nks_update`, `nks_arrow` (delete/reconnect/update), and `nks_delete_node` requires it. Read → write → re-read on conflict.

**Cross-realm.** Text references in descriptions. Never arrows.

## Vimarsha genres

| You want to say… | Genre |
|---|---|
| "What could go wrong?" | **risk** |
| "Is this correct?" | **samshaya** |
| "Case the rule misses" | **vyabhichara** |
| "I disagree" | **prati-paksha** |
| "Reasoning is flawed" | **hetu-dosha** |
| "Term has drifted" | **semantic-drift** |
| "Future agent: read this" | **hint** |

Can't pick one → two questions tangled. Separate.

## Starting triples & closure — carrier canon

Each род (type × given_as × genre) has **one axis that carries liveness** (U1); the others only qualify. The `nks_add_*` factories print the **canonical STARTING TRIPUTI** for the род and `nks_look` glosses the carrier per node — **read them; don't stamp a divergent triple.** The trap the canon fixes: **`virodha` does NOT uniformly mean "closed" — it is polarized by род (U3):**

- **risk** — `virodha` is the *live* mode: an active risk *stands* in virodha. It closes only via `visarjana` ∨ `addressed_by` ∨ `realized_as`, never by virodha itself.
- **kriya / karta / phenomenon(vollzug)** — `virodha` = **депрекация** (deprecation): a live tension "we want to retire this", not a closure. Closes at `atita` (kriya/karta also `nashta`) ∨ `visarjana`.
- **samshaya / prati-paksha / hint** — here `virodha` *is* a closure (отказ — refusal).

And projected work is born `anagata` in the *project* triad, never the "ready" `pramanita/vartamana/upeksha` (that lies the deed already runs) — the **design** skill owns those starting modes.

## Batch ordering (nks_batch)

**Load the factory schemas before a create-batch.** `nks_batch` wraps the `nks_add_*` factories but does **not** relax their discipline — every create op is validated against its factory's full schema. In a deferred-tool environment the batch loads without them, so composing a factory-create batch blind means learning each required param one `422` per round-trip. Before you batch: `tool_search` and read the schema of every `nks_add_*` you'll call. The **first** create of an unfamiliar node type is safer as a single factory call than buried in a megabatch — and don't pack heavy multi-paragraph descriptions into a megabatch.

Order within the batch:

1. Phenomena first
2. Kriyas second (referencing phenomena)
3. Cross-cutting arrows last

### Inline-arrow form

Inline `arrows` on the factories take the same canonical shape as `arrow_link`, with the new node as the implicit source: `{arrow_type, target, sense?, direction?, quantifier?, attrs?, <modes>}`. Only `arrow_type` and `target` are required; `direction` flips the orientation when the new node is the *target* rather than the source. The factory **validates the form strictly**: an unknown key — e.g. the pre-rename `edge_type` — is rejected with a named error pointing at `arrow_type`, and a missing `target` says so. No silent acceptance, no raw TypeError — you learn the form before the first write, not by decoding a stack trace.

Two patterns, both first-class:
- **Inline `arrows`** — for edges that *originate at the new node* (a vimarsha's `vimarsha_of`, a phenomenon's `context`). Pass them in the create op.
- **Separate `arrow_link` with `temp:N`** — for edges *between two nodes created in the same batch*, or pointing *into* the new node. Reference each created node by its 0-based `temp:N` index; a `temp:N` must point at a lower-indexed create op.

**A kriya's constitutive `ahara`/`utpatti` must stay inline.** The factory validates each `add_kriya` against its *own* inline `arrows` at create time — a consume/produce edge deferred to a trailing `arrow_link` is not counted, and the kriya fails ("a kriya must declare ahara or utpatti"). Put `ahara`/`utpatti` in the create op's `arrows`; when the consumed/produced phenomenon is created in the same batch, order it earlier and reference it inline by `temp:N` — inline arrows resolve `temp:N` just like `arrow_link` does. Only genuinely cross-cutting edges (`next`, an `upadhi` to a pre-existing node) belong in trailing `arrow_link`s.

`anga`/`anantara` on `nks_add_bianhua` are the exception — pass them as their own `anga=` / `anantara_after=` params, never in `arrows`.

## Scope

This skill: the act of writing. Not covered:
- **Design** → design
- **Weaving** → weaving
- **Reading** → entry

