DOC24_KDA_R3_DRAFT_v0_3_1.md
Current Specs/DOC24/DOC24_KDA_R3_DRAFT_v0_3_1.md
ELNOR REPO READER TEXT MIRROR
Original path: Current Specs/DOC24/DOC24_KDA_R3_DRAFT_v0_3_1.md
Source repo: /Users/OpenClaw1/Elnor/Elnor Specs
Git branch: main
Git commit: dbaa25962edc11ab30e8d4ca1715f9ae5bf77331
Generated: 2026-06-09T01:23:58.539Z
---
# DOC24 Knowledge Delivery Architecture — Shared Contracts, Rendering, and Neuroplasticity R3 Draft v0.3
**Status:** Draft operative companion revision v0.3 — generated from the BDSM/KDA adjudication card V1.3.1-OPA15, patched by `DOC24_KDA_R3_DRAFT_V0_2_PATCH_PLAN.md`, and preservation-patched by `DOC24_KDA_R3_DRAFT_V0_3_PATCH_PLAN.md`.
**Supersedes:** DOC24 Knowledge Delivery Architecture R2 for KDA-owned rendering, tiering, cache, manifest-patch, and neuroplasticity behavior.
**Primary target doc:** DOC24 R3.1.1+ delivery/runtime lifecycle.
**Cross-doc owners consumed:** DOC24, DOC72, DOC8/BDSM, DOC73, PropA, EC Core, DOC11/OpenClaw, DOC25, DOC23 Addenda B, OP-A V3.15.
**Interpretation rule:** This document is normative for KDA R3 v0.3 draft review. Requirements use SHALL, MUST, MUST NOT, SHOULD, and MAY. Where this document references DOC24/DOC72/PropA/EC-owned types, KDA consumes them and MUST NOT redefine them. v0.3 is a mechanical preservation patch over v0.2, closing the ten KDA R2 preservation gaps enumerated in the v0.3 patch plan.
---
## R3 change summary
KDA R3 is a compatibility and buildability revision. It keeps R2's core design — deterministic rendering from DOC72 graph payloads, no LLM call at render time, compact/standard/full rendering tiers, execution-strategy cache, dynamic composition, and neuroplasticity — but replaces the R2-local manifest, client, allocator, cache, and canary surfaces that no longer fit DOC24 R3.1.1.
R3 makes these changes:
1. **KDA no longer emits a local injection manifest.** KDA returns a `KdaManifestPatch` discriminated union; DOC24 alone writes `PacketInjectionManifest` and `FinalPromptInjectionManifest`.
2. **Reference-only and excluded cards are presence states, not compact renderings.** `included_reference_only` is distinct from `included_inline`; `excluded` cards carry zero tokens.
3. **Rendering returns structured results.** Every render result carries token counts, tokenizer reference, render variant, template version, and provenance.
4. **KDA tiering consumes DOC24 canonical constraints.** KDA consumes resolved card presence, canonical `DirectiveConstraint[]`, tier floors/ceilings, and normalized relevance. KDA does not invent force-level or hedge vocabularies.
5. **Tier allocation is constraint-aware and exact-token verified.** Allocation is banded by direct-target procedure, non-direct procedure, and non-procedure budgets; exact post-render token counts are validated by band and total.
6. **Client kind is canonicalized.** `elnor_native` is the local/native client value. `local_elnor` is a migration alias only. Unknown values fail closed.
7. **PropA destination policy applies before rendering.** `block`, `strip`, `redact`, `warn`, and literal-retention confirmation are executable gates.
8. **KDA renderer is pure.** Render functions consume a snapshot bundle and perform zero durable reads, zero cache reads, zero network calls, and zero LLM calls.
9. **Execution-strategy cache keys are versioned and policy-sensitive.** Procedure payload, step set, template, app, tool catalog, client kind, render policy, and policy generation all participate in cache identity.
10. **Neuroplasticity is scoped, materialized, and canary-governed.** Annotation utility records, specialization IDs, template hashes, scope partitions, and a total canary state machine are first-class.
11. **Composition preserves component attribution.** Composed cards carry stable component spans and DOC72 ordering provenance.
12. **Tokenizer drift is an explicit decision path.** KDA records assembly-token counts; final-prompt drift is consumed through a decision contract.
13. **Work products route to DOC25/document-tier rendering.** KDA records a reference patch and does not inline-render large work products as ordinary knowledge cards.
14. **Reason codes are closed literals.** Runtime details go in metadata, not interpolated strings.
15. **Migration from R2 is explicit.** Local manifests, `local_elnor`, scalar relevance fields, unscoped specialization registries, and old cache keys are migrated or retired.
---
## v0.2 incremental patch summary
The v0.2 patch applies the focused interim patch memo produced after the first KDA R3 draft audit. It closes the remaining KDA-facing gaps from the final adjudication card without reopening the adjudication: resolved directive tiering, canonical DOC24 constraint resolution, disjoint budget-band partitioning, full delivery-learning inspector support, retired-vocabulary guards, restore/import validation, cache-stable render pipeline integration, redaction reason-code emission, named R2→R3 migration steps, and fixture ownership by adjudication package.
## v0.3 incremental patch summary
The v0.3 patch applies the preservation audit memo produced after the KDA R3 v0.2 non-destructive audit. It restores or explicitly supersedes R2 surfaces that v0.2 silently dropped or weakened: canonical `steps[]` procedure payload projection, `step_nature`, `environment`, contract quality, derivation quality, routing-only field exclusions, Knowledge Manager preview rendering, extraction-model ownership, R2 non-change boundaries, SKILL.md export-only status, R2 → R3 cross-doc obligation disposition, the full R2 renderable node-kind set, and remote `full | guidance_only | suppress` rendering behavior.
## V0.3.1 seam patch note
V0.3.1 is a focused seam-hardening patch over v0.3. It adds the KDA-owned variant-outcome schema consumed by BDSM/DOC8, removes local duplicates of DOC24-owned inspector/tokenizer drift types, expands canary transition reason codes, and makes KDA the single owner of `KdaNeuroplasticityAction` and attribution-constrained KDA action arbitration.
## 0. Architectural invariants
### 0.1 Contract ownership — DOC72 owns shape, KDA owns rendering
The shared knowledge payload contracts consumed by KDA are DOC72-governed payload schemas. KDA owns rendering templates, rendering tier allocation, deterministic rendering functions, execution-strategy cache semantics, render-result metadata, composition decisions, and neuroplasticity registries.
KDA MUST NOT mutate DOC72 graph truth directly. All durable writes go through EC-owned commands and owner-doc write paths.
### 0.2 One context authority — KDA feeds DOC24 / DOC11 / OpenClaw
KDA produces rendered text and manifest patches for DOC24's packet lifecycle. KDA does not assemble final prompts, does not write packet manifests, and does not bypass DOC10/DOC11/OpenClaw.
The runtime chain is:
```text
DOC72 graph payload snapshots
→ DOC24 candidate / packet lifecycle
→ KDA pure rendering from snapshot bundles
→ DOC24 PacketInjectionManifest writer
→ DOC11/OpenClaw final prompt owner
→ FinalPromptInjectionManifest spans
→ reconciliation events
→ BDSM/DOC8 attribution and KDA variant utility
```
### 0.3 No LLM call at render time
KDA render functions are deterministic template assembly. They MUST NOT call an LLM, graph database, execution cache, filesystem, network, route registry, or external service at render time. All needed inputs must arrive in a `KdaRenderInputBundle` prepared earlier by DOC24/EC.
### 0.4 Semantic procedures, not mechanical UI scripts
Procedures store semantic intent and constraints. Mechanical app/tool details live in the derived execution-strategy cache. KDA may render cached tool directives for `elnor_native` when policy permits; it MUST NOT treat cached directives as canonical DOC72 payload content.
### 0.5 Manifest patch, not manifest ownership
KDA R3 deletes the R2 local `InjectionManifestSchema`. KDA returns `KdaManifestPatch`. DOC24 writes all durable packet/final-prompt manifests.
### 0.6 Reference-only is not compact
`included_reference_only` means the LLM receives a diagnostic/reference label only. It is not a compact rendering tier, and it MUST NOT carry a substantive rendering tier.
### 0.7 Scope partitioning applies to neuroplasticity
Rendering specializations, annotation utility indexes, canary counters, extraction hints, and aggregate counters MUST be partitioned by learning visibility scope, model class, matter/firewall/principal scope, and policy generation where applicable.
---
### 0.8 Retired names and non-operative constructs
KDA R3 MUST NOT define, import, alias, render, or persist any of the retired DOC24/R3-era manifest or reconciliation names listed below. KDA emits `KdaManifestPatch`; DOC24 writes `PacketInjectionManifest`; DOC11/OpenClaw write final-prompt span delivery truth; reconciliation is an append-only event stream.
```ts
export type RetiredKdaContractName =
| "InjectionManifestSchema"
| "UnifiedInjectionManifestSchema"
| "PacketReconciliationOverlay"
| "reconciliation_overlay"
| "renderProcedureInjectionCard_returns_string";
export const RETIRED_KDA_CONTRACT_NAMES: RetiredKdaContractName[] = [
"InjectionManifestSchema",
"UnifiedInjectionManifestSchema",
"PacketReconciliationOverlay",
"reconciliation_overlay",
"renderProcedureInjectionCard_returns_string",
];
export function assertNoRetiredKdaContractName(input: {
text: string;
surface: "source" | "generated_artifact" | "migration_adapter";
}): void {
for (const retired_name of RETIRED_KDA_CONTRACT_NAMES) {
if (input.text.includes(retired_name)) {
throw new KdaValidationError({
reason_code: "kda.retired_contract_name_used",
metadata: { retired_name, surface: input.surface },
});
}
}
}
```
## 1. Relationship to R2
R2's following ideas are preserved:
- DOC72-governed shared knowledge contracts.
- Universal fixed fields plus extensible annotations.
- Deterministic rendering; no LLM at render time.
- `RenderingTier = compact | standard | full`.
- Execution-strategy cache as derived, not canonical payload.
- Dynamic composition as a rendering optimization.
- Neuroplasticity through pattern detection, canary, promotion, and rollback.
R2's following constructs are retired or replaced:
| R2 construct | R3 disposition |
|---|---|
| `InjectionManifestSchema` | DELETE. DOC24 writes manifests; KDA emits `KdaManifestPatch`. |
| `renderProcedureInjectionCard(): Promise<string>` | REPLACE with `renderKnowledgeCardV3(input): KdaRenderResult`. |
| `ClientKind = local_elnor` | MIGRATE to `elnor_native`; `local_elnor` is alias only. |
| free-form `relevance_score` allocator input | REPLACE with `normalized_relevance ∈ [0,1]` from DOC24/BDSM boundary. |
| compact rendering used for reference-only cards | FORBIDDEN. Use `included_reference_only`. |
| graph/cache reads inside renderer | FORBIDDEN. Renderer consumes snapshot bundles only. |
| global rendering specialization registry | REPLACE with scoped specialization registry. |
| open-string annotation specialization key | REPLACE with namespaced `AnnotationTypeKey`. |
| execution cache key based only on procedure/app/catalog | REPLACE with versioned policy-sensitive cache key. |
| nullable or flat render result | REPLACE with discriminated manifest-patch union. |
---
### 1.1 Preserved non-change boundaries from R2
KDA R3 changes rendering contracts, manifest patch metadata, tokenizer accounting, cache identity, and neuroplasticity governance. It does **not** change the following R2 boundaries:
1. **DOC72 node kinds and table structure are unchanged by KDA.** KDA does not add DOC72 node kinds or DOC72 tables. Shared payload schemas are DOC72-governed; KDA consumes render-input snapshots.
2. **DOC72 confidence is unchanged.** KDA never writes or canonicalizes DOC72 alpha/beta confidence. KDA may emit rendering utility observations for BDSM/DOC8, but that is not DOC72 epistemic confidence.
3. **DOC72 staleness and lifecycle policies are unchanged.** KDA consumes lifecycle/staleness state; it does not define lifecycle transitions.
4. **DOC24 routing cascade is unchanged.** KDA renders after DOC24 has selected eligible cards and resolved policy/authority/card-presence decisions. KDA does not discover, select, or promote cards into packets.
5. **DOC10 / DOC11 / OpenClaw orchestration is unchanged.** KDA produces deterministic render output and manifest patches consumed by DOC24/DOC11/OpenClaw. KDA is not a prompt assembler or runtime orchestrator.
6. **User skill workflow is unchanged.** Users still demonstrate, review, promote, and use skills through the existing owner-doc flows. KDA changes the internal rendering path from graph node to prompt card; it does not change the user-facing skill lifecycle.
## 2. Shared knowledge contracts consumed by KDA
### 2.1 Contract-source rule
KDA consumes DOC72-owned payload schemas. This section describes the render-input expectations KDA requires from those payloads; it is not a parallel schema owner.
The canonical node payload shape is owned by DOC72. KDA renderers consume immutable `node_snapshot.payload` values provided by DOC24/EC. KDA MUST NOT write payload fields directly.
### 2.2 Annotation type key
R2 used a raw open string as `annotation_type`. R3 keeps open vocabulary for the content layer but requires a namespaced key for rendering specialization and utility aggregation.
```ts
export type AnnotationTypeKey = {
annotation_type: string;
namespace: "global" | "domain_signal_profile" | "node_kind" | "user_configured";
domain_signal_profile_id?: string;
node_kind?: string;
owner_principal_id?: string;
schema_version: 1;
};
```
Rules:
- Raw annotation strings MAY remain inside DOC72 graph payloads for user-facing semantics.
- KDA specialization, canary, and utility indexes MUST key by `AnnotationTypeKey`, not raw string.
- A specialization keyed to one namespace MUST NOT apply to another namespace unless EC/PropA approval explicitly broadens it.
### 2.3 Literal retention class
Procedure parameters may carry R2 literal retention classes:
```ts
export type LiteralRetentionClass =
| "placeholder_only"
| "retain_if_user_confirmed"
| "retain_allowed";
```
KDA R3 interprets those classes through the PropA render policy gate in §3.2C. A `retain_if_user_confirmed` value may render literally only when a `literal_retention_confirmation_id` is present. Otherwise it renders as a placeholder.
### 2.4 Render-input payload minimum and procedure projection
Every KDA renderer expects at minimum:
```ts
export type KdaNodeSnapshot = {
node_id: string;
node_kind: string;
canonical_name: string;
confidence: number;
payload_hash: string;
payload: unknown;
};
```
KDA R3 remains a universal knowledge-rendering layer, not a procedure-only renderer. Procedures and standing procedures use the procedure renderer. Work products route to DOC25 / document-tier reference rendering. Memory directives, domain concepts, goals, and obligations render through DOC72 owner-provided render-input contracts, but they still use KDA's manifest patch union, tokenizer accounting, PropA render policy, tier allocation, and reason-code discipline.
```ts
export type KdaRenderableNodeKind =
| "procedure"
| "memory_directive"
| "domain_concept"
| "goal"
| "obligation"
| "standing_procedure"
| "work_product";
export type KdaRenderableNodeKindDecision =
| {
kind: "supported";
node_kind: KdaRenderableNodeKind;
render_path:
| "procedure_renderer"
| "doc72_owner_render_input_contract"
| "doc25_work_product_reference";
schema_version: 1;
}
| {
kind: "unsupported";
node_kind: string;
reason_code: "kda.unsupported_renderable_node_kind";
schema_version: 1;
};
export function resolveKdaRenderableNodeKind(
node_kind: string,
): KdaRenderableNodeKindDecision {
if (node_kind === "procedure" || node_kind === "standing_procedure") {
return { kind: "supported", node_kind, render_path: "procedure_renderer", schema_version: 1 };
}
if (node_kind === "work_product") {
return { kind: "supported", node_kind, render_path: "doc25_work_product_reference", schema_version: 1 };
}
if (
node_kind === "memory_directive" ||
node_kind === "domain_concept" ||
node_kind === "goal" ||
node_kind === "obligation"
) {
return {
kind: "supported",
node_kind,
render_path: "doc72_owner_render_input_contract",
schema_version: 1,
};
}
return {
kind: "unsupported",
node_kind,
reason_code: "kda.unsupported_renderable_node_kind",
schema_version: 1,
};
}
```
Procedure projection consumes DOC72/R2 canonical field names. KDA MUST NOT look for a render input field named `semantic_steps`; the canonical field is `steps`.
```ts
export type KdaStepNature = "mechanical" | "cognitive" | "hybrid";
export type KdaLiteralRetentionClass =
| "placeholder_only"
| "retain_if_user_confirmed"
| "retain_allowed";
export type KdaProcedureParameterProjection = {
name: string;
value: string;
context?: string;
is_variable: boolean;
literal_retention_class: KdaLiteralRetentionClass;
};
export type KdaProcedureVerificationProjection = {
check: string;
method:
| "applescript_query"
| "ax_state_check"
| "visual_confirmation"
| "user_confirmation"
| "mcp_tool_result"
| "none";
query?: string;
};
export type KdaSemanticStepProjection = {
step_index: number;
intent: string;
detailed_instructions?: string;
parameters: KdaProcedureParameterProjection[];
verification?: KdaProcedureVerificationProjection;
conditional?: string;
rationale?: string;
capability_area?: string;
step_nature: KdaStepNature;
};
export type KdaProcedureConstraintProjection = {
rule: string;
scope: "this_procedure" | "this_app" | "global";
priority: "absolute" | "strong" | "default" | "suggestion";
source: "user_stated" | "inferred" | "imported" | "system";
};
export type KdaEnvironmentScopeProjection = {
app_entity_id: string;
app_name: string;
platform: "mac" | "windows" | "web" | "unknown";
app_variant?: string;
app_bundle_id?: string;
};
export type KdaContractQualityProjection = {
extraction_model_ref: string;
overall_quality_score: number; // [0,1]
field_quality: Record<string, number>; // each [0,1]
missing_fields: string[];
};
export type KdaDerivationMetadata = {
derivation_model?: string;
derivation_model_class?:
| "cheap_local"
| "cheap_api"
| "medium"
| "expensive_frontier"
| "unknown";
derivation_quality?: "high" | "medium" | "low";
extraction_model_config_ref?: string;
schema_version: 1;
};
export type KdaProcedureRenderPayloadProjection = {
canonical_name: string;
description: string;
use_conditions: string[];
non_use_conditions: string[];
// Routing-only metadata. Present for routing/debug inspection; never rendered.
trigger_phrases: string[];
semantic_lookup_phrases: string[];
preconditions: string[];
postconditions: string[];
steps: KdaSemanticStepProjection[];
is_composite: boolean;
used_procedure_ids?: string[];
constituent_ordering?: Array<{
procedure_id: string;
order_position: number;
depends_on: string[];
dependency_reason?: string;
}>;
execution_topology: "linear" | "branching";
decision_points: Array<{
decision_id: string;
prompt: string;
branches: Array<{ when: string; then_step_indices: number[] }>;
}>;
constraints: KdaProcedureConstraintProjection[];
artifact_class?: string;
document_region?: string;
derivation_quality: "high" | "medium" | "low";
capability_tags: string[];
environment: KdaEnvironmentScopeProjection;
source:
| "manual_demonstration"
| "doc3_learned"
| "trace_captured"
| "imported"
| "system"
| "onboarding";
contract_quality?: KdaContractQualityProjection;
derivation_metadata?: KdaDerivationMetadata;
annotations: KnowledgeAnnotation[];
schema_version: 1;
};
export const KDA_ROUTING_ONLY_PROCEDURE_FIELDS = [
"trigger_phrases",
"semantic_lookup_phrases",
] as const;
export const KDA_NEVER_RENDER_PROCEDURE_FIELDS = [
...KDA_ROUTING_ONLY_PROCEDURE_FIELDS,
"source_event_ids",
"derivation_metadata.extraction_model_config_ref",
] as const;
export type KdaProcedureProjectionResult =
| {
kind: "projected";
payload: KdaProcedureRenderPayloadProjection;
degraded_reason_codes: KdaReasonCode[];
schema_version: 1;
}
| {
kind: "invalid_payload";
reason_code:
| "kda.procedure_payload_missing_steps"
| "kda.procedure_payload_legacy_semantic_steps_only"
| "kda.procedure_payload_invalid_contract_quality"
| "kda.procedure_payload_invalid_environment";
metadata: Record<string, unknown>;
schema_version: 1;
};
export function projectProcedurePayloadForKda(
raw_payload: unknown,
): KdaProcedureProjectionResult {
const payload = raw_payload as Partial<KdaProcedureRenderPayloadProjection> & {
semantic_steps?: unknown;
};
if (!Array.isArray(payload.steps) || payload.steps.length === 0) {
if (Array.isArray(payload.semantic_steps)) {
return {
kind: "invalid_payload",
reason_code: "kda.procedure_payload_legacy_semantic_steps_only",
metadata: { observed_field: "semantic_steps", expected_field: "steps" },
schema_version: 1,
};
}
return { kind: "invalid_payload", reason_code: "kda.procedure_payload_missing_steps", metadata: {}, schema_version: 1 };
}
if (!payload.environment || !payload.environment.app_entity_id || !payload.environment.app_name) {
return {
kind: "invalid_payload",
reason_code: "kda.procedure_payload_invalid_environment",
metadata: { has_environment: Boolean(payload.environment) },
schema_version: 1,
};
}
if (
payload.contract_quality &&
(!Number.isFinite(payload.contract_quality.overall_quality_score) ||
payload.contract_quality.overall_quality_score < 0 ||
payload.contract_quality.overall_quality_score > 1)
) {
return {
kind: "invalid_payload",
reason_code: "kda.procedure_payload_invalid_contract_quality",
metadata: { overall_quality_score: payload.contract_quality.overall_quality_score },
schema_version: 1,
};
}
const projected: KdaProcedureRenderPayloadProjection = {
canonical_name: payload.canonical_name ?? "Untitled procedure",
description: payload.description ?? "",
use_conditions: payload.use_conditions ?? [],
non_use_conditions: payload.non_use_conditions ?? [],
trigger_phrases: payload.trigger_phrases ?? [],
semantic_lookup_phrases: payload.semantic_lookup_phrases ?? [],
preconditions: payload.preconditions ?? [],
postconditions: payload.postconditions ?? [],
steps: payload.steps.map((step, i) => ({
step_index: Number.isInteger(step.step_index) ? step.step_index : i + 1,
intent: step.intent,
detailed_instructions: step.detailed_instructions,
parameters: step.parameters ?? [],
verification: step.verification,
conditional: step.conditional,
rationale: step.rationale,
capability_area: step.capability_area,
step_nature: step.step_nature ?? "mechanical",
})),
is_composite: payload.is_composite ?? false,
used_procedure_ids: payload.used_procedure_ids,
constituent_ordering: payload.constituent_ordering,
execution_topology: payload.execution_topology ?? "linear",
decision_points: payload.decision_points ?? [],
constraints: payload.constraints ?? [],
artifact_class: payload.artifact_class,
document_region: payload.document_region,
derivation_quality: payload.derivation_quality ?? "medium",
capability_tags: payload.capability_tags ?? [],
environment: payload.environment,
source: payload.source ?? "system",
contract_quality: payload.contract_quality,
derivation_metadata: payload.derivation_metadata,
annotations: payload.annotations ?? [],
schema_version: 1,
};
return { kind: "projected", payload: projected, degraded_reason_codes: [], schema_version: 1 };
}
```
KDA MAY render other DOC72 node kinds using owner-provided render-input contracts, but it MUST follow the same render-result and manifest-patch rules defined below. KDA renderers SHALL NOT emit fields listed in `KDA_NEVER_RENDER_PROCEDURE_FIELDS` into prompt text.
### 2.5 Extraction-model configuration is not KDA runtime rendering policy
KDA R3 does not own extraction-model selection. The R2 `ExtractionModelConfigSchema` is superseded as a KDA-owned runtime setting.
The owner split is:
- DOC72 / DOC3 / EC own extraction/intake model selection, extraction execution, extraction receipts, and derivation metadata.
- KDA consumes derivation metadata already attached to the DOC72 payload or render snapshot.
- KDA never calls an extraction model and never selects an extraction model during rendering.
- KDA uses derivation quality only as a rendering caution / tier cap input per §3.4.
```ts
export type KdaConsumedDerivationMetadata = {
derivation_model?: string;
derivation_model_class?:
| "cheap_local"
| "cheap_api"
| "medium"
| "expensive_frontier"
| "unknown";
derivation_quality?: "high" | "medium" | "low";
extraction_model_config_ref?: string;
extraction_receipt_id?: string;
schema_version: 1;
};
```
If derivation metadata indicates low-quality extraction or cheap-model extraction, KDA applies §3.4 quality-derived tier caps. KDA does not alter DOC72 confidence and does not mutate payload quality metadata.
## 3. Rendering pipeline
### 3.1 Runtime lifecycle placement
KDA participates only after DOC24 has passed through structural relevance, Matrix boost, directive assignment, and rendering-tier allocation inputs. The relevant lifecycle order is:
```text
structurally_relevant
→ matrix_boosted
→ directives_assigned
→ rendering_tier_allocated
→ overflow_resolved
→ manifest_written
→ policy_revalidated
→ dispatched | aborted_for_retry
→ reconciled
```
KDA renders at the `rendering_tier_allocated` / `overflow_resolved` boundary and returns structured render results before `manifest_written`.
KDA MUST NOT mutate card selection after `manifest_written`. If KDA detects invalid constraints, budget infeasibility, policy block, cache invalidation, or tokenizer failure before manifest write, it returns an explicit patch/decision and DOC24 decides whether to retry, reference-only render, suppress, or abort.
### 3.2 Canonical imports and local type discipline
KDA consumes these owner-doc types. The import names here are illustrative; implementations use the actual package paths established by the repo.
```ts
import type {
DirectiveConstraint,
ForceLevel,
TokenizerRef,
FinalPromptInjectionManifest,
PacketInjectionManifest,
PacketReconciliationEvent,
} from "@elnor/doc24-runtime-lifecycle";
import type {
LearningVisibilityScope,
MatrixModelClass,
} from "@elnor/learning-scope-contracts";
import type {
PolicyDecision,
PropASharingAction,
} from "@elnor/policy-contracts";
```
KDA MUST NOT locally redefine DOC24 `ForceLevel`, `DirectiveConstraint`, `CardPresence`, `DeliveryTag`, `ConstraintOrigin`, or `DOC24DeliveryDirective`.
### 3.2A Rendering tiers
```ts
export type RenderingTier = "compact" | "standard" | "full";
```
`RenderingTier` is canonical in KDA R3 as `compact | standard | full`. There is no `auto` tier value.
### 3.2B Canonical manifest patch discriminated union
KDA R3 owns exactly one `KdaManifestPatch` definition. Any other flat or nullable KDA manifest patch type is non-operative.
```ts
export type KdaReasonCode =
| "kda.render_blocked_by_policy"
| "kda.render_stripped_by_policy"
| "kda.render_redacted_by_policy"
| "kda.literal_retention_confirmation_required"
| "kda.authority_reference_only"
| "kda.policy_reference_only"
| "kda.reference_only_required"
| "kda.compact_budget_overflow"
| "kda.direct_target_exceeds_budget"
| "kda.rendered_token_budget_overflow"
| "kda.invalid_tier_constraints"
| "kda.execution_strategy_invalidated"
| "kda.execution_strategy_missing"
| "kda.unknown_client_kind"
| "kda.work_product_routed_to_document_tier"
| "kda.tokenizer_drift_detected"
| "kda.tokenizer_count_invalid"
| "kda.composed_component_span_invalid"
| "kda.composed_card_split_by_final_prompt_owner"
| "kda.canary_admitted"
| "kda.canary_effective_state_blocks_activation"
| "kda.canary_insufficient_evidence"
| "kda.canary_regression_threshold_exceeded"
| "kda.canary_success_threshold_met"
| "kda.canary_recanary_requested"
| "kda.canary_rollback_completed"
| "kda.canary_demoted_terminal"
| "kda.specialization_scope_broadening_requires_policy_approval"
| "kda.default_tier_from_force"
| "kda.default_tier_capped_by_low_confidence"
| "kda.default_tier_capped_by_authority"
| "kda.contract_quality_caps_tier"
| "kda.derivation_quality_caps_tier"
| "kda.cheap_derivation_model_caps_tier"
| "kda.default_tier_capped_by_quality"
| "kda.remote_mode_local_full"
| "kda.remote_mode_remote_guidance_only"
| "kda.remote_mode_remote_full_tools_available"
| "kda.remote_mode_suppressed_by_policy"
| "kda.remote_mode_guidance_only_partial_strategy"
| "kda.remote_mode_full_pure_semantic"
| "kda.remote_rendering_suppressed"
| "kda.unsupported_renderable_node_kind"
| "kda.procedure_payload_missing_steps"
| "kda.procedure_payload_legacy_semantic_steps_only"
| "kda.procedure_payload_invalid_contract_quality"
| "kda.procedure_payload_invalid_environment"
| "kda.preview_blocked_by_policy"
| "kda.preview_reference_only"
| "kda.preview_unsupported_node_kind"
| "kda.preview_payload_invalid"
| "kda.retired_contract_name_used"
| "kda.restore_snapshot_mismatch"
| "kda.restore_schema_unsupported"
| "kda.restore_hash_mismatch"
| "kda.restore_artifact_invalid";
export type KdaManifestPatch =
| {
card_presence: "included_inline";
card_id: string;
rendering_tier: RenderingTier;
rendered_token_count: number;
tokenizer_ref: TokenizerRef;
count_method: "exact";
rendering_specialization_id?: string;
render_variant_id: string;
template_version: string;
degraded_reason_codes: KdaReasonCode[];
schema_version: 1;
}
| {
card_presence: "included_reference_only";
card_id: string;
reference_label: string;
rendering_tier: null;
rendered_token_count: number;
tokenizer_ref: TokenizerRef;
count_method: "exact" | "estimated";
render_variant_id:
| "authority_reference_only_v1"
| "policy_reference_only_v1"
| "doc25_work_product_reference_v1";
template_version: string;
degraded_reason_codes: KdaReasonCode[];
schema_version: 1;
}
| {
card_presence: "excluded";
card_id: string;
rendering_tier: null;
rendered_token_count: 0;
suppression_kind: "authority_blocked" | "policy_excluded" | "budget_blocked";
degraded_reason_codes: KdaReasonCode[];
schema_version: 1;
};
```
Invariants:
- `included_inline` requires a non-null `rendering_tier` and exact token count.
- `included_reference_only` requires `rendering_tier: null` and a stable `card_id`. It MUST NOT use `reference_label` as identity.
- `excluded` requires zero rendered tokens and no substantive rendered text.
- Invalid combinations are schema failures, not soft warnings.
Reference-only helper:
```ts
export type KdaPresenceRenderPatchResult = {
rendered_text: string;
manifest_patch: KdaManifestPatch;
schema_version: 1;
};
export function renderReferenceOnlyCardPatch(input: {
card_id: string;
reference_label: string;
reference_mode: "authority_reference_only" | "policy_reference_only";
tokenizer_ref: TokenizerRef;
countTokens: (text: string, tokenizer: TokenizerRef) => number;
}): KdaPresenceRenderPatchResult {
const rendered_text = `[${input.reference_label} — reference only]`;
const render_variant_id = input.reference_mode === "authority_reference_only"
? "authority_reference_only_v1"
: "policy_reference_only_v1";
const degraded_reason_code = input.reference_mode === "authority_reference_only"
? "kda.authority_reference_only"
: "kda.policy_reference_only";
return {
rendered_text,
manifest_patch: {
card_presence: "included_reference_only",
card_id: input.card_id,
reference_label: input.reference_label,
rendering_tier: null,
rendered_token_count: input.countTokens(rendered_text, input.tokenizer_ref),
tokenizer_ref: input.tokenizer_ref,
count_method: "exact",
render_variant_id,
template_version: "reference_only@1",
degraded_reason_codes: [degraded_reason_code],
schema_version: 1,
},
schema_version: 1,
};
}
export function excludedKdaRenderPatch(input: {
card_id: string;
suppression_kind: "authority_blocked" | "policy_excluded" | "budget_blocked";
degraded_reason_codes: KdaReasonCode[];
}): KdaPresenceRenderPatchResult {
return {
rendered_text: "",
manifest_patch: {
card_presence: "excluded",
card_id: input.card_id,
rendering_tier: null,
rendered_token_count: 0,
suppression_kind: input.suppression_kind,
degraded_reason_codes: input.degraded_reason_codes,
schema_version: 1,
},
schema_version: 1,
};
}
```
### 3.2C PropA destination-aware render policy and literal retention
```ts
export type KdaSharingAction = "allow" | "warn" | "block" | "strip" | "redact";
export type KdaDestinationClass = "same_machine_local_runtime" | "cloud_api" | "external_share";
export type KdaRenderPolicyInput = {
destination: KdaDestinationClass;
policy_decision_id: string;
sharing_action: KdaSharingAction;
visibility_class: "blocked" | "local_only" | "cloud_warn" | "cloud_allowed";
warning_receipt_id?: string;
redaction_map_ref?: string;
schema_version: 1;
};
export type LiteralRetentionDecision =
| { kind: "retain"; value: string }
| { kind: "placeholder"; placeholder: string }
| { kind: "strip" }
| { kind: "redacted"; redaction_map_ref: string };
export function enforceKdaRenderPolicy(input: KdaRenderPolicyInput):
| { kind: "render_allowed" }
| { kind: "render_blocked"; reason_code: "kda.render_blocked_by_policy" }
| { kind: "render_stripped"; reason_code: "kda.render_stripped_by_policy" }
| { kind: "render_redacted"; redaction_map_ref: string } {
if (input.sharing_action === "block" || input.visibility_class === "blocked") {
return { kind: "render_blocked", reason_code: "kda.render_blocked_by_policy" };
}
if (input.sharing_action === "warn" && input.destination !== "same_machine_local_runtime" && !input.warning_receipt_id) {
return { kind: "render_blocked", reason_code: "kda.render_blocked_by_policy" };
}
if (input.sharing_action === "strip") {
return { kind: "render_stripped", reason_code: "kda.render_stripped_by_policy" };
}
if (input.sharing_action === "redact") {
if (!input.redaction_map_ref) {
return { kind: "render_blocked", reason_code: "kda.render_blocked_by_policy" };
}
return { kind: "render_redacted", redaction_map_ref: input.redaction_map_ref };
}
return { kind: "render_allowed" };
}
export function applyLiteralRetentionClass(input: {
value: string;
literal_retention_class: LiteralRetentionClass;
render_policy: KdaRenderPolicyInput;
literal_retention_confirmation_id?: string;
}): LiteralRetentionDecision {
const policy = enforceKdaRenderPolicy(input.render_policy);
if (policy.kind === "render_blocked" || policy.kind === "render_stripped") return { kind: "strip" };
if (policy.kind === "render_redacted") return { kind: "redacted", redaction_map_ref: policy.redaction_map_ref };
if (input.literal_retention_class === "placeholder_only") {
return { kind: "placeholder", placeholder: "[value omitted]" };
}
if (input.literal_retention_class === "retain_if_user_confirmed" && !input.literal_retention_confirmation_id) {
return { kind: "placeholder", placeholder: "[value requires confirmation]" };
}
return { kind: "retain", value: input.value };
}
```
Rules:
- `warn` for cloud/external destinations requires a warning receipt.
- `redact` requires a redaction map. KDA MUST NOT guess a redaction.
- `block` and `strip` return no substantive render.
- Literal-retention confirmation is separate from sharing warning receipt.
### 3.2D Render result and pure renderer
```ts
export type KdaRenderResult = {
rendered_text: string;
manifest_patch: KdaManifestPatch;
render_provenance: {
node_id: string;
node_payload_hash: string;
template_hash: string;
policy_decision_id: string;
execution_strategy_snapshot_hash?: string;
};
schema_version: 1;
};
// KDA-owned render-variant outcome record consumed by BDSM/DOC8 after the
// DOC24 manifest/final-prompt/reconciliation join. KDA owns the schema
// because it describes render-variant identity. BDSM/DOC8 compute the outcome;
// EC writes the durable record.
export type KdaVariantOutcome = {
card_id: string;
packet_id: string;
render_variant_id: string;
rendering_specialization_id?: string;
template_version: string;
rendering_tier: RenderingTier | null;
canary_state?: KdaCanaryState;
composition_id?: string;
component_card_ids?: string[];
variant_outcome:
| "variant_used"
| "variant_ignored"
| "variant_corrected"
| "variant_negative"
| "no_variant_signal";
attribution_decision_id: string;
schema_version: 1;
};
export type ExecutionStrategySnapshot = {
snapshot_hash: string;
state: "strategy_available" | "strategy_invalidated" | "strategy_missing";
execution_strategy_id?: string;
tool_directive_text?: string;
degraded_reason_codes: KdaReasonCode[];
schema_version: 1;
};
export type KdaRenderInputBundle = {
packet_id: string;
card_id: string;
node_snapshot: KdaNodeSnapshot;
linked_goal_snapshots: Array<{ node_id: string; canonical_name: string }>;
execution_strategy_snapshot?: ExecutionStrategySnapshot;
render_policy: KdaRenderPolicyInput;
rendering_tier: RenderingTier;
tokenizer_ref: TokenizerRef;
remote_rendering_mode?: KdaRemoteRenderingMode;
schema_version: 1;
};
```
Before rendering a procedure or standing-procedure node, KDA SHALL call `projectProcedurePayloadForKda`. If the result is `invalid_payload`, KDA SHALL NOT fabricate missing fields. DOC24 may include a reference-only diagnostic card or exclude the card according to policy/budget, but KDA MUST NOT render a procedure by reading legacy `semantic_steps` or by dumping unknown payload JSON into the prompt.
KDA renderers SHALL NOT emit fields listed in `KDA_NEVER_RENDER_PROCEDURE_FIELDS` into prompt text. In particular, `trigger_phrases` and `semantic_lookup_phrases` are routing-only metadata.
Step rendering preserves R2 mechanical/cognitive/hybrid semantics:
```ts
export type KdaRenderedStep = {
step_index: number;
rendered_text: string;
used_tool_directive: boolean;
rendered_as: "mechanical" | "cognitive" | "hybrid";
degraded_reason_codes: KdaReasonCode[];
schema_version: 1;
};
export type KdaStepExecutionStrategyState =
| { kind: "strategy_available"; tool_directive_text: string; execution_strategy_id: string; tool_ref?: string }
| { kind: "strategy_invalidated"; degraded_reason_code: "kda.execution_strategy_invalidated"; fallback_text?: string }
| { kind: "strategy_missing"; degraded_reason_code: "kda.execution_strategy_missing"; fallback_text?: string };
export function renderSemanticStepV3(input: {
step: KdaSemanticStepProjection;
rendering_tier: RenderingTier;
remote_rendering_mode: KdaRemoteRenderingMode;
execution_strategy_state?: KdaStepExecutionStrategyState;
include_rationale: boolean;
schema_version: 1;
}): KdaRenderedStep {
const reasons: KdaReasonCode[] = [];
const parts: string[] = [];
const step = input.step;
const instruction = step.detailed_instructions && input.rendering_tier === "full" ? step.detailed_instructions : step.intent;
parts.push(`${step.step_index}. ${instruction}`);
if (step.conditional) parts.push(` Skip if: ${step.conditional}`);
if (step.parameters.length > 0 && input.rendering_tier !== "compact") {
const rendered_params = step.parameters.map((p) => `${p.name}: ${p.value}`).join("; ");
parts.push(` Parameters: ${rendered_params}`);
}
let used_tool_directive = false;
if (step.step_nature === "cognitive") {
parts.push(" Cognitive instruction: evaluate the available document/context; no tool directive is required for this step.");
} else {
const strategy = input.execution_strategy_state;
if (input.remote_rendering_mode === "suppress") {
reasons.push("kda.remote_rendering_suppressed");
return { step_index: step.step_index, rendered_text: "", used_tool_directive: false, rendered_as: step.step_nature, degraded_reason_codes: reasons, schema_version: 1 };
}
if (input.remote_rendering_mode === "guidance_only") {
parts.push(" Guidance only: use ordinary UI navigation or available tools; cached tool directive is not exposed for this client.");
} else if (strategy?.kind === "strategy_available") {
parts.push(` Tool directive: ${strategy.tool_directive_text}`);
used_tool_directive = true;
} else if (strategy?.kind === "strategy_invalidated") {
reasons.push(strategy.degraded_reason_code);
parts.push(` UI fallback: ${strategy.fallback_text ?? "Use ordinary UI navigation; cached tool shortcut is unavailable."}`);
} else if (strategy?.kind === "strategy_missing") {
reasons.push(strategy.degraded_reason_code);
parts.push(` UI fallback: ${strategy.fallback_text ?? "Use ordinary UI navigation; no cached tool shortcut is available."}`);
}
}
if (step.step_nature === "hybrid") {
parts.push(" Hybrid step: perform the mechanical action and apply the cognitive review described above.");
}
if (step.verification && input.rendering_tier === "full") parts.push(` Verify: ${step.verification.check}`);
if (step.rationale && input.include_rationale && input.rendering_tier === "full") parts.push(` Rationale: ${step.rationale}`);
return { step_index: step.step_index, rendered_text: parts.filter(Boolean).join("\n"), used_tool_directive, rendered_as: step.step_nature, degraded_reason_codes: reasons, schema_version: 1 };
}
```
Cognitive steps SHALL render as document/context evaluation instructions and SHALL NOT require an execution-strategy cache entry. Mechanical steps MAY render tool directives when the client, policy, and execution-strategy snapshot permit. Hybrid steps SHALL render both semantic instruction and, where permitted, a tool directive or UI-navigation fallback.
Canonical renderer:
```ts
export function renderKnowledgeCardV3(input: KdaRenderInputBundle): KdaRenderResult {
const node_kind_decision = resolveKdaRenderableNodeKind(input.node_snapshot.node_kind);
if (node_kind_decision.kind === "unsupported") {
return {
rendered_text: "",
manifest_patch: {
card_presence: "excluded",
card_id: input.card_id,
rendering_tier: null,
rendered_token_count: 0,
suppression_kind: "policy_excluded",
degraded_reason_codes: [node_kind_decision.reason_code],
schema_version: 1,
},
render_provenance: renderProvenanceFromInput(input),
schema_version: 1,
};
}
if (node_kind_decision.render_path === "doc25_work_product_reference") {
return renderDoc25WorkProductReference(input);
}
const policy = enforceKdaRenderPolicy(input.render_policy);
if (policy.kind === "render_blocked" || policy.kind === "render_stripped") {
return {
rendered_text: "",
manifest_patch: {
card_presence: "excluded",
card_id: input.card_id,
rendering_tier: null,
rendered_token_count: 0,
suppression_kind: "policy_excluded",
degraded_reason_codes: [policy.reason_code],
schema_version: 1,
},
render_provenance: renderProvenanceFromInput(input),
schema_version: 1,
};
}
if (node_kind_decision.render_path === "procedure_renderer") {
const projected = projectProcedurePayloadForKda(input.node_snapshot.payload);
if (projected.kind === "invalid_payload") {
return {
rendered_text: `[${input.node_snapshot.canonical_name} — procedure payload invalid]`,
manifest_patch: {
card_presence: "included_reference_only",
card_id: input.card_id,
reference_label: input.node_snapshot.canonical_name,
rendering_tier: null,
rendered_token_count: countTokens(`[${input.node_snapshot.canonical_name} — procedure payload invalid]`, input.tokenizer_ref),
tokenizer_ref: input.tokenizer_ref,
count_method: "exact",
render_variant_id: "policy_reference_only_v1",
template_version: "payload_invalid_reference@1",
degraded_reason_codes: [projected.reason_code],
schema_version: 1,
},
render_provenance: renderProvenanceFromInput(input),
schema_version: 1,
};
}
}
const rendered_text = renderTemplateFromSnapshot(input, policy);
const degraded_reason_codes: KdaReasonCode[] = [
...(input.execution_strategy_snapshot?.degraded_reason_codes ?? []),
];
if (policy.kind === "render_redacted") degraded_reason_codes.push("kda.render_redacted_by_policy");
return {
rendered_text,
manifest_patch: {
card_presence: "included_inline",
card_id: input.card_id,
rendering_tier: input.rendering_tier,
render_variant_id: selectRenderVariantId(input),
template_version: selectTemplateVersion(input),
rendered_token_count: countTokens(rendered_text, input.tokenizer_ref),
tokenizer_ref: input.tokenizer_ref,
count_method: "exact",
degraded_reason_codes,
schema_version: 1,
},
render_provenance: renderProvenanceFromInput(input),
schema_version: 1,
};
}
```
The helper names above (`renderTemplateFromSnapshot`, `selectRenderVariantId`, `countTokens`, etc.) are deterministic template utilities. They MUST NOT perform durable reads.
### 3.2E DOC25 work-product/document-tier routing
KDA MUST NOT inline-render large work products as ordinary knowledge cards. KDA emits a reference patch and routes substantive document text to DOC25/DOC24 document-tier rendering.
```ts
export function renderDoc25WorkProductReference(input: KdaRenderInputBundle): KdaRenderResult {
const rendered_text = `[Work product: ${input.node_snapshot.canonical_name} — document-tier rendering via DOC25/DOC24]`;
return {
rendered_text,
manifest_patch: {
card_id: input.card_id,
card_presence: "included_reference_only",
reference_label: input.node_snapshot.canonical_name,
rendering_tier: null,
render_variant_id: "doc25_work_product_reference_v1",
template_version: "doc25_work_product_reference@1",
rendered_token_count: countTokens(rendered_text, input.tokenizer_ref),
tokenizer_ref: input.tokenizer_ref,
count_method: "exact",
degraded_reason_codes: ["kda.work_product_routed_to_document_tier"],
schema_version: 1,
},
render_provenance: {
node_id: input.node_snapshot.node_id,
node_payload_hash: input.node_snapshot.payload_hash,
template_hash: "doc25_work_product_reference@1",
policy_decision_id: input.render_policy.policy_decision_id,
},
schema_version: 1,
};
}
```
### 3.3 Client-kind canonicalization and remote rendering mode
```ts
export type ClientKind = "elnor_native" | "claude_remote" | "chatgpt_remote";
export type ClientKindParseResult =
| { kind: "ok"; client_kind: ClientKind; migrated_from?: "local_elnor" }
| { kind: "error"; reason_code: "kda.unknown_client_kind"; observed_value: string };
export function normalizeClientKind(input: string): ClientKindParseResult {
if (input === "local_elnor") return { kind: "ok", client_kind: "elnor_native", migrated_from: "local_elnor" };
if (input === "elnor_native" || input === "claude_remote" || input === "chatgpt_remote") {
return { kind: "ok", client_kind: input };
}
return { kind: "error", reason_code: "kda.unknown_client_kind", observed_value: input };
}
```
Rules:
- `local_elnor` is accepted only as migration alias.
- Persistent records MUST be rewritten to `elnor_native` during migration.
- Unknown client kinds fail closed. They do not default to a remote client.
KDA preserves R2 remote rendering modes while integrating PropA/DOC24 policy and tool availability.
```ts
export type KdaRemoteRenderingMode = "full" | "guidance_only" | "suppress";
export type KdaRemoteRenderingModeDecision = {
mode: KdaRemoteRenderingMode;
reason_code:
| "kda.remote_mode_local_full"
| "kda.remote_mode_remote_guidance_only"
| "kda.remote_mode_remote_full_tools_available"
| "kda.remote_mode_suppressed_by_policy"
| "kda.remote_mode_guidance_only_partial_strategy"
| "kda.remote_mode_full_pure_semantic";
stripped_tool_directives: boolean;
schema_version: 1;
};
export type KdaMountedToolSnapshot = {
client_kind: ClientKind;
mounted_tool_refs: string[];
snapshot_hash: string;
schema_version: 1;
};
export type KdaExecutionStrategySummary = {
step_index: number;
strategy_state: "available" | "missing" | "invalidated";
path?: "mcp_tool" | "system_run" | "ui_navigation" | "none";
tool_ref?: string;
schema_version: 1;
};
export function resolveRemoteRenderingModeV3(input: {
client_kind: ClientKind;
destination: "same_machine_local_runtime" | "cloud_api" | "external_share";
render_policy: KdaRenderPolicyInput;
procedure_steps: KdaSemanticStepProjection[];
execution_strategies: KdaExecutionStrategySummary[];
mounted_tools: KdaMountedToolSnapshot;
schema_version: 1;
}): KdaRemoteRenderingModeDecision {
if (input.render_policy.sharing_action === "block" || input.render_policy.visibility_class === "blocked") {
return { mode: "suppress", reason_code: "kda.remote_mode_suppressed_by_policy", stripped_tool_directives: true, schema_version: 1 };
}
if (input.client_kind === "elnor_native" && input.destination === "same_machine_local_runtime") {
return { mode: "full", reason_code: "kda.remote_mode_local_full", stripped_tool_directives: false, schema_version: 1 };
}
const mechanical_steps = input.procedure_steps.filter((s) => s.step_nature !== "cognitive");
if (mechanical_steps.length === 0) {
return { mode: "full", reason_code: "kda.remote_mode_full_pure_semantic", stripped_tool_directives: false, schema_version: 1 };
}
const strategy_by_step = new Map(input.execution_strategies.map((s) => [s.step_index, s]));
const all_mcp_tools_available = mechanical_steps.every((step) => {
const strategy = strategy_by_step.get(step.step_index);
return (
strategy?.strategy_state === "available" &&
strategy.path === "mcp_tool" &&
Boolean(strategy.tool_ref) &&
input.mounted_tools.mounted_tool_refs.includes(strategy.tool_ref as string)
);
});
if (all_mcp_tools_available) {
return { mode: "full", reason_code: "kda.remote_mode_remote_full_tools_available", stripped_tool_directives: false, schema_version: 1 };
}
const has_any_strategy = input.execution_strategies.length > 0;
return {
mode: "guidance_only",
reason_code: has_any_strategy ? "kda.remote_mode_guidance_only_partial_strategy" : "kda.remote_mode_remote_guidance_only",
stripped_tool_directives: true,
schema_version: 1,
};
}
```
### 3.4 Constraint-aware tier bounds
KDA consumes canonical DOC24 directive constraints and resolved card presence. KDA must not redefine force, policy, authority, or hedge semantics.
```ts
export type KdaTierBounds = {
card_id: string;
resolved_min_tier: RenderingTier;
resolved_max_tier: RenderingTier;
card_presence: "included_inline" | "included_reference_only" | "excluded";
degraded_reason_codes: KdaReasonCode[];
schema_version: 1;
};
const TIER_RANK: Record<RenderingTier, number> = { compact: 1, standard: 2, full: 3 };
export function compareTier(a: RenderingTier, b: RenderingTier): number {
return TIER_RANK[a] - TIER_RANK[b];
}
export function minTier(a: RenderingTier, b: RenderingTier): RenderingTier {
return compareTier(a, b) <= 0 ? a : b;
}
export function maxTier(a: RenderingTier, b: RenderingTier): RenderingTier {
return compareTier(a, b) >= 0 ? a : b;
}
export function clampTierToBounds(input: { desired: RenderingTier; min_tier: RenderingTier; max_tier: RenderingTier }): RenderingTier {
if (compareTier(input.min_tier, input.max_tier) > 0) return input.max_tier;
return maxTier(input.min_tier, minTier(input.desired, input.max_tier));
}
export type KdaConstraintConflictDecision =
| { kind: "ok"; schema_version: 1 }
| {
kind: "conflict";
reason_code: "kda.invalid_tier_constraints";
card_id: string;
min_tier: RenderingTier;
max_tier: RenderingTier;
metadata: { constraint_count: number };
schema_version: 1;
};
export function validateTierBounds(input: {
card_id: string;
min_tier: RenderingTier;
max_tier: RenderingTier;
constraint_count: number;
}): KdaConstraintConflictDecision {
if (compareTier(input.min_tier, input.max_tier) <= 0) return { kind: "ok", schema_version: 1 };
return { kind: "conflict", reason_code: "kda.invalid_tier_constraints", card_id: input.card_id, min_tier: input.min_tier, max_tier: input.max_tier, metadata: { constraint_count: input.constraint_count }, schema_version: 1 };
}
```
Resolved directive tier defaults:
```ts
export const LOW_EPISTEMIC_CONFIDENCE_THRESHOLD = 0.35;
export const STANDARD_TIER_RELEVANCE_THRESHOLD = 0.50;
export const FULL_TIER_RELEVANCE_THRESHOLD = 0.60;
export const KDA_LOW_CONTRACT_QUALITY_COMPACT_CAP_THRESHOLD = 0.60;
export type KdaAuthorityTierCeiling = RenderingTier | "reference_only" | "excluded";
export type KdaQualityTierCapInput = {
card_id: string;
current_max_tier: RenderingTier;
is_direct_target: boolean;
contract_quality?: KdaContractQualityProjection;
derivation_quality?: "high" | "medium" | "low";
derivation_model_class?: "cheap_local" | "cheap_api" | "medium" | "expensive_frontier" | "unknown";
schema_version: 1;
};
export type KdaQualityTierCapDecision = {
card_id: string;
resolved_max_tier: RenderingTier;
degraded_reason_codes: KdaReasonCode[];
cap_applied: boolean;
metadata: Record<string, unknown>;
schema_version: 1;
};
export function applyQualityTierCaps(input: KdaQualityTierCapInput): KdaQualityTierCapDecision {
const reasons: KdaReasonCode[] = [];
const metadata: Record<string, unknown> = {};
let max_tier = input.current_max_tier;
if (input.is_direct_target) {
return { card_id: input.card_id, resolved_max_tier: max_tier, degraded_reason_codes: reasons, cap_applied: false, metadata, schema_version: 1 };
}
const quality_score = input.contract_quality?.overall_quality_score;
if (quality_score !== undefined) {
if (!Number.isFinite(quality_score) || quality_score < 0 || quality_score > 1) {
max_tier = minTier(max_tier, "compact");
reasons.push("kda.contract_quality_caps_tier");
metadata.invalid_contract_quality_score = quality_score;
} else if (quality_score < KDA_LOW_CONTRACT_QUALITY_COMPACT_CAP_THRESHOLD) {
max_tier = minTier(max_tier, "compact");
reasons.push("kda.contract_quality_caps_tier");
metadata.contract_quality_score = quality_score;
}
}
if (input.derivation_quality === "low") {
max_tier = minTier(max_tier, "compact");
reasons.push("kda.derivation_quality_caps_tier");
metadata.derivation_quality = input.derivation_quality;
}
if (input.derivation_model_class === "cheap_local" || input.derivation_model_class === "cheap_api") {
max_tier = minTier(max_tier, "standard");
reasons.push("kda.cheap_derivation_model_caps_tier");
metadata.derivation_model_class = input.derivation_model_class;
}
return { card_id: input.card_id, resolved_max_tier: max_tier, degraded_reason_codes: reasons, cap_applied: reasons.length > 0, metadata, schema_version: 1 };
}
export type KdaResolvedDirectiveTierInput = {
card_id: string;
card_presence: "included_inline" | "included_reference_only" | "excluded";
resolved_force_level: ForceLevel;
normalized_relevance: number;
epistemic_confidence: number | null;
authority_tier_ceiling?: KdaAuthorityTierCeiling;
directly_requested: boolean;
resolved_min_tier: RenderingTier;
resolved_max_tier: RenderingTier;
contract_quality?: KdaContractQualityProjection;
derivation_quality?: "high" | "medium" | "low";
derivation_metadata?: KdaDerivationMetadata;
schema_version: 1;
};
export type KdaDefaultTierDecision =
| {
kind: "inline_tier";
card_id: string;
tier: RenderingTier;
reason_code:
| "kda.default_tier_from_force"
| "kda.default_tier_capped_by_low_confidence"
| "kda.default_tier_capped_by_authority"
| "kda.default_tier_capped_by_quality";
degraded_reason_codes: KdaReasonCode[];
metadata: Record<string, unknown>;
schema_version: 1;
}
| { kind: "not_inline"; card_id: string; card_presence: "included_reference_only" | "excluded"; reason_code: "kda.reference_only_required" | "kda.render_blocked_by_policy"; schema_version: 1 }
| { kind: "invalid"; card_id: string; reason_code: "kda.invalid_tier_constraints"; metadata: Record<string, unknown>; schema_version: 1 };
export function defaultTierFromResolvedDirective(input: KdaResolvedDirectiveTierInput): KdaDefaultTierDecision {
if (input.card_presence === "included_reference_only") {
return { kind: "not_inline", card_id: input.card_id, card_presence: "included_reference_only", reason_code: "kda.reference_only_required", schema_version: 1 };
}
if (input.card_presence === "excluded") {
return { kind: "not_inline", card_id: input.card_id, card_presence: "excluded", reason_code: "kda.render_blocked_by_policy", schema_version: 1 };
}
if (!Number.isFinite(input.normalized_relevance) || input.normalized_relevance < 0 || input.normalized_relevance > 1 || compareTier(input.resolved_min_tier, input.resolved_max_tier) > 0) {
return { kind: "invalid", card_id: input.card_id, reason_code: "kda.invalid_tier_constraints", metadata: { normalized_relevance: input.normalized_relevance, resolved_min_tier: input.resolved_min_tier, resolved_max_tier: input.resolved_max_tier }, schema_version: 1 };
}
if (input.authority_tier_ceiling === "reference_only") {
return { kind: "not_inline", card_id: input.card_id, card_presence: "included_reference_only", reason_code: "kda.reference_only_required", schema_version: 1 };
}
if (input.authority_tier_ceiling === "excluded") {
return { kind: "not_inline", card_id: input.card_id, card_presence: "excluded", reason_code: "kda.render_blocked_by_policy", schema_version: 1 };
}
let desired: RenderingTier;
if (input.resolved_force_level === "hard") desired = "full";
else if (input.resolved_force_level === "strong") desired = input.normalized_relevance >= FULL_TIER_RELEVANCE_THRESHOLD ? "full" : "standard";
else if (input.resolved_force_level === "standard") desired = input.normalized_relevance >= STANDARD_TIER_RELEVANCE_THRESHOLD ? "standard" : "compact";
else desired = "compact";
let reason_code: "kda.default_tier_from_force" | "kda.default_tier_capped_by_low_confidence" | "kda.default_tier_capped_by_authority" | "kda.default_tier_capped_by_quality" = "kda.default_tier_from_force";
if (input.epistemic_confidence !== null && Number.isFinite(input.epistemic_confidence) && input.epistemic_confidence < LOW_EPISTEMIC_CONFIDENCE_THRESHOLD && !input.directly_requested) {
desired = minTier(desired, "standard");
reason_code = "kda.default_tier_capped_by_low_confidence";
}
if (input.authority_tier_ceiling && input.authority_tier_ceiling !== "reference_only" && input.authority_tier_ceiling !== "excluded") {
desired = minTier(desired, input.authority_tier_ceiling);
reason_code = "kda.default_tier_capped_by_authority";
}
const qualityCap = applyQualityTierCaps({
card_id: input.card_id,
current_max_tier: input.resolved_max_tier,
is_direct_target: input.directly_requested,
contract_quality: input.contract_quality,
derivation_quality: input.derivation_quality,
derivation_model_class: input.derivation_metadata?.derivation_model_class,
schema_version: 1,
});
return {
kind: "inline_tier",
card_id: input.card_id,
tier: clampTierToBounds({ desired, min_tier: input.resolved_min_tier, max_tier: qualityCap.resolved_max_tier }),
reason_code: qualityCap.cap_applied ? "kda.default_tier_capped_by_quality" : reason_code,
degraded_reason_codes: qualityCap.degraded_reason_codes,
metadata: qualityCap.metadata,
schema_version: 1,
};
}
```
### 3.4A Canonical DOC24 directive-constraint resolution
KDA consumes DOC24 `DirectiveConstraint[]`; it MUST NOT create local lookalike constraints. This function converts canonical DOC24 constraints into KDA card presence and tier bounds.
```ts
export type KdaConstraintResolutionResult =
| {
kind: "resolved";
card_id: string;
card_presence: "included_inline" | "included_reference_only" | "excluded";
resolved_min_tier: RenderingTier;
resolved_max_tier: RenderingTier;
degraded_reason_codes: KdaReasonCode[];
metadata: {
force_floor_count: number;
force_ceiling_count: number;
reference_only_required: boolean;
block_inline_rendering: boolean;
redaction_applied: boolean;
};
schema_version: 1;
}
| {
kind: "conflict";
card_id: string;
reason_code: "kda.invalid_tier_constraints";
metadata: Record<string, unknown>;
schema_version: 1;
};
export function tierFloorForForceLevel(force: ForceLevel): RenderingTier {
if (force === "avoid") {
throw new KdaValidationError({
reason_code: "kda.invalid_tier_constraints",
metadata: { field: "force_level_floor", observed_force_level: force },
});
}
if (force === "hard" || force === "strong") return "full";
return "standard";
}
export function tierCeilingForForceLevel(force: ForceLevel): RenderingTier {
if (force === "hard") return "full";
if (force === "strong") return "standard";
// `standard` and `avoid` ceilings both prevent rich inline rendering.
// DOC24, not KDA, decides whether the card is excluded entirely.
return "compact";
}
export function resolveKdaConstraints(input: {
card_id: string;
constraints: DirectiveConstraint[];
initial_card_presence: "included_inline" | "included_reference_only" | "excluded";
initial_min_tier?: RenderingTier;
initial_max_tier?: RenderingTier;
}): KdaConstraintResolutionResult {
let card_presence = input.initial_card_presence;
let min_tier = input.initial_min_tier ?? "compact";
let max_tier = input.initial_max_tier ?? "full";
let force_floor_count = 0;
let force_ceiling_count = 0;
let reference_only_required = false;
let block_inline_rendering = false;
let redaction_applied = false;
const degraded_reason_codes: KdaReasonCode[] = [];
for (const constraint of input.constraints) {
if (constraint.kind === "force_level_floor") {
force_floor_count += 1;
if (constraint.floor === "avoid") {
return {
kind: "conflict",
card_id: input.card_id,
reason_code: "kda.invalid_tier_constraints",
metadata: { constraint_kind: constraint.kind, floor: constraint.floor },
schema_version: 1,
};
}
min_tier = maxTier(min_tier, tierFloorForForceLevel(constraint.floor));
continue;
}
if (constraint.kind === "force_level_ceiling") {
force_ceiling_count += 1;
max_tier = minTier(max_tier, tierCeilingForForceLevel(constraint.ceiling));
continue;
}
if (constraint.kind === "reference_only_required") {
reference_only_required = true;
card_presence = "included_reference_only";
degraded_reason_codes.push("kda.reference_only_required");
continue;
}
if (constraint.kind === "block_inline_rendering") {
block_inline_rendering = true;
if (!reference_only_required) {
card_presence = "excluded";
degraded_reason_codes.push("kda.render_blocked_by_policy");
}
continue;
}
if (constraint.kind === "redaction_applied") {
redaction_applied = true;
degraded_reason_codes.push("kda.render_redacted_by_policy");
continue;
}
}
if (card_presence === "included_inline" && compareTier(min_tier, max_tier) > 0) {
return {
kind: "conflict",
card_id: input.card_id,
reason_code: "kda.invalid_tier_constraints",
metadata: {
min_tier,
max_tier,
force_floor_count,
force_ceiling_count,
},
schema_version: 1,
};
}
return {
kind: "resolved",
card_id: input.card_id,
card_presence,
resolved_min_tier: min_tier,
resolved_max_tier: max_tier,
degraded_reason_codes,
metadata: {
force_floor_count,
force_ceiling_count,
reference_only_required,
block_inline_rendering,
redaction_applied,
},
schema_version: 1,
};
}
```
Candidate construction rule: every `KdaTierCandidate` MUST be constructed from `KdaConstraintResolutionResult.kind === "resolved"`; conflict results fail packet assembly before inline tier allocation.
### 3.5 Tier candidate schema
```ts
export type KdaTierCandidate = {
id: string;
card_id: string;
node_kind: "procedure" | "memory_directive" | "domain_concept" | "goal" | "obligation" | "standing_procedure" | "work_product" | "other";
card_presence: "included_inline" | "included_reference_only" | "excluded";
is_direct_target: boolean;
normalized_relevance: number;
compact_cost: number;
standard_cost: number;
full_cost: number;
resolved_min_tier: RenderingTier;
resolved_max_tier: RenderingTier;
stable_tie_break_key: string;
schema_version: 1;
};
```
Validation rules:
- `normalized_relevance` MUST be finite and in `[0,1]`.
- `compact_cost <= standard_cost <= full_cost`.
- `resolved_min_tier <= resolved_max_tier`.
- Non-inline candidates do not enter inline tier allocation.
- Work products are routed through §3.2E.
- `card_presence`, `resolved_min_tier`, and `resolved_max_tier` SHALL come from `resolveKdaConstraints(...)` or a DOC24-owned equivalent resolution result.
### 3.6 Budget policy and banded allocation
```ts
export type KnowledgePacketBudgetPolicy = {
max_packet_tokens_absolute: number;
max_packet_tokens_pct_of_context: number;
procedure_sub_budget_pct: number;
direct_target_procedure_budget_pct: number;
schema_version: 1;
};
export type KnowledgePacketBudgetBreakdown = {
effective_budget_tokens: number;
direct_target_procedure_budget_tokens: number;
non_direct_procedure_budget_tokens: number;
non_procedure_budget_tokens: number;
tokenizer_ref: TokenizerRef;
schema_version: 1;
};
export const DEFAULT_KDA_BUDGET_POLICY: KnowledgePacketBudgetPolicy = {
max_packet_tokens_absolute: 4000,
max_packet_tokens_pct_of_context: 0.20,
procedure_sub_budget_pct: 0.25,
direct_target_procedure_budget_pct: 0.70,
schema_version: 1,
};
export function computeBudgetBreakdown(input: {
policy: KnowledgePacketBudgetPolicy;
model_context_window: number;
has_direct_target_procedure: boolean;
tokenizer_ref: TokenizerRef;
}): KnowledgePacketBudgetBreakdown {
if (
!Number.isFinite(input.model_context_window) ||
input.model_context_window <= 0 ||
!Number.isFinite(input.policy.max_packet_tokens_absolute) ||
!Number.isFinite(input.policy.max_packet_tokens_pct_of_context) ||
!Number.isFinite(input.policy.procedure_sub_budget_pct) ||
!Number.isFinite(input.policy.direct_target_procedure_budget_pct)
) {
throw new KdaValidationError({
reason_code: "kda.invalid_tier_constraints",
metadata: { field: "budget_policy" },
});
}
const effective = Math.max(0, Math.min(
Math.floor(input.policy.max_packet_tokens_absolute),
Math.floor(input.model_context_window * input.policy.max_packet_tokens_pct_of_context),
));
const direct_target_procedure_budget_tokens = input.has_direct_target_procedure
? Math.floor(effective * input.policy.direct_target_procedure_budget_pct)
: 0;
const remaining_after_direct = effective - direct_target_procedure_budget_tokens;
const non_direct_procedure_budget_tokens = Math.floor(
remaining_after_direct * input.policy.procedure_sub_budget_pct,
);
const non_procedure_budget_tokens =
effective - direct_target_procedure_budget_tokens - non_direct_procedure_budget_tokens;
return {
effective_budget_tokens: effective,
direct_target_procedure_budget_tokens,
non_direct_procedure_budget_tokens,
non_procedure_budget_tokens,
tokenizer_ref: input.tokenizer_ref,
schema_version: 1,
};
}
```
Tier decision:
```ts
export type RenderingTierDecision =
| {
kind: "included";
id: string;
card_id: string;
node_kind: KdaTierCandidate["node_kind"];
tier: RenderingTier;
estimated_token_cost: number;
budget_band: "direct_target_procedure" | "procedure" | "non_procedure";
schema_version: 1;
}
| {
kind: "suppressed_for_budget";
id: string;
card_id: string;
node_kind: KdaTierCandidate["node_kind"];
reason_code: "kda.compact_budget_overflow" | "kda.direct_target_exceeds_budget";
estimated_token_cost: number;
budget_band: "direct_target_procedure" | "procedure" | "non_procedure";
schema_version: 1;
}
| {
kind: "not_inline";
id: string;
card_id: string;
card_presence: "included_reference_only" | "excluded";
schema_version: 1;
};
```
Allocator:
```ts
function tierCost(c: KdaTierCandidate, tier: RenderingTier): number {
if (tier === "compact") return c.compact_cost;
if (tier === "standard") return c.standard_cost;
return c.full_cost;
}
function initialTier(c: KdaTierCandidate): RenderingTier {
return c.resolved_min_tier;
}
function sortForAllocation(a: KdaTierCandidate, b: KdaTierCandidate): number {
if (a.is_direct_target !== b.is_direct_target) return a.is_direct_target ? -1 : 1;
if (a.normalized_relevance !== b.normalized_relevance) return b.normalized_relevance - a.normalized_relevance;
return a.stable_tie_break_key.localeCompare(b.stable_tie_break_key);
}
export function allocateRenderingTiersV3(input: {
candidates: KdaTierCandidate[];
budget: KnowledgePacketBudgetBreakdown;
}): RenderingTierDecision[] {
const out: RenderingTierDecision[] = [];
const inline = input.candidates.filter(c => c.card_presence === "included_inline");
for (const c of input.candidates) {
if (c.card_presence !== "included_inline") {
out.push({ kind: "not_inline", id: c.id, card_id: c.card_id, card_presence: c.card_presence, schema_version: 1 });
}
}
for (const c of inline) {
if (!Number.isFinite(c.normalized_relevance) || c.normalized_relevance < 0 || c.normalized_relevance > 1) {
throw new KdaValidationError({ reason_code: "kda.invalid_tier_constraints", metadata: { card_id: c.card_id, field: "normalized_relevance" } });
}
if (c.compact_cost < 0 || c.standard_cost < c.compact_cost || c.full_cost < c.standard_cost) {
throw new KdaValidationError({ reason_code: "kda.invalid_tier_constraints", metadata: { card_id: c.card_id, field: "tier_costs" } });
}
if (compareTier(c.resolved_min_tier, c.resolved_max_tier) > 0) {
throw new KdaValidationError({ reason_code: "kda.invalid_tier_constraints", metadata: { card_id: c.card_id, field: "tier_bounds" } });
}
}
const byBand = {
direct_target_procedure: inline.filter(c => c.node_kind === "procedure" && c.is_direct_target).sort(sortForAllocation),
procedure: inline.filter(c => c.node_kind === "procedure" && !c.is_direct_target).sort(sortForAllocation),
non_procedure: inline.filter(c => c.node_kind !== "procedure").sort(sortForAllocation),
};
const budgets = {
direct_target_procedure: input.budget.direct_target_procedure_budget_tokens,
procedure: input.budget.non_direct_procedure_budget_tokens,
non_procedure: input.budget.non_procedure_budget_tokens,
};
for (const band of ["direct_target_procedure", "procedure", "non_procedure"] as const) {
let used = 0;
for (const c of byBand[band]) {
const tier = initialTier(c);
const cost = tierCost(c, tier);
if (used + cost <= budgets[band]) {
out.push({ kind: "included", id: c.id, card_id: c.card_id, node_kind: c.node_kind, tier, estimated_token_cost: cost, budget_band: band, schema_version: 1 });
used += cost;
continue;
}
out.push({
kind: "suppressed_for_budget",
id: c.id,
card_id: c.card_id,
node_kind: c.node_kind,
reason_code: band === "direct_target_procedure" ? "kda.direct_target_exceeds_budget" : "kda.compact_budget_overflow",
estimated_token_cost: cost,
budget_band: band,
schema_version: 1,
});
}
}
const included = out.filter((d): d is Extract<RenderingTierDecision, { kind: "included" }> => d.kind === "included");
const byId = new Map(inline.map(c => [c.id, c]));
let total = included.reduce((s, d) => s + d.estimated_token_cost, 0);
for (const d of included.sort((a, b) => {
const ca = byId.get(a.id)!;
const cb = byId.get(b.id)!;
return sortForAllocation(ca, cb);
})) {
const c = byId.get(d.id)!;
for (const candidateTier of ["full", "standard"] as RenderingTier[]) {
if (compareTier(candidateTier, d.tier) <= 0) continue;
if (compareTier(candidateTier, c.resolved_max_tier) > 0) continue;
const delta = tierCost(c, candidateTier) - d.estimated_token_cost;
if (total + delta <= input.budget.effective_budget_tokens) {
total += delta;
d.tier = candidateTier;
d.estimated_token_cost = tierCost(c, candidateTier);
break;
}
}
}
return out;
}
```
### 3.7 Exact rendered budget validation
After provisional render, KDA/DOC24 MUST validate exact rendered token counts by band and total before manifest write.
```ts
export type ExactRenderedBandBudgetValidation =
| {
kind: "within_budget";
actual_total_tokens: number;
actual_direct_target_procedure_tokens: number;
actual_non_direct_procedure_tokens: number;
actual_non_procedure_tokens: number;
schema_version: 1;
}
| {
kind: "overflow";
actual_total_tokens: number;
actual_direct_target_procedure_tokens: number;
actual_non_direct_procedure_tokens: number;
actual_non_procedure_tokens: number;
overflow_band: "total" | "direct_target_procedure" | "non_direct_procedure" | "non_procedure";
action: "retry_downgrade_or_suppress" | "block_packet";
reason_code: "kda.rendered_token_budget_overflow";
schema_version: 1;
};
export function validateExactRenderedBandBudgets(input: {
render_results: KdaRenderResult[];
decisions: RenderingTierDecision[];
budget: KnowledgePacketBudgetBreakdown;
}): ExactRenderedBandBudgetValidation {
const bandByCard = new Map(input.decisions
.filter((d): d is Extract<RenderingTierDecision, { kind: "included" }> => d.kind === "included")
.map(d => [d.card_id, d.budget_band]));
let direct = 0;
let nonDirectProcedure = 0;
let nonProcedure = 0;
let total = 0;
for (const r of input.render_results) {
const tokens = r.manifest_patch.rendered_token_count;
if (!Number.isFinite(tokens) || tokens < 0 || !Number.isInteger(tokens)) {
throw new KdaValidationError({
reason_code: "kda.tokenizer_count_invalid",
metadata: { card_id: r.manifest_patch.card_id },
});
}
total += tokens;
const band = bandByCard.get(r.manifest_patch.card_id);
if (band === "direct_target_procedure") direct += tokens;
else if (band === "procedure") nonDirectProcedure += tokens;
else if (band === "non_procedure") nonProcedure += tokens;
}
if (direct > input.budget.direct_target_procedure_budget_tokens) {
return { kind: "overflow", overflow_band: "direct_target_procedure", action: "block_packet", reason_code: "kda.rendered_token_budget_overflow", actual_total_tokens: total, actual_direct_target_procedure_tokens: direct, actual_non_direct_procedure_tokens: nonDirectProcedure, actual_non_procedure_tokens: nonProcedure, schema_version: 1 };
}
if (nonDirectProcedure > input.budget.non_direct_procedure_budget_tokens) {
return { kind: "overflow", overflow_band: "non_direct_procedure", action: "retry_downgrade_or_suppress", reason_code: "kda.rendered_token_budget_overflow", actual_total_tokens: total, actual_direct_target_procedure_tokens: direct, actual_non_direct_procedure_tokens: nonDirectProcedure, actual_non_procedure_tokens: nonProcedure, schema_version: 1 };
}
if (nonProcedure > input.budget.non_procedure_budget_tokens) {
return { kind: "overflow", overflow_band: "non_procedure", action: "retry_downgrade_or_suppress", reason_code: "kda.rendered_token_budget_overflow", actual_total_tokens: total, actual_direct_target_procedure_tokens: direct, actual_non_direct_procedure_tokens: nonDirectProcedure, actual_non_procedure_tokens: nonProcedure, schema_version: 1 };
}
if (total > input.budget.effective_budget_tokens) {
return { kind: "overflow", overflow_band: "total", action: "retry_downgrade_or_suppress", reason_code: "kda.rendered_token_budget_overflow", actual_total_tokens: total, actual_direct_target_procedure_tokens: direct, actual_non_direct_procedure_tokens: nonDirectProcedure, actual_non_procedure_tokens: nonProcedure, schema_version: 1 };
}
return { kind: "within_budget", actual_total_tokens: total, actual_direct_target_procedure_tokens: direct, actual_non_direct_procedure_tokens: nonDirectProcedure, actual_non_procedure_tokens: nonProcedure, schema_version: 1 };
}
```
### 3.8 Tokenizer drift decision contract
Tokenizer drift component and decision types are DOC24-owned lifecycle types. KDA records packet-tokenizer counts in `KdaManifestPatch`, then consumes DOC24's tokenizer-drift decision for render retry/degrade behavior. KDA MUST NOT define a local `TokenizerDriftComponent` or local drift decision union.
```ts
import type {
TokenizerDriftComponent,
TokenizerDriftDecision,
} from "@elnor/doc24-runtime-lifecycle";
export type KdaTokenizerDriftConsumerReceipt = {
packet_id: string;
card_id: string;
component: TokenizerDriftComponent;
doc24_decision: TokenizerDriftDecision;
kda_action:
| "accept_existing_render"
| "retry_rerender"
| "block_packet"
| "audit_only_no_kda_change";
reason_code?: "kda.tokenizer_drift_detected" | "kda.tokenizer_count_invalid";
schema_version: 1;
};
export function kdaActionFromTokenizerDriftDecision(input: {
packet_id: string;
component: TokenizerDriftComponent;
decision: TokenizerDriftDecision;
}): KdaTokenizerDriftConsumerReceipt {
switch (input.decision.kind) {
case "accept":
return { packet_id: input.packet_id, card_id: input.component.card_id, component: input.component, doc24_decision: input.decision, kda_action: "accept_existing_render", schema_version: 1 };
case "retry_rerender":
return { packet_id: input.packet_id, card_id: input.component.card_id, component: input.component, doc24_decision: input.decision, kda_action: "retry_rerender", reason_code: "kda.tokenizer_drift_detected", schema_version: 1 };
case "block_packet":
return { packet_id: input.packet_id, card_id: input.component.card_id, component: input.component, doc24_decision: input.decision, kda_action: "block_packet", reason_code: "kda.tokenizer_drift_detected", schema_version: 1 };
case "audit_only":
return { packet_id: input.packet_id, card_id: input.component.card_id, component: input.component, doc24_decision: input.decision, kda_action: "audit_only_no_kda_change", reason_code: "kda.tokenizer_count_invalid", schema_version: 1 };
}
}
```
### 3.9 Execution-strategy cache
The execution-strategy cache is derived, EC-written, and invalidatable. It stores tool-directive snapshots separate from canonical semantic payloads.
Missing or invalidated execution strategies SHALL NOT by themselves make a semantic procedure unusable. When policy and budget allow, KDA SHALL strip cached tool directives and render ordinary semantic / UI-navigation guidance. KDA suppresses the card only when PropA/DOC24 policy blocks rendering, when budget cannot fit even the allowed fallback, or when the owner payload is invalid.
```ts
export type ExecutionStrategyCacheKeyV2 = {
procedure_id: string;
procedure_version_id: string;
procedure_payload_hash: string;
procedure_step_set_version: string;
step_index?: number;
app_entity_id: string;
app_version: string;
app_version_hint_hash?: string;
tool_catalog_version: string;
tool_catalog_hash: string;
resolver_version: string;
execution_template_version: string;
client_kind: ClientKind;
render_policy_hash: string;
policy_generation_id: string;
schema_version: 2;
};
export type KdaCacheInvalidationReason =
| "tool_catalog_changed"
| "procedure_payload_changed"
| "procedure_version_changed"
| "procedure_step_set_changed"
| "execution_template_changed"
| "resolver_version_changed"
| "client_kind_policy_changed"
| "policy_generation_changed"
| "sensitivity_or_visibility_reclassified";
export type KdaCacheLifecyclePolicy = {
ttl_ms: number;
max_entries: number;
eviction_order: "least_recently_used_then_oldest";
p99_latency_measurement_source: "ec_cache_metrics" | "kda_render_metrics";
schema_version: 1;
};
export const DEFAULT_KDA_CACHE_LIFECYCLE_POLICY: KdaCacheLifecyclePolicy = {
ttl_ms: 30 * 24 * 60 * 60 * 1000,
max_entries: 50000,
eviction_order: "least_recently_used_then_oldest",
p99_latency_measurement_source: "ec_cache_metrics",
schema_version: 1,
};
```
Invalidated/missing cache render state:
```ts
export type KdaExecutionStrategyRenderState =
| { kind: "strategy_available"; execution_strategy_id: string; tool_directive_text: string }
| { kind: "strategy_invalidated"; invalidated_strategy_id: string; degraded_reason_code: "kda.execution_strategy_invalidated"; fallback_rendering: "ui_navigation_guidance" }
| { kind: "strategy_missing"; degraded_reason_code: "kda.execution_strategy_missing"; fallback_rendering: "ui_navigation_guidance" };
```
### 3.10 Cache-stable rendering and shared entity deduplication
Mutable delivery wrappers must not invalidate static payload caches.
```ts
export type KdaStaticRenderPayload = {
static_payload_hash: string;
template_version: string;
node_payload_hash: string;
shared_entity_refs: string[];
schema_version: 1;
};
export type KdaRenderWrapperHashInput = {
directive_constraints_hash: string;
render_policy_hash: string;
rendering_tier: RenderingTier;
tokenizer_ref_hash: string;
schema_version: 1;
};
export function staticRenderCacheKey(input: KdaStaticRenderPayload): string {
return sha256(canonicalJson({
static_payload_hash: input.static_payload_hash,
template_version: input.template_version,
node_payload_hash: input.node_payload_hash,
shared_entity_refs: [...input.shared_entity_refs].sort(),
schema_version: input.schema_version,
}));
}
export function renderInstanceHash(input: {
static_payload: KdaStaticRenderPayload;
wrapper: KdaRenderWrapperHashInput;
}): string {
return sha256(canonicalJson({ static_payload: input.static_payload, wrapper: input.wrapper }));
}
export type SharedEntityRenderBlock = {
shared_entity_id: string;
rendered_once_text: string;
rendered_token_count: number;
tokenizer_ref: TokenizerRef;
referenced_by_card_ids: string[];
schema_version: 1;
};
```
Rules:
- `staticRenderCacheKey` MUST NOT include mutable wrapper/directive fields.
- `renderInstanceHash` includes wrapper fields for audit identity.
- Shared entities may render once per packet and be referenced by card-local labels to avoid duplicated tokens.
---
Pipeline integration artifacts:
```ts
export type KdaPacketRenderCacheArtifacts = {
packet_id: string;
static_payloads: KdaStaticRenderPayload[];
static_cache_keys: Record<string, string>; // card_id or shared_entity_id -> static key
render_instance_hashes: Record<string, string>; // card_id -> instance hash
shared_entity_blocks: SharedEntityRenderBlock[];
schema_version: 1;
};
export function computePacketRenderCacheArtifacts(input: {
packet_id: string;
card_static_payloads: Array<{ card_id: string; payload: KdaStaticRenderPayload; wrapper: KdaRenderWrapperHashInput }>;
shared_entity_blocks: SharedEntityRenderBlock[];
}): KdaPacketRenderCacheArtifacts {
const static_cache_keys: Record<string, string> = {};
const render_instance_hashes: Record<string, string> = {};
for (const card of input.card_static_payloads) {
static_cache_keys[card.card_id] = staticRenderCacheKey(card.payload);
render_instance_hashes[card.card_id] = renderInstanceHash({
static_payload: card.payload,
wrapper: card.wrapper,
});
}
for (const block of input.shared_entity_blocks) {
static_cache_keys[block.shared_entity_id] = sha256(canonicalJson({
shared_entity_id: block.shared_entity_id,
rendered_once_text: block.rendered_once_text,
tokenizer_ref: block.tokenizer_ref,
schema_version: block.schema_version,
}));
}
return {
packet_id: input.packet_id,
static_payloads: input.card_static_payloads.map(c => c.payload),
static_cache_keys,
render_instance_hashes,
shared_entity_blocks: input.shared_entity_blocks,
schema_version: 1,
};
}
```
Additional pipeline rules:
- Every inline render MUST compute `staticRenderCacheKey(...)` before applying mutable wrapper/directive/policy fields.
- Every inline render MUST compute `renderInstanceHash(...)` after applying mutable wrapper/directive/policy fields.
- Shared entity blocks are packet-level render artifacts. They render once and are referenced by card IDs; card-local renders must not duplicate the same shared entity text.
- Wrapper or directive changes MUST NOT invalidate the static payload cache key. They only change the render-instance hash.
## 4. Dynamic composition of related procedures
### 4.1 When composition is allowed
KDA may compose procedures only when all of these are true:
1. All component procedures are inline-eligible.
2. All component procedures share compatible render policy and destination class.
3. DOC72 composite ordering exists, or an ephemeral `KdaCompositionDecision` records the ordering source.
4. Component attribution spans can be recorded.
5. Composition does not violate token budgets or directive constraints.
### 4.2 Composition decision
```ts
export type KdaCompositionDecision = {
composition_id: string;
request_context_hash: string;
selected_component_procedure_ids: string[];
ordering_source:
| "doc72_constituent_ordering"
| "dependency_topological_sort"
| "capability_area_sort"
| "user_requested_order";
component_order: Array<{
procedure_id: string;
order_position: number;
depends_on: string[];
ordering_reason: "doc72_ordering" | "dependency_sort" | "capability_sort" | "user_requested_order";
}>;
may_propose_doc72_composite: boolean;
proposed_composite_candidate_ref?: string;
schema_version: 1;
};
```
If a DOC72 composite procedure exists, KDA MUST honor DOC72 `constituent_ordering` unless a policy decision blocks it.
### 4.3 Composed render result
KDA composition must preserve component attribution.
```ts
export type KdaComposedComponentRef = {
component_card_id: string;
node_id: string;
node_kind: "procedure";
component_order: number;
rendered_utf8_byte_start: number;
rendered_utf8_byte_end: number;
rendering_specialization_id?: string;
render_variant_id: string;
template_version: string;
attribution_mode: "component_span_direct" | "component_shared_context" | "not_attributable_component";
};
export type KdaComposedRenderResult = KdaRenderResult & {
composed_card_id: string;
component_cards: KdaComposedComponentRef[];
};
```
Span validation:
```ts
export function validateComposedComponentSpans(input: {
rendered_text_utf8_byte_length: number;
components: KdaComposedComponentRef[];
}): void {
let previousEnd = 0;
for (const c of input.components.sort((a, b) => a.rendered_utf8_byte_start - b.rendered_utf8_byte_start)) {
if (!Number.isInteger(c.rendered_utf8_byte_start) || !Number.isInteger(c.rendered_utf8_byte_end) || c.rendered_utf8_byte_start < previousEnd || c.rendered_utf8_byte_end <= c.rendered_utf8_byte_start || c.rendered_utf8_byte_end > input.rendered_text_utf8_byte_length) {
throw new KdaValidationError({
reason_code: "kda.composed_component_span_invalid",
metadata: {
component_card_id: c.component_card_id,
byte_start: c.rendered_utf8_byte_start,
byte_end: c.rendered_utf8_byte_end,
},
});
}
previousEnd = c.rendered_utf8_byte_end;
}
}
```
Final-prompt split/trim behavior:
- If DOC11/OpenClaw splits a composed card, `FinalPromptInjectionManifest` spans must preserve component span references where possible.
- If a component span is trimmed out, that component receives no utility signal.
- If the composed-card wrapper survives but a component span is unobservable, KDA/BDSM attribution records `not_attributable_component` for that component.
---
## 5. Neuroplasticity — self-evolving rendering
### 5.1 Scope partitioning
```ts
export type RenderingSpecializationScope = {
learning_visibility_scope: LearningVisibilityScope;
firewall_scope_id?: string;
matter_id?: string;
principal_id?: string;
model_class?: MatrixModelClass;
policy_generation_id?: string;
schema_version: 1;
};
```
All neuroplasticity records MUST carry a scope. Scope-less specializations are invalid in R3.
### 5.2 Rendering specialization schema
```ts
export type RenderingSpecializationV2 = {
specialization_id: string;
annotation_type_key: AnnotationTypeKey;
render_template: string;
template_version: string;
template_hash: string;
current_render_variant_id: string;
canary_generation_id?: string;
promoted_by: "doc8_pattern_detection" | "user_configured" | "system_default";
promoted_at: string;
usage_count: number;
positive_utility_count: number;
negative_utility_count: number;
canary_state: "proposed" | "canary_active" | "promoted" | "rollback_pending" | "demoted";
scope: RenderingSpecializationScope;
schema_version: 2;
};
```
### 5.3 Annotation utility index
KDA does not infer canary promotion from raw feedback logs at render time. DOC8/BDSM/EC materialize utility summaries into a scoped utility index.
```ts
export type AnnotationUtilityIndexRecord = {
annotation_type_key: AnnotationTypeKey;
scope: RenderingSpecializationScope;
render_variant_id: string;
total_exposures: number;
positive_count: number;
negative_count: number;
corrected_count: number;
no_observable_outcome_count: number;
regression_count: number;
positive_rate_lower95: number | null;
regression_rate_upper95: number | null;
last_updated_at: string;
schema_version: 1;
};
```
No-observable rows do not enter positive/negative denominators.
### 5.4 Scope broadening decision
```ts
export type SpecializationScopeBroadeningDecision =
| { kind: "allowed_same_or_narrower_scope"; schema_version: 1 }
| {
kind: "requires_policy_approval";
reason_code: "kda.specialization_scope_broadening_requires_policy_approval";
required_receipt_kind: "propa_ec_scope_broadening_approval";
schema_version: 1;
};
export function decideSpecializationScopeBroadening(input: {
learned_scope: RenderingSpecializationScope;
requested_application_scope: RenderingSpecializationScope;
approval_receipt_id?: string;
}): SpecializationScopeBroadeningDecision {
if (isSameOrNarrowerScope(input.requested_application_scope, input.learned_scope)) {
return { kind: "allowed_same_or_narrower_scope", schema_version: 1 };
}
if (input.approval_receipt_id) {
return { kind: "allowed_same_or_narrower_scope", schema_version: 1 };
}
return {
kind: "requires_policy_approval",
reason_code: "kda.specialization_scope_broadening_requires_policy_approval",
required_receipt_kind: "propa_ec_scope_broadening_approval",
schema_version: 1,
};
}
```
### 5.5 Neuroplasticity effective state
```ts
export type KdaNeuroplasticityEffectiveState = {
signal_capture_enabled: boolean;
canary_activation_enabled: boolean;
specialization_promotion_enabled: boolean;
effective_state_generation_id: string;
divergence_reason_codes: KdaReasonCode[];
schema_version: 1;
};
```
KDA canary activation and promotion MUST read EC effective state. User-facing controls that appear to enable or suppress neuroplasticity MUST route through EC commands and read models.
### 5.6 Canary policy and total state machine
```ts
export type KdaCanaryState = "proposed" | "canary_active" | "promoted" | "rollback_pending" | "demoted";
export type KdaCanaryTransitionReasonCode =
| "kda.canary_admitted"
| "kda.canary_effective_state_blocks_activation"
| "kda.canary_insufficient_evidence"
| "kda.canary_regression_threshold_exceeded"
| "kda.canary_success_threshold_met"
| "kda.canary_recanary_requested"
| "kda.canary_rollback_completed"
| "kda.canary_demoted_terminal";
export type KdaCanaryPolicy = {
min_canary_uses: number;
max_canary_days: number;
min_positive_lower95: number;
max_regression_upper95: number;
cohort_fraction: number;
cohort_hash_seed: string;
schema_version: 1;
};
export type KdaCanaryEvidence = {
observed_uses: number;
positive_rate_lower95: number | null;
regression_rate_upper95: number | null;
applicable_render_count: number;
rollback_receipt_id?: string;
recanary_event_id?: string;
schema_version: 1;
};
export type KdaCanaryTransition = {
from_state: KdaCanaryState;
to_state: KdaCanaryState;
reason_code: KdaCanaryTransitionReasonCode;
schema_version: 1;
};
export function nextKdaCanaryState(input: {
state: KdaCanaryState;
policy: KdaCanaryPolicy;
evidence: KdaCanaryEvidence;
effective_state: KdaNeuroplasticityEffectiveState;
cohort_admitted: boolean;
}): KdaCanaryTransition {
const { state, policy, evidence, effective_state } = input;
if (state === "proposed") {
if (!effective_state.canary_activation_enabled || evidence.applicable_render_count <= 0 || !input.cohort_admitted) {
return { from_state: state, to_state: "proposed", reason_code: "kda.canary_effective_state_blocks_activation", schema_version: 1 };
}
return { from_state: state, to_state: "canary_active", reason_code: "kda.canary_admitted", schema_version: 1 };
}
if (state === "canary_active") {
if (evidence.regression_rate_upper95 !== null && evidence.regression_rate_upper95 > policy.max_regression_upper95) {
return { from_state: state, to_state: "demoted", reason_code: "kda.canary_regression_threshold_exceeded", schema_version: 1 };
}
if (evidence.observed_uses < policy.min_canary_uses || evidence.positive_rate_lower95 === null) {
return { from_state: state, to_state: "canary_active", reason_code: "kda.canary_insufficient_evidence", schema_version: 1 };
}
if (evidence.positive_rate_lower95 >= policy.min_positive_lower95) {
return { from_state: state, to_state: "promoted", reason_code: "kda.canary_success_threshold_met", schema_version: 1 };
}
return { from_state: state, to_state: "canary_active", reason_code: "kda.canary_insufficient_evidence", schema_version: 1 };
}
if (state === "promoted") {
if (evidence.regression_rate_upper95 !== null && evidence.regression_rate_upper95 > policy.max_regression_upper95) {
return { from_state: state, to_state: "rollback_pending", reason_code: "kda.canary_regression_threshold_exceeded", schema_version: 1 };
}
return { from_state: state, to_state: "promoted", reason_code: "kda.canary_success_threshold_met", schema_version: 1 };
}
if (state === "rollback_pending") {
if (evidence.rollback_receipt_id) {
return { from_state: state, to_state: "demoted", reason_code: "kda.canary_rollback_completed", schema_version: 1 };
}
return { from_state: state, to_state: "rollback_pending", reason_code: "kda.canary_regression_threshold_exceeded", schema_version: 1 };
}
if (state === "demoted") {
if (evidence.recanary_event_id && effective_state.canary_activation_enabled) {
return { from_state: state, to_state: "proposed", reason_code: "kda.canary_recanary_requested", schema_version: 1 };
}
return { from_state: state, to_state: "demoted", reason_code: "kda.canary_demoted_terminal", schema_version: 1 };
}
return { from_state: "demoted", to_state: "demoted", reason_code: "kda.canary_demoted_terminal", schema_version: 1 };
}
```
## 5.7 Positive-attribution arbitration
KDA owns `KdaNeuroplasticityAction` and the arbitration function that constrains KDA actions based on BDSM attribution outcomes. BDSM imports this type and function; BDSM MUST NOT redefine them.
```ts
export type KdaNeuroplasticityAction =
| { kind: "drop_card" }
| { kind: "compact_card" }
| { kind: "reposition_card" }
| { kind: "split_card" }
| { kind: "compose_with_related_card" }
| { kind: "change_template_variant" };
export type KdaAttributionConstraintInput =
| "positive"
| "negative"
| "ignored"
| "corrected"
| "no_signal"
| "no_exposure_evidence"
| "unknown";
export function constrainKdaActionByAttribution(input: {
proposed_action: KdaNeuroplasticityAction;
bdsm_attribution: KdaAttributionConstraintInput;
}): KdaNeuroplasticityAction {
if (input.proposed_action.kind === "drop_card" && input.bdsm_attribution === "positive") {
return { kind: "change_template_variant" };
}
if (input.proposed_action.kind === "drop_card" && input.bdsm_attribution === "corrected") {
return { kind: "change_template_variant" };
}
return input.proposed_action;
}
```
### 5.8 Extraction hint registry
Extraction hints are derived, scoped, and invalidatable. They are not part of canonical DOC72 payload truth.
```ts
export type ExtractionHintV2 = {
hint_id: string;
annotation_type_key: AnnotationTypeKey;
suggested_extraction_instruction: string;
scope: RenderingSpecializationScope;
source_specialization_id?: string;
policy_generation_id: string;
created_at: string;
last_validated_at?: string;
invalidated_at?: string;
invalidation_reason?: KdaCacheInvalidationReason;
schema_version: 2;
};
```
---
## 6. PropA reclassification and KDA invalidation
When a node sensitivity, visibility, matter, firewall, or policy-generation attribute changes, KDA invalidates dependent derived artifacts in this order:
1. Abort pending packet renders involving the node before manifest write.
2. Invalidate execution-strategy cache entries by node/procedure ID.
3. Invalidate rendering specializations trained on the node or scope.
4. Invalidate extraction hints trained on the node or scope.
5. Mark affected render-instance hashes stale.
6. Emit EC invalidation receipts.
```ts
export type KdaPolicyReclassificationInvalidationEvent = {
event_id: string;
node_id: string;
changed_policy_fields: Array<"sensitivity_tags" | "visibility_class" | "matter_id" | "firewall_scope_id" | "policy_generation_id">;
invalidate: {
execution_strategy_cache: true;
rendering_specializations: true;
extraction_hints: true;
pending_packet_renders: true;
render_instance_hashes: true;
};
emitted_at: string;
schema_version: 1;
};
```
---
## 6A. Backup, export, import, and restore behavior
KDA-derived artifacts are rebuildable derived state. Import/restore MUST NOT trust active cache or specialization state merely because an exported file claims it was active.
Restored KDA artifacts enter `validation_pending` until EC validates policy generation, DOC72 graph snapshot, PropA policy snapshot, template registry generation, and schema version. KDA must not render from restored execution-strategy cache entries, rendering specializations, extraction hints, or annotation utility indexes until the corresponding validation receipt exists.
```ts
export type KdaRestorableArtifactKind =
| "execution_strategy_cache"
| "rendering_specialization_registry"
| "extraction_hint_registry"
| "annotation_utility_index"
| "static_render_cache";
export type KdaRestoredArtifactState =
| "validation_pending"
| "active_after_validation"
| "rebuild_required"
| "rejected";
export type KdaRestoreValidationInput = {
artifact_kind: KdaRestorableArtifactKind;
artifact_ref: string;
artifact_schema_version: number;
doc72_graph_snapshot_id: string;
propA_policy_snapshot_id: string;
template_registry_generation_id: string;
policy_generation_id: string;
restored_hash: string;
schema_version: 1;
};
export type KdaRestoreValidationDecision =
| {
kind: "activate_after_validation";
artifact_kind: KdaRestorableArtifactKind;
validation_receipt_id: string;
schema_version: 1;
}
| {
kind: "rebuild_required";
artifact_kind: KdaRestorableArtifactKind;
reason_code:
| "kda.restore_snapshot_mismatch"
| "kda.restore_schema_unsupported"
| "kda.restore_hash_mismatch";
schema_version: 1;
}
| {
kind: "reject_restored_artifact";
artifact_kind: KdaRestorableArtifactKind;
reason_code: "kda.restore_artifact_invalid";
schema_version: 1;
};
```
Rules:
1. Restored execution-strategy cache entries begin `validation_pending` and cannot produce tool directives until validation.
2. Restored rendering specializations begin `validation_pending`; canary state cannot resume until scope and template hashes validate.
3. Restored extraction hints begin `validation_pending` and cannot alter rendering until DOC72 graph snapshot validates.
4. Restored annotation utility indexes are read-only until policy/matter/firewall scope validates.
5. Static render caches may be reused only if `staticRenderCacheKey(...)` recomputes to the restored key.
6. KTO export triggers remain non-operative; future KTO requires a separate security/redaction spec.
## 7. Inspectability
### 7.1 KDA does not own the packet inspector
DOC24 owns the Packet Inspector. KDA provides render metadata, canary state, variant IDs, token counts, and composition spans for DOC24 inspector rows.
### 7.2 KDA inspector projection
```ts
export type KdaInspectorProjection = {
packet_id: string;
card_id: string;
node_id: string;
card_presence: "included_inline" | "included_reference_only" | "excluded";
rendering_tier: RenderingTier | null;
render_variant_id?: string;
template_version?: string;
rendering_specialization_id?: string;
rendered_token_count: number;
tokenizer_ref?: TokenizerRef;
count_method?: "exact" | "estimated";
execution_strategy_state?: "strategy_available" | "strategy_invalidated" | "strategy_missing";
canary_state?: KdaCanaryState;
composition_id?: string;
component_card_ids?: string[];
degraded_reason_codes: KdaReasonCode[];
schema_version: 1;
};
```
The inspector projection is not the canonical `KdaManifestPatch`; it is a read model derived from render results, manifests, and reconciliation.
### 7.3 Delivery-learning inspector support
DOC24 owns the canonical delivery-learning inspector row. KDA MUST NOT define `DeliveryLearningInspectorRow`. KDA supplies only the KDA subobject fields that DOC24 writes into the row.
```ts
import type { DeliveryLearningInspectorRow } from "@elnor/doc24-runtime-lifecycle";
export type KdaInspectorSubobject = DeliveryLearningInspectorRow["kda"];
export function buildKdaInspectorSubobject(input: {
manifest_patch: KdaManifestPatch;
canary_state?: KdaCanaryState;
composition_id?: string;
component_card_ids?: string[];
}): KdaInspectorSubobject {
if (input.manifest_patch.card_presence === "excluded") {
return {};
}
return {
rendering_specialization_id: input.manifest_patch.rendering_specialization_id,
render_variant_id: input.manifest_patch.render_variant_id,
template_version: input.manifest_patch.template_version,
rendering_tier: input.manifest_patch.rendering_tier,
canary_state: input.canary_state,
composition_id: input.composition_id,
component_card_ids: input.component_card_ids,
};
}
```
Rules:
- KDA does **not** write `DeliveryLearningInspectorRow`; DOC24 writes it from manifests, final-prompt spans, reconciliation, BDSM attribution, and KDA render metadata.
- KDA must supply the fields in `row.kda` through `KdaManifestPatch`, composition metadata, and specialization/canary metadata.
- The flattened `row.kda.rendering_tier` projection is not the canonical `KdaManifestPatch`; it is a read-model projection.
### 7.4 Knowledge Manager preview rendering
Preview rendering restores the KDA R2 Knowledge Manager “Preview injection” surface. Preview is non-durable and is not a `PacketInjectionManifest`.
```ts
export type KdaPreviewRenderRequest = {
request_id: string;
node_id: string;
node_kind: KdaRenderableNodeKind;
requested_tiers: RenderingTier[]; // default UI: compact, standard, full
client_kind: ClientKind;
destination: "same_machine_local_runtime" | "cloud_api" | "external_share";
policy_decision_id: string;
tokenizer_ref: TokenizerRef;
requested_at: string;
schema_version: 1;
};
export type KdaPreviewTierResult =
| {
kind: "rendered";
tier: RenderingTier;
rendered_text: string;
manifest_patch: KdaManifestPatch;
rendered_token_count: number;
schema_version: 1;
}
| {
kind: "not_rendered";
tier: RenderingTier;
reason_code:
| "kda.preview_blocked_by_policy"
| "kda.preview_reference_only"
| "kda.preview_unsupported_node_kind"
| "kda.preview_payload_invalid";
metadata: Record<string, unknown>;
schema_version: 1;
};
export type KdaPreviewRenderResult = {
request_id: string;
node_id: string;
node_kind: KdaRenderableNodeKind;
results: KdaPreviewTierResult[];
non_durable: true;
not_a_packet_manifest: true;
created_at: string;
schema_version: 1;
};
```
Knowledge Manager MAY call KDA preview rendering for operator inspection. Preview rendering SHALL use the same pure renderer, policy gate, literal-retention handling, tokenizer accounting, and `KdaManifestPatch` union as runtime rendering. Preview rendering SHALL NOT create a `PacketInjectionManifest`, SHALL NOT create attribution eligibility, and SHALL NOT update KDA neuroplasticity utility counters. Preview output is a user-facing inspection surface only.
## 8. Reason-code registry obligations
All KDA reason codes are closed literal strings. Runtime values belong in metadata.
```ts
export type KdaReasonCodeRegistryEntry = {
reason_code: KdaReasonCode;
owner_namespace: "kda";
producer_function: string;
display_text: string;
fixture_name: string;
consumer_surfaces: Array<"packet_inspector" | "render_log" | "canary_dashboard" | "ec_orchestrator" | "doc24_manifest">;
schema_version: 1;
};
```
Build rule:
```text
Any literal assigned to reason_code, degraded_reason_code, blocked_reason_code,
invalidation_reason_code, validation_code, or no_signal_reason_code MUST resolve to a registry row.
Any dynamic string interpolation in a reason-code field fails build.
```
---
## 9. Schema versioning and migration
### 9.1 Derived artifact parser
```ts
export type KdaDerivedArtifactKind =
| "kda_manifest_patch"
| "kda_render_result"
| "kda_execution_strategy_cache"
| "kda_rendering_specialization_registry"
| "kda_extraction_hint_registry"
| "kda_annotation_utility_index";
export type KdaSchemaVersionPolicy = {
artifact_kind: KdaDerivedArtifactKind;
min_supported: number;
max_supported: number;
migration_available_from: number[];
schema_version: 1;
};
export type KdaDerivedArtifactParseError =
| { kind: "missing_schema_version"; artifact_kind: KdaDerivedArtifactKind }
| { kind: "future_schema_version"; artifact_kind: KdaDerivedArtifactKind; observed: number; max_supported: number }
| { kind: "deprecated_schema_version"; artifact_kind: KdaDerivedArtifactKind; observed: number; min_supported: number };
```
### 9.2 Required R2 → R3 migrations
```ts
export type KdaMigrationStep = {
step_id: string;
source_artifact_kind: string;
target_artifact_kind: string;
required: true;
validation_fixture: string;
schema_version: 1;
};
export const KDA_R2_R3_MIGRATION_STEPS: KdaMigrationStep[] = [
{
step_id: "KDA-R2R3-001-delete-local-injection-manifest",
source_artifact_kind: "InjectionManifestSchema",
target_artifact_kind: "KdaManifestPatch",
required: true,
validation_fixture: "kda_retired_injection_manifest_schema_fails_build",
schema_version: 1,
},
{
step_id: "KDA-R2R3-002-renderer-string-to-result",
source_artifact_kind: "renderProcedureInjectionCard_string_return",
target_artifact_kind: "KdaRenderResult",
required: true,
validation_fixture: "no_duplicate_kda_manifest_patch_definition",
schema_version: 1,
},
{
step_id: "KDA-R2R3-003-client-kind-migration",
source_artifact_kind: "local_elnor_client_kind",
target_artifact_kind: "elnor_native_client_kind",
required: true,
validation_fixture: "unknown_client_kind_fails_closed",
schema_version: 1,
},
{
step_id: "KDA-R2R3-004-relevance-normalization",
source_artifact_kind: "raw_relevance_score",
target_artifact_kind: "normalized_relevance",
required: true,
validation_fixture: "kda_tier_allocator_rejects_raw_or_signed_relevance_field",
schema_version: 1,
},
{
step_id: "KDA-R2R3-005-reference-only-presence",
source_artifact_kind: "reference_only_encoded_as_compact",
target_artifact_kind: "included_reference_only_card_presence",
required: true,
validation_fixture: "reference_only_card_is_not_compact",
schema_version: 1,
},
{
step_id: "KDA-R2R3-006-variant-tracking",
source_artifact_kind: "unversioned_render_template",
target_artifact_kind: "render_variant_id_template_version_specialization_id",
required: true,
validation_fixture: "kda_manifest_patch_invalid_combinations_rejected",
schema_version: 1,
},
{
step_id: "KDA-R2R3-007-tokenizer-accounting",
source_artifact_kind: "estimated_or_missing_token_count",
target_artifact_kind: "tokenizer_ref_rendered_token_count_count_method",
required: true,
validation_fixture: "tokenizer_drift_invalid_counts_rejected",
schema_version: 1,
},
{
step_id: "KDA-R2R3-008-execution-cache-rekey",
source_artifact_kind: "execution_strategy_cache_key_v1",
target_artifact_kind: "ExecutionStrategyCacheKeyV2",
required: true,
validation_fixture: "procedure_payload_hash_change_invalidates_execution_strategy_cache",
schema_version: 1,
},
{
step_id: "KDA-R2R3-009-specialization-rekey",
source_artifact_kind: "RenderingSpecializationSchema_R2",
target_artifact_kind: "RenderingSpecializationV2",
required: true,
validation_fixture: "kda_canary_transition_grid_total",
schema_version: 1,
},
{
step_id: "KDA-R2R3-010-annotation-utility-index-materialization",
source_artifact_kind: "implicit_utility_signals_array",
target_artifact_kind: "AnnotationUtilityIndexRecord",
required: true,
validation_fixture: "kda_positive_bdsm_attribution_blocks_drop_action",
schema_version: 1,
},
{
step_id: "KDA-R2R3-011-reason-code-registry-generation",
source_artifact_kind: "freeform_reason_code_strings",
target_artifact_kind: "KdaReasonCodeRegistryEntry",
required: true,
validation_fixture: "dynamic_reason_code_interpolation_fails_build",
schema_version: 1,
},
{
step_id: "KDA-R2R3-012-ui-projection-rebuild",
source_artifact_kind: "r2_preview_manager_manifest_rows",
target_artifact_kind: "KdaInspectorProjection",
required: true,
validation_fixture: "kda_inspector_projection_is_not_manifest_patch",
schema_version: 1,
},
];
```
Migration rule:
```text
KDA R3 migrations run before any restored KDA derived artifact becomes active. If any required migration step fails, the affected artifact enters `rebuild_required` or `rejected`; it MUST NOT be used by runtime rendering.
```
## 10. Acceptance tests and fixture gate
The following fixtures are required before KDA R3 implementation handoff. Each fixture carries the adjudication package that owns the requirement so fixture failures can be routed back to the correct patch package.
| fixture_name | target_section | target_adj_id |
|---|---|---|
| kda_manifest_patch_invalid_combinations_rejected | §3.2B | ADJ-006 |
| kda_reference_only_stable_card_id | §3.2B | ADJ-006 |
| no_duplicate_kda_manifest_patch_definition | §3.2B / §3.2D | ADJ-006 / ADJ-008 |
| sharing_action_block_returns_no_render | §3.2C | ADJ-007 |
| cloud_warn_requires_warning_receipt | §3.2C | ADJ-007 |
| retain_if_user_confirmed_requires_confirmation_receipt | §3.2C | ADJ-007 |
| redact_uses_redaction_map_not_placeholder_guess | §3.2C | ADJ-007 |
| kda_redacted_inline_render_emits_reason_code | §3.2D | ADJ-007 / ADJ-027 |
| unknown_client_kind_fails_closed | §3.3 | ADJ-030 |
| kda_resolve_constraints_consumes_reference_only_required | §3.4A | ADJ-045 |
| kda_force_floor_avoid_is_invalid | §3.4A | ADJ-045 |
| kda_min_tier_above_max_tier_conflict | §3.4A | ADJ-045 |
| kda_low_confidence_caps_full_tier_unless_direct_request | §3.4 | ADJ-001 |
| kda_authority_reference_only_bypasses_inline_tier_default | §3.4 | ADJ-001 |
| kda_tier_allocator_rejects_raw_or_signed_relevance_field | §3.5 | ADJ-009 |
| kda_budget_breakdown_partitions_effective_budget | §3.6 | ADJ-009 |
| kda_direct_target_procedure_budget_enforced | §3.6 | ADJ-009 |
| kda_exact_band_budget_overflow_detected | §3.7 | ADJ-009 |
| kda_exact_non_direct_procedure_band_overflow_detected | §3.7 | ADJ-009 |
| reference_only_card_is_not_compact | §3.2B | ADJ-006 |
| excluded_card_has_zero_tokens | §3.2B | ADJ-006 |
| tokenizer_drift_invalid_counts_rejected | §3.8 | ADJ-048 |
| procedure_payload_hash_change_invalidates_execution_strategy_cache | §3.9 | ADJ-032 |
| template_version_change_invalidates_execution_strategy_cache | §3.9 | ADJ-032 |
| cache_static_key_unchanged_by_wrapper_hash | §3.10 | ADJ-047 |
| kda_shared_entity_block_rendered_once_per_packet | §3.10 | ADJ-047 |
| kda_render_instance_hash_changes_when_wrapper_changes | §3.10 | ADJ-047 |
| kda_composed_card_preserves_component_attribution | §4.3 | ADJ-031 |
| kda_composed_card_component_spans_cover_rendered_text | §4.3 | ADJ-031 |
| kda_canary_transition_grid_total | §5.6 | ADJ-033 |
| kda_positive_bdsm_attribution_blocks_drop_action | §5.7 | ADJ-033 |
| sensitivity_reclassification_invalidates_kda_cache | §6 | ADJ-025 |
| kda_restored_cache_starts_validation_pending | §6A | ADJ-036 |
| kda_restored_specialization_scope_mismatch_rebuild_required | §6A | ADJ-036 |
| kda_restored_static_cache_hash_recomputed_before_reuse | §6A | ADJ-036 |
| kda_inspector_projection_supports_join_and_attribution_ids | §7.3 | ADJ-038 |
| kda_inspector_can_represent_invariant_failure | §7.3 | ADJ-038 |
| kda_inspector_projection_is_not_manifest_patch | §7.2 / §7.3 | ADJ-038 |
| dynamic_reason_code_interpolation_fails_build | §8 | ADJ-027 |
| schema_version_below_min_supported_deprecated | §9 | ADJ-043 |
| kda_migration_steps_have_unique_ids | §9.2 | ADJ-043 |
| kda_required_migration_step_has_fixture | §9.2 | ADJ-043 |
| kda_failed_migration_blocks_restored_runtime_use | §9.2 | ADJ-043 |
| kda_retired_injection_manifest_schema_fails_build | §0.8 / Appendix A | ADJ-003 |
| kda_packet_reconciliation_overlay_fails_build | §0.8 / Appendix A | ADJ-003 |
| work_product_card_uses_doc25_document_tier | §3.2E | ADJ-051 |
| kda_procedure_projection_accepts_canonical_steps | §2.4 | KDA-PATCH-011 |
| kda_procedure_projection_rejects_semantic_steps_only | §2.4 | KDA-PATCH-011 |
| kda_routing_only_fields_not_rendered | §2.4 / §3.2D | KDA-PATCH-011 |
| kda_step_nature_survives_projection | §2.4 / §3.2D | KDA-PATCH-011 |
| kda_contract_quality_below_060_caps_optional_procedure_to_compact | §3.4 | KDA-PATCH-012 |
| kda_direct_target_bypasses_contract_quality_compact_cap | §3.4 | KDA-PATCH-012 |
| kda_low_derivation_quality_caps_optional_procedure_to_compact | §3.4 | KDA-PATCH-012 |
| kda_cheap_derivation_model_caps_optional_card_to_standard | §3.4 | KDA-PATCH-012 |
| kda_cognitive_step_renders_without_execution_strategy | §3.2D | KDA-PATCH-013 |
| kda_mechanical_step_uses_tool_directive_when_available | §3.2D | KDA-PATCH-013 |
| kda_mechanical_step_guidance_only_strips_tool_directive | §3.2D / §3.3 | KDA-PATCH-013 / 020 |
| kda_invalidated_execution_strategy_renders_ui_fallback | §3.2D / §3.9 | KDA-PATCH-013 / 020 |
| kda_preview_is_not_packet_manifest | §7.4 | KDA-PATCH-014 |
| kda_preview_renders_three_tiers_for_supported_procedure | §7.4 | KDA-PATCH-014 |
| kda_preview_does_not_update_neuroplasticity | §7.4 | KDA-PATCH-014 |
| kda_does_not_define_extraction_model_config_runtime_setting | §2.5 / Appendix A | KDA-PATCH-015 |
| kda_consumes_derivation_metadata_without_mutating_confidence | §2.5 / §3.4 | KDA-PATCH-015 |
| cheap_model_derivation_applies_tier_caution | §2.5 / §3.4 | KDA-PATCH-015 |
| kda_r3_does_not_define_new_doc72_node_kind | §1.1 | KDA-PATCH-016 |
| kda_r3_does_not_write_doc72_confidence | §1.1 | KDA-PATCH-016 |
| kda_r3_no_parallel_prompt_assembler | §1.1 | KDA-PATCH-016 |
| graph_backed_procedure_does_not_render_through_skill_md | Appendix A.X | KDA-PATCH-017 |
| skill_md_export_is_non_runtime | Appendix A.X | KDA-PATCH-017 |
| native_imported_skill_runtime_remains_outside_kda_graph_rendering | Appendix A.X | KDA-PATCH-017 |
| kda_r2_r3_disposition_table_present | §11.9 | KDA-PATCH-018 |
| kda_r2_local_manifest_marked_superseded | §11.9 | KDA-PATCH-018 |
| kda_r2_skill_md_marked_export_only | §11.9 | KDA-PATCH-018 |
| kda_supports_r2_renderable_node_kind_set | §2.4 | KDA-PATCH-019 |
| kda_work_product_routes_to_doc25_reference | §2.4 / §3.2E | KDA-PATCH-019 |
| kda_unknown_node_kind_rejected_with_reason | §2.4 | KDA-PATCH-019 |
| kda_remote_desktop_procedure_guidance_only | §3.3 | KDA-PATCH-020 |
| kda_remote_mcp_tools_available_full | §3.3 | KDA-PATCH-020 |
| kda_remote_policy_block_suppresses | §3.3 | KDA-PATCH-020 |
| kda_missing_strategy_renders_ui_fallback_not_suppress | §3.9 | KDA-PATCH-020 |
---
## 11. Cross-document impact
### 11.1 DOC24
DOC24 consumes KDA render results and writes packet/final-prompt manifests. DOC24 owns the lifecycle, Packet Inspector, InjectionSlotRegistry, and final manifest writing. KDA must not write manifests directly.
### 11.2 DOC72
DOC72 owns graph payload contracts, node identity, composite procedure ordering, and payload versioning. KDA consumes immutable node snapshots.
### 11.3 BDSM / DOC8
BDSM/DOC8 consume KDA variant metadata and component spans for attribution. KDA consumes BDSM/DOC8 outcome utility only through materialized scoped utility indexes and canary records.
### 11.4 PropA
PropA owns render/sharing/visibility policy decisions. KDA enforces `sharing_action` and invalidates derived artifacts on reclassification.
### 11.5 EC Core
EC writes all durable KDA artifacts, owns effective-state controls, owns background job orchestration, and enforces no phantom controls.
### 11.6 DOC11 / OpenClaw
DOC11/OpenClaw own final prompt assembly and may produce token drift. KDA metadata must support final-prompt span mapping and reconciliation.
### 11.7 DOC25
DOC25 owns document-tier rendering and work-product materialization. KDA routes work products by reference and does not inline-render large document content.
### 11.8 OP-A V3.15
KDA R3 implementation must update or satisfy the OP-A rows for manifest patch union, KDA variant tracking, ClientKind canonicalization, banded budget allocator, canary state machine, cache-stable rendering, tokenizer drift consumption, work-product document-tier routing, and closed reason codes.
---
### 11.9 R2 → R3 cross-document obligation disposition
| R2 target / surface | R3 disposition | R3 owner / tracking note |
|---|---|---|
| DOC72 shared payload schemas for `procedure`, `memory_directive`, `domain_concept`, `goal`, `obligation`, `standing_procedure` | **Superseded by DOC72 ownership; preserved by KDA consumption.** | DOC72 owns canonical payload shapes. KDA consumes render-input snapshots and does not redefine graph schemas. |
| DOC72 annotation index / node payload validation | **Preserved outside KDA runtime.** | DOC72 / EC write-time validation and indexing own the graph substrate. KDA consumes validated snapshots. |
| DOC24 rendering tier system and packet budget | **Preserved and updated.** | KDA R3 owns deterministic rendering/tier allocation; DOC24 owns packet assembly and manifests. |
| DOC24 local KDA injection manifest | **Superseded.** | Deleted. DOC24 owns `PacketInjectionManifest`; KDA emits `KdaManifestPatch`. |
| DOC3 graph-backed procedure execution through DOC24 injection | **Preserved.** | Graph-backed procedures render through DOC24/KDA injection path, not SKILL.md. |
| DOC3 SKILL.md materialization for graph procedures | **Superseded / non-operative.** | SKILL.md is export-only for graph-backed procedures; native/imported non-graph skills remain outside KDA runtime. |
| DOC3 interpretation prompt filling shared contracts | **Moved upstream.** | DOC3/DOC72/EC extraction/intake path owns extraction model selection and payload write. KDA consumes derivation metadata. |
| DOC8 annotation pattern detection / rendering specialization proposals | **Preserved and tightened.** | KDA R3 scoped neuroplasticity + annotation utility index + canary state machine. DOC8/BDSM provides governed utility signals. |
| DOC15 CIL tier priority recognition | **Superseded by DOC24 R3.1.1 manifest/lifecycle integration.** | DOC24/DOC11/OpenClaw final prompt assembly consumes rendered cards and spans; KDA does not own CIL. |
| DOC11 SKILL.md bridge removal for graph procedures | **Preserved.** | DOC11/OpenClaw consume final prompt/card spans; graph-backed procedures do not require SKILL.md projection. |
| DOC11 RuntimeAbilityLoadReceipt from R2 | **Superseded by DOC24/DOC11 final-prompt manifest/span receipts.** | Use `FinalPromptInjectionManifest` spans and DOC11/OpenClaw delivery receipts. |
| DOC21/22 UI preview / injection details | **Preserved as KDA preview + DOC24 packet inspector surfaces.** | KDA owns preview render result; DOC24 owns packet inspector. |
| Knowledge Store Integration Map SKILL.md → export-only | **Preserved.** | Appendix A export-only note is normative. |
| R2 `local_elnor` client kind | **Superseded.** | `elnor_native` is canonical; `local_elnor` is migration alias only. |
| R2 remote rendering mode `full | guidance_only | suppress` | **Preserved with R3 policy integration.** | KDA §3.3 / §3.9 resolve remote rendering mode using ClientKind, PropA policy, execution strategy, and mounted tools. |
## Appendix A — Non-operative R2 constructs
The following R2 constructs are superseded and MUST NOT be implemented in R3:
```ts
export const KdaNonOperativeContractMarkers = [
{
legacy_name: "InjectionManifestSchema",
superseded_by: "KdaManifestPatch consumed by DOC24 PacketInjectionManifest writer",
implementation_status: "MUST_NOT_IMPLEMENT",
reason: "KDA does not own manifest writing in DOC24 R3.1.1+",
schema_version: 1,
},
{
legacy_name: "UnifiedInjectionManifestSchema",
superseded_by: "DOC24 PacketInjectionManifest / FinalPromptInjectionManifest chain",
implementation_status: "MUST_NOT_IMPLEMENT",
reason: "UnifiedInjectionManifestSchema is retired; KDA must not revive it locally",
schema_version: 1,
},
{
legacy_name: "PacketReconciliationOverlay",
superseded_by: "append-only PacketReconciliationEvent[]",
implementation_status: "MUST_NOT_IMPLEMENT",
reason: "Reconciliation overlay mental model is retired; KDA consumes event-derived views only",
schema_version: 1,
},
{
legacy_name: "reconciliation_overlay",
superseded_by: "reconciliation_event",
implementation_status: "MUST_NOT_IMPLEMENT",
reason: "Field name is retired per DOC24 R3.1.1 event model",
schema_version: 1,
},
{
legacy_name: "renderProcedureInjectionCard(): Promise<string>",
superseded_by: "renderKnowledgeCardV3(input): KdaRenderResult",
implementation_status: "MUST_NOT_IMPLEMENT",
reason: "BDSM attribution requires variant metadata, token count, and manifest patch fields",
schema_version: 1,
},
{
legacy_name: "ExtractionModelConfigSchema",
superseded_by: "DOC72/DOC3/EC extraction-intake model configuration; KDA consumes derivation metadata only",
implementation_status: "MUST_NOT_IMPLEMENT",
reason: "KDA R3 is runtime rendering, not extraction-model selection",
schema_version: 1,
},
{
legacy_name: "ClientKind.local_elnor",
superseded_by: "ClientKind.elnor_native with migration alias",
implementation_status: "MUST_NOT_IMPLEMENT",
reason: "Canonical client-kind value changed; local_elnor is migration-only",
schema_version: 1,
},
] as const;
```
The following R2 / pre-R3 constructs fail build if present outside historical prose or migration notes:
- `InjectionManifestSchema`
- `UnifiedInjectionManifestSchema`
- `PacketReconciliationOverlay`
- `reconciliation_overlay`
- `renderProcedureInjectionCard(): Promise<string>`
### Appendix A.X — SKILL.md export-only status
KDA R3 SHALL NOT render graph-backed DOC72 procedure nodes through SKILL.md files.
SKILL.md remains permitted only as:
1. the native/imported skill runtime format for skills that are not yet graph-ingested; and
2. an optional portability/export format outside the DOC24 packet rendering path.
If a future export feature emits SKILL.md from a graph-backed procedure, that feature is non-runtime and must be governed by DOC3 / DOC11 / EC export and rollback rules. The export path must compare the exported file against the prior export, flag regressions, preserve the previous export for rollback, and emit an export receipt. KDA runtime rendering ignores SKILL.md exports.
```ts
export type KdaSkillMarkdownDisposition =
| { kind: "native_or_imported_skill_runtime"; graph_backed: false; runtime_allowed: true; schema_version: 1 }
| { kind: "graph_backed_procedure_export"; graph_backed: true; runtime_allowed: false; export_receipt_id: string; schema_version: 1 };
```
## Appendix B — Utility functions referenced by this spec
The following functions are required imports or local deterministic utilities. Implementations MUST define or import them before build:
```ts
declare function canonicalJson(value: unknown): string;
declare function sha256(value: string): string;
declare function countTokens(text: string, tokenizer: TokenizerRef): number;
declare function renderTemplateFromSnapshot(input: KdaRenderInputBundle, policy: ReturnType<typeof enforceKdaRenderPolicy>): string;
declare function selectRenderVariantId(input: KdaRenderInputBundle): string;
declare function selectTemplateVersion(input: KdaRenderInputBundle): string;
declare function activeTemplateHash(input: KdaRenderInputBundle): string;
declare function renderProvenanceFromInput(input: KdaRenderInputBundle): KdaRenderResult["render_provenance"];
declare function isSameOrNarrowerScope(requested: RenderingSpecializationScope, learned: RenderingSpecializationScope): boolean;
declare function projectProcedurePayloadForKda(raw_payload: unknown): KdaProcedureProjectionResult;
declare function resolveKdaRenderableNodeKind(node_kind: string): KdaRenderableNodeKindDecision;
declare function resolveRemoteRenderingModeV3(input: {
client_kind: ClientKind;
destination: "same_machine_local_runtime" | "cloud_api" | "external_share";
render_policy: KdaRenderPolicyInput;
procedure_steps: KdaSemanticStepProjection[];
execution_strategies: KdaExecutionStrategySummary[];
mounted_tools: KdaMountedToolSnapshot;
schema_version: 1;
}): KdaRemoteRenderingModeDecision;
declare function renderSemanticStepV3(input: {
step: KdaSemanticStepProjection;
rendering_tier: RenderingTier;
remote_rendering_mode: KdaRemoteRenderingMode;
execution_strategy_state?: KdaStepExecutionStrategyState;
include_rationale: boolean;
schema_version: 1;
}): KdaRenderedStep;
declare class KdaValidationError extends Error {
constructor(input: { reason_code: KdaReasonCode; metadata?: Record<string, unknown> });
}
```