15 KiB
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の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規則を使用する。単純な成分も引用してよい。
::と#は引用符の外側でだけ境界となる。区切りの前後に空白を出力しない。
"/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
object at "/issues/123" {
name: "123";
description: "Issue 123の公開操作。本文はOperationで取得する。";
interfaces: ["/::issue.read", "/::issue.lifecycle"];
}
Objectはobject at "<path>" { ... }と表示する。Pathが分からない場合はobject { ... }とし、nameやrefからpathを推測しない。
Block内は次の順に表示する。
name: "...";にObjectのnameをそのまま表示する。自由なtitleへ置き換えない。descriptionがある場合はdescription: "...";で表示する。Object全体の説明を通常のpropertyとして示す。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
/// "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 "<reference>" { ... }と表示する。<reference>は構造化参照から生成した完全な短縮表記であり、前述の規則で全体を引用表示する。
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)は異なる表示になる。
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の表記
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とする。
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は、対象の直前に/// "<summary>"として表示する。対象はInterface、type、Operation、parameter、record field、enum / union caseである。Objectの説明だけは、Object signatureのdescription propertyを使う。
通常表示にはsummaryを使い、detailsを含める場合は、同じ対象のsummary行に続けて/// details "<details>"を追加する。表示するsummaryと、選択されたdetailsは短縮しない。
Documentationがなければ、説明を生成して補わない。空文字列が存在する場合は、""として表示する。
ReturnDeclarationのdocumentationは、parameter listの閉じ括弧の後、return arrowの直前に置く。
/// "対象を検索する。"
/// 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は要求しない。一方、文字列・名前の内部にある空白は表示上の余白ではないため、元の値として保持する。