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 #29") — never arrows.
Reader-and-use novelty gate
Before every create or semantic update, name:
- the later role/session — or the named reader/query class — expected to retrieve this state;
- the concrete decision, answer, verification, or handoff that retrieval can change;
- 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
userfield binds one to the other. "Дмитрий" → "Product owner" is still the role; passuser="me"(or another member'ssubfromnks_admin(action="list_members")) onnks_add_karta/nks_updatewhen 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 apratibimba(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_asis inherited from the parent role. - Only svatantra / adhikarin may
stewarda holon; apratibimba/agantukadoes 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 innks_historyand 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 inattrs, 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).
Consumes? →
aharato phenomenon. ahara = DESTRUCTION. Just read → upadhi.Produces? →
utpattito phenomenon. Can't name utpatti? Stop — you don't understand the kriya.Who acts? →
actorto karta.Context? →
upadhito phenomenon.attrs.mutable=trueif modified.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, passparent_id=<seq>(creates acontainsedge 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.Made of what steps? →
containsto 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. Anadhikarinacting with nostewardedge is a warning — it works but answers for nothing.group→ senior karta (sub-role);actoris 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 theunanchoredcheck 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 vianks_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 replacevimarsha_of: the inbox edge alone places the question in no one's holon-orientation. The mirror failure is just as real:vimarsha_ofwithoutposed_toon 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 graduateschanda → adhimoksha; an affordance in a tool schema is not a mandate).vimarsha_of(о ЧЁМ) vsanga(куда двигаю) — don't collapse them.vimarsha_ofnames the subject: the present, as-is node the doubt is about.anganames 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 intovimarsha_ofwhen they belong onanga. 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_assachverhalt. 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. Passanga=<refs>onnks_add_bianhua, ornks_arrow(action="link", arrow_type="anga", source=<ref>, target=<bianhua>)later. The carrier keeps its own anchoring (a vimarsha itsvimarsha_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 onticanagata→vartamana, volitivechanda/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, itsresolvedread from the carrier's triputi. anantara(ordering): bianhua → the bianhua that must complete first.anantara_after=<refs>. Acyclic; sets the critical path.telosis the description: write the destination quality ("the system becomes …"), rendered asTELOS:innks_look. No given_as, nocontext, 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
- Read the
CHECKS:block the create response prints. The factory self-validates — no separate call needed. Clean? Move on. Fix warnings first. Note:not_orphanon a fresh phenomenon is expected until a kriya picks it up (ahara/utpatti/upadhi) — acontextarrow 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. - Phenomenon with ahara/utpatti:
nks_orient(lens="trace", focus=<seq>)— lifecycle connected? - Kriya: actor, ahara, utpatti phenomena all exist? And — if the pariṇāma names phases — are they
contains-children, or still prose?nks_lookrenders them asHOW; an emptyHOWunder a body that promises steps is a black box, and it is silent: nothing will flag it for you. - 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. - Release what you replaced. Locate-before-write looks for duplicates before the write; this is its mirror after. The live arrow matrix permits
supersedesonly 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: migratekey: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-checknks_arrow(realm="?")before teaching or automating a replacement pattern. A successor that does not release its predecessor leaves a live duplicate canon. - Do not confuse graph checks with reality evidence.
CHECKS:, trace connectivity, actors, and legal arrows establish graph integrity only. For a behavioralsachverhalt:- code inspection justifies
anumita; a focused internal/mock-only test can justifypratyakshita(evidence the audit gradesprovisionalmints at most that);pramanitarequires 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
anumitaand 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
pramanitaonly 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.
- code inspection justifies
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 —
virodhais the live mode: an active risk stands in virodha. It closes only viavisarjana∨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 atatita(kriya/karta alsonashta) ∨visarjana. - samshaya / prati-paksha / hint — here
virodhais 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:
- Phenomena first
- Kriyas second (referencing phenomena)
- 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'svimarsha_of, a phenomenon'scontext). Pass them in the create op. - Separate
arrow_linkwithtemp:N— for edges between two nodes created in the same batch, or pointing into the new node. Reference each created node by its 0-basedtemp:Nindex; atemp:Nmust 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_links.
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