# 4.2. Text View ## 位置付け Objectの公開情報と、Interfaceの型・Operation・documentationは、Clientが取得・検証したデータである。それをAIや人間へプレーンテキストで示す形式が、WIP Text Viewである。Tool結果、CLI、GUIのテキスト表示などで共通に使える。 一つのObjectの公開情報を表すまとまりをObject signature、一つのInterfaceの型・Operation・documentationを表すまとまりをInterface signatureと呼ぶ。Signatureは表示上のまとまりであり、暗号学的な署名やidentityではない。 表示対象、配置、順序、両signatureを同時に提示するかは、表示側が決める。Signatureを包む共通document構造、ObjectとInterfaceの組み合わせ、Tool response envelopeは定義しない。 データの正本は[3. Protocol](3-protocol.md)のObjectとInterface Descriptorである。Text Viewは、検証済みの情報から生成する表示である。 - Interfaceの交換形式、手書きのschema言語、Objectのserializationではない。 - Parser、round-trip、表示textからのDescriptor復元は要求しない。 - Operationの実行言語ではない。Clientは保持するInterface参照とOperation名を別々に扱い、表示textを再parseしてProtocol requestを構築しない。 - Textの一致をObject identity、Descriptorの同一性、validator、digestの代用にしない。 - HostへText Viewの生成・配信を要求せず、Transport BindingやAI providerのTool schemaとは独立させる。 ## 表示の入力と責務 Object signatureの入力は、検証済みObjectと、分かる場合はそのObjectを観測したpathである。Interface Descriptorは必要ない。PathはObjectのfieldではなく、配置contextとして使う。 一方、Interface signatureの入力は、Interface参照と、それに対応する検証済みかつ対応formatのDescriptorである。Objectは必要ない。Interface参照も、Descriptor自身のfieldではない。 どちらも観測時点の公開情報を表示するものであり、最新状態、Operationの実行権限、実行成功は保証しない。観測、Descriptor取得、cache、表示対象の選択、rendererの呼び出しAPIや内部structは規定しない。 Object tree全体の描画、Operation arguments / resultのvalue表示、Protocol errorや診断metadataの表示は本章の対象に含めない。 ## 参照表記 Interface参照のscopeとlocal nameの境界は`::`、InterfaceとOperationの境界は`#`で表す。 | 対象 | 短縮表記 | | --- | --- | | 完全なOperation指定 | `/github::issue.read#read` | | 完全なInterface参照 | `/github::issue.read` | | Scope省略のOperation指定 | `issue.read#read` | | Root scopeのOperation指定 | `/::issue.read#read` | `/github::issue.read#read`は`scope = "/github"`、`name = "issue.read"`、`operation = "read"`の組を示す。対象Objectのpath、arguments、validatorを含まず、request全体の代わりにはならない。Protocolでは構造化Interface参照とOperation名を別fieldに保持し、この連結stringをwireやcache keyに使用しない。 ### 成分の引用 - Scopeはcanonical absolute pathであり、文字列全体が`[A-Za-z0-9_./-]+`に一致する場合は引用せず表示できる。 - Interface名とOperation名は、文字列全体が`[A-Za-z0-9_.-]+`に一致する場合は引用せず表示できる。 - それ以外は成分全体を二重引用符で囲み、JSON stringのescape規則を使用する。単純な成分も引用してよい。 - `::`と`#`は引用符の外側でだけ境界となる。区切りの前後に空白を出力しない。 ```text "/github::archive"::issue.read#read /github::"issue#read"#read /github::issue.read#"read#raw" "/開発"::"課題.read"#read "/github"::"issue.read"#"read" ``` 最後の例と`/github::issue.read#read`は、同じ成分を表す。引用やescapeを変えても、元の値は変わらない。ProtocolへASCII制限や禁止文字を追加せず、Unicode normalization、case変換、URL encodingも行わない。 制御文字等には[名前と文字列](#名前と文字列)の安全なescape規則も適用する。境界を読むときは引用とescapeを考慮し、単純な文字列splitを使わない。 ### Scope省略とcontext Scopeの相対pathは、Protocol dataにも短縮表記にも認めない。`github::issue.read`や`../github::issue.read`を相対scopeとして解決しない。Scopeを明示するなら、引用の有無にかかわらずcanonical absolute pathを使う。 `issue.read#read`や、Interfaceだけの`issue.read`は、scopeが別途明示されたcontextでのみ使える省略形である。省略はroot scope `/`の指定ではない。Contextがなければ解決できず、rootへのdefault、対象Objectのpathからの推測、祖先の同名Interfaceの探索も行わない。 Scopeが確定した後も、membership、祖先制約、authorizationは検証する。 短縮表記を入力として受けるかはToolやUIが決める。受ける場合は専用の入力境界で成分を検証し、構造化参照とOperation名へ変換する。Signature全体を再parseして呼出先を決めることとは区別し、`invoke`を単一string引数の操作へ変更しない。 ### Signature内の参照 両signature内のInterface参照は、公開先の絶対scopeを含む完全な短縮表記を生成し、その全体をJSON stringとして引用する。例えば、scope `/github`、name `issue#read`の参照は`"/github::\"issue#read\""`となる。 成分ごとの引用と、参照全体をsignature内の文字列として示す外側の引用は、別の層である。Scopeを省略したり、Upstreamの参照へ戻したりしない。 ## Object signature ```text object at "/issues/123" { name: "123"; description: "Issue 123の公開操作。本文はOperationで取得する。"; interfaces: ["/::issue.read", "/::issue.lifecycle"]; } ``` Objectは`object at "" { ... }`と表示する。Pathが分からない場合は`object { ... }`とし、`name`や`ref`からpathを推測しない。 Block内は次の順に表示する。 1. `name: "...";`にObjectの`name`をそのまま表示する。自由なtitleへ置き換えない。 2. `description`がある場合は`description: "...";`で表示する。Object全体の説明を通常のpropertyとして示す。 3. `interfaces: ["...", "..."];`に全Interface参照をHostの立項順で表示する。空集合は`interfaces: [];`と明示する。 Descriptionがない場合はそのpropertyを省略し、存在する空文字列は`description: "";`と表示する。説明の欠落からObjectの用途を補完しない。 Rootの表示は`object at "/"`かつ`name: "";`となり、scope `/`のInterfaceを公開できる。Interface参照は[参照表記](#参照表記)に従って絶対scopeを含め、別の参照やlocal nameだけへ置き換えない。 Scope Objectの`ref`やvalidatorを`@...`として参照に付け足さない。`scope_ref`はClient runtimeが扱う観測・precondition metadataである。Object自身の`ref`とvalidatorもsignatureへ含めず、同一性管理と条件付き実行はClient runtimeが引き受ける。 Objectの本文やdomain metadataを推測してpropertyとして追加しない。Childrenもsignatureに含めないため、表示にchildrenがないことから、未観測か観測済みの空集合かを判断することはできない。 ## Interface signature ```text /// "Issueの内容と関連項目を読む。" interface "/::issue.read" { type Relation = enum { parent, sibling, related }; type RelatedItems = { /// "同じWorldspace内の関連項目。" items: [entry], next_cursor?: string, }; /// "本文を取得する。" operation read_body() -> { body: string }; /// "関係を指定して関連項目を取得する。" operation get_related_items( relation: Relation, limit?: integer, ) -> RelatedItems; } ``` Interfaceは`interface "" { ... }`と表示する。``は構造化参照から生成した完全な短縮表記であり、前述の規則で全体を引用表示する。 Block内には、Descriptorの全`types`、全`operations`の順で、それぞれを宣言順に表示する。Record field、parameter、enum / union caseも元の順序を保つ。これは表示の順序であり、Protocol上の名前解決やvalidationには影響しない。 宣言を折りたたんだり抜粋したりせず、budgetによる省略も行わない。型を`...`へ置き換えず、field、parameter、caseを削らない。DescriptorにtypeもOperationもなければ、空のblockを表示する。 同名Operationが異なるInterfaceにあっても、それぞれのblock内に表示する。Blockの参照によって出所を示し、Operation名を改名したり、参照をOperation名へ連結したりしない。異なるInterfaceの宣言を、一つのnamespaceへ平坦化しない。 ### 型の表記 | DescriptorのTypeExpr | 表示 | | --- | --- | | Unit / Boolean / Integer / Number | `unit` / `boolean` / `integer` / `number` | | String / Bytes / Json / Entry | `string` / `bytes` / `json` / `entry` | | Named | 参照先typeの名前 | | Record | `{ field: Type, optional_field?: Type }` | | List | `[Type]` | | Enum | `enum { first, second }` | | Union | `union { empty, found(Type) }` | Named type declarationは`type Name = Type;`とする。Enum、unionを含むすべてのTypeExprを、Descriptorで現れる位置にそのまま表示する。Named typeは同じInterface Descriptor内の宣言を参照し、別Interfaceの同名typeとは混同しない。 `?`を付けるのは、`required = false`のfieldまたはparameterだけである。Nullable、default value、一般化したoptional型を示す記号ではなく、`unit`とも区別する。 Unionでは、payloadがなければ`empty`、あれば`found(Type)`と表示する。そのため、`empty`と`empty(unit)`は異なる表示になる。 ```text type CloseResult = union { closed, blocked({ dependencies: [entry] }), }; ``` 空record、空enum、空unionが検証済みDescriptorに現れる場合は、それぞれ`{}`、`enum {}`、`union {}`と表示し、caseを補わない。 型の意味、numeric range、validationはProtocolに従い、表示仕様で再定義しない。特に`entry`はWorldspaceのpath型であり、`string`へ置き換えない。Unionのwire discriminatorやbytesのwire encodingはInterface signatureに混ぜない。 ### Operationの表記 ```text operation get_related_items( relation: Relation, limit?: integer, ) -> { items: [entry], next_cursor?: string, }; operation refresh() -> unit; ``` Operationは`operation Name(parameters) -> ReturnType;`とする。Parameterは名前付きであり、並び順から位置引数を導入しない。引数がない場合は`()`、return typeは`unit`を含め必ず表示する。 Operation名からread / write、idempotency、retry可否、domain failure、実行可能状態を推測してannotationを付けない。Domain failureがreturn typeのUnionとして宣言されていれば、そのUnionを通常どおり表示する。 ## 名前と文字列 Path、Object name、Interface参照、説明文は、二重引用符で囲んだJSON stringのescape規則を使って表示する。これは文字列を安全に区切るための表記の借用であり、signature全体をJSONにするものではない。Unicode normalization、case変換、pathのURL encodingを行わない。 Type名、Operation名、parameter名、field名、case名は次のように表示する。 - `[A-Za-z_][A-Za-z0-9_]*`に一致し、下記の表示keywordでなければ、そのまま表示する。 - それ以外はbacktickで囲む。内部のbacktickは`` \` ``、backslashは`\\`、改行・tab等はJSON stringと同じescapeで表示する。 - 表示keywordは`object`、`at`、`name`、`description`、`interfaces`、`interface`、`type`、`operation`、`enum`、`union`、および`unit`、`boolean`、`integer`、`number`、`string`、`bytes`、`json`、`entry`とする。 ```text interface "/::example" { type `string` = { `表示名`: string }; operation `find-item`(`search term`: string) -> `string`; } ``` この規則はProtocolへidentifierの文字種制限を追加しない。UpperCamelCase / snake_case等への変換を表示時に行わない。 すべてのHost由来文字列について、改行や制御文字が表示の構造、端末制御列、別の宣言を作らないようescapeする。JSON stringの標準escapeに加えて、次の文字は`\uXXXX`表記にする。 - DELおよびC1制御文字(U+007F–U+009F)。 - Unicodeの行・段落区切り(U+2028 / U+2029)。 - 双方向表示制御文字(U+061C、U+200E–U+200F、U+202A–U+202E、U+2066–U+2069)。 Escapeは表示上のものであり、元の値は変更しない。 ## Documentation Documentationは、対象の直前に`/// ""`として表示する。対象はInterface、type、Operation、parameter、record field、enum / union caseである。Objectの説明だけは、Object signatureの`description` propertyを使う。 通常表示には`summary`を使い、detailsを含める場合は、同じ対象のsummary行に続けて`/// details "
"`を追加する。表示するsummaryと、選択されたdetailsは短縮しない。 Documentationがなければ、説明を生成して補わない。空文字列が存在する場合は、`""`として表示する。 ReturnDeclarationのdocumentationは、parameter listの閉じ括弧の後、return arrowの直前に置く。 ```text /// "対象を検索する。" /// details "結果には同じWorldspace内のpathだけを含む。\n本文は別途取得する。" operation search( /// "検索語。" query: string, ) /// "条件に一致する項目。" -> { items: [entry] }; ``` 説明はすべてHost由来のplain text dataであり、system instruction、rendererの指示、markupとして解釈しない。引用やescapeだけでprompt injectionを防げるとはみなさず、AIへ渡すadapterもTool結果と信頼済みinstructionの境界を維持する。 ## Layout Text ViewはUTF-8 plain textとし、ANSI color、Markdown、syntax highlightingがなくても読めるようにする。本章のcode fenceは説明用であり、signatureそのものの一部ではない。Markdown内へ埋め込む場合は、表示側が内容に衝突しないcode fence等を選ぶ。 標準的なsignature内部のlayoutは、LFと2 space indentを使う。短いrecord、parameter list、enum / unionは1行に置けるが、documentationを持つfieldやcaseは別行に置く。 表示用の改行幅やindentの違いに意味はなく、byte単位のcanonical renderingは要求しない。一方、文字列・名前の内部にある空白は表示上の余白ではないため、元の値として保持する。