Files

239 lines
15 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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>" { ... }`と表示する。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 "<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)`は異なる表示になる。
```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は、対象の直前に`/// "<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の直前に置く。
```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は要求しない。一方、文字列・名前の内部にある空白は表示上の余白ではないため、元の値として保持する。