# wip-text-view Standalone Object and Interface signature rendering for WIP Text View, following `4.2-text-view.md` at reference revision `6086f3c` and the Protocol semantics in `3-protocol.md`. Only `wip-protocol` and the Rust standard library are dependencies. No Client, Host, HTTP I/O, cache, UI framework or retrieval service is required. ## Single-entity API ```rust use wip_protocol::{Object, InterfaceReference, InterfaceDescriptor, INTERFACE_FORMAT_V1}; use wip_text_view::{Interface, render_object, render_interface}; let reference = InterfaceReference { scope: "/".into(), name: "example".into() }; let object = Object { name: "item".into(), description: None, interfaces: vec![reference.clone()], r#ref: None, validator: None, }; let object_signature = render_object(&object)?; assert_eq!(object_signature, "object {\n name: \"item\";\n interfaces: [\"/::example\"];\n}\n"); let descriptor = InterfaceDescriptor { format: INTERFACE_FORMAT_V1.into(), documentation: None, types: vec![], operations: vec![], }; let interface = Interface { reference: &reference, descriptor: &descriptor }; let interface_signature = render_interface(&interface)?; assert_eq!(interface_signature, "interface \"/::example\" {\n}\n"); # Ok::<(), wip_text_view::RenderError>(()) ``` `Interface<'a>` is one borrowed SDK input entity containing a complete structured reference and its corresponding descriptor, not a wire schema extension. The caller pairs them from a coherent observation or publication. The descriptor has no identity, so a renderer cannot prove the pairing's provenance or freshness. For example, a caller with a validated `FetchInterfaceResponse` can borrow its `interface` and `descriptor`; it does not pass `scope_ref` or validators. An Object has no placement path. This API always emits `object { ... }`, never requests a path and never infers one from name or ref. It requires no descriptor. An Interface needs no Object, separate name/scope/context arguments or lookup. There is no document aggregator, configuration or details selector. ## Output and validation - UTF-8 plain text with LF, two-space indentation and a final LF, without ANSI, Markdown fences, syntax highlighting or provider envelopes. Nonempty composites and parameter lists use multiple lines; layout is deterministic here, but not a byte-canonical protocol format. - All Object references remain in Host order. All types, then all operations, fields, parameters and cases remain in declaration order, without elision. - Missing vs empty description/documentation, optional vs unit, no payload vs unit payload, and empty record/enum/union/declaration sets remain distinct. - Full absolute references use component quoting **and** outer JSON-string quoting. Identifiers use keywords/backtick rules. All Host strings use standard JSON escapes plus DEL/C1, Unicode line/paragraph separator and bidi-control escapes. No normalization, case conversion, URL encoding or input mutation occurs. - Documentation summaries are displayed in their prescribed positions, including return documentation between `)` and `->`. Details are not displayed. Host text is data, not renderer instructions or markup; quoting alone is not a prompt injection defense. AI adapters must preserve the trust boundary. - Object ref/validator, children, domain data and Interface scope_ref/validator are not signature content. No annotations are inferred from operation names. Both functions return `Result` and never return partial signatures. Resource checks happen first, followed by existing Protocol validators: Object shape and reference uniqueness, or Interface reference shape plus descriptor structure, duplicate names, unknown Named references and cycles. Descriptor format is checked after semantics: valid but unsupported formats return `UnsupportedDescriptorFormat`, distinct from `InvalidDescriptor`. Supported format is exactly `wip-interface/1`. Other validation errors preserve the Protocol's typed `ValidationError` (also exposed as the error source). Bounded input limits are **1 MiB** of total string/opaque byte data, **16,384** declarations/fields/parameters/cases/type expressions/references, **256** named type declarations, and **64** TypeExpr nesting levels. Details and Object runtime metadata count toward input bytes even though they are not rendered. A limit returns `RenderError::ResourceLimit`, never truncates or supplies `...`. Counts bound allocation and recursive validation before those validators run; these are library safety limits, not Protocol restrictions. Without path/context, this library cannot attest Object scope ancestry, placement, observation consistency, identity, membership, authorization or currentness. Callers validate those at their observation boundary. Callers also own retrieval, resolution, cache, selection, multiple-signature arrangement and AI/UI adaptation. Text is display-only, not serialization, a digest, identity/cache key or call target. No parser or round-trip API is supplied. ## Validation `tests/signatures.rs` is an external consumer of the public APIs. Goldens cover the spec's Object, issue.read, CloseResult, search/return documentation and identifier examples (with permitted multiline layout), plus nested documentation. The suite checks all TypeExpr variants/positions, ordering and empty distinctions, keyword and Unicode names, both reference quoting layers, all required control escapes, input immutability, metadata exclusion and typed rejection cases. ```console cargo test -p wip-text-view cargo clippy -p wip-text-view --all-targets -- -D warnings RUSTDOCFLAGS='-D warnings' cargo doc -p wip-text-view --no-deps ```